ubiquity-mediasilo-api-v3 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/.gitignore +15 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +100 -0
- data/Rakefile +2 -0
- data/bin/ubiquity-mediasilo-api-v3 +26 -0
- data/lib/ubiquity/cli.rb +127 -0
- data/lib/ubiquity/mediasilo/api/v3.rb +11 -0
- data/lib/ubiquity/mediasilo/api/v3/cli.rb +94 -0
- data/lib/ubiquity/mediasilo/api/v3/client.rb +712 -0
- data/lib/ubiquity/mediasilo/api/v3/client/paginator.rb +133 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests.rb +18 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_copy_to_folder.rb +19 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_copy_to_project.rb +19 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_create.rb +25 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_delete.rb +15 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_get_by_id.rb +14 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_move_to_folder.rb +16 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/asset_move_to_project.rb +16 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/assets_get.rb +56 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/assets_get_by_folder_id.rb +14 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/assets_get_by_project_id.rb +14 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/base_request.rb +250 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/batch.rb +20 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/project_create.rb +15 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/quicklink_create.rb +54 -0
- data/lib/ubiquity/mediasilo/api/v3/client/requests/quicklink_share.rb +32 -0
- data/lib/ubiquity/mediasilo/api/v3/http_client.rb +259 -0
- data/lib/ubiquity/mediasilo/api/v3/utilities.rb +1145 -0
- data/lib/ubiquity/mediasilo/api/v3/version.rb +9 -0
- data/ubiquity-mediasilo-api-v3.gemspec +23 -0
- metadata +104 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ubiquity::MediaSilo::API::V3::Client::Requests
|
2
|
+
|
3
|
+
# @see http://docs.mediasilo.com/v3.0/docs/batch-overview
|
4
|
+
class Batch < BaseRequest
|
5
|
+
|
6
|
+
HTTP_METHOD = :post
|
7
|
+
HTTP_PATH = 'batch'
|
8
|
+
HTTP_SUCCESS_CODE = 200
|
9
|
+
|
10
|
+
PARAMETERS = [
|
11
|
+
{ :name => :requests, :send_in => :body, :send_key => false }
|
12
|
+
]
|
13
|
+
|
14
|
+
def body
|
15
|
+
@body ||= arguments[:requests]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Ubiquity::MediaSilo::API::V3::Client::Requests
|
2
|
+
|
3
|
+
class QuicklinkCreate < BaseRequest
|
4
|
+
|
5
|
+
HTTP_METHOD = :post
|
6
|
+
HTTP_PATH = '/quicklinks'
|
7
|
+
DEFAULT_PARAMETER_SEND_IN_VALUE = :body
|
8
|
+
|
9
|
+
PARAMETERS = [
|
10
|
+
{ :name => :title, :required => true },
|
11
|
+
:description,
|
12
|
+
:assetIds,
|
13
|
+
:configuration,
|
14
|
+
:expires,
|
15
|
+
:authorizedUserIds,
|
16
|
+
|
17
|
+
# :settings,
|
18
|
+
# :configuration_id,
|
19
|
+
# :audience,
|
20
|
+
# :playback,
|
21
|
+
# :allow_download,
|
22
|
+
# :allow_feedback,
|
23
|
+
# :show_metadata,
|
24
|
+
# :notify_email,
|
25
|
+
# :include_directlink,
|
26
|
+
# :password
|
27
|
+
]
|
28
|
+
|
29
|
+
# def post_process_arguments
|
30
|
+
# settings = arguments.delete(:settings)
|
31
|
+
# audience = arguments.delete(:audience)
|
32
|
+
# playback = arguments.delete(:playback)
|
33
|
+
# allow_download = arguments.delete(:allow_download)
|
34
|
+
# allow_feedback = arguments.delete(:allow_feedback)
|
35
|
+
# show_metadata = arguments.delete(:show_metadata)
|
36
|
+
# notify_email = arguments.delete(:notify_email)
|
37
|
+
# include_directlink = arguments.delete(:include_directlink)
|
38
|
+
# password = arguments.delete(:password)
|
39
|
+
#
|
40
|
+
# configuration = arguments[:configuration] || { }
|
41
|
+
# configuration_id = arguments[:configuration_id]
|
42
|
+
#
|
43
|
+
# # TODO Symbolize Configuration Keys
|
44
|
+
# configuration[:id] ||= configuration_id || ''
|
45
|
+
#
|
46
|
+
# settings ||= configuration[:settings] || { }
|
47
|
+
#
|
48
|
+
# settings[:audience] = audience
|
49
|
+
#
|
50
|
+
# end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Ubiquity::MediaSilo::API::V3::Client::Requests
|
2
|
+
|
3
|
+
class QuicklinkShare < BaseRequest
|
4
|
+
|
5
|
+
HTTP_METHOD = :post
|
6
|
+
HTTP_PATH = '/shares'
|
7
|
+
DEFAULT_PARAMETER_SEND_IN_VALUE = :body
|
8
|
+
|
9
|
+
PARAMETERS = [
|
10
|
+
{ :name => :targetObjectId, :required => true },
|
11
|
+
:emailShare,
|
12
|
+
:subject,
|
13
|
+
:message,
|
14
|
+
:audience
|
15
|
+
]
|
16
|
+
|
17
|
+
def post_process_arguments
|
18
|
+
_email_share = arguments[:emailShare]
|
19
|
+
_email_share ||= { }
|
20
|
+
_audience = arguments[:audience] || _email_share[:audience] || _email_share['audience'] || [ ]
|
21
|
+
_subject = arguments[:subject] || _email_share[:subject] || _email_share['subject']
|
22
|
+
_message = arguments[:message] || _email_share[:message] || _email_share['message']
|
23
|
+
_email_share[:audience] ||= _audience
|
24
|
+
_email_share[:subject] ||= _subject if _subject
|
25
|
+
_email_share[:message] ||= _message if _message
|
26
|
+
|
27
|
+
arguments[:emailShare] = _email_share
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,259 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'json'
|
3
|
+
require 'logger'
|
4
|
+
require 'net/http'
|
5
|
+
require 'net/https'
|
6
|
+
|
7
|
+
require 'ubiquity/mediasilo/api/v3'
|
8
|
+
|
9
|
+
module Ubiquity
|
10
|
+
module MediaSilo
|
11
|
+
class API
|
12
|
+
module V3
|
13
|
+
|
14
|
+
class HTTPClient
|
15
|
+
|
16
|
+
class RateLimitException < StandardError; end
|
17
|
+
|
18
|
+
# Ruby uses all lower case headers but Jetty uses case sensitive headers
|
19
|
+
class CaseSensitiveHeaderKey < String
|
20
|
+
def downcase; self end
|
21
|
+
def capitalize; self end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
attr_accessor :logger, :http, :http_host_address, :http_host_port, :base_uri
|
26
|
+
attr_accessor :hostname, :username, :password
|
27
|
+
|
28
|
+
attr_accessor :default_request_headers
|
29
|
+
|
30
|
+
attr_accessor :log_request_body, :log_response_body, :log_pretty_print_body
|
31
|
+
|
32
|
+
attr_accessor :request, :response
|
33
|
+
|
34
|
+
# DEFAULT_HTTP_HOST_ADDRESS = 'api.mediasilo.com'
|
35
|
+
DEFAULT_HTTP_HOST_ADDRESS = 'p-api-new.mediasilo.com'
|
36
|
+
DEFAULT_HTTP_HOST_PORT = 443
|
37
|
+
|
38
|
+
def initialize(args = { })
|
39
|
+
args = args.dup
|
40
|
+
initialize_logger(args)
|
41
|
+
initialize_http(args)
|
42
|
+
|
43
|
+
@hostname = args[:hostname] || ''
|
44
|
+
@username = args[:username] || ''
|
45
|
+
@password = args[:password] || ''
|
46
|
+
@api_key = args[:api_key]
|
47
|
+
@base_uri = args[:base_uri] || "http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}/v3/"
|
48
|
+
|
49
|
+
@user_agent_default = "#{@hostname}:#{@username} Ubiquity Ruby SDK Version #{Ubiquity::MediaSilo::API::V3::VERSION}"
|
50
|
+
|
51
|
+
authorization_header_name = CaseSensitiveHeaderKey.new('Authorization')
|
52
|
+
authorization_header_value = 'Basic ' + ["#{username}:#{password}"].pack('m').delete("\r\n")
|
53
|
+
|
54
|
+
host_context_header_name = CaseSensitiveHeaderKey.new('MediaSiloHostContext')
|
55
|
+
host_context_header_value = hostname.downcase
|
56
|
+
|
57
|
+
@default_request_headers = {
|
58
|
+
'user-agent' => @user_agent_default,
|
59
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
60
|
+
'Accept' => 'application/json',
|
61
|
+
host_context_header_name => host_context_header_value,
|
62
|
+
authorization_header_name => authorization_header_value,
|
63
|
+
}
|
64
|
+
|
65
|
+
if @api_key
|
66
|
+
api_key_header_name = CaseSensitiveHeaderKey.new('MediaSiloApiKey')
|
67
|
+
default_request_headers[api_key_header_name] = @api_key
|
68
|
+
end
|
69
|
+
|
70
|
+
@log_request_body = args.fetch(:log_request_body, true)
|
71
|
+
@log_response_body = args.fetch(:log_response_body, true)
|
72
|
+
@log_pretty_print_body = args.fetch(:log_pretty_print_body, true)
|
73
|
+
|
74
|
+
@delay_between_rate_limit_retries = 300
|
75
|
+
@cancelled = false
|
76
|
+
@parse_response = args.fetch(:parse_response, true)
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize_logger(args = { })
|
80
|
+
@logger = args[:logger] ||= Logger.new(args[:log_to] || STDOUT)
|
81
|
+
log_level = args[:log_level]
|
82
|
+
if log_level
|
83
|
+
@logger.level = log_level
|
84
|
+
args[:logger] = @logger
|
85
|
+
end
|
86
|
+
@logger
|
87
|
+
end
|
88
|
+
|
89
|
+
def initialize_http(args = { })
|
90
|
+
@http_host_address = args[:http_host_address] ||= DEFAULT_HTTP_HOST_ADDRESS
|
91
|
+
@http_host_port = args[:http_host_port] ||= DEFAULT_HTTP_HOST_PORT
|
92
|
+
@http = Net::HTTP.new(http_host_address, http_host_port)
|
93
|
+
http.use_ssl = true
|
94
|
+
|
95
|
+
# TODO Add SSL Patch
|
96
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
97
|
+
|
98
|
+
http
|
99
|
+
end
|
100
|
+
|
101
|
+
# Formats a HTTPRequest or HTTPResponse body for log output.
|
102
|
+
# @param [HTTPRequest|HTTPResponse] obj
|
103
|
+
# @return [String]
|
104
|
+
def format_body_for_log_output(obj)
|
105
|
+
if obj.content_type == 'application/json'
|
106
|
+
if @log_pretty_print_body
|
107
|
+
_body = obj.body
|
108
|
+
output = "\n" << JSON.pretty_generate(JSON.parse(_body)) rescue _body
|
109
|
+
return output
|
110
|
+
else
|
111
|
+
return obj.body
|
112
|
+
end
|
113
|
+
else
|
114
|
+
return obj.body.inspect
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param [Net::HTTPRequest] request
|
119
|
+
def send_request(request)
|
120
|
+
@response_parsed = nil
|
121
|
+
@request = request
|
122
|
+
|
123
|
+
begin
|
124
|
+
logger.debug { %(REQUEST: #{request.method} http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}#{request.path} HEADERS: #{request.to_hash.inspect} #{log_request_body and request.request_body_permitted? ? "BODY: #{format_body_for_log_output(request)}" : ''}) }
|
125
|
+
|
126
|
+
@response = http.request(request)
|
127
|
+
logger.debug { %(RESPONSE: #{response.inspect} HEADERS: #{response.to_hash.inspect} #{log_response_body and response.respond_to?(:body) ? "BODY: #{format_body_for_log_output(response)}" : ''}) }
|
128
|
+
raise RateLimitException, "#{response.to_hash.inspect}" if response.code == '420'
|
129
|
+
rescue RateLimitException => e
|
130
|
+
logger.warn { "Rate Limited. Will retry in #{@delay_between_rate_limit_retries} seconds." }
|
131
|
+
sleep_break @delay_between_rate_limit_retries
|
132
|
+
retry unless @cancelled
|
133
|
+
end
|
134
|
+
|
135
|
+
@parse_response ? response_parsed : response.body
|
136
|
+
end
|
137
|
+
|
138
|
+
def sleep_break(seconds)
|
139
|
+
while (seconds > 0)
|
140
|
+
sleep(1)
|
141
|
+
seconds -= 1
|
142
|
+
break if @cancelled
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def response_parsed
|
147
|
+
@response_parsed ||= begin
|
148
|
+
response_content_type = response.content_type
|
149
|
+
logger.debug { "Parsing Response: #{response_content_type}" }
|
150
|
+
|
151
|
+
case response_content_type
|
152
|
+
when 'application/json'
|
153
|
+
JSON.parse(response.body) rescue response
|
154
|
+
# when 'text/html'
|
155
|
+
# when 'text/plain'
|
156
|
+
else
|
157
|
+
response.body
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def build_uri(path = '', query = nil)
|
163
|
+
_query = query.is_a?(Hash) ? query.map { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v)}" }.join('&') : query
|
164
|
+
_path = "#{path}#{_query and _query.respond_to?(:empty?) and !_query.empty? ? "?#{_query}" : ''}"
|
165
|
+
URI.parse(File.join(base_uri, _path))
|
166
|
+
end
|
167
|
+
|
168
|
+
if RUBY_VERSION.start_with? '1.8.'
|
169
|
+
def request_method_name_to_class_name(method_name)
|
170
|
+
method_name.to_s.capitalize
|
171
|
+
end
|
172
|
+
else
|
173
|
+
def request_method_name_to_class_name(method_name)
|
174
|
+
method_name.to_s.capitalize.to_sym
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# @param [Symbol] method_name (:get)
|
179
|
+
# @param [Hash] args
|
180
|
+
# @option args [Hash] :headers ({})
|
181
|
+
# @option args [String] :path ('')
|
182
|
+
# @option args [Hash] :query ({})
|
183
|
+
# @option args [Any] :body (nil)
|
184
|
+
# @param [Hash] options
|
185
|
+
# @option options [Hash] :default_request_headers (@default_request_headers)
|
186
|
+
def call_method(method_name = :get, args = { }, options = { })
|
187
|
+
headers = args[:headers] || options[:headers] || { }
|
188
|
+
path = args[:path] || ''
|
189
|
+
query = args[:query] || { }
|
190
|
+
body = args[:body]
|
191
|
+
|
192
|
+
# Allow the default request headers to be overridden
|
193
|
+
_default_request_headers = options.fetch(:default_request_headers, default_request_headers)
|
194
|
+
_default_request_headers ||= { }
|
195
|
+
_headers = _default_request_headers.merge(headers)
|
196
|
+
|
197
|
+
@uri = build_uri(path, query)
|
198
|
+
klass_name = request_method_name_to_class_name(method_name)
|
199
|
+
klass = Net::HTTP.const_get(klass_name)
|
200
|
+
|
201
|
+
request = klass.new(@uri.request_uri, _headers)
|
202
|
+
|
203
|
+
if request.request_body_permitted?
|
204
|
+
_body = (body and !body.is_a?(String)) ? JSON.generate(body) : body
|
205
|
+
logger.debug { "Processing Body: '#{_body}'" }
|
206
|
+
request.body = _body if _body
|
207
|
+
end
|
208
|
+
|
209
|
+
send_request(request)
|
210
|
+
end
|
211
|
+
|
212
|
+
def delete(path, options = { })
|
213
|
+
query = options.fetch(:query, { })
|
214
|
+
@uri = build_uri(path, query)
|
215
|
+
|
216
|
+
|
217
|
+
request = Net::HTTP::Delete.new(@uri.request_uri, default_request_headers)
|
218
|
+
body = options[:body]
|
219
|
+
if body
|
220
|
+
body = JSON.generate(body) unless body.is_a?(String)
|
221
|
+
request.body = body
|
222
|
+
end
|
223
|
+
|
224
|
+
send_request(request)
|
225
|
+
end
|
226
|
+
|
227
|
+
def get(path, query = nil, options = { })
|
228
|
+
query ||= options.fetch(:query, { })
|
229
|
+
@uri = build_uri(path, query)
|
230
|
+
request = Net::HTTP::Get.new(@uri.request_uri, default_request_headers)
|
231
|
+
send_request(request)
|
232
|
+
end
|
233
|
+
|
234
|
+
def put(path, body, options = { })
|
235
|
+
query = options.fetch(:query, { })
|
236
|
+
@uri = build_uri(path, query)
|
237
|
+
body = JSON.generate(body) unless body.is_a?(String)
|
238
|
+
|
239
|
+
request = Net::HTTP::Put.new(@uri.request_uri, default_request_headers)
|
240
|
+
request.body = body
|
241
|
+
send_request(request)
|
242
|
+
end
|
243
|
+
|
244
|
+
def post(path, body, options = { })
|
245
|
+
query = options.fetch(:query, { })
|
246
|
+
@uri = build_uri(path, query)
|
247
|
+
body = JSON.generate(body) unless body.is_a?(String)
|
248
|
+
|
249
|
+
request = Net::HTTP::Post.new(@uri.request_uri, default_request_headers)
|
250
|
+
request.body = body
|
251
|
+
send_request(request)
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
@@ -0,0 +1,1145 @@
|
|
1
|
+
require 'ubiquity/mediasilo/api/v3/client'
|
2
|
+
require 'open-uri' # for download_file
|
3
|
+
|
4
|
+
class Exception
|
5
|
+
def prefix_message(message_prefix = nil)
|
6
|
+
begin
|
7
|
+
raise self, "#{message_prefix ? "#{message_prefix} " : ''}#{message}", backtrace
|
8
|
+
rescue Exception => e
|
9
|
+
return e
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Ubiquity::MediaSilo::API::V3::Utilities < Ubiquity::MediaSilo::API::V3::Client
|
15
|
+
|
16
|
+
# VALID_ASSET_SEARCH_FIELD_NAMES = %w(approvalStatus archiveStatus averageRating commentCount dateCreated dateModified derivatives description external fileName folderId id myRating permissions private progress projectId tags title transcriptStatus type uploadedBy)
|
17
|
+
# VALID_ASSET_SEARCH_FIELDS = {
|
18
|
+
# :approvalstatus => 'approvalStatus',
|
19
|
+
# :archivestatus => 'archiveStatus',
|
20
|
+
# :averagerating => 'averageRating',
|
21
|
+
# :commentcount => 'commentCount',
|
22
|
+
# :datecreated => 'dateCreated',
|
23
|
+
# :datemodified => 'dateModified',
|
24
|
+
# :derivatives => 'derivatives',
|
25
|
+
# :description => 'description',
|
26
|
+
# :external => 'external',
|
27
|
+
# :filename => 'fileName',
|
28
|
+
# :folderid => 'folderId',
|
29
|
+
# :id => 'id',
|
30
|
+
# :metadatamatch => 'metadatamatch',
|
31
|
+
# :myrating => 'myRating', :permissions => 'permissions', :private => 'private', :progress => 'progress', :projectid => 'projectId', :tags => 'tags', :title => 'title', :transcriptstatus => 'transcriptStatus', :type => 'type', :uploadedby => 'uploadedBy' }
|
32
|
+
|
33
|
+
|
34
|
+
def default_case_sensitive_search
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates an asset building any missing parts of the path (Project/Folder/Asset)
|
39
|
+
#
|
40
|
+
# Required Parameters
|
41
|
+
# :url
|
42
|
+
# :mediasilo_path or :file_path
|
43
|
+
#
|
44
|
+
# Optional Parameters
|
45
|
+
# :metadata
|
46
|
+
# :overwrite_existing_asset
|
47
|
+
# :asset_search_field_name
|
48
|
+
def asset_create_using_path(args = { })
|
49
|
+
|
50
|
+
file_url = args[:url] || args[:file_url] || args[:source_url]
|
51
|
+
raise ArgumentError ':url is a required parameter.' unless file_url
|
52
|
+
|
53
|
+
file_path = args[:mediasilo_path] || args[:file_path]
|
54
|
+
raise ArgumentError ':mediasilo_path is a required parameter.' unless file_path
|
55
|
+
|
56
|
+
ms_metadata = args[:metadata]
|
57
|
+
|
58
|
+
asset_title = args[:title]
|
59
|
+
asset_description = args[:description]
|
60
|
+
additional_asset_create_params = { }
|
61
|
+
additional_asset_create_params['title'] = asset_title if asset_title
|
62
|
+
additional_asset_create_params['description'] = asset_description if asset_description
|
63
|
+
|
64
|
+
overwrite_existing_asset = args.fetch(:overwrite_existing_asset, false)
|
65
|
+
asset_search_field_name = args[:asset_search_field_name] || :filename
|
66
|
+
|
67
|
+
#logger.info { "Creating Asset on MediaSilo Using File Path: '#{file_path}'. File URL: #{file_url}" }
|
68
|
+
|
69
|
+
#ms_uuid = ms.asset_create(file_url, { }, ms_project)
|
70
|
+
path_create_options = {
|
71
|
+
:overwrite_existing_asset => overwrite_existing_asset,
|
72
|
+
:additional_asset_create_params => additional_asset_create_params,
|
73
|
+
:asset_search_field_name => asset_search_field_name
|
74
|
+
}
|
75
|
+
begin
|
76
|
+
result = path_create(file_path, true, file_url, ms_metadata, path_create_options)
|
77
|
+
# rescue => e
|
78
|
+
# raise e, "Exception Creating Asset Using File Path. #{e.message}", e.backtrace
|
79
|
+
end
|
80
|
+
|
81
|
+
output_values = { }
|
82
|
+
output_values[:result] = result
|
83
|
+
|
84
|
+
return false unless result and result.has_key?(:asset)
|
85
|
+
#return publish_error('Error creating asset.') unless result and result.has_key?(:asset)
|
86
|
+
|
87
|
+
result_asset = result[:asset]
|
88
|
+
if result_asset == false
|
89
|
+
ms_asset_id = false
|
90
|
+
elsif result[:asset_missing] == false
|
91
|
+
ms_asset_id = result[:existing][:asset]['id'] # if not result[:existing][:asset]['uuid'].nil?
|
92
|
+
elsif result_asset.is_a?(Array)
|
93
|
+
|
94
|
+
#Metadata creation failed but asset was created Array(false, "uuid")
|
95
|
+
#TODO: HANDLE CASE WHERE METADATA IS NOT CREATED BUT THE ASSET IS
|
96
|
+
ms_asset_id = result_asset[1]
|
97
|
+
|
98
|
+
else
|
99
|
+
ms_asset_id = result_asset['id']
|
100
|
+
ms_asset_id ||= result_asset
|
101
|
+
end
|
102
|
+
#Setting metadata during asset_create doesn't work so we set it here
|
103
|
+
#response = ms.metadata_create(ms_uuid, ms_metadata) unless ms_metadata.nil?
|
104
|
+
|
105
|
+
if ms_asset_id
|
106
|
+
output_values[:asset_id] = ms_asset_id
|
107
|
+
return output_values
|
108
|
+
else
|
109
|
+
#return publish_error("Error creating asset.\nResponse: #{response}\nMS UUID: #{ms_uuid}\nMS Creating Missing Path Result: #{result}")
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
alias :asset_create_using_file_path :asset_create_using_path
|
114
|
+
|
115
|
+
def asset_derivatives_transform_to_hash(derivatives)
|
116
|
+
return { } unless derivatives.is_a?(Array)
|
117
|
+
_derivatives = derivatives.map do |d|
|
118
|
+
strategies = d['strategies']
|
119
|
+
|
120
|
+
d['strategies'] = Hash[strategies.map { |s| [ s['type'], s ] }] if strategies
|
121
|
+
|
122
|
+
[ d['type'], d ]
|
123
|
+
end
|
124
|
+
Hash[_derivatives]
|
125
|
+
end
|
126
|
+
|
127
|
+
# Downloads a file from a URI or file location and saves it to a local path
|
128
|
+
#
|
129
|
+
# @param [String] download_file_path The source path of the file being downloaded
|
130
|
+
# @param [String] destination_file_path The destination path for the file being downloaded
|
131
|
+
# @param [Boolean] overwrite Determines if the destination file will be overwritten if it is found to exist
|
132
|
+
#
|
133
|
+
# @return [Hash]
|
134
|
+
# * :download_file_path [String] The source path of the file being downloaded
|
135
|
+
# * :overwrite [Boolean] The value of the overwrite parameter when the method was called
|
136
|
+
# * :file_downloaded [Boolean] Indicates if the file was downloaded, will be false if overwrite was true and the file existed
|
137
|
+
# * :destination_file_existed [String|Boolean] The value will be 'unknown' if overwrite is true because the file exist check will not have been run inside of the method
|
138
|
+
# * :destination_file_path [String] The destination path for the file being downloaded
|
139
|
+
def download_file(download_file_path, destination_file_path, overwrite = false)
|
140
|
+
logger.debug { "Downloading '#{download_file_path}' -> '#{destination_file_path}' Overwrite: #{overwrite}" }
|
141
|
+
file_existed = 'unknown'
|
142
|
+
if overwrite or not(file_existed = File.exists?(destination_file_path))
|
143
|
+
File.open(destination_file_path, 'wb') { |tf|
|
144
|
+
open(download_file_path) { |sf| tf.write sf.read }
|
145
|
+
}
|
146
|
+
file_downloaded = true
|
147
|
+
else
|
148
|
+
file_downloaded = false
|
149
|
+
end
|
150
|
+
return { :download_file_path => download_file_path, :overwrite => overwrite, :file_downloaded => file_downloaded, :destination_file_existed => file_existed, :destination_file_path => destination_file_path }
|
151
|
+
end
|
152
|
+
|
153
|
+
# @option [String] derivative_name Known options are proxy, proxy2m, source, and waveform
|
154
|
+
def asset_download_derivative(derivative_name, asset, destination_file_path, overwrite = false, field_name = 'url')
|
155
|
+
return asset.map { |a| asset_download_derivative(derivative_name, a, destination_file_path, overwrite) } if asset.is_a?(Array)
|
156
|
+
asset = asset_get_by_id_extended( { :asset_id => asset }, :include_derivatives_hash => true ) if asset.is_a? String
|
157
|
+
_derivatives = asset['derivatives_hash'] || begin
|
158
|
+
asset_derivatives_transform_to_hash(asset['derivatives'])
|
159
|
+
end
|
160
|
+
|
161
|
+
file_to_download = _derivatives[derivative_name][field_name]
|
162
|
+
asset_download_resource(file_to_download, destination_file_path, overwrite)
|
163
|
+
end
|
164
|
+
|
165
|
+
def asset_download_poster_frame_file(asset, destination_file_path, overwrite = false)
|
166
|
+
return asset.map { |a| asset_download_poster_frame_file(a, destination_file_path, overwrite) } if asset.is_a?(Array)
|
167
|
+
asset = asset_get_by_id(:asset_id => asset ) if asset.is_a? String
|
168
|
+
|
169
|
+
file_to_download = asset['posterFrame']
|
170
|
+
asset_download_resource(file_to_download, destination_file_path, overwrite)
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param [String|Hash] asset
|
174
|
+
# @param [String] destination_file_path
|
175
|
+
# @param [Boolean] overwrite
|
176
|
+
# @return [Hash] see (MediaSilo#download_file)
|
177
|
+
def asset_download_proxy_file(asset, destination_file_path, overwrite = false)
|
178
|
+
asset_download_derivative('proxy', asset, destination_file_path, overwrite)
|
179
|
+
end
|
180
|
+
|
181
|
+
# @param [String] download_file_path
|
182
|
+
# @param [String] destination_file_path
|
183
|
+
# @param [Boolean] overwrite
|
184
|
+
def asset_download_resource(download_file_path, destination_file_path, overwrite = false)
|
185
|
+
# download_file_path = URI.encode(download_file_path)
|
186
|
+
|
187
|
+
destination_file_path = File.join(destination_file_path, File.basename(URI.decode(download_file_path))) if File.directory? destination_file_path
|
188
|
+
download_file(download_file_path, destination_file_path, overwrite)
|
189
|
+
end
|
190
|
+
|
191
|
+
# @param [String|Hash] asset
|
192
|
+
# @param [String] destination_file_path
|
193
|
+
# @param [Boolean] overwrite
|
194
|
+
# @return [Hash] see (MediaSilo#download_file)
|
195
|
+
def asset_download_source_file(asset, destination_file_path, overwrite = false)
|
196
|
+
asset_download_derivative('source', asset, destination_file_path, overwrite)
|
197
|
+
end
|
198
|
+
|
199
|
+
def asset_download_proxy_poster_frame_file(asset, destination_file_path, overwrite = false)
|
200
|
+
asset_download_derivative('proxy', asset, destination_file_path, overwrite, 'posterFrame')
|
201
|
+
end
|
202
|
+
|
203
|
+
def asset_download_proxy_thumbnail_file(asset, destination_file_path, overwrite = false)
|
204
|
+
asset_download_derivative('proxy', asset, destination_file_path, overwrite, 'thumbnail')
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
# @param [String] asset_uuid
|
209
|
+
# @param [Hash] args A hash of arguments
|
210
|
+
# @option args [String] :asset_id The uuid of the asset to edit
|
211
|
+
# @option args [Hash] :metadata The asset's metadata.
|
212
|
+
# @option args [Boolean] :mirror_metadata If set to true then the metadata will mirror :metadata which means that any keys existing on MediaSilo that don't exists in :metadata will be deleted from MediaSilo.
|
213
|
+
# @option args [Array] :tags_to_add_to_asset An array of tag names to add to the asset
|
214
|
+
# @option args [Array] :tags_to_remove_from_asset An array of tag names to remove from the asset
|
215
|
+
# @option args [Boolean|Hash|Array] :add_quicklink_to_asset
|
216
|
+
# @option args (see MediaSilo#asset_edit)
|
217
|
+
def asset_edit_extended(asset_id, args = { }, options = { })
|
218
|
+
logger.debug { "Asset Edit Extended: #{asset_id} ARGS: #{args.inspect}" }
|
219
|
+
if asset_id.is_a?(Hash)
|
220
|
+
options = args.dup
|
221
|
+
args = asset_id.dup
|
222
|
+
asset_id = args[:asset_id]
|
223
|
+
raise ArgumentError, 'Error Editing Asset. Missing required argument :asset_id' unless asset_id
|
224
|
+
else
|
225
|
+
args = args.dup
|
226
|
+
args[:asset_id] = asset_id
|
227
|
+
end
|
228
|
+
|
229
|
+
ms_metadata = args.delete(:metadata) { false }
|
230
|
+
mirror_metadata = args.delete(:mirror_metadata) { false }
|
231
|
+
#
|
232
|
+
add_tag_to_asset = args.delete(:tags_to_add) { [ ] }
|
233
|
+
add_tag_to_asset = args.delete(:tags_to_add_to_asset) { add_tag_to_asset }
|
234
|
+
|
235
|
+
remove_tag_from_asset = args.delete(:tags_to_remove) { [ ] }
|
236
|
+
remove_tag_from_asset = args.delete(:tags_to_remove_from_asset) { remove_tag_from_asset }
|
237
|
+
#
|
238
|
+
# add_quicklink_to_asset = args.delete(:add_quicklink_to_asset) { false }
|
239
|
+
|
240
|
+
_response = { :success => false }
|
241
|
+
if args[:title] or args[:description]
|
242
|
+
result = asset_edit(args)
|
243
|
+
_response[:asset_edit_result] = result
|
244
|
+
_response[:asset_edit_response] = response
|
245
|
+
_response[:asset_edit_success] = success?
|
246
|
+
unless success?
|
247
|
+
_response[:error_message] = "Error Editing Asset. #{error_message}"
|
248
|
+
return _response
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
if ms_metadata.is_a?(Hash)
|
253
|
+
if mirror_metadata
|
254
|
+
result = metadata_mirror(:asset_id => asset_id, :metadata => ms_metadata)
|
255
|
+
else
|
256
|
+
result = metadata_create_or_update(:asset_id => asset_id, :metadata => ms_metadata)
|
257
|
+
end
|
258
|
+
_response[:metadata_edit_result] = result
|
259
|
+
_response[:metadata_edit_response] = response
|
260
|
+
_response[:metadata_edit_success] = success?
|
261
|
+
unless success?
|
262
|
+
_response[:error_message] = "Error Editing Asset's Metadata. #{error_message}"
|
263
|
+
return _response
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
batch_execute do
|
268
|
+
unless remove_tag_from_asset.nil? or remove_tag_from_asset.empty?
|
269
|
+
[*remove_tag_from_asset].uniq.each { |tag_to_remove| asset_tag_remove(:asset_id => asset_id, :tag => tag_to_remove) if tag_to_remove.is_a?(String); }
|
270
|
+
end
|
271
|
+
unless add_tag_to_asset.nil? or add_tag_to_asset.empty?
|
272
|
+
[*add_tag_to_asset].uniq.each { |tag_to_add| asset_tag_add(:asset_id => asset_id, :tags => tag_to_add) if tag_to_add.is_a?(String) }
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
#
|
277
|
+
# if add_quicklink_to_asset
|
278
|
+
# add_quicklink_to_asset.is_a?(Hash) ? quicklink_create(asset_id, add_quicklink_to_asset) : quicklink_create(asset_id)
|
279
|
+
# _response[:quicklink_create_response] = response.body_parsed
|
280
|
+
# _response[:quicklink_create_success] = success?
|
281
|
+
# unless success?
|
282
|
+
# _response[:error_message] = "Error Adding Quicklink to Asset. #{error_message}"
|
283
|
+
# return _response
|
284
|
+
# end
|
285
|
+
# end
|
286
|
+
|
287
|
+
_response[:success] = true
|
288
|
+
_response
|
289
|
+
end
|
290
|
+
|
291
|
+
# @param [String] search_field_name
|
292
|
+
# @param [String] search_value
|
293
|
+
# @param [String|nil] project_id
|
294
|
+
# @param [String|nil] folder_id
|
295
|
+
# @param [Hash] options
|
296
|
+
# @option options [Boolean] :limit_to_project_root (true)
|
297
|
+
# @return [Array]
|
298
|
+
def asset_get_by_field_search(search_field_name, search_value, project_id = nil, folder_id = nil, options = { })
|
299
|
+
|
300
|
+
path = if folder_id and !folder_id == 0
|
301
|
+
limit_to_project_root = false
|
302
|
+
"/folders/#{folder_id}/assets"
|
303
|
+
elsif project_id
|
304
|
+
limit_to_project_root = options.fetch(:limit_to_project_root, true)
|
305
|
+
"/projects/#{project_id}/assets"
|
306
|
+
else
|
307
|
+
limit_to_project_root = false
|
308
|
+
'/assets'
|
309
|
+
end
|
310
|
+
|
311
|
+
# _search_field_name = VALID_ASSET_SEARCH_FIELDS[search_field_name.to_s.downcase.to_sym]
|
312
|
+
# raise ArgumentError, "The argument for the search_field_name parameter is invalid. '#{search_field_name}' not found in #{VALID_ASSET_SEARCH_FIELDS.values.inspect}" unless _search_field_name
|
313
|
+
|
314
|
+
_search_field_name = search_field_name.to_s
|
315
|
+
search_operator_default = search_value.is_a?(Array) ? 'in' : nil
|
316
|
+
search_operator = options[:operator] || search_operator_default
|
317
|
+
case search_operator
|
318
|
+
when nil
|
319
|
+
search_field_query = { _search_field_name => search_value }
|
320
|
+
else
|
321
|
+
search_field_query = { _search_field_name => %({"#{search_operator}":"#{[*search_value].join(',')}"}) }
|
322
|
+
end
|
323
|
+
|
324
|
+
# query = { :type => '{"in":"video,image,document,archive,audio"}' }.merge((options[:query] || { })).merge(search_field_query)
|
325
|
+
query = (options[:query] || { }).merge(search_field_query)
|
326
|
+
assets = http_client.get(path, query)
|
327
|
+
assets = [ ] if http_client.response.code == '404'
|
328
|
+
limit_to_project_root ? assets.delete_if { |v| v['folderId'] } : assets
|
329
|
+
end
|
330
|
+
|
331
|
+
def asset_get_by_id_extended(args = { }, options = { })
|
332
|
+
include_metadata = options.delete(:include_metadata)
|
333
|
+
include_derivatives_hash = options.delete(:include_derivatives_hash) { true }
|
334
|
+
transform_metadata = options.delete(:transform_metadata) { true }
|
335
|
+
|
336
|
+
asset_id = args[:asset_id]
|
337
|
+
|
338
|
+
asset = asset_get_by_id({ :asset_id => asset_id }, options)
|
339
|
+
|
340
|
+
if include_metadata
|
341
|
+
md = metadata_get( { :asset_id => asset['id'] }, options )
|
342
|
+
md = metadata_transform_to_hash(md) if transform_metadata
|
343
|
+
asset['metadata'] = md
|
344
|
+
end
|
345
|
+
|
346
|
+
if include_derivatives_hash
|
347
|
+
_derivatives = asset['derivatives']
|
348
|
+
asset['derivatives_hash'] = asset_derivatives_transform_to_hash(_derivatives)
|
349
|
+
end
|
350
|
+
|
351
|
+
asset
|
352
|
+
end
|
353
|
+
|
354
|
+
# @param [Hash] args
|
355
|
+
# @param [Hash] options
|
356
|
+
# @option options [Boolean] :include_metadata
|
357
|
+
# @option options [Boolean] :transform_metadata Will cause metadata to be transformed to a simple Hash
|
358
|
+
def assets_get_extended(args = { }, options = { })
|
359
|
+
include_metadata = options.delete(:include_metadata)
|
360
|
+
include_derivatives_hash = options.delete(:include_derivatives_hash) { true }
|
361
|
+
transform_metadata = options.delete(:transform_metadata) { true }
|
362
|
+
|
363
|
+
assets = assets_get(args, options)
|
364
|
+
|
365
|
+
assets.map! do |a|
|
366
|
+
|
367
|
+
if include_metadata
|
368
|
+
md = metadata_get(:asset_id => a['id'])
|
369
|
+
md = metadata_transform_to_hash(md) if transform_metadata
|
370
|
+
a['metadata'] = md
|
371
|
+
end
|
372
|
+
|
373
|
+
if include_derivatives_hash
|
374
|
+
_derivatives = a['derivatives'].map do |d|
|
375
|
+
strategies = d['strategies']
|
376
|
+
|
377
|
+
d['strategies'] = Hash[strategies.map { |s| [s['type'], s] }] if strategies
|
378
|
+
|
379
|
+
[ d['type'], d ]
|
380
|
+
end
|
381
|
+
|
382
|
+
a['derivatives_hash'] = Hash[_derivatives]
|
383
|
+
end
|
384
|
+
|
385
|
+
a
|
386
|
+
end if (include_metadata || include_derivatives_hash)
|
387
|
+
|
388
|
+
assets
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
|
393
|
+
# Refines asset_get_by_field_search results to exact (full string case sensitive) matches
|
394
|
+
#
|
395
|
+
# @param [String] search_value
|
396
|
+
# @param [String] field_name The field to search.
|
397
|
+
# ["approvalstatus", "archivestatus", "averagerating", "datecreated", "datemodified", "description",
|
398
|
+
# "duration", "external", "filename", "height", "progress", "rating", "secure", "size", "thumbnail_large",
|
399
|
+
# "thumbnail_small", "title", "totalcomments", "transcriptstatus", "type", "uploaduser", "uuid", "width"]
|
400
|
+
# @param [Array] assets The assets as returned by asset_adavanced_search_by_results
|
401
|
+
# @param [Hash] options
|
402
|
+
# @option options [Boolean] :return_first_match (false)
|
403
|
+
# @option options [Boolean] :match_full_string (true)
|
404
|
+
# @option options [Boolean] :case_sensitive (#default_case_sensitive_search)
|
405
|
+
def refine_asset_get_by_field_search_results(field_name, search_value, assets, options)
|
406
|
+
return unless assets
|
407
|
+
return_first_match = options.fetch(:return_first_match, false)
|
408
|
+
match_full_string = options.fetch(:match_full_string, true)
|
409
|
+
case_sensitive = options.fetch(:case_sensitive, default_case_sensitive_search)
|
410
|
+
search_value = search_value.to_s.downcase unless case_sensitive
|
411
|
+
method = return_first_match ? :drop_while : :delete_if
|
412
|
+
assets.send(method) do |asset|
|
413
|
+
asset_value = case_sensitive ? asset[field_name] : asset[field_name].to_s.downcase
|
414
|
+
nomatch = match_full_string ? (asset_value != search_value) : (!asset_value.include?(search_value))
|
415
|
+
#logger.debug "COMPARING: '#{search_value}' #{nomatch ? '!' : '='}= '#{asset_value}'"
|
416
|
+
nomatch
|
417
|
+
end if assets and (match_full_string or case_sensitive)
|
418
|
+
return assets.first if assets and return_first_match
|
419
|
+
assets
|
420
|
+
end
|
421
|
+
|
422
|
+
def asset_get_by_filename(asset_name, project_id = nil, folder_id = nil, options = { })
|
423
|
+
assets = asset_get_by_field_search(:filename, asset_name, project_id, folder_id, options)
|
424
|
+
refine_asset_get_by_field_search_results('fileName', asset_name, assets, options)
|
425
|
+
end
|
426
|
+
|
427
|
+
def asset_get_by_title(asset_name, project_id = nil, folder_id = nil, options = { })
|
428
|
+
assets = asset_get_by_field_search(:title, asset_name, project_id, folder_id, options)
|
429
|
+
refine_asset_get_by_field_search_results('title', asset_name, assets, options)
|
430
|
+
end
|
431
|
+
|
432
|
+
def folder_get_by_name(project_id, folder_name, parent_id, options = { })
|
433
|
+
logger.debug { "Searching For Folder by Name: '#{folder_name}' Project Id: '#{project_id}' Parent Id: '#{parent_id}'"}
|
434
|
+
case_sensitive = options.fetch(:case_sensitive, default_case_sensitive_search)
|
435
|
+
return_all_matches = !options.fetch(:return_first_match, false)
|
436
|
+
|
437
|
+
folders = options[:folders] || (parent_id ? folders_get_by_parent_id(:parent_id => parent_id) : folders_get_by_project_id(:project_id => project_id))
|
438
|
+
return false unless folders
|
439
|
+
|
440
|
+
# Use delete_if instead of keep_if to be ruby 1.8 compatible
|
441
|
+
folders.dup.delete_if do |folder|
|
442
|
+
folder_name_to_test = folder['name']
|
443
|
+
folder_name_to_test.upcase! unless case_sensitive
|
444
|
+
no_match = (folder_name_to_test != folder_name)
|
445
|
+
return folder unless no_match or return_all_matches
|
446
|
+
no_match
|
447
|
+
end
|
448
|
+
return nil unless return_all_matches
|
449
|
+
folders
|
450
|
+
end
|
451
|
+
|
452
|
+
# # A metadata creation utility method that checks for existing keys to avoid duplication
|
453
|
+
# #
|
454
|
+
# # @param [String] asset_id
|
455
|
+
# # @param [Hash] metadata
|
456
|
+
# # @return [Boolean]
|
457
|
+
# def metadata_create_if_not_exists(asset_id, metadata)
|
458
|
+
# return asset_id.map { |au| metadata_create_if_not_exists(au, metadata) } if asset_id.is_a?(Array)
|
459
|
+
# return unless metadata.is_a?(Hash) and !metadata.empty?
|
460
|
+
#
|
461
|
+
# md_existing = metadata_get_by_asset_uuid(asset_id)
|
462
|
+
# md_existing_keys = {}
|
463
|
+
# md_existing.each do |ms_md|
|
464
|
+
# md_existing_keys[ms_md['key']] = ms_md
|
465
|
+
# end if md_existing.is_a?(Array)
|
466
|
+
#
|
467
|
+
# md_to_create = [ ]
|
468
|
+
# md_to_edit = [ ]
|
469
|
+
#
|
470
|
+
# metadata.each do |key, value|
|
471
|
+
# if md_existing_keys.has_key?(key)
|
472
|
+
# md_current = md_existing_keys[key]
|
473
|
+
# md_to_edit << { 'key' => key, 'value' => value } unless (md_current['value'] == value)
|
474
|
+
# else
|
475
|
+
# md_to_create << { 'key' => key, 'value' => value }
|
476
|
+
# end
|
477
|
+
# end
|
478
|
+
#
|
479
|
+
# # logger.debug { <<-MD
|
480
|
+
# #
|
481
|
+
# # Metadata
|
482
|
+
# #
|
483
|
+
# # Create
|
484
|
+
# # #{PP.pp(md_to_create, '')}
|
485
|
+
# #
|
486
|
+
# # Edit
|
487
|
+
# # #{PP.pp(md_to_edit, '')}
|
488
|
+
# # MD
|
489
|
+
# # }
|
490
|
+
#
|
491
|
+
# batch_execute do
|
492
|
+
# #md_to_edit.each { |data| metadata_update(data.merge({ :asset_id => asset_id })) }
|
493
|
+
# #md_to_create.each { |data| next unless data and !data.empty?; metadata_create(data.merge({ :asset_id => asset_id })) }
|
494
|
+
#
|
495
|
+
# md_to_edit.each_slice(50) { |data| metadata_update(:asset_id => asset_id, :metadata => data) }
|
496
|
+
# md_to_create.each_slice(50) { |data| logger.debug { "Data: #{data.inspect}" }; metadata_create(:asset_id => asset_id, :metadata => data) }
|
497
|
+
#
|
498
|
+
# end
|
499
|
+
#
|
500
|
+
# end
|
501
|
+
|
502
|
+
# # A method that mirrors the metadata passed to the asset, deleting any keys that don't exist in the metadata param
|
503
|
+
# #
|
504
|
+
# # @param [String] asset_id
|
505
|
+
# # @param [Hash] metadata
|
506
|
+
# def metadata_mirror(asset_id, metadata = { })
|
507
|
+
# return asset_id.map { |au| metadata_mirror(au, metadata) } if asset_id.is_a?(Array)
|
508
|
+
#
|
509
|
+
# md_to_delete = [ ]
|
510
|
+
# md_existing_keys = { }
|
511
|
+
#
|
512
|
+
# md_existing = metadata_get_by_asset_uuid(asset_id)
|
513
|
+
# md_existing.each do |ms_md|
|
514
|
+
# ms_md_key = ms_md['key']
|
515
|
+
# if metadata.key?(ms_md_key)
|
516
|
+
# md_existing_keys[ms_md_key] = ms_md
|
517
|
+
# else
|
518
|
+
# md_to_delete << ms_md_key
|
519
|
+
# end
|
520
|
+
# end
|
521
|
+
#
|
522
|
+
# md_to_create = [ ]
|
523
|
+
# md_to_edit = [ ]
|
524
|
+
#
|
525
|
+
# metadata.each do |key, value|
|
526
|
+
# if md_existing_keys.has_key?(key)
|
527
|
+
# md_current = md_existing_keys[key]
|
528
|
+
# md_to_edit << { 'key' => key, 'value' => value } unless (md_current['value'] == value)
|
529
|
+
# else
|
530
|
+
# md_to_create << { 'key' => key, 'value' => value }
|
531
|
+
# end
|
532
|
+
# end
|
533
|
+
#
|
534
|
+
# batch_execute do
|
535
|
+
# md_to_edit.each { |data| metadata_update(data.merge({ :asset_id => asset_id })) }
|
536
|
+
# md_to_create.each { |data| metadata_create(data.merge({ :asset_id => asset_id })) }
|
537
|
+
# md_to_delete.each { |data| metadata_delete({ :asset_id => asset_id, :metadata_key => data }) }
|
538
|
+
# end
|
539
|
+
#
|
540
|
+
# end
|
541
|
+
|
542
|
+
# @param [Array] metadata_in
|
543
|
+
def metadata_transform_to_hash(metadata_in)
|
544
|
+
case metadata_in
|
545
|
+
when Array
|
546
|
+
# This is what we want
|
547
|
+
return Hash[ metadata_in.map { |m| [m['key'], m['value'] ] } ]
|
548
|
+
when Hash
|
549
|
+
return metadata_in
|
550
|
+
else
|
551
|
+
return { }
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
# Checks to see if a project/folder/asset path exists and records each as existing or missing
|
556
|
+
#
|
557
|
+
# @param [String] path The path to be checked for existence. Format: project[/folder][/filename]
|
558
|
+
# @param [Boolean] path_contains_asset (false) Indicates that the path contains an asset filename
|
559
|
+
# @param [Hash] options ({ })
|
560
|
+
# @option options [Boolean] :asset_name_field (:filename)
|
561
|
+
# (@see #resolve_path)
|
562
|
+
def path_check(path, path_contains_asset = false, options = { })
|
563
|
+
return false unless path
|
564
|
+
|
565
|
+
# Remove any and all instances of '/' from the beginning of the path
|
566
|
+
path = path[1..-1] while path.start_with? '/'
|
567
|
+
|
568
|
+
path_ary = path.split('/')
|
569
|
+
|
570
|
+
existing_path_result = resolve_path(path, path_contains_asset, options)
|
571
|
+
existing_path_ary = existing_path_result[:id_path_ary]
|
572
|
+
check_path_length = path_ary.length
|
573
|
+
|
574
|
+
# Get a count of the number of elements which were found to exist
|
575
|
+
existing_path_length = existing_path_ary.length
|
576
|
+
|
577
|
+
# Drop the first n elements of the array which corresponds to the number of elements found to be existing
|
578
|
+
missing_path = path_ary.drop(existing_path_length)
|
579
|
+
# In the following logic tree the goal is indicate what was searched for and what was found. If we didn't search
|
580
|
+
# for the component (folder/asset) then we don't want to set the missing indicator var
|
581
|
+
# (folder_missing/asset_missing) for component as a boolean but instead leave it nil.
|
582
|
+
missing_path_length = missing_path.length
|
583
|
+
if missing_path_length > 0
|
584
|
+
# something is missing
|
585
|
+
|
586
|
+
if missing_path_length == check_path_length
|
587
|
+
# everything is missing in our path
|
588
|
+
|
589
|
+
project_missing = true
|
590
|
+
if path_contains_asset
|
591
|
+
# we are missing everything and we were looking for an asset so it must be missing
|
592
|
+
asset_missing = true
|
593
|
+
|
594
|
+
if check_path_length > 2
|
595
|
+
#if we were looking for more than two things (project, folder, and asset) and we are missing everything then folders are missing also
|
596
|
+
searched_folders = true
|
597
|
+
folder_missing = true
|
598
|
+
else
|
599
|
+
|
600
|
+
#if we are only looking for 2 things then that is only project and asset, folders weren't in the path so we aren't missing them
|
601
|
+
searched_folders = false
|
602
|
+
folder_missing = false
|
603
|
+
end
|
604
|
+
else
|
605
|
+
if check_path_length > 1
|
606
|
+
# If we are looking for more than one thing then it was project and folder and both are missing
|
607
|
+
searched_folders = true
|
608
|
+
folder_missing = true
|
609
|
+
else
|
610
|
+
searched_folders = false
|
611
|
+
folder_missing = false
|
612
|
+
end
|
613
|
+
end
|
614
|
+
else
|
615
|
+
#we have found at least one thing and it starts with project
|
616
|
+
project_missing = false
|
617
|
+
if path_contains_asset
|
618
|
+
#missing at least 1 and the asset is at the end so we know it's missing
|
619
|
+
asset_missing = true
|
620
|
+
if missing_path_length == 1
|
621
|
+
#if we are only missing one thing and it's the asset then it's not a folder!
|
622
|
+
folder_missing = false
|
623
|
+
searched_folders = check_path_length > 2
|
624
|
+
else
|
625
|
+
# missing_path_length is more than 1
|
626
|
+
if check_path_length > 2
|
627
|
+
#we are looking for project, folder, and asset and missing at least 3 things so they are all missing
|
628
|
+
searched_folders = true
|
629
|
+
folder_missing = true
|
630
|
+
else
|
631
|
+
#we are only looking for project and asset so no folders are missing
|
632
|
+
searched_folders = false
|
633
|
+
folder_missing = false
|
634
|
+
end
|
635
|
+
end
|
636
|
+
else
|
637
|
+
#if we are missing something and the project was found and there was no asset then it must be a folder
|
638
|
+
searched_folders = true
|
639
|
+
folder_missing = true
|
640
|
+
end
|
641
|
+
end
|
642
|
+
else
|
643
|
+
searched_folders = !existing_path_result[:folders].empty?
|
644
|
+
project_missing = folder_missing = asset_missing = false
|
645
|
+
end
|
646
|
+
|
647
|
+
{
|
648
|
+
:check_path_ary => path_ary,
|
649
|
+
:existing => existing_path_result,
|
650
|
+
:missing_path => missing_path,
|
651
|
+
:searched_folders => searched_folders,
|
652
|
+
:project_missing => project_missing,
|
653
|
+
:folder_missing => folder_missing,
|
654
|
+
:asset_missing => asset_missing,
|
655
|
+
}
|
656
|
+
end
|
657
|
+
alias :check_path :path_check
|
658
|
+
|
659
|
+
|
660
|
+
# Calls check_path to see if any part of a project/folder/asset path are missing from MediaSilo and creates any part that is missing
|
661
|
+
#
|
662
|
+
# @param [String] path The path to create inside of MediaSilo
|
663
|
+
# @param [Boolean] contains_asset see #path_resolve
|
664
|
+
# @param [String|nil] asset_url
|
665
|
+
# @param [Hash|nil] metadata
|
666
|
+
# @param [Hash] options
|
667
|
+
# @option options [Hash] :additional_asset_create_params Additional arguments to pass to the asset_create call
|
668
|
+
# @option options [Boolean] :overwrite_asset Will cause the asset to be deleted and recreated
|
669
|
+
# @option options [Boolean] :path_creation_delay A delay between folder_create calls to allow
|
670
|
+
# @return [Hash]
|
671
|
+
# {
|
672
|
+
# :check_path_ary=>["create_missing_path_test"],
|
673
|
+
# :existing=>{
|
674
|
+
# :name_path=>"/",
|
675
|
+
# :id_path=>"/",
|
676
|
+
# :name_path_ary=>[],
|
677
|
+
# :id_path_ary=>[],
|
678
|
+
# :project=>false,
|
679
|
+
# :asset=>nil,
|
680
|
+
# :folders=>[]
|
681
|
+
# },
|
682
|
+
# :missing_path=>[],
|
683
|
+
# :searched_folders=>false,
|
684
|
+
# :project_missing=>true,
|
685
|
+
# :folder_missing=>false,
|
686
|
+
# :asset_missing=>nil,
|
687
|
+
# :project=>{
|
688
|
+
# "id"=>30620,
|
689
|
+
# "datecreated"=>"June, 05 2013 15:20:15",
|
690
|
+
# "description"=>"",
|
691
|
+
# "uuid"=>"15C84A5F-B2D9-0E2F-507D94189F8A1FDC",
|
692
|
+
# "name"=>"create_missing_path_test"
|
693
|
+
# },
|
694
|
+
# :project_id=>30620,
|
695
|
+
# :parent_folder_id=>0
|
696
|
+
# }
|
697
|
+
def path_create(path, contains_asset = false, asset_url = nil, metadata = nil, options = { })
|
698
|
+
overwrite_asset = options.fetch(:overwrite_asset, false)
|
699
|
+
additional_asset_create_params = options[:additional_asset_create_params] || { }
|
700
|
+
path_creation_delay = options[:path_creation_delay] || 10
|
701
|
+
asset_search_field_name = options[:asset_search_field_name] || :filename
|
702
|
+
|
703
|
+
cp_result = check_path(path, contains_asset, :asset_search_field_name => asset_search_field_name)
|
704
|
+
logger.debug { "CHECK PATH RESULT #{cp_result.inspect}" }
|
705
|
+
return false unless cp_result
|
706
|
+
|
707
|
+
project_missing = cp_result[:project_missing]
|
708
|
+
folder_missing = cp_result[:folder_missing]
|
709
|
+
asset_missing = cp_result[:asset_missing]
|
710
|
+
|
711
|
+
existing = cp_result[:existing]
|
712
|
+
|
713
|
+
asset = existing[:asset]
|
714
|
+
|
715
|
+
# This was meant as a Bypass if nothing needed to be done, complicated code maintenance
|
716
|
+
# unless project_missing or folder_missing or asset_missing or (!asset_missing and overwrite_asset)
|
717
|
+
# project_id = cp_result[:existing][:id_path_ary].first
|
718
|
+
# asset = cp_result[:existing][:asset]
|
719
|
+
# if contains_asset
|
720
|
+
# asset_id = cp_result[:existing][:id_path_ary].last
|
721
|
+
# parent_folder_id = cp_result[:existing][:id_path_ary].fetch(-2)
|
722
|
+
#
|
723
|
+
# asset_edit_extended(asset_id, additional_asset_create_params) if metadata and !metadata.empty?
|
724
|
+
# # metadata_create_if_not_exists(asset_id, metadata) if metadata and !metadata.empty?
|
725
|
+
# else
|
726
|
+
# asset_id = nil
|
727
|
+
# parent_folder_id = cp_result[:existing][:id_path_ary].last
|
728
|
+
# end
|
729
|
+
#
|
730
|
+
# result = cp_result.merge({ :project_id => project_id, :parent_folder_id => parent_folder_id, :asset_id => asset_id, :asset => asset })
|
731
|
+
# logger.debug { "Create Missing Path Result: #{result.inspect}" }
|
732
|
+
# return result
|
733
|
+
# end
|
734
|
+
searched_folders = cp_result[:searched_folders]
|
735
|
+
|
736
|
+
missing_path = cp_result[:missing_path]
|
737
|
+
|
738
|
+
project_name = cp_result[:check_path_ary][0]
|
739
|
+
#logger.debug "PMP: #{missing_path}"
|
740
|
+
if project_missing
|
741
|
+
logger.debug { "Missing Project - Creating Project '#{project_name}'" }
|
742
|
+
project = project_create(project_name)
|
743
|
+
raise "Error Creating Project. Response: #{project}" unless project.is_a?(Hash)
|
744
|
+
|
745
|
+
cp_result[:project] = project
|
746
|
+
project_id = project['id']
|
747
|
+
missing_path.shift
|
748
|
+
logger.debug { "Created Project '#{project_name}' - #{project_id}" }
|
749
|
+
else
|
750
|
+
project_id = existing[:id_path_ary].first
|
751
|
+
end
|
752
|
+
|
753
|
+
if searched_folders
|
754
|
+
if folder_missing
|
755
|
+
# logger.debug "FMP: #{missing_path}"
|
756
|
+
|
757
|
+
parent_folder_id = (existing[:id_path_ary].length <= 1) ? 0 : existing[:id_path_ary].last
|
758
|
+
|
759
|
+
asset_name = missing_path.pop if contains_asset
|
760
|
+
|
761
|
+
previous_missing = project_missing
|
762
|
+
missing_path.each do |folder_name|
|
763
|
+
sleep path_creation_delay if path_creation_delay and previous_missing
|
764
|
+
begin
|
765
|
+
logger.debug { "Creating folder '#{folder_name}' parent id: #{parent_folder_id} project id: #{project_id}" }
|
766
|
+
new_folder = folder_create(:name => folder_name, :project_id => project_id, :parent_id => parent_folder_id)
|
767
|
+
raise "Error Creating Folder. Response: #{new_folder}" unless new_folder.is_a?(Hash)
|
768
|
+
|
769
|
+
logger.debug { "New Folder: #{new_folder.inspect}" }
|
770
|
+
parent_folder_id = new_folder['id']
|
771
|
+
logger.debug { "Folder Created #{new_folder} - #{parent_folder_id}" }
|
772
|
+
rescue => e
|
773
|
+
raise e.prefix_message("Failed to create folder '#{folder_name}' parent id: '#{parent_folder_id}' project id: '#{project_id}'. Exception:")
|
774
|
+
end
|
775
|
+
previous_missing = true
|
776
|
+
end
|
777
|
+
|
778
|
+
else
|
779
|
+
if contains_asset and not asset_missing
|
780
|
+
parent_folder_id = existing[:id_path_ary].fetch(-2)
|
781
|
+
else
|
782
|
+
parent_folder_id = existing[:id_path_ary].last
|
783
|
+
end
|
784
|
+
end
|
785
|
+
else
|
786
|
+
parent_folder_id = 0
|
787
|
+
end
|
788
|
+
|
789
|
+
if contains_asset
|
790
|
+
additional_asset_create_params = { } unless additional_asset_create_params.is_a?(Hash)
|
791
|
+
additional_asset_create_params['folderId'] = parent_folder_id
|
792
|
+
additional_asset_create_params['projectId'] = project_id
|
793
|
+
additional_asset_create_params[:metadata] = metadata
|
794
|
+
additional_asset_create_params[:source_url] = asset_url
|
795
|
+
|
796
|
+
if asset_missing
|
797
|
+
asset = asset_create(additional_asset_create_params)
|
798
|
+
raise "Error Creating Asset: #{asset.inspect} Args: #{additional_asset_create_params.inspect}" unless success?
|
799
|
+
else
|
800
|
+
if overwrite_asset
|
801
|
+
asset_id = existing[:id_path_ary].last
|
802
|
+
begin
|
803
|
+
raise "Error Message: #{error_message}" unless asset_delete(asset_id)
|
804
|
+
rescue => e
|
805
|
+
raise e.prefix_message("Error Deleting Existing Asset. Asset ID: #{asset_id} Exception: ")
|
806
|
+
end
|
807
|
+
asset = asset_create(additional_asset_create_params)
|
808
|
+
raise "Error Creating Asset: #{asset.inspect} Args: #{additional_asset_create_params.inspect}" unless success?
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
additional_asset_create_params = additional_asset_create_params.delete_if { |k,v| asset[k] == v }
|
813
|
+
asset_edit_extended(asset['id'], additional_asset_create_params) unless additional_asset_create_params.empty?
|
814
|
+
# metadata_create_if_not_exists(asset['id'], metadata) if metadata and !metadata.empty?
|
815
|
+
|
816
|
+
cp_result[:asset] = asset
|
817
|
+
end
|
818
|
+
result = cp_result.merge({ :project_id => project_id, :parent_folder_id => parent_folder_id })
|
819
|
+
logger.debug { "Create Missing Path Result: #{result.inspect}" }
|
820
|
+
return result
|
821
|
+
end
|
822
|
+
alias :create_path :path_create
|
823
|
+
|
824
|
+
def path_delete(path, options = { })
|
825
|
+
raise_exception_on_error = options.fetch(:raise_exception_on_error, true)
|
826
|
+
recursive = (options.fetch(:recursive, false) === true) ? true : false
|
827
|
+
include_assets = (options.fetch(:include_assets, false) === true) ? true : false
|
828
|
+
|
829
|
+
path = path[1..-1] if path.start_with? '/' # Remove the leading slash if it is present
|
830
|
+
path_ary = path.split('/') # Turn the path into an array of names
|
831
|
+
|
832
|
+
raise ArgumentError, 'Path is empty. Nothing to do.' if path_ary.empty?
|
833
|
+
|
834
|
+
if path_ary.last == '*'
|
835
|
+
path_ary.pop
|
836
|
+
|
837
|
+
if path_ary.empty?
|
838
|
+
delete_all_projects = options.fetch(:delete_all_projects)
|
839
|
+
raise ArgumentError, 'Wildcard Project Deletion is not Enabled.' unless (delete_all_projects === true)
|
840
|
+
|
841
|
+
projects = projects_get
|
842
|
+
return projects.map { |project| path_delete(project['name'], options)}
|
843
|
+
end
|
844
|
+
|
845
|
+
delete_contents_only = true
|
846
|
+
else
|
847
|
+
delete_contents_only = options.fetch(:delete_contents_only, false)
|
848
|
+
end
|
849
|
+
|
850
|
+
result = check_path(path_ary.join('/'))
|
851
|
+
raise "Error checking path. '#{error_message}'" unless result
|
852
|
+
|
853
|
+
existing_path = result[:existing][:id_path_ary]
|
854
|
+
missing_path = result[:missing_path]
|
855
|
+
|
856
|
+
#The path was not found
|
857
|
+
raise "Path not found. Path: '#{path}' Check Path Result: #{result.inspect}" unless missing_path.empty?
|
858
|
+
|
859
|
+
id_path_ary = existing_path
|
860
|
+
|
861
|
+
project_id = id_path_ary.shift # Pull the project_id out of the beginning of the array
|
862
|
+
|
863
|
+
if id_path_ary.empty?
|
864
|
+
folder_id = 0
|
865
|
+
else
|
866
|
+
folder_id = id_path_ary.last
|
867
|
+
end
|
868
|
+
|
869
|
+
path_delete_by_id(project_id, folder_id, recursive, include_assets, delete_contents_only, options)
|
870
|
+
rescue ArgumentError, RuntimeError => e
|
871
|
+
raise e if raise_exception_on_error
|
872
|
+
return false
|
873
|
+
end
|
874
|
+
|
875
|
+
# Deletes a project's and/or folder's contents.
|
876
|
+
#
|
877
|
+
# @param [String|Integer] project_id The id of the project that you wish to delete.
|
878
|
+
# @param [String|Integer] folder_id (0) The parent_folder in the project that you would want to delete the
|
879
|
+
# contents of. Defaults to 0 which is the root folder of the project.
|
880
|
+
# @param [Boolean] recursive (false) Tells the method to recurse into any sub-folders. Usually you would want
|
881
|
+
# this to be true, but the default requires you to be explicit about wanting to delete sub-folders so the
|
882
|
+
# default is false.
|
883
|
+
# @param [Boolean] include_assets (false) Tells the method to delete any assets in any directory that it
|
884
|
+
# traverses into. Usually you would want this to be true, but the default requires you to be explicit about
|
885
|
+
# wanting to delete assets so the default is false
|
886
|
+
# @param [Boolean] delete_contents_only (true) Tells the method to not delete the parent object
|
887
|
+
# (project or folder) unless this is set to true.
|
888
|
+
# @param [Hash] options
|
889
|
+
# @option option [Boolean] :dry_run
|
890
|
+
# @option option [Boolean] :delete_assets_only Will only delete assets along the path but will leave the project
|
891
|
+
# and folders in place
|
892
|
+
def path_delete_by_id(project_id, folder_id = 0, recursive = false, include_assets = false, delete_contents_only = true, options = { })
|
893
|
+
dry_run = options.fetch(:dry_run, false)
|
894
|
+
delete_assets_only = options.fetch(:delete_assets_only, false)
|
895
|
+
|
896
|
+
raise ArgumentError, 'include_assets must be true to use the delete_assets_only option.' if delete_assets_only and !include_assets
|
897
|
+
|
898
|
+
@logger.debug { "Deleting Path By ID - Project ID: #{project_id} Folder ID: #{folder_id} Recursive: #{recursive} Include Assets: #{include_assets} Delete Contents Only: #{delete_contents_only} Options: #{options.inspect}" }
|
899
|
+
|
900
|
+
if folder_id and folder_id != 0
|
901
|
+
folders = folders_get_by_parent_id(folder_id) || [ ]
|
902
|
+
else
|
903
|
+
folders = folders_get_by_project_id(project_id) || [ ]
|
904
|
+
end
|
905
|
+
folders = [ ] unless folders.is_a?(Array)
|
906
|
+
if recursive
|
907
|
+
folders = [ ] if folders.is_a?(String)
|
908
|
+
total_folders = folders.length
|
909
|
+
folder_counter = 0
|
910
|
+
folders.delete_if do |folder|
|
911
|
+
folder_counter += 1
|
912
|
+
|
913
|
+
@logger.debug { "Deleting Contents of Folder #{folder_counter} of #{total_folders} - #{folder}" }
|
914
|
+
|
915
|
+
# Pass delete_assets_only as the delete_contents_only argument. This way if we aren't deleting assets only then
|
916
|
+
# sub-folders and assets will get deleted recursively, otherwise only assets will be deleted
|
917
|
+
path_delete_by_id(project_id, folder['id'], recursive, include_assets, delete_assets_only, options)
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
|
922
|
+
if include_assets
|
923
|
+
if folder_id == 0
|
924
|
+
assets = assets_get_by_project_id(:id => project_id)
|
925
|
+
else
|
926
|
+
assets = assets_get_by_folder_id(:id => folder_id)
|
927
|
+
end
|
928
|
+
assets = [ ] unless assets.is_a?(Array)
|
929
|
+
total_assets = assets.length
|
930
|
+
asset_counter = 0
|
931
|
+
|
932
|
+
# batch_execute {
|
933
|
+
# assets.each { |asset| asset_delete(asset['id']) }
|
934
|
+
# }
|
935
|
+
|
936
|
+
response = assets.map { |asset| asset_delete(asset['id']) }
|
937
|
+
|
938
|
+
# if dry_run
|
939
|
+
# assets = [ ]
|
940
|
+
# else
|
941
|
+
# assets = response.dup.delete_if { |r| %w(204 404).include?(r['httpStatus']) } unless assets.empty?
|
942
|
+
# end
|
943
|
+
|
944
|
+
assets = [ ]
|
945
|
+
|
946
|
+
# assets.delete_if { |asset|
|
947
|
+
# asset_counter += 1
|
948
|
+
#
|
949
|
+
# dry_run ? true : asset_delete(asset['id'])
|
950
|
+
# }
|
951
|
+
else
|
952
|
+
assets = [ ] # make assets.empty? pass later on. let ms throw an error if the project/folder isn't empty
|
953
|
+
end
|
954
|
+
|
955
|
+
unless delete_contents_only or delete_assets_only
|
956
|
+
if folders.empty? and assets.empty?
|
957
|
+
if folder_id === 0
|
958
|
+
@logger.debug { "Deleting Project #{project_id}" }
|
959
|
+
return ( dry_run ? true : project_delete(project_id) )
|
960
|
+
else
|
961
|
+
@logger.debug { "Deleting Folder #{folder_id}" }
|
962
|
+
return ( dry_run ? true : folder_delete(folder_id) )
|
963
|
+
end
|
964
|
+
else
|
965
|
+
return true if dry_run
|
966
|
+
warn "Assets remaining in project/folder: #{project_id}/#{folder_id} : Assets: #{assets.inspect}" unless assets.empty?
|
967
|
+
warn "Folders remaining in project/folder: #{project_id}/#{folder_id} : Folders: #{folders.inspect}" unless folders.empty?
|
968
|
+
return false
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
972
|
+
return true
|
973
|
+
end
|
974
|
+
|
975
|
+
|
976
|
+
def project_get_by_name(args = { }, options = { })
|
977
|
+
project_name = case args
|
978
|
+
when String; args
|
979
|
+
when Hash; args[:name] || args[:project_name]
|
980
|
+
end
|
981
|
+
|
982
|
+
case_sensitive = options.fetch(:case_sensitive, default_case_sensitive_search)
|
983
|
+
return_all_matches = !options.fetch(:return_first_match, false)
|
984
|
+
|
985
|
+
|
986
|
+
projects = options[:projects] || projects_get
|
987
|
+
logger.debug { "Searching Projects: #{projects.inspect}" }
|
988
|
+
return false unless projects
|
989
|
+
|
990
|
+
project_name.upcase! unless case_sensitive
|
991
|
+
|
992
|
+
# Use delete_if instead of keep_if to be ruby 1.8 compatible
|
993
|
+
projects = projects.dup.delete_if do |project|
|
994
|
+
project_name_to_test = project['name']
|
995
|
+
project_name_to_test.upcase! unless case_sensitive
|
996
|
+
no_match = (project_name_to_test != project_name)
|
997
|
+
logger.debug { "Comparing: #{project_name_to_test} #{no_match ? '!' : '='}= #{project_name}"}
|
998
|
+
return project unless no_match or return_all_matches
|
999
|
+
no_match
|
1000
|
+
end
|
1001
|
+
return nil unless return_all_matches
|
1002
|
+
projects
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
def path_resolve(path, path_contains_asset = false, options = { })
|
1006
|
+
logger.debug { "Resolving Path: '#{path}' Path Contains Asset: #{path_contains_asset} Options: #{options}" }
|
1007
|
+
|
1008
|
+
return_first_matching_asset = options.fetch(:return_first_matching_asset, true)
|
1009
|
+
|
1010
|
+
id_path_ary = [ ]
|
1011
|
+
name_path_ary = [ ]
|
1012
|
+
|
1013
|
+
if path.is_a?(String)
|
1014
|
+
# Remove any leading slashes
|
1015
|
+
path = path[1..-1] while path.start_with?('/')
|
1016
|
+
|
1017
|
+
path_ary = path.split('/')
|
1018
|
+
elsif path.is_a?(Array)
|
1019
|
+
path_ary = path.dup
|
1020
|
+
else
|
1021
|
+
raise ArgumentError, "path is required to be a String or an Array. Path Class Name: #{path.class.name}"
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
asset_name = path_ary.pop if path_contains_asset
|
1025
|
+
|
1026
|
+
# The first element must be the name of the project
|
1027
|
+
project_name = path_ary.shift
|
1028
|
+
raise ArgumentError, 'path must contain a project name.' unless project_name
|
1029
|
+
logger.debug { "Search for Project Name: #{project_name}" }
|
1030
|
+
project = project_get_by_name(project_name, :return_first_match => true, :projects => options[:projects])
|
1031
|
+
return {
|
1032
|
+
:name_path => '/',
|
1033
|
+
:name_path_ary => [ ],
|
1034
|
+
|
1035
|
+
:id_path => '/',
|
1036
|
+
:id_path_ary => [ ],
|
1037
|
+
|
1038
|
+
:project => nil,
|
1039
|
+
:asset => nil,
|
1040
|
+
:folders => [ ]
|
1041
|
+
} if !project or project.empty?
|
1042
|
+
|
1043
|
+
project_id = project['id']
|
1044
|
+
id_path_ary << project_id
|
1045
|
+
name_path_ary << project_name
|
1046
|
+
|
1047
|
+
parsed_folders = (project && project['folderCount'] > 0) ? resolve_folder_path(project_id, path_ary) : nil
|
1048
|
+
if parsed_folders.nil?
|
1049
|
+
asset_folder_id = 0
|
1050
|
+
folders = []
|
1051
|
+
else
|
1052
|
+
id_path_ary.concat(parsed_folders[:id_path_ary])
|
1053
|
+
name_path_ary.concat(parsed_folders[:name_path_ary])
|
1054
|
+
asset_folder_id = parsed_folders[:id_path_ary].last if path_contains_asset
|
1055
|
+
folders = parsed_folders.fetch(:folder_ary, [])
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
asset = nil
|
1059
|
+
if path_contains_asset and (asset_folder_id or path_ary.length == 2)
|
1060
|
+
# The name of the attribute to search the asset name for (Valid options are :title or :filename)
|
1061
|
+
asset_name_field = options[:asset_search_field_name] || :filename
|
1062
|
+
case asset_name_field.to_s.downcase.to_sym
|
1063
|
+
when :filename, 'filename'
|
1064
|
+
asset = asset_get_by_filename(asset_name, project_id, asset_folder_id, :return_first_match => return_first_matching_asset)
|
1065
|
+
when :title, 'title'
|
1066
|
+
asset = asset_get_by_title(asset_name, project_id, asset_folder_id, :return_first_match => return_first_matching_asset)
|
1067
|
+
else
|
1068
|
+
raise ArgumentError, ":asset_name_field value is not a valid option. It must be :title or :filename. Current value: #{asset_name_field}"
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
if asset
|
1072
|
+
if asset.empty?
|
1073
|
+
|
1074
|
+
|
1075
|
+
elsif asset.is_a?(Array)
|
1076
|
+
# Just add the whole array to the array
|
1077
|
+
id_path_ary << asset.map { |_asset| _asset['id'] }
|
1078
|
+
name_path_ary << asset.map { |_asset| _asset['fileName'] }
|
1079
|
+
else
|
1080
|
+
id_path_ary << asset['id']
|
1081
|
+
name_path_ary << asset['fileName']
|
1082
|
+
end
|
1083
|
+
end
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
return {
|
1087
|
+
:name_path => "/#{name_path_ary.join('/')}",
|
1088
|
+
:name_path_ary => name_path_ary,
|
1089
|
+
|
1090
|
+
:id_path => "/#{id_path_ary.join('/')}",
|
1091
|
+
:id_path_ary => id_path_ary,
|
1092
|
+
|
1093
|
+
:project => project,
|
1094
|
+
:asset => asset,
|
1095
|
+
:folders => folders
|
1096
|
+
}
|
1097
|
+
end
|
1098
|
+
alias :resolve_path :path_resolve
|
1099
|
+
|
1100
|
+
# Takes a file system type path and resolves the MediaSilo id's for each of the folders of that path
|
1101
|
+
#
|
1102
|
+
# @param [Integer] project_id The id of the project the folder resides in
|
1103
|
+
# @param [String] path A directory path separated by / of folders to traverse
|
1104
|
+
# @param [Integer] parent_id The ID of the parent folder to begin the search in
|
1105
|
+
def resolve_folder_path(project_id, path, parent_id = nil)
|
1106
|
+
if path.is_a?(Array)
|
1107
|
+
path_ary = path.dup
|
1108
|
+
elsif path.is_a? String
|
1109
|
+
path = path[1..-1] while path.start_with?('/')
|
1110
|
+
path_ary = path.split('/')
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
return nil if !path_ary or path_ary.empty?
|
1114
|
+
|
1115
|
+
id_path_ary = [ ]
|
1116
|
+
name_path_ary = [ ]
|
1117
|
+
|
1118
|
+
folder_name = path_ary.shift
|
1119
|
+
name_path_ary << folder_name
|
1120
|
+
|
1121
|
+
folder = folder_get_by_name(project_id, folder_name, parent_id, :return_first_match => true)
|
1122
|
+
return nil unless folder
|
1123
|
+
|
1124
|
+
folder_ary = [ folder ]
|
1125
|
+
|
1126
|
+
folder_id = folder['id']
|
1127
|
+
|
1128
|
+
id_path_ary << folder_id.to_s
|
1129
|
+
|
1130
|
+
resolved_folder_path = (folder and folder['folderCount'] > 0) ? resolve_folder_path(project_id, path_ary, folder_id) : nil
|
1131
|
+
|
1132
|
+
unless resolved_folder_path.nil?
|
1133
|
+
id_path_ary.concat(resolved_folder_path[:id_path_ary] || [ ])
|
1134
|
+
name_path_ary.concat(resolved_folder_path[:name_path_ary] || [ ])
|
1135
|
+
folder_ary.concat(resolved_folder_path[:folder_ary] || [ ])
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
return {
|
1139
|
+
:id_path_ary => id_path_ary,
|
1140
|
+
:name_path_ary => name_path_ary,
|
1141
|
+
:folder_ary => folder_ary
|
1142
|
+
}
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
end
|