forked from alchemy-fr/Phlickr
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Uploader.php
398 lines (370 loc) · 12.5 KB
/
Uploader.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
<?php
/**
* @version $Id$
* @author Andrew Morton <[email protected]>
* @license http://opensource.org/licenses/lgpl-license.php
* GNU Lesser General Public License, Version 2.1
* @package Phlickr
*/
/**
* Phlickr_Api includes the core classes.
*/
require_once dirname(__FILE__) . '/Api.php';
/**
* One or more methods returns Phlickr_Photo objects.
*/
require_once dirname(__FILE__) . '/AuthedPhoto.php';
/**
* uploadBatch() uses this to create a photoset.
*/
require_once dirname(__FILE__) . '/AuthedPhotosetList.php';
/**
* uploadBatch() accepts Phlickr_Framework_IUploadBatch as a parameter.
*/
require_once dirname(__FILE__) . '/Framework/IUploadBatch.php';
/**
* uploadBatch() accepts Phlickr_Framework_IUploadListener as a parameter.
*/
require_once dirname(__FILE__) . '/Framework/IUploadListener.php';
/**
* Uploads photos to Flickr.
*
* Sample usage:
* <code>
* <?php
* require_once dirname(__FILE__) . '/Api.php';
* require_once dirname(__FILE__) . '/Uploader.php';
*
* define('UPLOAD_DIRECTORY', 'D:\sf\phlickr\samples\files_to_testupload');
* define('PHOTO_EXTENSION', '.jpg');
*
* // create an api
* $api = new Phlickr_Api(FLICKR_API_KEY, FLICKR_API_SECRET, FLICKR_API_TOKEN);
* // create an uploader
* $uploader = new Phlickr_Uploader($api);
* // array to keep track of the photo ids as they're uploaded
* $photo_ids = array();
* // create a DirectoryIterator (part of the Standard PHP Library)
* $di = new DirectoryIterator(UPLOAD_DIRECTORY);
*
* // upload all the photos in the directory
* foreach($di as $item) {
* // only upload files with the given extension
* if ($item->isFile()) {
* $extension = substr($item, - strlen(PHOTO_EXTENSION));
* if (strtolower($extension) === strtolower(PHOTO_EXTENSION)) {
* print "Uploading $item...\n";
* // upload the photo
* $id = $uploader->upload($item->getPathname(), 'a title',
* 'a description', 'some tags');
* // save the photo's id to an array
* $photo_id[] = $id;
* }
* }
* }
*
* // print out the post-upload edit link.
* if (count($photo_ids)) {
* printf("All done! If you care to make some changes:\n%s",
* $uploader->buildEditUrl($photo_ids));
* }
* ?>
* </code>
*
*
* This class is responsible for:
* - Uploading a file to Flickr with the specified title, description, tags
* and permissions.
*
* To do this, makes use public static methods of the Phlickr_Request and
* Phlickr_Response classes.
*
* @package Phlickr
* @author Andrew Morton <[email protected]>
* @since 0.1.0
*/
class Phlickr_Uploader {
/**
* @var Phlickr_API
*/
protected $_api = null;
/**
* Should photos be visible to everyone?
*
* @var boolean
*/
protected $_forPublic = true;
/**
* Should photos be visible to friend?
*
* @var boolean
*/
protected $_forFriends = true;
/**
* Should photos be visible to family?
*
* @var boolean
*/
protected $_forFamily = true;
/**
* Array of tags that will be added to the photo.
*
* @var array
*/
protected $_tags = array();
/**
* The URL that photo uploads should be POSTed to.
*
* @var string
*/
const UPLOAD_URL = 'http://www.flickr.com/services/upload/';
/**
* The URL that the user should be redirected to for editing uploads.
*
* @var string
*/
const EDIT_URL = 'http://www.flickr.com/tools/uploader_edit.gne';
/**
* Number of seconds to wait for an upload to complete.
* @var integer
*/
const TIMEOUT = 200;
/**
* Constructor
*
* @param Phlickr_API $api
*/
function __construct(Phlickr_Api $api) {
$this->_api = $api;
}
/**
* Return a URL that the user can visit to make changes to uploaded photos.
*
* @param array $ids Array of photos ids returned by upload()
* @return string
*/
static function buildEditUrl($ids) {
return self::EDIT_URL . '?ids=' . implode(',', $ids);
}
/**
* Will the uploaded photos be publicly visible?
*
* @return boolean
* @since 0.2.2
* @see setPerms()
*/
public function isForPublic() {
return $this->_forPublic;
}
/**
* Will the uploaded photos be visible to contacts marked as friends?
*
* @return boolean
* @since 0.2.2
* @see setPerms()
*/
public function isForFriends() {
return $this->_forFriends;
}
/**
* Will the uploaded photos be visible to contacts marked asfamily?
*
* @return boolean
* @since 0.2.2
* @see setPerms()
*/
public function isForFamily() {
return $this->_forFamily;
}
/**
* Get an array of the tags that will be added to the photos.
*
* @return array
* @since 0.2.2
* @see setTags()
*/
public function getTags() {
return $this->_tags;
}
/**
* Set the visibility permission for the uploaded photos.
*
* If the photo is visible to public, the friends and family settings are
* pretty much ignored.
*
* @param boolean $public Can anyone view the photos?
* @param boolean $friends Can contacts marked as friends view the photos?
* @param boolean $family Can contacts marked as family view the photos?
* @return void
* @see isForPublic(), isForFriends(), isForFamily()
* @since 0.2.2
*/
public function setPerms($public, $friends, $family) {
$this->_forPublic = (boolean) $public;
$this->_forFriends =(boolean) $friends;
$this->_forFamily = (boolean) $family;
}
/**
* Set the tags that will be added to the photos.
*
* @param array $tags Array of tag strings
* @return void
* @since 0.2.2
* @see getTags()
*/
public function setTags($tags) {
$this->_tags = (array) $tags;
}
/**
* Upload a photo to Flickr.
*
* If tags are specified, they'll be appended to those listed in getTags().
* If permissions are specified, they'll override those set by setPerms().
*
* The permissions assigned will based on those set using setPerms().
*
* @param string $fullFilePath Full path and file name of the photo.
* @param string $title Photo title.
* @param string $desc Photo description.
* @param string|array $tags A space separated list of tags to add to the photo.
* These will be added to those listed in getTags().
* @return string id of the new photo
* @throws Phlickr_ConnectionException
* @see isForPublic(), isForFriends(), isForFamily(), getTags()
*/
public function upload($fullFilePath, $title = '', $desc = '', $tags = '') {
if (!file_exists($fullFilePath) || !is_readable($fullFilePath)) {
throw new Phlickr_Exception(
"The file '{$fullFilePath}' does not exist or can not be accessed."
);
}
// concat the class's tags with this photos.
if (is_array($tags)) {
$tags = '"' . implode('" "', $this->_tags + $tags) . '"';
} elseif ($tags) {
$tags = '"' . implode('" "', $this->_tags) . '" ' . (string) $tags;
} else {
$tags = '';
}
// get the parameters ready for signing ...
$params = array_merge(
$this->_api->getParamsForRequest(),
array(
'title' => $title,
'description' => $desc,
'tags' => $tags,
'is_public' => (integer) $this->_forPublic,
'is_friend' => (integer) $this->_forFriends,
'is_family' => (integer) $this->_forFamily
)
);
// ... compute a signature ...
ksort($params);
$signing = '';
foreach($params as $key => $value) {
$signing .= $key . $value;
}
$params['api_sig'] = md5($this->_api->getSecret() . $signing);
// ... then put in the photo. the @ tells CURL to upload the file's
// contents
$params['photo'] = '@' . $fullFilePath;
// use the requst to submit
$result = Phlickr_Request::SubmitHttpPost(self::UPLOAD_URL, $params, self::TIMEOUT);
// use the reponse object to parse the results
$resp = new Phlickr_Response($result, true);
// return a photo id
return (string) $resp->getXml()->photoid;
}
/**
* Upload a batch of files to Flickr.
*
* @param Phlickr_Uploader $uploader
* @param Phlickr_Framework_IUploadBatch $batch Provides a list of files
* and information on them.
* @param Phlickr_Framework_IUploadListener $listener Listens to event
* notifications on the status of the upload process.
* @return array An array of Phlickr_AuthedPhoto objects with the ids as
* the keys.
* @uses upload() to do the actual file uploads.
* @uses Phlickr_AuthedPhotosetList::create() to create the photoset
* if it's requested.
* @uses Phlickr_AuthedPhotoset::editPhotos() to put the photos into the
* set and select the primary photo.
* @uses Phlickr_AuthedPhoto::setTaken() to set the taken date if it's
* provided.
* @since 0.2.5
*/
function uploadBatch(Phlickr_Framework_IUploadBatch $batch, Phlickr_Framework_IUploadListener $listener)
{
// array of uploaded photo objects keyed by id
$photos = array();
// array of photo ids keyed by original filename
$photoIds = array();
// notify that the upload is starting
$listener->beforeUpload();
foreach($batch->getFiles() as $file) {
// notify that a file will be uploaded
$listener->beforeFileUpload($file);
// fetch the info for the photo
$title = $batch->getTitleForFile($file);
$desc = $batch->getDescriptionForFile($file);
$tags = $batch->getTagsForFile($file);
// upload it
try {
$photoId = $this->upload($file, $title, $desc, $tags);
// some times it takes a second for the photo to show up.
try {
$photo = new Phlickr_AuthedPhoto($this->_api, $photoId);
} catch (Phlickr_MethodFailureException $ex) {
// give it 10 seconds and try again.
sleep(10);
$photo = new Phlickr_AuthedPhoto($this->_api, $photoId);
}
// keep a filename:id mapping...
$photoIds[$file] = $photoId;
// ... and a id:photo mapping
$photos[$photoId] = $photo;
// notify of success
$listener->afterFileUpload($file, $photo);
} catch (Phlickr_Exception $ex) {
// notify of failure
$listener->failedFileUpload($file, $ex);
}
// assign the taken date if one is provided
try {
$taken = $batch->getTakenDateForFile($file);
if ($taken) {
$photo->setTaken($taken);
}
} catch (Phlickr_Exception $ex) {
// don't worry about it.
}
}
// create a photo set? only if we've got photos and a name.
if ($photoIds && $batch->isSetWanted()) {
// figure out the primary photo (if none was specified use the
// first image)
if (array_key_exists($batch->getSetPrimary(), $photoIds)) {
$primaryId = $photoIds[$batch->getSetPrimary()];
} else {
// reset $photoIds so we can use current() to find the first value
reset($photoIds);
$primaryId = current($photoIds);
}
// create the photoset
$list = new Phlickr_AuthedPhotosetList($this->_api);
$set = $list->create(
$batch->getSetTitle(),
$batch->getSetDescription(),
$primaryId
);
// add the photos to the set
$set->editPhotos($primaryId, $photoIds);
// notify of the photoset creation
$listener->afterCreatePhotoset($set);
}
// notify that the upload is complete
$listener->afterUpload($photos);
return $photos;
}
}