PluginProbe
Photo Engine (Media Organizer & Lightroom) / 0.5
Photo Engine (Media Organizer & Lightroom) v0.5
6.5.5 6.5.4 6.5.3 6.5.2 trunk 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.6 0.8.8 1.2.4 1.3.0 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 All 157 releases
wplr-sync / lrsync_core.php

lrsync_core.php in Photo Engine (Media Organizer & Lightroom) 0.5, at lrsync_core.php

560 lines 16.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class Meow_WPLR_Sync_Core {
4 private $error;
5
6 public function __construct() {
7 add_action( 'delete_attachment', array( $this, 'delete_attachment' ) );
8 add_filter( 'manage_media_columns', array( $this, 'manage_media_columns' ) );
9 add_action( 'manage_media_custom_column', array( $this, 'manage_media_custom_column' ), 10, 2 );
10 add_action( 'admin_head', array( $this, 'admin_head' ), 10, 2 );
11 add_action( 'wp_ajax_wplrsync_link', array( $this, 'wplrsync_link' ) );
12 add_action( 'wp_ajax_wplrsync_unlink', array( $this, 'wplrsync_unlink' ) );
13 add_action( 'admin_init', array( $this, 'admin_init' ) );
14
15 }
16
17 /*
18 OPTIONS
19 */
20
21 function admin_init() {
22 add_settings_section( "wplrsync_media_options", "WP/LR Sync",
23 array( $this, 'media_options_callback' ), "media" );
24 add_settings_field( 'wplr_tools_enabled', "WPLR Tools",
25 array( $this, 'toggle_content_callback' ), "media", 'wplrsync_media_options',
26 array( "Enable" ) );
27 register_setting( 'media', 'wplr_tools_enabled' );
28 }
29
30 function media_options_callback() {
31 echo "<p>Those settings should be used for debugging purposes only.</p>";
32 }
33
34 function toggle_content_callback( $args ) {
35 $html = '<input type="checkbox" id="wplr_tools_enabled" name="wplr_tools_enabled" value="1" ' . checked( 1, get_option( 'wplr_tools_enabled' ), false ) . '/>';
36 $html .= '<label for="wplr_tools_enabled"> ' . $args[0] . '</label>';
37 echo $html;
38 }
39
40 function admin_init_options( $args ) {
41
42 }
43
44 /*
45 CORE
46 */
47
48 function reset_db() {
49 meow_wplrsync_uninstall();
50 meow_wplrsync_activate();
51 }
52
53 function get_error() {
54 if ( $this->error ) {
55 return $this->error;
56 }
57 else {
58 return new IXR_Error( 401, __( 'Unknown error.' ) );
59 }
60 }
61
62 function delete_media( $lr_id ) {
63 global $wpdb;
64 $table_name = $wpdb->prefix . "lrsync";
65 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE lr_id = %d", $lr_id), OBJECT );
66 if ( $sync ) {
67 if ( wp_delete_attachment( $sync->wp_id ) ) {
68 $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE lr_id = %d", $lr_id ) );
69 return true;
70 }
71 }
72 $this->error = new IXR_Error( 403, __( "The attachment could not be removed." ) );
73 return false;
74 }
75
76 function delete_attachment( $wp_id ) {
77 global $wpdb;
78 $table_name = $wpdb->prefix . "lrsync";
79 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE wp_id = %d", $wp_id), OBJECT );
80 if ( $sync ) {
81 $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE lr_id = %d", $sync->lr_id ) );
82 }
83 }
84
85 function unlink_media( $lr_id, $wp_id ) {
86 global $wpdb;
87 $table_name = $wpdb->prefix . "lrsync";
88 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE lr_id = %d AND wp_id = %d", $lr_id, $wp_id), OBJECT );
89 if ( $sync ) {
90 $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE lr_id = %d AND wp_id = %d", $sync->lr_id, $sync->wp_id ) );
91 return true;
92 }
93 $this->error = new IXR_Error( 403, __( "There is no link for this media." ) );
94 return false;
95 }
96
97 function link_media( $lr_id, $wp_id ) {
98 global $wpdb;
99 $table_name = $wpdb->prefix . "lrsync";
100 if ( empty( $wp_id ) ) {
101 $this->error = new IXR_Error( 403, __( "The arguments lr_id and wp_id are required." ) );
102 return false;
103 }
104 if ( !wp_attachment_is_image( $wp_id ) ) {
105 $this->error = new IXR_Error( 403, __( "Attachment " . ($wp_id ? $wp_id : "[null]") . " does not exist or is not an image." ) );
106 return false;
107 }
108 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE wp_id = %d", $wp_id), OBJECT );
109 if ( !$sync ) {
110 $wpdb->insert( $table_name,
111 array(
112 'wp_id' => $wp_id,
113 'lr_id' => $lr_id,
114 'lr_file' => null,
115 'lastsync' => null
116 )
117 );
118 }
119 else {
120 $wpdb->query( $wpdb->prepare( "UPDATE $table_name
121 SET lr_id = %d
122 WHERE wp_id = %d", $lr_id, $wp_id )
123 );
124 }
125 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE wp_id = %d", $wp_id), OBJECT );
126 $info = Meow_WPLR_LRInfo::fromRow( $sync );
127 return $info;
128 }
129
130 function list_sync_media() {
131 global $wpdb;
132 $table_name = $wpdb->prefix . "lrsync";
133 $sync_files = $wpdb->get_results( "SELECT * FROM $table_name WHERE lr_id >= 0 AND wp_id >= 0", OBJECT );
134 $list = array();
135 foreach ( $sync_files as $sync_file ) {
136 $info = Meow_WPLR_LRInfo::fromRow( $sync_file );
137 array_push( $list, $info );
138 }
139 return $list;
140 }
141
142 function sync_media_update( $lrinfo, $tmp_path, $sync ) {
143 global $wpdb;
144 $table_name = $wpdb->prefix . "lrsync";
145 $wp_id = $sync->wp_id;
146 $meta = wp_get_attachment_metadata( $sync->wp_id );
147 $current_file = get_attached_file( $sync->wp_id );
148
149 // Support for WP Retina 2x
150 if ( function_exists( 'wr2x_generate_images' ) )
151 wr2x_delete_attachment( $sync->wp_id );
152
153 $pathinfo = pathinfo( $current_file );
154 $basepath = $pathinfo['dirname'];
155
156 // Let's clean everything first
157 if ( wp_attachment_is_image( $sync->wp_id ) ) {
158 $sizes = $this->get_image_sizes();
159 foreach ($sizes as $name => $attr) {
160 if (isset($meta['sizes'][$name]) && isset($meta['sizes'][$name]['file']) && file_exists( trailingslashit( $basepath ) . $meta['sizes'][$name]['file'] )) {
161 $normal_file = trailingslashit( $basepath ) . $meta['sizes'][$name]['file'];
162 $pathinfo = pathinfo( $normal_file );
163
164 // Support for WP Retina 2x
165 if ( function_exists( 'wr2x_generate_images' ) )
166 $retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . wr2x_retina_extension() . $pathinfo['extension'];
167
168 // Test if the file exists and if it is actually a file (and not a dir)
169 // Some old WordPress Media Library are sometimes broken and link to directories
170 if ( file_exists( $normal_file ) && is_file( $normal_file ) )
171 unlink( $normal_file );
172
173 // Support for WP Retina 2x
174 if ( function_exists( 'wr2x_generate_images' ) && ( file_exists( $retina_file ) && is_file( $retina_file ) ) )
175 unlink( $retina_file );
176 }
177 }
178 }
179 if ( file_exists( $current_file ) )
180 unlink( $current_file );
181
182 // Insert the new file and delete the temporary one
183 copy( $tmp_path, $current_file );
184 chmod( $current_file, 0644 );
185
186 // Generate the images
187 wp_update_attachment_metadata( $sync->wp_id, wp_generate_attachment_metadata( $sync->wp_id, $current_file ) );
188
189 // Update Title, Description and Caption
190 if ( $lrinfo->sync_title || $lrinfo->sync_caption || $lrinfo->sync_desc ) {
191 $post = array( 'ID' => $wp_id );
192 if ( $lrinfo->sync_title )
193 $post['post_title'] = $lrinfo->lr_title;
194 if ( $lrinfo->sync_desc )
195 $post['post_content'] = $lrinfo->lr_desc;
196 if ( $lrinfo->sync_caption )
197 $post['post_excerpt'] = $lrinfo->lr_caption;
198 wp_update_post( $post );
199 }
200
201 // Update Alt Text if needed
202 if ( $lrinfo->sync_alt_text )
203 update_post_meta( $wp_id, '_wp_attachment_image_alt', $lrinfo->lr_alt_text );
204
205 // Support for WP Retina 2x
206 if ( function_exists( 'wr2x_generate_images' ) )
207 wr2x_generate_images( wp_get_attachment_metadata( $sync->wp_id ) );
208
209 $wpdb->query( $wpdb->prepare( "UPDATE $table_name
210 SET lr_file = %s, lastsync = NOW()
211 WHERE lr_id = %d", $lrinfo->lr_file, $lrinfo->lr_id )
212 );
213 }
214
215 function sync_media_add( $lrinfo, $tmp_path ) {
216 global $wpdb;
217 $table_name = $wpdb->prefix . "lrsync";
218 $upload_dir = wp_upload_dir();
219 $newfile = wp_unique_filename( $upload_dir["path"], $lrinfo->lr_file );
220 $newpath = trailingslashit( $upload_dir["path"] ) . $newfile;
221 if ( !@rename( $tmp_path, $newpath ) )
222 {
223 $this->error = new IXR_Error( 403, __( "Could not copy the file." ) );
224 return false;
225 }
226 $wp_upload_dir = wp_upload_dir();
227 if ( !$wp_id = wp_insert_attachment( array(
228 'guid' => $wp_upload_dir['url'] . '/' . basename( $newpath ),
229 'post_title' => $lrinfo->lr_title,
230 'post_content' => $lrinfo->lr_desc,
231 'post_excerpt' => $lrinfo->lr_caption,
232 'post_mime_type' => $lrinfo->type,
233 'post_status' => "inherit",
234 ), $newpath ) ) {
235 $this->error = new IXR_Error( 403, __( "Could not insert attachment for " . $newpath ) );
236 return false;
237 }
238 $attach_data = wp_generate_attachment_metadata( $wp_id, $newpath );
239 wp_update_attachment_metadata( $wp_id, $attach_data );
240
241 // Create Alt Text
242 update_post_meta( $wp_id, '_wp_attachment_image_alt', $lrinfo->lr_alt_text );
243
244 // Support for WP Retina 2x
245 if ( function_exists( 'wr2x_generate_images' ) ) {
246 wr2x_generate_images( $attach_data );
247 }
248
249 $wpdb->insert( $table_name,
250 array(
251 'wp_id' => $wp_id,
252 'lr_id' => ( $lrinfo->lr_id == "" || $lrinfo->lr_id == null ) ? -1 : $lrinfo->lr_id,
253 'lr_file' => $lrinfo->lr_file,
254 'lastsync' => current_time('mysql')
255 )
256 );
257 return true;
258 }
259
260 function sync_media( $lrinfo, $tmp_path ) {
261 global $wpdb;
262 $table_name = $wpdb->prefix . "lrsync";
263 $sync_files = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE lr_id = %d", $lrinfo->lr_id ), OBJECT );
264
265 if ( $tmp_path == null || empty( $tmp_path ) ) {
266 $this->error = new IXR_Error( 403, __( "The file was not uploaded." ) );
267 return false;
268 }
269
270 if ( !$sync_files ) {
271 if ( !$this->sync_media_add( $lrinfo, $tmp_path ) )
272 return false;
273 }
274 else {
275 foreach ( $sync_files as $sync ) {
276 $this->sync_media_update( $lrinfo, $tmp_path, $sync );
277 }
278 unlink( $tmp_path );
279 }
280
281 // Returns only one result even if there are many.
282 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE lr_id = %d", $lrinfo->lr_id ), OBJECT );
283 $info = Meow_WPLR_LRInfo::fromRow( $sync );
284 return $info;
285 }
286
287 function get_image_sizes() {
288 $sizes = array();
289 global $_wp_additional_image_sizes;
290 foreach (get_intermediate_image_sizes() as $s) {
291 $crop = false;
292 if (isset($_wp_additional_image_sizes[$s])) {
293 $width = intval($_wp_additional_image_sizes[$s]['width']);
294 $height = intval($_wp_additional_image_sizes[$s]['height']);
295 $crop = $_wp_additional_image_sizes[$s]['crop'];
296 } else {
297 $width = get_option($s.'_size_w');
298 $height = get_option($s.'_size_h');
299 $crop = get_option($s.'_crop');
300 }
301 $sizes[$s] = array( 'width' => $width, 'height' => $height, 'crop' => $crop );
302 }
303 return $sizes;
304 }
305
306 // Returns link info for a file at this path
307 function linkinfo_upload( $path, $meta = null ) {
308 $I = PHasher::Instance();
309 $exif = null;
310 if ( $meta == null) {
311 $meta = wp_read_image_metadata( $path );
312 $exif = ( isset( $meta, $meta["created_timestamp"] ) && (int)$meta["created_timestamp"] > 0 ) ? date( "Y/m/d H:i:s", $meta["created_timestamp"] ) : null;
313 }
314 else if ( isset( $meta, $meta["image_meta"], $meta["image_meta"]["created_timestamp"] ) && (int)$meta["image_meta"]["created_timestamp"] > 0 ) {
315 $exif = date( "Y/m/d H:i:s", $meta["image_meta"]["created_timestamp"] );
316 }
317 return array(
318 'wp_phash' => $I->HashAsString( $I->HashImage( $path, 0, 0, 16 ), true ),
319 'wp_exif' => $exif
320 );
321 }
322
323 // Returns link info to help LR to find the original image
324 function linkinfo_media( $wp_id ) {
325 if ( !wp_attachment_is_image( $wp_id ) ) {
326 $this->error = new IXR_Error( 403, __( "Attachment " . ($wp_id ? $wp_id : "[null]") . " does not exist or is not an image." ) );
327 return false;
328 }
329 $linkinfo = $this->linkinfo_upload( get_attached_file( $wp_id ), wp_get_attachment_metadata( $wp_id ) );
330 return array(
331 'wp_id' => $wp_id,
332 'wp_url' => wp_get_attachment_url( $wp_id ),
333 'wp_phash' => $linkinfo["wp_phash"],
334 'wp_exif' => $linkinfo["wp_exif"]
335 );
336 }
337
338 function list_unlinks( $allfields = false ) {
339 global $wpdb;
340 $table_name = $wpdb->prefix . "lrsync";
341 $potentials = array();
342
343 if ( $allfields ) {
344 $posts = $wpdb->get_results( "SELECT * FROM $wpdb->posts p
345 WHERE post_status = 'inherit'
346 AND post_mime_type = 'image/jpeg'
347 AND p.ID NOT IN (SELECT wp_id FROM $table_name)
348 ORDER BY p.ID DESC" );
349 }
350 else {
351 $posts = $wpdb->get_col( "SELECT p.ID FROM $wpdb->posts p
352 WHERE post_status = 'inherit'
353 AND post_mime_type = 'image/jpeg'
354 AND p.ID NOT IN (SELECT wp_id FROM $table_name)
355 ORDER BY p.ID DESC" );
356 }
357
358 foreach ( $posts as $post ) {
359 if ( $allfields ) {
360 if ( !wp_attachment_is_image( $post->ID ) )
361 continue;
362 array_push( $potentials, $post );
363 }
364 else {
365 if ( !wp_attachment_is_image( $post ) )
366 continue;
367 array_push( $potentials, $post );
368 }
369 }
370 return $potentials;
371 }
372
373 /*
374 UTILS FUNCTIONS
375 */
376
377 function b64_to_file( $str ) {
378 $tmpHandle = tmpfile();
379 $metaDatas = stream_get_meta_data($tmpHandle);
380 $file = $metaDatas['uri'];
381 fclose($tmpHandle);
382 $ifp = fopen( $file, "wb" );
383 fwrite( $ifp, base64_decode( $str ) );
384 fclose( $ifp );
385 return $file;
386 }
387
388 /*
389 MEDIA LIBRARY COLUMN
390 */
391
392 function html_for_media( $wpid, $sync = null ) {
393 $html = "";
394 if ( !$sync ) {
395 $html .= "<div>Unknown</div>";
396 $html .= "<div>
397 <small>LR ID:
398 <input type='text' class='wplr-sync-lrid-input' id='wplrsync-link-" . $wpid . "'></input>
399 <span class='wplr-sync-ok-button' onclick='wplrsync_link($wpid)'>Link</span>
400 </small></div>";
401 }
402 else {
403 if ( $sync->lr_id > 0 ) {
404 $html .= "<div style='color: #006EFF;'>Enabled</div>";
405
406 if ( !strtotime( $sync->lastsync ) )
407 $html .= "<div style='color: #0BF;'><small>Never synced.</small></div>";
408 else {
409 if ( date('Ymd') == date('Ymd', strtotime( $sync->lastsync )) )
410 $html .= "<div><small>Synced at " . date("g:ia", strtotime( $sync->lastsync )) . "</small></div>";
411 else
412 $html .= "<div><small>Synced on " . date("Y/m/d", strtotime( $sync->lastsync )) . "</small></div>";
413 }
414 $html .= "<div><small>LR ID: " . $sync->lr_id . "</small></div>";
415 }
416 else if ( $sync->lr_id == 0 ) {
417 $html .= "<div style='color: gray;'>Ignored</div>";
418 }
419 $html .= "<small><span class='wplr-sync-ok-button' onclick='wplrsync_unlink($sync->lr_id, $wpid)'>(undo)</span></small>";
420 }
421 return $html;
422 }
423
424 function wplrsync_unlink() {
425 $this->wplrsync_ajax_link_unlink(true);
426 }
427
428 function wplrsync_link() {
429 $this->wplrsync_ajax_link_unlink();
430 }
431
432 function wplrsync_ajax_link_unlink( $is_unlink = false ) {
433 if ( !current_user_can('upload_files') ) {
434 echo json_encode( array( 'success' => false, 'message' => "You do not have the roles to perform this action." ) );
435 die;
436 }
437 if ( !isset( $_POST['lr_id'] ) || $_POST['lr_id'] == "" || !isset( $_POST['wp_id'] ) || empty( $_POST['wp_id'] ) ) {
438 echo json_encode( array( 'success' => false, 'message' => "Some information is missing." ) );
439 die;
440 }
441
442 $lr_id = intval( $_POST['lr_id'] );
443 $wp_id = intval( $_POST['wp_id'] );
444
445 $sync = null;
446 if ( $is_unlink ) {
447 if ( $this->unlink_media( $lr_id, $wp_id ) ) {
448 echo json_encode( array(
449 'success' => true,
450 'html' => $this->html_for_media( $wp_id, null )
451 ) );
452 }
453 else {
454 echo json_encode( array(
455 'success' => false,
456 'message' => $this->error || "Unknown error."
457 ) );
458 }
459 }
460 else {
461 $sync = $this->link_media( $lr_id, $wp_id );
462 if ( $sync ) {
463 echo json_encode( array(
464 'success' => true,
465 'html' => $this->html_for_media( $wp_id, $sync )
466 ) );
467 }
468 else {
469 echo json_encode( array(
470 'success' => false,
471 'message' => $this->error || "Unknown error."
472 ) );
473 }
474 }
475 die();
476 }
477
478 function admin_head() {
479 echo '
480 <style type="text/css">
481
482 .wplr-sync-info {
483 line-height: 14px;
484 }
485
486 .wplr-sync-lrid-input {
487 width: 60px;
488 font-size: 10px;
489 font-weight: bold;
490 color: black !important;
491 }
492
493 .wplr-sync-ok-button {
494 color: #5E5E5E;
495 }
496
497 .wplr-sync-ok-button:hover {
498 cursor: pointer;
499 color: #2ea2cc;
500 }
501
502 </style>
503
504 <script>
505
506 function wplrsync_handle_response( wp_id, response ) {
507 reply = jQuery.parseJSON(response);
508 if ( reply.success ) {
509 // Remove box (if in WP/LR Dashboard)
510 jQuery("#wplr-image-box-" + wp_id).remove();
511 // Update row (if in Media Library)
512 jQuery("#wplrsync-media-" + wp_id).html(reply.html);
513 }
514 else {
515 alert(reply.message);
516 }
517 }
518
519 function wplrsync_unlink( lr_id, wp_id ) {
520 var data = { action: "wplrsync_unlink", lr_id: lr_id, wp_id: wp_id };
521 jQuery.post(ajaxurl, data, function (response) {
522 wplrsync_handle_response( wp_id, response );
523 });
524 }
525
526 function wplrsync_link( wp_id ) {
527 lr_id = jQuery("#wplrsync-link-" + wp_id).val();
528 var data = { action: "wplrsync_link", lr_id: lr_id, wp_id: wp_id };
529 jQuery.post(ajaxurl, data, function (response) {
530 wplrsync_handle_response( wp_id, response );
531 });
532 }
533 </script>
534 ';
535 }
536
537 function manage_media_columns( $cols ) {
538 $cols["WP/LR Sync"] = "LR Sync";
539 return $cols;
540 }
541
542 function manage_media_custom_column( $column_name, $wpid ) {
543 global $wpdb;
544 $table_name = $wpdb->prefix . "lrsync";
545 if ( $column_name != 'WP/LR Sync' )
546 return;
547 $meta = wp_get_attachment_metadata( $wpid );
548 if ( !($meta && isset( $meta['width'] ) && isset( $meta['height'] )) ) {
549 return;
550 }
551 $sync = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE wp_id = %d", $wpid ), OBJECT );
552
553 echo "<div id='wplrsync-media-" . $wpid . "' class='wplr-sync-info'>";
554 echo $this->html_for_media( $wpid, $sync );
555 echo "</div>";
556
557 }
558 }
559
560 ?>