cloudfs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +13 -0
- data/lib/cloudfs.rb +18 -0
- data/lib/cloudfs/account.rb +95 -0
- data/lib/cloudfs/client/connection.rb +154 -0
- data/lib/cloudfs/client/constants.rb +80 -0
- data/lib/cloudfs/client/error.rb +452 -0
- data/lib/cloudfs/client/utils.rb +93 -0
- data/lib/cloudfs/container.rb +51 -0
- data/lib/cloudfs/file.rb +209 -0
- data/lib/cloudfs/filesystem.rb +111 -0
- data/lib/cloudfs/filesystem_common.rb +228 -0
- data/lib/cloudfs/folder.rb +94 -0
- data/lib/cloudfs/item.rb +640 -0
- data/lib/cloudfs/media.rb +32 -0
- data/lib/cloudfs/rest_adapter.rb +1233 -0
- data/lib/cloudfs/session.rb +256 -0
- data/lib/cloudfs/share.rb +286 -0
- data/lib/cloudfs/user.rb +107 -0
- data/lib/cloudfs/version.rb +3 -0
- data/spec/account_spec.rb +93 -0
- data/spec/container_spec.rb +37 -0
- data/spec/file_spec.rb +134 -0
- data/spec/filesystem_spec.rb +16 -0
- data/spec/folder_spec.rb +106 -0
- data/spec/item_spec.rb +194 -0
- data/spec/session_spec.rb +102 -0
- data/spec/share_spec.rb +159 -0
- data/spec/user_spec.rb +70 -0
- metadata +124 -0
@@ -0,0 +1,228 @@
|
|
1
|
+
require_relative 'rest_adapter'
|
2
|
+
|
3
|
+
module CloudFS
|
4
|
+
# @private
|
5
|
+
# Provides common filesystem operations consumed by other classes
|
6
|
+
module FileSystemCommon
|
7
|
+
extend self
|
8
|
+
|
9
|
+
# @return [Audio, Video, Photo, Document, File] based on mime type
|
10
|
+
def create_file_from_mime_type(rest_adapter, parent: nil,
|
11
|
+
in_trash: false, in_share: false, old_version: false, ** hash)
|
12
|
+
require_relative 'file'
|
13
|
+
require_relative 'media'
|
14
|
+
|
15
|
+
mime = hash[:mime]
|
16
|
+
if mime.include?('audio')
|
17
|
+
Audio.new(rest_adapter, parent: parent,
|
18
|
+
in_trash: in_trash, in_share: in_share,
|
19
|
+
old_version: old_version, ** hash)
|
20
|
+
elsif mime.include?('video')
|
21
|
+
Video.new(rest_adapter, parent: parent,
|
22
|
+
in_trash: in_trash, in_share: in_share,
|
23
|
+
old_version: old_version, ** hash)
|
24
|
+
elsif mime.include?('image')
|
25
|
+
Photo.new(rest_adapter, parent: parent,
|
26
|
+
in_trash: in_trash, in_share: in_share,
|
27
|
+
old_version: old_version, ** hash)
|
28
|
+
elsif mime.include?('text') || mime.include?('pdf')
|
29
|
+
Document.new(rest_adapter, parent: parent,
|
30
|
+
in_trash: in_trash, in_share: in_share,
|
31
|
+
old_version: old_version, ** hash)
|
32
|
+
else
|
33
|
+
File.new(rest_adapter, parent: parent,
|
34
|
+
in_trash: in_trash, in_share: in_share,
|
35
|
+
old_version: old_version, ** hash)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# Create item from hash
|
41
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
42
|
+
# @param parent [Item, String] parent item of type folder
|
43
|
+
# @option parent_state [Hash] parent_state the parent state of the item
|
44
|
+
# @param in_trash [Boolean] set true to specify, item exists in trash
|
45
|
+
# @param in_share [Boolean] set true to specify, item exists in share
|
46
|
+
# @param old_version [Boolean] set true to specify, item is an old version
|
47
|
+
# @param hash [Hash] item properties
|
48
|
+
# @return [File, Folder, Share] item
|
49
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
50
|
+
# @review not creating file objects based on mime type,
|
51
|
+
# since save operation cannot update the class of file object,
|
52
|
+
# if mime is changed
|
53
|
+
def create_item_from_hash(rest_adapter, parent: nil, parent_state: nil,
|
54
|
+
in_trash: false, in_share: false, old_version: false, ** hash)
|
55
|
+
require_relative 'file'
|
56
|
+
require_relative 'folder'
|
57
|
+
require_relative 'share'
|
58
|
+
|
59
|
+
return Share.new(rest_adapter, ** hash) if hash.key?(:share_key)
|
60
|
+
fail RestAdapter::Errors::ArgumentError,
|
61
|
+
'Did not recognize item' unless hash.key?(:type)
|
62
|
+
if hash[:type] == 'folder' || hash[:type] == 'root'
|
63
|
+
Folder.new(rest_adapter, parent: parent, parent_state: parent_state,
|
64
|
+
in_trash: in_trash, in_share: in_share, ** hash)
|
65
|
+
else
|
66
|
+
File.new(rest_adapter, parent: parent, parent_state: parent_state,
|
67
|
+
in_trash: in_trash, in_share: in_share,
|
68
|
+
old_version: old_version, ** hash)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create array items from corresponding array of hashes
|
73
|
+
# @param hashes [Array<Hash>] array of hash properties of items
|
74
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
75
|
+
# @option parent [Item, String] parent item of type folder
|
76
|
+
# @option parent_state [Hash] parent_state the parent state of the item
|
77
|
+
# @option in_trash [Boolean] set true to specify, items exist in trash
|
78
|
+
# @option in_share [Boolean] set true to specify, items exist in share
|
79
|
+
# @option old_version [Boolean] set true to specify, items are old version
|
80
|
+
# @return [Array<File, Folder, Share>] items
|
81
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
82
|
+
def create_items_from_hash_array(hashes, rest_adapter,
|
83
|
+
parent: nil, parent_state: nil, in_trash: false, in_share: false, old_version: false)
|
84
|
+
items = []
|
85
|
+
hashes.each do |item|
|
86
|
+
resp = create_item_from_hash(rest_adapter, parent: parent, parent_state: parent_state,
|
87
|
+
in_trash: in_trash, in_share: in_share,
|
88
|
+
old_version: old_version, ** item)
|
89
|
+
items << resp
|
90
|
+
end
|
91
|
+
items
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get folder url
|
95
|
+
# @param folder [Item, String]
|
96
|
+
# @return [String] url of item
|
97
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
98
|
+
def get_folder_url(folder)
|
99
|
+
return nil if RestAdapter::Utils.is_blank?(folder)
|
100
|
+
return folder.url if (folder.respond_to?(:url) &&
|
101
|
+
folder.respond_to?(:type) && (folder.type == 'folder'))
|
102
|
+
return folder if folder.is_a?(String)
|
103
|
+
fail RestAdapter::Errors::ArgumentError,
|
104
|
+
"Invalid input of type #{folder.class}, expected destination item of type CloudFS::Folder or string"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Get item url
|
108
|
+
# @param item [File, Folder, String]
|
109
|
+
# @return [String] url of item
|
110
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
111
|
+
def get_item_url(item)
|
112
|
+
return nil if RestAdapter::Utils.is_blank?(item)
|
113
|
+
return item.url if item.respond_to?(:url)
|
114
|
+
return item if item.is_a?(String)
|
115
|
+
fail RestAdapter::Errors::ArgumentError,
|
116
|
+
'Invalid input, expected destination item of type file, folder or string'
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get item name
|
120
|
+
# @param item [File, Folder, String]
|
121
|
+
# @return [String] name of item
|
122
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
123
|
+
def get_item_name(item)
|
124
|
+
return nil if RestAdapter::Utils.is_blank?(item)
|
125
|
+
return item.name if item.respond_to?(:name)
|
126
|
+
return item if item.is_a?(String)
|
127
|
+
fail RestAdapter::Errors::ArgumentError,
|
128
|
+
'Invalid input, expected destination item of type file, folder or string'
|
129
|
+
end
|
130
|
+
|
131
|
+
# Validate item's current state for operations
|
132
|
+
# @param item [Item] item to validate
|
133
|
+
# @option in_trash [Boolean] set false to avoid check if item in trash
|
134
|
+
# @option in_share [Boolean] set false to avoid check if item in share
|
135
|
+
# @option exists [Boolean] set false to avoid check if item exists
|
136
|
+
# @version version [Boolean] set false to avoid check if item is not current version
|
137
|
+
# @raise [RestAdapter::Errors::InvalidItemError,
|
138
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
139
|
+
def validate_item_state(item, in_trash: true, in_share: true, exists: true,
|
140
|
+
old_version: true)
|
141
|
+
require_relative 'item'
|
142
|
+
require_relative 'file'
|
143
|
+
return nil unless item.kind_of?(Item)
|
144
|
+
fail RestAdapter::Errors::InvalidItemError,
|
145
|
+
'Operation not allowed as item does not exist anymore' if (exists && item.exists? == false)
|
146
|
+
fail RestAdapter::Errors::OperationNotAllowedError,
|
147
|
+
'Operation not allowed as item is in trash' if (in_trash && item.in_trash?)
|
148
|
+
fail RestAdapter::Errors::OperationNotAllowedError,
|
149
|
+
'Operation not allowed as item is in share' if (in_share && item.in_share?)
|
150
|
+
fail RestAdapter::Errors::OperationNotAllowedError,
|
151
|
+
'Operation not allowed as item is an older version' if (
|
152
|
+
item.kind_of?(CloudFS::File) && old_version && item.old_version?)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Validate share's current state for operations
|
156
|
+
# @param share [Share] share instance to validate
|
157
|
+
# @option exists [Boolean] set false to avoid check if share exists
|
158
|
+
# @raise [RestAdapter::Errors::InvalidShareError,
|
159
|
+
# RestAdapter::Errors::ArgumentError]
|
160
|
+
def validate_share_state(share, exists: true)
|
161
|
+
require_relative 'share'
|
162
|
+
fail RestAdapter::Errors::ArgumentError,
|
163
|
+
"Invalid object of type #{share.class}, expected Share" unless share.kind_of?(Share)
|
164
|
+
fail RestAdapter::Errors::InvalidShareError,
|
165
|
+
'Operation not allowed as share does not exist anymore' if (exists && share.exists? == false)
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
# Fetches properties of named path by recursively listing each member
|
170
|
+
# starting root with depth 1 and filter=name=path_member
|
171
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
172
|
+
# @option named_path [String] named (not pathid) cloudfs path of item i.e. /a/b/c
|
173
|
+
# @return [Hash] containing url and meta of item
|
174
|
+
# @raise [RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError]
|
175
|
+
def get_properties_of_named_path(rest_adapter, named_path)
|
176
|
+
fail RestAdapter::Errors::ArgumentError,
|
177
|
+
'Invalid input, expected destination string' if RestAdapter::Utils.is_blank?(named_path)
|
178
|
+
fail RestAdapter::Errors::ArgumentError,
|
179
|
+
'invalid rest_adapter, input type must be RestAdapter' unless rest_adapter.is_a?(RestAdapter)
|
180
|
+
|
181
|
+
named_path = "#{named_path}".insert(0, '/') unless (named_path[0] == '/')
|
182
|
+
first, *path_members = named_path.split('/')
|
183
|
+
path = first
|
184
|
+
|
185
|
+
response = []
|
186
|
+
path_members.each do |member|
|
187
|
+
response = rest_adapter.list_folder(path: path, depth: 1,
|
188
|
+
filter: "name=#{member}", strict_traverse: true)
|
189
|
+
path << "/#{response.first[:id]}"
|
190
|
+
end
|
191
|
+
|
192
|
+
{url: path, meta: response[0]}
|
193
|
+
end
|
194
|
+
|
195
|
+
# Get an item's properties from server
|
196
|
+
#
|
197
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
198
|
+
# @param parent_url [String] url of parent
|
199
|
+
# @param id [String] pathid of item
|
200
|
+
# @param type [String] ("file", "folder")
|
201
|
+
# @return [Hash] metadata of item
|
202
|
+
#
|
203
|
+
# @raise [RestAdapter::Errors::ServiceError]
|
204
|
+
def get_item_properties_from_server(rest_adapter, parent_url, id, type, in_trash: false)
|
205
|
+
item_url = parent_url.nil? ? "#{id}" : "#{parent_url}/#{id}"
|
206
|
+
if in_trash
|
207
|
+
properties = rest_adapter.browse_trash(path: item_url).fetch(:meta)
|
208
|
+
elsif type == 'folder'
|
209
|
+
properties = rest_adapter.get_folder_meta(item_url)
|
210
|
+
else
|
211
|
+
properties = rest_adapter.get_file_meta(item_url)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Get an item's properties from server
|
216
|
+
#
|
217
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
218
|
+
# @param item_url [String] url of item
|
219
|
+
# @return File, Folder, Share] item
|
220
|
+
#
|
221
|
+
# @raise [RestAdapter::Errors::ServiceError]
|
222
|
+
def get_item(rest_adapter, item_url)
|
223
|
+
item_meta = rest_adapter.get_file_meta(item_url)
|
224
|
+
create_item_from_hash(rest_adapter, ** item_meta)
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative 'container'
|
2
|
+
require_relative 'filesystem_common'
|
3
|
+
|
4
|
+
|
5
|
+
module CloudFS
|
6
|
+
# Represents a folder in the user's filesystem that can contain files and other folders.
|
7
|
+
#
|
8
|
+
# @author Mrinal Dhillon
|
9
|
+
# @example
|
10
|
+
# folder = session.filesystem.root.create_folder(name_of_folder)
|
11
|
+
# folder.name = "newname"
|
12
|
+
# folder.save
|
13
|
+
# file = folder.upload(local_file_path)
|
14
|
+
# folder.list #=> Array<File, Folder>
|
15
|
+
class Folder < Container
|
16
|
+
|
17
|
+
# Upload file to this folder
|
18
|
+
#
|
19
|
+
# @param file_system_path [String, #read&#pos&#pos=] local file path, in-memory string,
|
20
|
+
# an io object for example StringIO, File, Tempfile.
|
21
|
+
# @param name [String] default: nil, name of uploaded file, must be set
|
22
|
+
# if file_system_path does not respond to #path unless file_system_path is local file path
|
23
|
+
# @param exists [String] ('FAIL', 'OVERWRITE', 'RENAME')
|
24
|
+
# action to take in case of a conflict with an existing folder.
|
25
|
+
# @param upload_io [Boolean] default: false,
|
26
|
+
# if set to false, file_system_path is considered to be a local file path
|
27
|
+
#
|
28
|
+
# @return [File] instance reference to uploaded file
|
29
|
+
# @raise [Client::Errors::SessionNotLinked, Client::Errors::ServiceError,
|
30
|
+
# Client::Errors::InvalidItemError, Client::Errors::OperationNotAllowedError]
|
31
|
+
# @example
|
32
|
+
# Upload local file path
|
33
|
+
# file = folder.upload(local_file_path, name: "testfile.txt")
|
34
|
+
# @example
|
35
|
+
# Upload ::File instance
|
36
|
+
# file = ::File.open(local_file_path, "r") do |fp|
|
37
|
+
# folder.upload(fp, name: "testfile.txt", upload_io: true)
|
38
|
+
# end
|
39
|
+
# @example
|
40
|
+
# Upload string
|
41
|
+
# file = folder.upload("This is upload string",
|
42
|
+
# name: 'testfile.txt', upload_io: true)
|
43
|
+
# @example
|
44
|
+
# Upload stream
|
45
|
+
# io = StringIO.new
|
46
|
+
# io.write("this is test stringio")
|
47
|
+
# file = folder.upload(io, name: 'testfile.txt', upload_io: true)
|
48
|
+
# io.close
|
49
|
+
def upload(file_system_path, name: nil, exists: 'FAIL', upload_io: false)
|
50
|
+
FileSystemCommon.validate_item_state(self)
|
51
|
+
fail RestAdapter::Errors::ArgumentError,
|
52
|
+
'Invalid input, expected file system path.' if RestAdapter::Utils.is_blank?(file_system_path)
|
53
|
+
|
54
|
+
if upload_io == false
|
55
|
+
response = ::File.open(file_system_path, 'r') do |file|
|
56
|
+
@rest_adapter.upload(@url, file, name: name, exists: exists)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
response = @rest_adapter.upload(@url, file_system_path, name: name, exists: exists)
|
60
|
+
end
|
61
|
+
FileSystemCommon.create_item_from_hash(@rest_adapter,
|
62
|
+
parent: @url, ** response)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Create folder under this container
|
66
|
+
#
|
67
|
+
# @param name [String] name of folder to be created
|
68
|
+
# @param exists [String] ('FAIL', 'OVERWRITE', 'RENAME') action to take
|
69
|
+
# if the item already exists
|
70
|
+
#
|
71
|
+
# @return [Folder] instance
|
72
|
+
# @raise [RestAdapter::Errors::SessionNotLinked, RestAdapter::Errors::ServiceError,
|
73
|
+
# RestAdapter::Errors::ArgumentError, RestAdapter::Errors::InvalidItemError,
|
74
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
75
|
+
def create_folder(name, exists: 'FAIL')
|
76
|
+
FileSystemCommon.validate_item_state(self)
|
77
|
+
fail RestAdapter::Errors::ArgumentError,
|
78
|
+
'Invalid argument, must pass name' if RestAdapter::Utils.is_blank?(name)
|
79
|
+
|
80
|
+
properties = @rest_adapter.create_folder(name, path: @url, exists: exists)
|
81
|
+
FileSystemCommon.create_item_from_hash(@rest_adapter, parent: @url, ** properties)
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [String]
|
85
|
+
# @!visibility private
|
86
|
+
def to_s
|
87
|
+
"#{self.class}: url #{@url}, name: #{@name}"
|
88
|
+
end
|
89
|
+
|
90
|
+
alias inspect to_s
|
91
|
+
# overriding inherited properties that are not not valid for folder
|
92
|
+
private :blocklist_key, :blocklist_id, :versions, :old_version?
|
93
|
+
end
|
94
|
+
end
|
data/lib/cloudfs/item.rb
ADDED
@@ -0,0 +1,640 @@
|
|
1
|
+
require_relative 'client/constants'
|
2
|
+
require_relative 'filesystem_common'
|
3
|
+
require_relative 'rest_adapter'
|
4
|
+
|
5
|
+
module CloudFS
|
6
|
+
# An object managed by CloudFS. An item can be either a file or folder.
|
7
|
+
#
|
8
|
+
# Item is the base class for File, Container whereas Folder is derived from Container
|
9
|
+
# Provides common APIs for files, folders
|
10
|
+
# @author Mrinal Dhillon
|
11
|
+
class Item
|
12
|
+
|
13
|
+
# @return [String] the internal id of item that is right most path segment in url
|
14
|
+
attr_reader :id
|
15
|
+
|
16
|
+
# @return [String] id of parent of item
|
17
|
+
attr_reader :parent_id
|
18
|
+
|
19
|
+
# @return [String] type of item, either file or folder
|
20
|
+
attr_reader :type
|
21
|
+
|
22
|
+
# @return [String] known current version of item
|
23
|
+
attr_reader :version
|
24
|
+
|
25
|
+
# @return [Boolean] indicating whether the item was created by mirroring a file
|
26
|
+
attr_reader :is_mirrored
|
27
|
+
|
28
|
+
# @return [String] blocklist_key of file
|
29
|
+
attr_reader :blocklist_key
|
30
|
+
|
31
|
+
# @return [String] blocklist_id of file
|
32
|
+
attr_reader :blocklist_id
|
33
|
+
|
34
|
+
# @return [String] absolute path of item in user's account
|
35
|
+
attr_reader :url
|
36
|
+
|
37
|
+
# @return [String] absolute path of item in user's account
|
38
|
+
def path
|
39
|
+
@url
|
40
|
+
end
|
41
|
+
|
42
|
+
# name of item
|
43
|
+
#
|
44
|
+
# @param value [String] name.
|
45
|
+
#
|
46
|
+
# @raise [RestAdapter::Errors::InvalidItemError,
|
47
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
48
|
+
attr_reader :name
|
49
|
+
|
50
|
+
# Sets the new name and updates to CloudFS
|
51
|
+
def name=(new_name)
|
52
|
+
FileSystemCommon.validate_item_state(self)
|
53
|
+
fail RestAdapter::Errors::ArgumentError,
|
54
|
+
'Invalid input, expected new name' if RestAdapter::Utils.is_blank?(new_name)
|
55
|
+
|
56
|
+
@name = new_name
|
57
|
+
@changed_properties[:name] = new_name
|
58
|
+
change_attributes(@changed_properties)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @!attribute [r] date_created
|
62
|
+
# Time when item was created
|
63
|
+
# @overload date_created
|
64
|
+
# @return [Time] creation time
|
65
|
+
def date_created
|
66
|
+
if @date_created
|
67
|
+
Time.at(@date_created)
|
68
|
+
else
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# @!attribute [r] date_meta_last_modified
|
74
|
+
# Time when item's metadata was last modified
|
75
|
+
# @overload date_meta_last_modified
|
76
|
+
# @return [Time] time when metadata was last modified
|
77
|
+
def date_meta_last_modified
|
78
|
+
if @date_meta_last_modified
|
79
|
+
Time.at(@date_meta_last_modified)
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @!attribute [r] date_content_last_modified
|
86
|
+
# Time when item's content was last modified
|
87
|
+
# @overload date_content_last_modified
|
88
|
+
# @return [Time] time when content was last modified
|
89
|
+
def date_content_last_modified
|
90
|
+
if @date_content_last_modified
|
91
|
+
Time.at(@date_content_last_modified)
|
92
|
+
else
|
93
|
+
nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def application_data
|
98
|
+
if @application_data
|
99
|
+
Marshal.load(Marshal.dump(@application_data))
|
100
|
+
else
|
101
|
+
{}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def application_data=(hash={})
|
106
|
+
FileSystemCommon.validate_item_state(self)
|
107
|
+
if @application_data
|
108
|
+
@application_data.merge!(hash)
|
109
|
+
else
|
110
|
+
@application_data = hash.dup
|
111
|
+
end
|
112
|
+
@changed_properties[:application_data].merge!(hash)
|
113
|
+
change_attributes(@changed_properties)
|
114
|
+
end
|
115
|
+
|
116
|
+
# @param rest_adapter [RestAdapter] RESTful Client instance
|
117
|
+
# @param parent [Item, String] default: ("/") parent folder item or url
|
118
|
+
# @option parent_state [Hash] parent_state the parent state of the item
|
119
|
+
# @param in_trash [Boolean] set true to specify item exists in trash
|
120
|
+
# @param in_share [Boolean] set true to specify item exists in share
|
121
|
+
# @param old_version [Boolean] set true to specify item is an old version
|
122
|
+
# @param [Hash] properties metadata of item
|
123
|
+
# @option properties [String] :id path id of item
|
124
|
+
# @option properties [String] :parent_id (nil) pathid of parent of item
|
125
|
+
# @option properties [String] :type (nil) type of item either file, folder
|
126
|
+
# @option properties [String] :name (nil)
|
127
|
+
# @option properties [Timestamp] :date_created (nil)
|
128
|
+
# @option properties [Timestamp] :date_meta_last_modified (nil)
|
129
|
+
# @option properties [Timestamp] :date_content_last_modified (nil)
|
130
|
+
# @option properties [Fixnum] :version (nil)
|
131
|
+
# @option properties [Boolean] :is_mirrored (nil)
|
132
|
+
# @option properties [String] :mime (nil) applicable to item
|
133
|
+
# type file only
|
134
|
+
# @option properties [String] :blocklist_key (nil) applicable to item
|
135
|
+
# type file only
|
136
|
+
# @option properties [String] :blocklist_id (nil) applicable to item
|
137
|
+
# type file only
|
138
|
+
# @option properties [Fixnum] :size (nil) applicable to item of
|
139
|
+
# type file only
|
140
|
+
# @option properties [Hash] :application_data ({}) extra metadata of item
|
141
|
+
#
|
142
|
+
# @raise [RestAdapter::Errors::ArgumentError]
|
143
|
+
def initialize(rest_adapter, parent: nil, parent_state: nil, in_trash: false,
|
144
|
+
in_share: false, old_version: false, ** properties)
|
145
|
+
fail RestAdapter::Errors::ArgumentError,
|
146
|
+
'Invalid RestAdapter, input type must be CloudFS::RestAdapter' unless rest_adapter.is_a?(RestAdapter)
|
147
|
+
|
148
|
+
@rest_adapter = rest_adapter
|
149
|
+
set_item_properties(parent: parent, parent_state: parent_state, in_trash: in_trash,
|
150
|
+
in_share: in_share, old_version: old_version, ** properties)
|
151
|
+
end
|
152
|
+
|
153
|
+
# @see #initialize
|
154
|
+
# @review required properties
|
155
|
+
def set_item_properties(parent: nil, parent_state: nil, in_trash: false,
|
156
|
+
in_share: false, old_version: false, ** params)
|
157
|
+
# id, type and name are required instance variables
|
158
|
+
@id = params.fetch(:id) {
|
159
|
+
fail RestAdapter::Errors::ArgumentError, 'Provide item id' }
|
160
|
+
@type = params.fetch(:type) {
|
161
|
+
fail RestAdapter::Errors::ArgumentError, 'Provide item type' }
|
162
|
+
@name = params.fetch(:name) {
|
163
|
+
fail RestAdapter::Errors::ArgumentError, 'Provide item name' }
|
164
|
+
|
165
|
+
@type = 'folder' if @type == 'root'
|
166
|
+
@parent_id = params[:parent_id]
|
167
|
+
@date_created = params[:date_created]
|
168
|
+
@date_meta_last_modified = params[:date_meta_last_modified]
|
169
|
+
@date_content_last_modified = params[:date_content_last_modified]
|
170
|
+
@version = params[:version]
|
171
|
+
|
172
|
+
if @type == 'file'
|
173
|
+
@is_mirrored = params[:is_mirrored]
|
174
|
+
@mime = params[:mime]
|
175
|
+
@blocklist_key = params[:blocklist_key]
|
176
|
+
@extension = params[:extension]
|
177
|
+
@blocklist_id = params[:blocklist_id]
|
178
|
+
@size = params[:size]
|
179
|
+
end
|
180
|
+
|
181
|
+
@application_data = params[:application_data]
|
182
|
+
@in_trash = in_trash
|
183
|
+
@in_share = in_share
|
184
|
+
@old_version = old_version
|
185
|
+
@exists = true
|
186
|
+
|
187
|
+
@state = parent_state
|
188
|
+
|
189
|
+
set_url(parent)
|
190
|
+
changed_properties_reset
|
191
|
+
end
|
192
|
+
|
193
|
+
# @return [Boolean] whether the item is an older version
|
194
|
+
def old_version?
|
195
|
+
@old_version
|
196
|
+
end
|
197
|
+
|
198
|
+
# @return [Boolean] whether the item exists in trash
|
199
|
+
def in_trash?
|
200
|
+
@in_trash
|
201
|
+
end
|
202
|
+
|
203
|
+
# @return [Boolean] whether the item exists in share
|
204
|
+
def in_share?
|
205
|
+
@in_share
|
206
|
+
end
|
207
|
+
|
208
|
+
# @return [Boolean] whether item exists, false if item
|
209
|
+
# has been deleted permanently
|
210
|
+
def exists?
|
211
|
+
@exists
|
212
|
+
end
|
213
|
+
|
214
|
+
# Reset changed properties
|
215
|
+
def changed_properties_reset
|
216
|
+
@changed_properties = {application_data: {}}
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# Move this item to destination folder
|
221
|
+
# @note Updates this item and it's reference is returned.
|
222
|
+
# @note Locally changed properties get discarded
|
223
|
+
#
|
224
|
+
# @param destination [Item, String] destination to move item to, should be folder
|
225
|
+
# @param name [String] (nil) new name of moved item
|
226
|
+
# @param exists [String] ('FAIL', 'OVERWRITE', 'RENAME')
|
227
|
+
# action to take in case of a conflict with an existing folder, default 'RENAME'
|
228
|
+
#
|
229
|
+
# @return [Item] returns self
|
230
|
+
#
|
231
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
232
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError,
|
233
|
+
# RestAdapter::Errors::InvalidItemError,
|
234
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
235
|
+
def move(destination, name: nil, exists: 'RENAME')
|
236
|
+
FileSystemCommon.validate_item_state(self)
|
237
|
+
FileSystemCommon.validate_item_state(destination)
|
238
|
+
|
239
|
+
destination_url = FileSystemCommon.get_folder_url(destination)
|
240
|
+
name ||= @name
|
241
|
+
|
242
|
+
if @type == 'folder'
|
243
|
+
response = @rest_adapter.move_folder(
|
244
|
+
@url,
|
245
|
+
destination_url,
|
246
|
+
name,
|
247
|
+
exists: exists)
|
248
|
+
else
|
249
|
+
response = @rest_adapter.move_file(
|
250
|
+
@url,
|
251
|
+
destination_url,
|
252
|
+
name,
|
253
|
+
exists: exists)
|
254
|
+
end
|
255
|
+
# Overwrite this item's properties with Moved Item's properties
|
256
|
+
set_item_properties(parent: destination_url, ** response)
|
257
|
+
self
|
258
|
+
end
|
259
|
+
|
260
|
+
# Copy this item to destination
|
261
|
+
# @note Locally changed properties are not copied
|
262
|
+
#
|
263
|
+
# @param destination [Item, String] destination to copy item to,
|
264
|
+
# should be folder
|
265
|
+
# @param name [String] (nil) new name of copied item
|
266
|
+
# @param exists [String] ('FAIL', 'OVERWRITE', 'RENAME')
|
267
|
+
# action to take in case of a conflict with an existing folder,
|
268
|
+
# default 'RENAME'
|
269
|
+
#
|
270
|
+
# @return [Item] new instance of copied item
|
271
|
+
#
|
272
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
273
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError,
|
274
|
+
# RestAdapter::Errors::InvalidItemError,
|
275
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
276
|
+
def copy(destination, name: nil, exists: 'RENAME')
|
277
|
+
FileSystemCommon.validate_item_state(self)
|
278
|
+
FileSystemCommon.validate_item_state(destination)
|
279
|
+
|
280
|
+
destination_url = FileSystemCommon.get_folder_url(destination)
|
281
|
+
name = @name unless name
|
282
|
+
|
283
|
+
if @type == 'folder'
|
284
|
+
response = @rest_adapter.copy_folder(
|
285
|
+
@url,
|
286
|
+
destination_url,
|
287
|
+
name,
|
288
|
+
exists: exists)
|
289
|
+
else
|
290
|
+
response = @rest_adapter.copy_file(
|
291
|
+
@url,
|
292
|
+
destination_url,
|
293
|
+
name,
|
294
|
+
exists: exists)
|
295
|
+
end
|
296
|
+
FileSystemCommon.create_item_from_hash(
|
297
|
+
@rest_adapter,
|
298
|
+
parent: destination_url,
|
299
|
+
** response)
|
300
|
+
end
|
301
|
+
|
302
|
+
# Delete this item
|
303
|
+
# @note Updates this item if operation is successful
|
304
|
+
# @note Locally changed properties get discarded
|
305
|
+
#
|
306
|
+
# @param commit [Boolean] (false) set true to remove item permanently,
|
307
|
+
# else will be moved to trash, RestAdapter::Errors::InvalidItemError
|
308
|
+
# is raised for subsequent operation if commit: true
|
309
|
+
# @param force [Boolean] (false) set true to delete non-empty folder
|
310
|
+
# @param raise_exception [Boolean] (false)
|
311
|
+
# method suppresses exceptions and returns false if set to false,
|
312
|
+
# added so that consuming application can control behaviour
|
313
|
+
#
|
314
|
+
# @return [Boolean] whether operation is successful
|
315
|
+
#
|
316
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
317
|
+
# RestAdapter::Errors::ServiceError,
|
318
|
+
# RestAdapter::Errors::InvalidItemError,
|
319
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
320
|
+
#
|
321
|
+
# if raise_exception is true
|
322
|
+
def delete(commit: false, force: false, raise_exception: false)
|
323
|
+
FileSystemCommon.validate_item_state(self, in_trash: false)
|
324
|
+
|
325
|
+
if @in_trash
|
326
|
+
# @review NOOP if commit is false since item is already in trash, return true
|
327
|
+
if commit
|
328
|
+
@rest_adapter.delete_trash_item(path: @url)
|
329
|
+
@exists = false
|
330
|
+
@in_trash = false
|
331
|
+
end
|
332
|
+
return true
|
333
|
+
end
|
334
|
+
|
335
|
+
if @type == 'folder'
|
336
|
+
@rest_adapter.delete_folder(@url, commit: commit, force: force)
|
337
|
+
else
|
338
|
+
@rest_adapter.delete_file(@url, commit: commit)
|
339
|
+
end
|
340
|
+
|
341
|
+
if commit
|
342
|
+
@exists = false
|
343
|
+
@in_trash = false
|
344
|
+
else
|
345
|
+
@application_data[:_bitcasa_original_path] = ::File.dirname(@url)
|
346
|
+
set_url(nil)
|
347
|
+
@in_trash = true
|
348
|
+
end
|
349
|
+
changed_properties_reset
|
350
|
+
true
|
351
|
+
rescue RestAdapter::Errors::SessionNotLinked, RestAdapter::Errors::ServiceError,
|
352
|
+
RestAdapter::Errors::OperationNotAllowedError, RestAdapter::Errors::InvalidItemError
|
353
|
+
raise $! if raise_exception
|
354
|
+
false
|
355
|
+
end
|
356
|
+
|
357
|
+
# Get this item's properties from server
|
358
|
+
# @return [Hash] metadata of this item
|
359
|
+
# @raise [RestAdapter::Errors::SessionNotLinked, RestAdapter::Errors::ServiceError]
|
360
|
+
def get_properties_from_server
|
361
|
+
if @in_trash
|
362
|
+
properties = @rest_adapter.browse_trash(path: @url).fetch(:meta)
|
363
|
+
elsif @type == 'folder'
|
364
|
+
properties = @rest_adapter.get_folder_meta(@url)
|
365
|
+
else
|
366
|
+
properties = @rest_adapter.get_file_meta(@url)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# Refresh this item's properties from server
|
371
|
+
#
|
372
|
+
# @note Locally changed properties get discarded
|
373
|
+
#
|
374
|
+
# @return [Item] returns self
|
375
|
+
#
|
376
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
377
|
+
# RestAdapter::Errors::ServiceError,
|
378
|
+
# RestAdapter::Errors::InvalidItemError,
|
379
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
380
|
+
def refresh
|
381
|
+
FileSystemCommon.validate_item_state(self, in_trash: false, in_share: false)
|
382
|
+
|
383
|
+
properties = get_properties_from_server
|
384
|
+
parent_url = ::File.dirname(@url)
|
385
|
+
|
386
|
+
set_item_properties(
|
387
|
+
parent: parent_url,
|
388
|
+
in_trash: @in_trash,
|
389
|
+
in_share: @in_share,
|
390
|
+
** properties)
|
391
|
+
self
|
392
|
+
end
|
393
|
+
|
394
|
+
# Sets restored item's url and properties based on exists and destination url
|
395
|
+
# This method is called to update this item after it has been restored.
|
396
|
+
# If exist == 'Fail' then this item's expected url is its original path
|
397
|
+
# elseif exists == 'RESCUE' the url should be destination_url/(item's trashid)
|
398
|
+
# elseif exists == 'RECREATE' then url should be
|
399
|
+
# (url of named path)/(item' trashid)
|
400
|
+
#
|
401
|
+
# @param destination_url [String] ('RESCUE' (default root), RECREATE(named path))
|
402
|
+
# path depending on exists option to place item into
|
403
|
+
# if the original path does not exist.
|
404
|
+
# @param exists [String] ('FAIL', 'RESCUE', 'RECREATE')
|
405
|
+
# action to take if the recovery operation encounters issues, default 'FAIL'
|
406
|
+
#
|
407
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
408
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError]
|
409
|
+
def set_restored_item_properties(destination_url, exists)
|
410
|
+
begin
|
411
|
+
parent_url = @application_data[:_bitcasa_original_path]
|
412
|
+
properties = FileSystemCommon.get_item_properties_from_server(
|
413
|
+
@rest_adapter,
|
414
|
+
parent_url,
|
415
|
+
@id,
|
416
|
+
@type)
|
417
|
+
rescue
|
418
|
+
raise $! if exists == 'FAIL'
|
419
|
+
|
420
|
+
if exists == 'RESCUE'
|
421
|
+
parent_url = destination_url
|
422
|
+
properties = FileSystemCommon.get_item_properties_from_server(
|
423
|
+
@rest_adapter,
|
424
|
+
parent_url,
|
425
|
+
@id,
|
426
|
+
@type)
|
427
|
+
|
428
|
+
elsif exists == 'RECREATE'
|
429
|
+
response = FileSystemCommon.get_properties_of_named_path(
|
430
|
+
@rest_adapter,
|
431
|
+
destination_url)
|
432
|
+
|
433
|
+
parent_url = response[:url]
|
434
|
+
properties = FileSystemCommon.get_item_properties_from_server(
|
435
|
+
@rest_adapter,
|
436
|
+
parent_url,
|
437
|
+
@id,
|
438
|
+
@type)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
set_item_properties(parent: parent_url, in_trash: false, ** properties)
|
442
|
+
end
|
443
|
+
|
444
|
+
# Restore this item from trash
|
445
|
+
# @note This item's properties are updated if successful
|
446
|
+
#
|
447
|
+
# @param destination [Folder, String] ('RESCUE' (default root),
|
448
|
+
# RECREATE(named path)) destination folder path depending on exists
|
449
|
+
# option to place item into if the original path does not exist.
|
450
|
+
# @param method [String] ('FAIL', 'RESCUE', 'RECREATE')
|
451
|
+
# action to take if the recovery operation encounters issues, default 'FAIL'
|
452
|
+
# @param raise_exception [Boolean] (false)
|
453
|
+
# method suppresses exceptions and returns false if set to false,
|
454
|
+
# added so that consuming application can control behaviour
|
455
|
+
# @param restore_argument [String] update this item after it has been restored
|
456
|
+
#
|
457
|
+
# @return [Boolean] true/false
|
458
|
+
#
|
459
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
460
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError,
|
461
|
+
# RestAdapter::Errors::InvalidItemError,
|
462
|
+
# RestAdapter::Errors::OperationNotAllowedError] if raise_exception is true
|
463
|
+
#
|
464
|
+
# @note exist: 'RECREATE' with named path is expensive operation
|
465
|
+
# as items in named path hierarchy are traversed
|
466
|
+
# in order to fetch Restored item's properties.
|
467
|
+
#
|
468
|
+
# @example
|
469
|
+
# item.restore
|
470
|
+
# item.restore("/FOPqySw3ToK_25y-gagUfg", exists: 'RESCUE')
|
471
|
+
# item.restore(folderobj, exists: 'RESCUE')
|
472
|
+
# item.restore("/depth1/depth2", exists: 'RECREATE')
|
473
|
+
def restore(destination, method: 'FAIL', restore_argument: nil, raise_exception: false) # restore argument.
|
474
|
+
fail RestAdapter::Errors::OperationNotAllowedError,
|
475
|
+
'Item needs to be in trash for Restore operation' unless @in_trash
|
476
|
+
FileSystemCommon.validate_item_state(destination)
|
477
|
+
|
478
|
+
destination_url = FileSystemCommon.get_folder_url(destination)
|
479
|
+
@rest_adapter.recover_trash_item(
|
480
|
+
@url,
|
481
|
+
destination: destination_url,
|
482
|
+
restore: method)
|
483
|
+
|
484
|
+
if restore_argument
|
485
|
+
set_restored_item_properties(destination_url, method)
|
486
|
+
end
|
487
|
+
|
488
|
+
true
|
489
|
+
rescue RestAdapter::Errors::SessionNotLinked, RestAdapter::Errors::ServiceError,
|
490
|
+
RestAdapter::Errors::ArgumentError, RestAdapter::Errors::InvalidItemError,
|
491
|
+
RestAdapter::Errors::OperationNotAllowedError
|
492
|
+
raise $! if raise_exception
|
493
|
+
false
|
494
|
+
end
|
495
|
+
|
496
|
+
# List versions of this item if file.
|
497
|
+
# @note The list of files returned are mostly non-functional,
|
498
|
+
# though their meta-data is correct.
|
499
|
+
#
|
500
|
+
# @param start_version [Fixnum] version number to begin listing file versions
|
501
|
+
# @param stop_version [Fixnum] version number from which to stop
|
502
|
+
# listing file versions
|
503
|
+
# @param limit [Fixnum] how many versions to list in the result set.
|
504
|
+
# It can be negative to list items prior to given start version
|
505
|
+
#
|
506
|
+
# @return [Array<Item>] listed versions
|
507
|
+
#
|
508
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
509
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::InvalidItemError,
|
510
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
511
|
+
#
|
512
|
+
# @review confirm if versions should be allowed for items in trash, in share
|
513
|
+
def versions(start_version: 0, stop_version: nil, limit: 10)
|
514
|
+
FileSystemCommon.validate_item_state(self, in_trash: false, in_share: false)
|
515
|
+
fail OperationNotAllowedError,
|
516
|
+
"Operation not allowed for item of type #{@type}" unless @type == 'file'
|
517
|
+
|
518
|
+
response = @rest_adapter.list_file_versions(
|
519
|
+
@url,
|
520
|
+
start_version: start_version,
|
521
|
+
stop_version: stop_version,
|
522
|
+
limit: limit)
|
523
|
+
|
524
|
+
FileSystemCommon.create_items_from_hash_array(
|
525
|
+
response, @rest_adapter,
|
526
|
+
parent: @url,
|
527
|
+
in_share: @in_share,
|
528
|
+
in_trash: @in_trash,
|
529
|
+
old_version: true)
|
530
|
+
end
|
531
|
+
|
532
|
+
# Save this item's current state.
|
533
|
+
# Locally changed properties are committed to this item in user's account
|
534
|
+
#
|
535
|
+
# @param version_conflict [String] ('FAIL', 'IGNORE') action to take
|
536
|
+
# if the version on this item does not match the version on the server
|
537
|
+
#
|
538
|
+
# @return [Item] returns self
|
539
|
+
#
|
540
|
+
# @raise [RestAdapter::Errors::SessionNotLinked,
|
541
|
+
# RestAdapter::Errors::ServiceError, RestAdapter::Errors::ArgumentError,
|
542
|
+
# RestAdapter::Errors::InvalidItemError,
|
543
|
+
# RestAdapter::Errors::OperationNotAllowedError]
|
544
|
+
def save(version_conflict: 'FAIL')
|
545
|
+
FileSystemCommon.validate_item_state(self)
|
546
|
+
return self if RestAdapter::Utils.is_blank?(@changed_properties)
|
547
|
+
|
548
|
+
if @type == 'folder'
|
549
|
+
response = @rest_adapter.alter_folder_meta(
|
550
|
+
@url,
|
551
|
+
@version,
|
552
|
+
version_conflict: version_conflict,
|
553
|
+
** @changed_properties)
|
554
|
+
else
|
555
|
+
response = @rest_adapter.alter_file_meta(
|
556
|
+
@url,
|
557
|
+
@version,
|
558
|
+
version_conflict: version_conflict,
|
559
|
+
** @changed_properties)
|
560
|
+
end
|
561
|
+
|
562
|
+
parent_url = ::File.dirname(@url)
|
563
|
+
set_item_properties(parent: parent_url, ** response)
|
564
|
+
self
|
565
|
+
end
|
566
|
+
|
567
|
+
# Gets properties in hash format
|
568
|
+
# @return [Hash] metadata of item
|
569
|
+
def get_properties_in_hash
|
570
|
+
properties = {
|
571
|
+
:'name' => "#{@name}",
|
572
|
+
:'date_created' => "#{@date_created}",
|
573
|
+
:'date_meta_last_modified' => "#{@date_meta_last_modified}",
|
574
|
+
:'date_content_last_modified' => "#{@date_content_last_modified}",
|
575
|
+
:'extension' => "#{@extension}",
|
576
|
+
:'mime' => "#{@mime}",
|
577
|
+
:'application_data' => @application_data
|
578
|
+
}
|
579
|
+
properties
|
580
|
+
end
|
581
|
+
|
582
|
+
# Sets the url of item
|
583
|
+
#
|
584
|
+
# @param parent [Folder, String]
|
585
|
+
#
|
586
|
+
# @return [void]
|
587
|
+
def set_url(parent)
|
588
|
+
parent_url = FileSystemCommon.get_folder_url(parent)
|
589
|
+
@url = parent_url == '/' ? "/#{@id}" : "#{parent_url}/#{@id}"
|
590
|
+
end
|
591
|
+
|
592
|
+
# @return [String]
|
593
|
+
# @!visibility private
|
594
|
+
def to_s
|
595
|
+
"#{self.class}: url #{@url}, name: #{@name}"
|
596
|
+
end
|
597
|
+
|
598
|
+
alias inspect to_s
|
599
|
+
|
600
|
+
# @return [Boolean]
|
601
|
+
# @!visibility private
|
602
|
+
def eql?(item)
|
603
|
+
self.class.equal?(item.class) &&
|
604
|
+
item.respond_to?(:id) &&
|
605
|
+
item.id == @id
|
606
|
+
end
|
607
|
+
|
608
|
+
# Changes the attributes of a given file or folder.
|
609
|
+
#
|
610
|
+
# @param values [Hash] attribute changes.
|
611
|
+
# @param if_conflict [String] ('FAIL', 'IGNORE') action to take
|
612
|
+
# if the version on this item does not match the version on the server.
|
613
|
+
#
|
614
|
+
# @return [Boolean] based on the success or fail status of the action.
|
615
|
+
def change_attributes(values, if_conflict: 'FAIL')
|
616
|
+
if @type == 'folder'
|
617
|
+
response = @rest_adapter.alter_folder_meta(
|
618
|
+
@url,
|
619
|
+
@version,
|
620
|
+
version_conflict: if_conflict,
|
621
|
+
** values)
|
622
|
+
else
|
623
|
+
response = @rest_adapter.alter_file_meta(
|
624
|
+
@url,
|
625
|
+
@version,
|
626
|
+
version_conflict: if_conflict,
|
627
|
+
** values)
|
628
|
+
end
|
629
|
+
|
630
|
+
parent_url = ::File.dirname(@url)
|
631
|
+
set_item_properties(parent: parent_url, ** response)
|
632
|
+
response.has_key?(:id)
|
633
|
+
end
|
634
|
+
|
635
|
+
alias == eql?
|
636
|
+
private :set_item_properties, :changed_properties_reset,
|
637
|
+
:set_restored_item_properties, :get_properties_in_hash, :set_url,
|
638
|
+
:get_properties_from_server
|
639
|
+
end
|
640
|
+
end
|