Image Watermark - Version 1.6.0

Version Description

  • New: Image backup functionality, thanks to JoryHogeveen
  • New: Option to remove watermark (if backup is available)
Download this release

Release Info

Developer dfactory
Plugin Icon 128x128 Image Watermark
Version 1.6.0
Comparing to
See all releases

Code changes from version 1.5.6 to 1.6.0

css/image-watermark.css CHANGED
@@ -8,7 +8,7 @@
8
  .image-watermark-settings .df-credits form input { margin: 0; padding: 0; }
9
  .image-watermark-settings { margin-right: 300px; }
10
  .image-watermark-settings hr, .df-credits hr { border: solid #eee; border-width: 1px 0 0; clear: both; height: 0; }
11
- .image-watermark-settings form { float: left; min-width: 463px; width: auto; }
12
  .image-watermark-settings fieldset span.description { margin-bottom: 8px; margin-top: 4px; display: block; }
13
  .image-watermark-settings.ui-button { margin-bottom: 5px; }
14
  .image-watermark-settings .description { font-size: 13px; margin-bottom: 8px; }
@@ -19,7 +19,38 @@
19
  .image-watermark-settings { margin-right: 0; }
20
  }
21
 
 
 
 
 
 
22
  #cpt-select { margin-top: 5px; }
23
  .wplike-slider span.middle { width: 150px; }
24
  .wplike-slider span.left { margin-right: 10px; }
25
- .wplike-slider span.right { margin-left: 10px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  .image-watermark-settings .df-credits form input { margin: 0; padding: 0; }
9
  .image-watermark-settings { margin-right: 300px; }
10
  .image-watermark-settings hr, .df-credits hr { border: solid #eee; border-width: 1px 0 0; clear: both; height: 0; }
11
+ .image-watermark-settings form { float: left; min-width: 100%; width: auto; }
12
  .image-watermark-settings fieldset span.description { margin-bottom: 8px; margin-top: 4px; display: block; }
13
  .image-watermark-settings.ui-button { margin-bottom: 5px; }
14
  .image-watermark-settings .description { font-size: 13px; margin-bottom: 8px; }
19
  .image-watermark-settings { margin-right: 0; }
20
  }
21
 
22
+ /* Larger sizes */
23
+ @media only screen and (min-width: 959px) {
24
+ .df-credits { position: fixed; right: 0; margin: 0 20px; }
25
+ }
26
+
27
  #cpt-select { margin-top: 5px; }
28
  .wplike-slider span.middle { width: 150px; }
29
  .wplike-slider span.left { margin-right: 10px; }
30
+ .wplike-slider span.right { margin-left: 10px; }
31
+
32
+ #image_watermark_buttons {
33
+ margin: 10px 0;
34
+ }
35
+
36
+ .iw-overlay .spinner {
37
+ margin: 0;
38
+ height: 20px;
39
+ width: 40px;
40
+ padding: 0;
41
+ }
42
+
43
+ div.iw-notice {
44
+ margin: 12px 0;
45
+ }
46
+
47
+ .iw-watermark-action {
48
+ text-decoration: none;
49
+ }
50
+ .delete-watermark, .media-frame a.delete-watermark {
51
+ color: #bc0b0b;
52
+ }
53
+
54
+ .delete-watermark:hover, .delete-watermark:focus, .media-frame a.delete-watermark:hover, .media-frame a.delete-watermark:focus {
55
+ color: #f00;
56
+ }
image-watermark.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Image Watermark
4
  Description: Image Watermark allows you to automatically watermark images uploaded to the WordPress Media Library and bulk watermark previously uploaded images.
5
- Version: 1.5.6
6
  Author: dFactory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/image-watermark/
@@ -32,7 +32,7 @@ define( 'IMAGE_WATERMARK_PATH', plugin_dir_path( __FILE__ ) );
32
  * Image Watermark class.
33
  *
34
  * @class Image_Watermark
35
- * @version 1.5.6
36
  */
37
  final class Image_Watermark {
38
 
@@ -48,6 +48,8 @@ final class Image_Watermark {
48
  'image/pjpeg',
49
  'image/png'
50
  );
 
 
51
  public $extensions;
52
  public $defaults = array(
53
  'options' => array(
@@ -77,8 +79,12 @@ final class Image_Watermark {
77
  'draganddrop' => 0,
78
  'forlogged' => 0,
79
  ),
 
 
 
 
80
  ),
81
- 'version' => '1.5.6'
82
  );
83
  public $options = array();
84
 
@@ -97,16 +103,55 @@ final class Image_Watermark {
97
  add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
98
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
99
  add_action( 'admin_print_scripts', array( $this, 'admin_print_scripts' ), 20 );
 
100
  add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
101
- add_action( 'load-upload.php', array( $this, 'apply_watermark_bulk_action' ) );
102
  add_action( 'admin_init', array( $this, 'update_plugin' ) );
103
  add_action( 'admin_init', array( $this, 'check_extensions' ) );
104
  add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
 
 
105
 
106
  // filters
107
  add_filter( 'plugin_row_meta', array( $this, 'plugin_extend_links' ), 10, 2 );
108
  add_filter( 'plugin_action_links', array( $this, 'plugin_settings_link' ), 10, 2 );
109
  add_filter( 'wp_handle_upload', array( $this, 'handle_upload_files' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
 
112
  /**
@@ -194,8 +239,15 @@ final class Image_Watermark {
194
  <script type="text/javascript">
195
  jQuery( function( $ ) {
196
  $( document ).ready( function() {
 
 
197
  $( "<option>" ).val( "applywatermark" ).text( "<?php _e( 'Apply watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action']" );
198
  $( "<option>" ).val( "applywatermark" ).text( "<?php _e( 'Apply watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action2']" );
 
 
 
 
 
199
  });
200
  });
201
  </script>
@@ -204,10 +256,21 @@ final class Image_Watermark {
204
  }
205
  }
206
 
 
 
 
 
 
 
 
207
  /**
208
  * Enqueue admin scripts and styles.
209
  */
210
  public function admin_enqueue_scripts( $page ) {
 
 
 
 
211
  if ( $page === 'settings_page_watermark-options' ) {
212
  wp_enqueue_media();
213
 
@@ -238,8 +301,38 @@ final class Image_Watermark {
238
  )
239
  );
240
 
241
- wp_enqueue_style( 'watermark-style', plugins_url( 'css/image-watermark.css', __FILE__ ), array(), $this->defaults['version'] );
242
  wp_enqueue_style( 'wp-like-ui-theme', plugins_url( 'css/wp-like-ui-theme.css', __FILE__ ), array(), $this->defaults['version'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
  }
245
 
@@ -342,21 +435,114 @@ final class Image_Watermark {
342
  return $file;
343
  }
344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  /**
346
  * Apply watermark for selected images on media page.
347
  */
348
- public function apply_watermark_bulk_action() {
349
  global $pagenow;
350
 
351
  if ( $pagenow == 'upload.php' && $this->extension ) {
352
  $wp_list_table = _get_list_table( 'WP_Media_List_Table' );
353
 
354
- // only if manual watermarking is turned on and image watermark is set
355
- if ( $wp_list_table->current_action() === 'applywatermark' && $this->options['watermark_image']['manual_watermarking'] == 1 && $this->options['watermark_image']['url'] != 0 ) {
 
 
 
 
 
 
356
  // security check
357
  check_admin_referer( 'bulk-media' );
358
 
359
- $location = esc_url( remove_query_arg( array( 'watermarked', 'skipped', 'trashed', 'untrashed', 'deleted', 'message', 'ids', 'posted' ), wp_get_referer() ) );
360
 
361
  if ( ! $location ) {
362
  $location = 'upload.php';
@@ -365,27 +551,39 @@ final class Image_Watermark {
365
  $location = esc_url( add_query_arg( 'paged', $wp_list_table->get_pagenum(), $location ) );
366
 
367
  // make sure ids are submitted. depending on the resource type, this may be 'media' or 'ids'
368
- if ( isset( $_REQUEST['media'] ) ) {
369
- $post_ids = array_map( 'intval', $_REQUEST['media'] );
370
- }
371
 
372
  // do we have selected attachments?
373
  if ( $post_ids ) {
374
 
375
- $watermarked = $skipped = 0;
376
 
377
  foreach ( $post_ids as $post_id ) {
378
  $data = wp_get_attachment_metadata( $post_id, false );
379
 
380
  // is this really an image?
381
  if ( in_array( get_post_mime_type( $post_id ), $this->allowed_mime_types ) && is_array( $data ) ) {
382
- $this->apply_watermark( $data, $post_id, 'manual' );
383
- $watermarked ++;
384
- } else
 
 
 
 
 
 
 
 
 
 
 
385
  $skipped ++;
 
386
  }
387
 
388
- $location = esc_url( add_query_arg( array( 'watermarked' => $watermarked, 'skipped' => $skipped ), $location ), null, '' );
389
  }
390
 
391
  wp_redirect( $location );
@@ -431,14 +629,20 @@ final class Image_Watermark {
431
  }
432
  }
433
 
434
- if ( isset( $_REQUEST['watermarked'], $_REQUEST['skipped'] ) && $post_type === 'attachment' ) {
435
- $watermarked = (int) $_REQUEST['watermarked'];
436
- $skipped = (int) $_REQUEST['skipped'];
 
437
 
438
  if ( $watermarked === 0 ) {
439
  echo '<div class="error"><p>' . __( 'Watermark could not be applied to selected files or no valid images (JPEG, PNG) were selected.', 'image-watermark' ) . ($skipped > 0 ? ' ' . __( 'Images skipped', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
440
- } else {
441
  echo '<div class="updated"><p>' . sprintf( _n( 'Watermark was succesfully applied to 1 image.', 'Watermark was succesfully applied to %s images.', $watermarked, 'image-watermark' ), number_format_i18n( $watermarked ) ) . ($skipped > 0 ? ' ' . __( 'Skipped files', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
 
 
 
 
 
442
  }
443
 
444
  $_SERVER['REQUEST_URI'] = esc_url( remove_query_arg( array( 'watermarked', 'skipped' ), $_SERVER['REQUEST_URI'] ) );
@@ -488,7 +692,8 @@ final class Image_Watermark {
488
  * Apply watermark to selected image sizes.
489
  *
490
  * @param array $data
491
- * @param int|string $attachment_id Attachment ID or 'manual'
 
492
  * @return array
493
  */
494
  public function apply_watermark( $data, $attachment_id, $method = '' ) {
@@ -512,8 +717,16 @@ final class Image_Watermark {
512
 
513
  $upload_dir = wp_upload_dir();
514
 
515
- // is this really an iamge?
516
  if ( getimagesize( $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $data['file'] ) !== false ) {
 
 
 
 
 
 
 
 
517
  // loop through active image sizes
518
  foreach ( $this->options['watermark_on'] as $image_size => $active_size ) {
519
 
@@ -531,20 +744,70 @@ final class Image_Watermark {
531
  continue 2;
532
  }
533
 
534
- do_action( 'iw_before_apply_watermark' );
535
 
536
  // apply watermark
537
  $this->do_watermark( $attachment_id, $filepath, $image_size, $upload_dir );
538
 
539
- do_action( 'iw_after_apply_watermark' );
540
  }
541
  }
 
 
542
  }
543
 
544
  // pass forward attachment metadata
545
  return $data;
546
  }
547
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  /**
549
  * Apply watermark to image.
550
  *
@@ -638,6 +901,39 @@ final class Image_Watermark {
638
  }
639
  }
640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641
  /**
642
  * Get image resource accordingly to mimetype.
643
  *
@@ -670,6 +966,77 @@ final class Image_Watermark {
670
  return $image;
671
  }
672
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  /**
674
  * Calculate watermark dimensions.
675
  *
@@ -953,4 +1320,4 @@ function Image_Watermark() {
953
  return $instance;
954
  }
955
 
956
- Image_Watermark();
2
  /*
3
  Plugin Name: Image Watermark
4
  Description: Image Watermark allows you to automatically watermark images uploaded to the WordPress Media Library and bulk watermark previously uploaded images.
5
+ Version: 1.6.0
6
  Author: dFactory
7
  Author URI: http://www.dfactory.eu/
8
  Plugin URI: http://www.dfactory.eu/plugins/image-watermark/
32
  * Image Watermark class.
33
  *
34
  * @class Image_Watermark
35
+ * @version 1.6.0
36
  */
37
  final class Image_Watermark {
38
 
48
  'image/pjpeg',
49
  'image/png'
50
  );
51
+ private $is_watermarked_metakey = 'iw-is-watermarked';
52
+ public $is_backup_folder_writable = null;
53
  public $extensions;
54
  public $defaults = array(
55
  'options' => array(
79
  'draganddrop' => 0,
80
  'forlogged' => 0,
81
  ),
82
+ 'backup' => array(
83
+ 'backup_image' => true,
84
+ 'backup_quality' => 90,
85
+ ),
86
  ),
87
+ 'version' => '1.6.0'
88
  );
89
  public $options = array();
90
 
103
  add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
104
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
105
  add_action( 'admin_print_scripts', array( $this, 'admin_print_scripts' ), 20 );
106
+ add_action( 'wp_enqueue_media', array( $this, 'wp_enqueue_media' ) );
107
  add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
108
+ add_action( 'load-upload.php', array( $this, 'watermark_bulk_action' ) );
109
  add_action( 'admin_init', array( $this, 'update_plugin' ) );
110
  add_action( 'admin_init', array( $this, 'check_extensions' ) );
111
  add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
112
+ add_action( 'delete_attachment', array( $this, 'delete_attachment' ) );
113
+ add_action( 'wp_ajax_iw_watermark_bulk_action', array( $this, 'watermark_action_ajax' ) );
114
 
115
  // filters
116
  add_filter( 'plugin_row_meta', array( $this, 'plugin_extend_links' ), 10, 2 );
117
  add_filter( 'plugin_action_links', array( $this, 'plugin_settings_link' ), 10, 2 );
118
  add_filter( 'wp_handle_upload', array( $this, 'handle_upload_files' ) );
119
+ add_filter( 'attachment_fields_to_edit', array( $this, 'attachment_fields_to_edit' ), 10, 2 );
120
+
121
+ // Define our backup location
122
+ $upload_dir = wp_upload_dir();
123
+ define( 'IMAGE_WATERMARK_BACKUP_DIR', apply_filters( 'image_watermark_backup_dir', $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'iw-backup' ) );
124
+
125
+ // create backup folder and security if enabled
126
+ if ( $this->options['backup']['backup_image'] ) {
127
+
128
+ if ( is_writable( $upload_dir['basedir'] ) ) {
129
+ $this->is_backup_folder_writable = true;
130
+
131
+ // Create backup folder ( if it exists this returns true: https://codex.wordpress.org/Function_Reference/wp_mkdir_p )
132
+ $backup_folder_created = wp_mkdir_p( IMAGE_WATERMARK_BACKUP_DIR );
133
+
134
+ // Check if the folder exists and is writable
135
+ if ( $backup_folder_created && is_writable( IMAGE_WATERMARK_BACKUP_DIR ) ) {
136
+ // Check if the htaccess file exists
137
+ if ( ! file_exists( IMAGE_WATERMARK_BACKUP_DIR . DIRECTORY_SEPARATOR . '.htaccess' ) ) {
138
+ // htaccess security
139
+ file_put_contents( IMAGE_WATERMARK_BACKUP_DIR . DIRECTORY_SEPARATOR . '.htaccess', 'deny from all' );
140
+ }
141
+ } else {
142
+ $this->is_backup_folder_writable = false;
143
+ }
144
+ } else {
145
+ $this->is_backup_folder_writable = false;
146
+ }
147
+ if ( true !== $this->is_backup_folder_writable ) {
148
+ // Disable backup setting
149
+ $this->options['backup']['backup_image'] = false;
150
+ update_option( 'image_watermark_options', $this->options );
151
+ }
152
+
153
+ add_action( 'admin_notices', array( $this, 'filder_writable_admin_notice' ) );
154
+ }
155
  }
156
 
157
  /**
239
  <script type="text/javascript">
240
  jQuery( function( $ ) {
241
  $( document ).ready( function() {
242
+ var backup = <?php echo (int)$this->options['backup']['backup_image']; ?>;
243
+
244
  $( "<option>" ).val( "applywatermark" ).text( "<?php _e( 'Apply watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action']" );
245
  $( "<option>" ).val( "applywatermark" ).text( "<?php _e( 'Apply watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action2']" );
246
+
247
+ if ( backup === 1 ) {
248
+ $( "<option>" ).val( "removewatermark" ).text( "<?php _e( 'Remove watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action']" );
249
+ $( "<option>" ).val( "removewatermark" ).text( "<?php _e( 'Remove watermark', 'image-watermark' ); ?>" ).appendTo( "select[name='action2']" );
250
+ }
251
  });
252
  });
253
  </script>
256
  }
257
  }
258
 
259
+ /**
260
+ * Enqueue admin scripts and styles.
261
+ */
262
+ public function wp_enqueue_media( $page ) {
263
+ wp_enqueue_style( 'watermark-style', plugins_url( 'css/image-watermark.css', __FILE__ ), array(), $this->defaults['version'] );
264
+ }
265
+
266
  /**
267
  * Enqueue admin scripts and styles.
268
  */
269
  public function admin_enqueue_scripts( $page ) {
270
+ global $pagenow;
271
+
272
+ wp_register_style( 'watermark-style', plugins_url( 'css/image-watermark.css', __FILE__ ), array(), $this->defaults['version'] );
273
+
274
  if ( $page === 'settings_page_watermark-options' ) {
275
  wp_enqueue_media();
276
 
301
  )
302
  );
303
 
 
304
  wp_enqueue_style( 'wp-like-ui-theme', plugins_url( 'css/wp-like-ui-theme.css', __FILE__ ), array(), $this->defaults['version'] );
305
+ wp_enqueue_style( 'watermark-style' );
306
+
307
+ wp_enqueue_script( 'postbox' );
308
+ }
309
+
310
+ if ( $pagenow === 'upload.php' ) {
311
+ wp_enqueue_style( 'watermark-style' );
312
+ }
313
+
314
+ // I've omitted $pagenow === 'upload.php' because the image modal could be loaded in various places
315
+ if ( $this->options['watermark_image']['manual_watermarking'] == 1 ) {
316
+
317
+ wp_enqueue_script( 'watermark-admin-image-actions', plugins_url( '/js/admin-image-actions.js', __FILE__ ), array( 'jquery' ), $this->defaults['version'], true );
318
+
319
+ wp_localize_script(
320
+ 'watermark-admin-image-actions',
321
+ 'iwImageActionArgs',
322
+ array(
323
+ 'backup_image' => (int)$this->options['backup']['backup_image'],
324
+ '_nonce' => wp_create_nonce( 'image-watermark' ),
325
+ '__applied_none' => __( 'Watermark could not be applied to selected files or no valid images (JPEG, PNG) were selected.', 'image-watermark' ),
326
+ '__applied_one' => __( 'Watermark was succesfully applied to 1 image.', 'image-watermark' ),
327
+ '__applied_multi' => __( 'Watermark was succesfully applied to %s images.', 'image-watermark' ),
328
+ '__removed_none' => __( 'Watermark could not be removed from selected files or no valid images (JPEG, PNG) were selected.', 'image-watermark' ),
329
+ '__removed_one' => __( 'Watermark was succesfully removed from 1 image.', 'image-watermark' ),
330
+ '__removed_multi' => __( 'Watermark was succesfully removed from %s images.', 'image-watermark' ),
331
+ '__skipped' => __( 'Skipped files', 'image-watermark' ),
332
+ '__running' => __( 'Bulk action is currently running, please wait.', 'image-watermark' ),
333
+ '__dismiss' => __( 'Dismiss this notice.' ), // Wordpress default string
334
+ )
335
+ );
336
  }
337
  }
338
 
435
  return $file;
436
  }
437
 
438
+ /**
439
+ * Add watermark buttons on attachment image locations
440
+ */
441
+ public function attachment_fields_to_edit( $form_fields, $post ) {
442
+
443
+ if ( $this->options['watermark_image']['manual_watermarking'] == 1 && $this->options['backup']['backup_image'] ) {
444
+
445
+ $data = wp_get_attachment_metadata( $post->ID, false );
446
+
447
+ // is this really an image?
448
+ if ( in_array( get_post_mime_type( $post->ID ), $this->allowed_mime_types ) && is_array( $data ) ) {
449
+ $form_fields['image_watermark'] = array(
450
+ 'show_in_edit' => false,
451
+ 'tr' => '
452
+ <div id="image_watermark_buttons"' . ( get_post_meta( $post->ID, $this->is_watermarked_metakey, true ) ? ' class="watermarked"' : '' ) . ' data-id="' . $post->ID . '" style="display: none;">
453
+ <label class="setting">
454
+ <span class="name">' . __( 'Image Watermark', 'image-watermark' ) . '</span>
455
+ <span class="value" style="width: 63%"><a href="#" class="iw-watermark-action" data-action="applywatermark" data-id="' . $post->ID . '">' . __( 'Apply watermark', 'image-watermark' ) . '</a> | <a href="#" class="iw-watermark-action delete-watermark" data-action="removewatermark" data-id="' . $post->ID . '">' . __( 'Remove watermark', 'image-watermark' ) . '</a></span>
456
+ </label>
457
+ <div class="clear"></div>
458
+ </div>
459
+ <script>
460
+ jQuery( document ).ready( function ( $ ) {
461
+ if ( typeof watermarkImageActions != "undefined" ) {
462
+ $( "#image_watermark_buttons" ).show();
463
+ }
464
+ });
465
+ </script>'
466
+ );
467
+ }
468
+ }
469
+ return $form_fields;
470
+ }
471
+
472
+ /**
473
+ * Apply watermark for selected images on media page.
474
+ */
475
+ public function watermark_action_ajax() {
476
+ // Security & data check
477
+ if ( ! defined( 'DOING_AJAX' )
478
+ || ! DOING_AJAX
479
+ || ! isset( $_POST['_iw_nonce'] )
480
+ || ! isset( $_POST['iw-action'] )
481
+ || ! isset( $_POST['attachment_id'] )
482
+ || ! is_numeric( $_POST['attachment_id'] )
483
+ || ! wp_verify_nonce( $_POST['_iw_nonce'], 'image-watermark' )
484
+ || ! $this->options['backup']['backup_image']
485
+ )
486
+ wp_send_json_error( __('Cheatin uh?', 'image-watermark') );
487
+
488
+ $post_id = (int) $_POST['attachment_id'];
489
+ $action = false;
490
+
491
+ switch ( $_POST['iw-action'] ) {
492
+ case 'applywatermark': $action = 'applywatermark'; break;
493
+ case 'removewatermark': $action = 'removewatermark'; break;
494
+ }
495
+
496
+ // only if manual watermarking is turned and we have a valid action
497
+ // if the action is NOT "removewatermark" we also require a watermark image to be set
498
+ if ( $post_id > 0 && $action && $this->options['watermark_image']['manual_watermarking'] == 1 && ( $this->options['watermark_image']['url'] != 0 || $action == 'removewatermark' ) ) {
499
+
500
+ $data = wp_get_attachment_metadata( $post_id, false );
501
+
502
+ // is this really an image?
503
+ if ( in_array( get_post_mime_type( $post_id ), $this->allowed_mime_types ) && is_array( $data ) ) {
504
+
505
+ if ( $action === 'applywatermark' ) {
506
+ $this->apply_watermark( $data, $post_id, 'manual' );
507
+ wp_send_json_success( 'watermarked' );
508
+
509
+ } elseif ( $action === 'removewatermark' ) {
510
+ $success = $this->remove_watermark( $data, $post_id, 'manual' );
511
+ if ( $success ) {
512
+ wp_send_json_success( 'watermarkremoved' );
513
+ } else {
514
+ wp_send_json_success( 'skipped' );
515
+ }
516
+ }
517
+ } else {
518
+ wp_send_json_success( 'skipped' );
519
+ }
520
+ }
521
+
522
+ wp_send_json_error( __('Cheatin uh?', 'image-watermark') );
523
+ }
524
+
525
  /**
526
  * Apply watermark for selected images on media page.
527
  */
528
+ public function watermark_bulk_action() {
529
  global $pagenow;
530
 
531
  if ( $pagenow == 'upload.php' && $this->extension ) {
532
  $wp_list_table = _get_list_table( 'WP_Media_List_Table' );
533
 
534
+ $action = false;
535
+ switch ( $wp_list_table->current_action() ) {
536
+ case 'applywatermark': $action = 'applywatermark'; break;
537
+ case 'removewatermark': $action = 'removewatermark'; break;
538
+ }
539
+ // only if manual watermarking is turned and we have a valid action
540
+ // if the action is NOT "removewatermark" we also require a watermark image to be set
541
+ if ( $action && $this->options['watermark_image']['manual_watermarking'] == 1 && ( $this->options['watermark_image']['url'] != 0 || $action == 'removewatermark' ) ) {
542
  // security check
543
  check_admin_referer( 'bulk-media' );
544
 
545
+ $location = esc_url( remove_query_arg( array( 'watermarked', 'watermarkremoved', 'skipped', 'trashed', 'untrashed', 'deleted', 'message', 'ids', 'posted' ), wp_get_referer() ) );
546
 
547
  if ( ! $location ) {
548
  $location = 'upload.php';
551
  $location = esc_url( add_query_arg( 'paged', $wp_list_table->get_pagenum(), $location ) );
552
 
553
  // make sure ids are submitted. depending on the resource type, this may be 'media' or 'ids'
554
+ if ( isset( $_REQUEST['media'] ) ) {
555
+ $post_ids = array_map( 'intval', $_REQUEST['media'] );
556
+ }
557
 
558
  // do we have selected attachments?
559
  if ( $post_ids ) {
560
 
561
+ $watermarked = $watermarkremoved = $skipped = 0;
562
 
563
  foreach ( $post_ids as $post_id ) {
564
  $data = wp_get_attachment_metadata( $post_id, false );
565
 
566
  // is this really an image?
567
  if ( in_array( get_post_mime_type( $post_id ), $this->allowed_mime_types ) && is_array( $data ) ) {
568
+ if ( $action === 'applywatermark' ) {
569
+ $this->apply_watermark( $data, $post_id, 'manual' );
570
+ $watermarked ++;
571
+ $watermarkremoved = -1;
572
+ } elseif ( $action === 'removewatermark' ) {
573
+ $success = $this->remove_watermark( $data, $post_id, 'manual' );
574
+ if ( $success ) {
575
+ $watermarkremoved ++;
576
+ } else {
577
+ $skipped ++;
578
+ }
579
+ $watermarked = -1;
580
+ }
581
+ } else {
582
  $skipped ++;
583
+ }
584
  }
585
 
586
+ $location = esc_url( add_query_arg( array( 'watermarked' => $watermarked, 'watermarkremoved' => $watermarkremoved, 'skipped' => $skipped ), $location ), null, '' );
587
  }
588
 
589
  wp_redirect( $location );
629
  }
630
  }
631
 
632
+ if ( isset( $_REQUEST['watermarked'], $_REQUEST['watermarkremoved'], $_REQUEST['skipped'] ) && $post_type === 'attachment' ) {
633
+ $watermarked = (int) $_REQUEST['watermarked'];
634
+ $watermarkremoved = (int) $_REQUEST['watermarkremoved'];
635
+ $skipped = (int) $_REQUEST['skipped'];
636
 
637
  if ( $watermarked === 0 ) {
638
  echo '<div class="error"><p>' . __( 'Watermark could not be applied to selected files or no valid images (JPEG, PNG) were selected.', 'image-watermark' ) . ($skipped > 0 ? ' ' . __( 'Images skipped', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
639
+ } elseif ( $watermarked > 0 ) {
640
  echo '<div class="updated"><p>' . sprintf( _n( 'Watermark was succesfully applied to 1 image.', 'Watermark was succesfully applied to %s images.', $watermarked, 'image-watermark' ), number_format_i18n( $watermarked ) ) . ($skipped > 0 ? ' ' . __( 'Skipped files', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
641
+ }
642
+ if ( $watermarkremoved === 0 ) {
643
+ echo '<div class="error"><p>' . __( 'Watermark could not be removed from selected files or no valid images (JPEG, PNG) were selected.', 'image-watermark' ) . ($skipped > 0 ? ' ' . __( 'Images skipped', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
644
+ } elseif ( $watermarkremoved > 0 ) {
645
+ echo '<div class="updated"><p>' . sprintf( _n( 'Watermark was succesfully removed from 1 image.', 'Watermark was succesfully removed from %s images.', $watermarkremoved, 'image-watermark' ), number_format_i18n( $watermarkremoved ) ) . ($skipped > 0 ? ' ' . __( 'Skipped files', 'image-watermark' ) . ': ' . $skipped . '.' : '') . '</p></div>';
646
  }
647
 
648
  $_SERVER['REQUEST_URI'] = esc_url( remove_query_arg( array( 'watermarked', 'skipped' ), $_SERVER['REQUEST_URI'] ) );
692
  * Apply watermark to selected image sizes.
693
  *
694
  * @param array $data
695
+ * @param int|string $attachment_id Attachment ID
696
+ * @param string $method
697
  * @return array
698
  */
699
  public function apply_watermark( $data, $attachment_id, $method = '' ) {
717
 
718
  $upload_dir = wp_upload_dir();
719
 
720
+ // is this really an image?
721
  if ( getimagesize( $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $data['file'] ) !== false ) {
722
+ // Remove the watermark if this image was allready watermarked, not === because the database can't hold booleans
723
+ if ( get_post_meta( $attachment_id, $this->is_watermarked_metakey ) == true )
724
+ $this->remove_watermark( $data, $attachment_id, 'manual' );
725
+
726
+ // create a backup if this is enabled
727
+ if ( $this->options['backup']['backup_image'] )
728
+ $this->do_backup( $data, $upload_dir, $attachment_id );
729
+
730
  // loop through active image sizes
731
  foreach ( $this->options['watermark_on'] as $image_size => $active_size ) {
732
 
744
  continue 2;
745
  }
746
 
747
+ do_action( 'iw_before_apply_watermark', $attachment_id, $image_size );
748
 
749
  // apply watermark
750
  $this->do_watermark( $attachment_id, $filepath, $image_size, $upload_dir );
751
 
752
+ do_action( 'iw_after_apply_watermark', $attachment_id, $image_size );
753
  }
754
  }
755
+ // Update watermark status
756
+ update_post_meta( $attachment_id, $this->is_watermarked_metakey, true );
757
  }
758
 
759
  // pass forward attachment metadata
760
  return $data;
761
  }
762
 
763
+ /**
764
+ * Remove watermark to selected image sizes.
765
+ *
766
+ * @param array $data
767
+ * @param int|string $attachment_id Attachment ID
768
+ * @param string $method
769
+ * @return array
770
+ */
771
+ private function remove_watermark( $data, $attachment_id, $method = '' ) {
772
+ if ( $method !== 'manual' ) {
773
+ return $data;
774
+ }
775
+
776
+ $upload_dir = wp_upload_dir();
777
+
778
+ // is this really an image?
779
+ if ( getimagesize( $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $data['file'] ) !== false ) {
780
+
781
+ // Live file path (probably watermarked)
782
+ $filepath = get_attached_file( $attachment_id );
783
+
784
+ // Backup file path (not watermarked)
785
+ $backup_filepath = $this->get_image_backup_filepath( get_post_meta( $attachment_id, '_wp_attached_file', true ) );
786
+
787
+ // Replace the image in uploads with our backup if one exists
788
+ if ( file_exists( $backup_filepath ) ) {
789
+ if ( ! copy( $backup_filepath, $filepath ) ) {
790
+ // Failed to copy
791
+ }
792
+ }
793
+ // If no backup exists, use the current full-size image to regenerate
794
+ // If the "full" size is enabled for watermarks and no backup has been made the removal of watermarks can't be done
795
+
796
+ // Regenerate metadata (and thumbs)
797
+ $metadata = wp_generate_attachment_metadata( $attachment_id, $filepath );
798
+
799
+ // Update attachment metadata with new metadata
800
+ wp_update_attachment_metadata( $attachment_id, $metadata );
801
+
802
+ // Update watermark status
803
+ update_post_meta( $attachment_id, $this->is_watermarked_metakey, false );
804
+
805
+ // Return the attachment metadata
806
+ return wp_get_attachment_metadata( $attachment_id );
807
+ }
808
+ return false;
809
+ }
810
+
811
  /**
812
  * Apply watermark to image.
813
  *
901
  }
902
  }
903
 
904
+ /**
905
+ * Make a backup of the full size image
906
+ *
907
+ * $param
908
+ * $return bool
909
+ */
910
+ private function do_backup( $data, $upload_dir, $attachment_id ) {
911
+ // get the filepath for the backup image we're creating
912
+ $backup_filepath = $this->get_image_backup_filepath( $data['file'] );
913
+
914
+ // Make sure the backup isn't created yet
915
+ if ( ! file_exists( $backup_filepath ) ) {
916
+ // The original (full size) image
917
+ $filepath = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $data['file'];
918
+ $mime = wp_check_filetype( $filepath );
919
+
920
+ // get image resource
921
+ $image = $this->get_image_resource( $filepath, $mime['type'] );
922
+
923
+ if ( false !== $image ) {
924
+ // create backup directory if needed
925
+ wp_mkdir_p( $this->get_image_backup_folder_location( $data['file'] ) );
926
+
927
+ // save backup image
928
+ $this->save_image_file( $image, $mime['type'], $backup_filepath, $this->options['backup']['backup_quality'] );
929
+
930
+ // clear backup memory
931
+ imagedestroy( $image );
932
+ $image = null;
933
+ }
934
+ }
935
+ }
936
+
937
  /**
938
  * Get image resource accordingly to mimetype.
939
  *
966
  return $image;
967
  }
968
 
969
+ /**
970
+ * Get image filename without the uploaded folders
971
+ *
972
+ * @param string $filepath
973
+ * @return string $filename
974
+ */
975
+ private function get_image_filename( $filepath ) {
976
+ return basename( $filepath );
977
+ }
978
+
979
+ /**
980
+ * Get image backup folder
981
+ *
982
+ * @param string $filepath
983
+ * @return string $image_backup_folder
984
+ */
985
+ private function get_image_backup_folder_location( $filepath ) {
986
+ $path = explode( DIRECTORY_SEPARATOR, $filepath );
987
+ array_pop( $path );
988
+ $path = implode( DIRECTORY_SEPARATOR, $path );
989
+ // Multisite?
990
+ /*if ( is_multisite() && ! is_main_site() ) {
991
+ $path = 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . $path;
992
+ }*/
993
+ return IMAGE_WATERMARK_BACKUP_DIR . DIRECTORY_SEPARATOR . $path;
994
+ }
995
+
996
+ /**
997
+ * Get image resource from the backup folder (if available).
998
+ *
999
+ * @param string $filepath
1000
+ * @return string $backup_filepath
1001
+ */
1002
+ private function get_image_backup_filepath( $filepath ) {
1003
+ // Multisite?
1004
+ /*if ( is_multisite() && ! is_main_site() ) {
1005
+ $filepath = 'sites' . DIRECTORY_SEPARATOR . get_current_blog_id() . DIRECTORY_SEPARATOR . $filepath;
1006
+ }*/
1007
+ return IMAGE_WATERMARK_BACKUP_DIR . DIRECTORY_SEPARATOR . $filepath;
1008
+ }
1009
+
1010
+ /**
1011
+ * Delete the image backup if one exists
1012
+ *
1013
+ * @param int $attachment_id
1014
+ * @return bool $force_delete
1015
+ */
1016
+ public function delete_attachment( $attachment_id ) {
1017
+ // see get_attached_file() in wp-includes/post.php
1018
+ $filepath = get_post_meta( $attachment_id, '_wp_attached_file', true );
1019
+ $backup_filepath = $this->get_image_backup_filepath( $filepath );
1020
+
1021
+ if ( file_exists( $backup_filepath ) ) {
1022
+ unlink( $backup_filepath );
1023
+ }
1024
+ }
1025
+
1026
+ /**
1027
+ * Create admin notice when we can't create the backup folder
1028
+ * @return void
1029
+ */
1030
+ function filder_writable_admin_notice() {
1031
+ if ( current_user_can('manage_options') && true !== $this->is_backup_folder_writable ) {
1032
+ ?>
1033
+ <div class="notice notice-error is-dismissible">
1034
+ <p><?php _e( 'Image Watermark', 'image-watermark' ); ?> - <?php _e( 'Image backup', 'image-watermark' ); ?>: <?php _e( "Your uploads folder is not writable so we can't create a backup of your image uploads. We've disabled this feature for now.", 'image-watermark' ); ?></p>
1035
+ </div>
1036
+ <?php
1037
+ }
1038
+ }
1039
+
1040
  /**
1041
  * Calculate watermark dimensions.
1042
  *
1320
  return $instance;
1321
  }
1322
 
1323
+ Image_Watermark();
includes/class-settings.php CHANGED
@@ -80,6 +80,11 @@ class Image_Watermark_Settings {
80
  add_settings_field( 'iw_protection_right_click', __( 'Right click', 'image-watermark' ), array( $this, 'iw_protection_right_click' ), 'image_watermark_options', 'image_watermark_protection' );
81
  add_settings_field( 'iw_protection_drag_drop', __( 'Drag and drop', 'image-watermark' ), array( $this, 'iw_protection_drag_drop' ), 'image_watermark_options', 'image_watermark_protection' );
82
  add_settings_field( 'iw_protection_logged', __( 'Logged-in users', 'image-watermark' ), array( $this, 'iw_protection_logged' ), 'image_watermark_options', 'image_watermark_protection' );
 
 
 
 
 
83
  }
84
 
85
  /**
@@ -104,7 +109,7 @@ class Image_Watermark_Settings {
104
  <h2>' . __( 'Image Watermark', 'image-watermark' ) . '</h2>';
105
 
106
  echo '
107
- <div class="image-watermark-settings">
108
  <div class="df-sidebar">
109
  <div class="df-credits">
110
  <h3 class="hndle">' . __( 'Image Watermark', 'image-watermark' ) . ' ' . Image_Watermark()->defaults['version'] . '</h3>
@@ -127,10 +132,11 @@ class Image_Watermark_Settings {
127
  <p class="df-link inner">' . __( 'Created by', 'image-watermark' ) . ' <a href="http://www.dfactory.eu/?utm_source=image-watermark-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="dFactory - Quality plugins for WordPress"><img src="' . plugins_url( '../images/logo-dfactory.png', __FILE__ ) . '" title="dFactory - Quality plugins for WordPress" alt="dFactory - Quality plugins for WordPress" /></a></p>
128
  </div>
129
  </div>
130
- <form action="options.php" method="post">';
131
-
 
132
  settings_fields( 'image_watermark_options' );
133
- do_settings_sections( 'image_watermark_options' );
134
 
135
  echo '
136
  <p class="submit">';
@@ -142,10 +148,23 @@ class Image_Watermark_Settings {
142
 
143
  echo '
144
  </p>
 
145
  </form>
146
  </div>
147
  <div class="clear"></div>
148
  </div>';
 
 
 
 
 
 
 
 
 
 
 
 
149
  }
150
 
151
  /**
@@ -200,6 +219,7 @@ class Image_Watermark_Settings {
200
  $input['watermark_image']['frontend_active'] = isset( $_POST['iw_options']['watermark_image']['frontend_active'] ) ? ((bool) $_POST['iw_options']['watermark_image']['frontend_active'] == 1 ? true : false) : Image_Watermark()->defaults['options']['watermark_image']['frontend_active'];
201
  $input['watermark_image']['deactivation_delete'] = isset( $_POST['iw_options']['watermark_image']['deactivation_delete'] ) ? ((bool) $_POST['iw_options']['watermark_image']['deactivation_delete'] == 1 ? true : false) : Image_Watermark()->defaults['options']['watermark_image']['deactivation_delete'];
202
 
 
203
  $positions = array();
204
 
205
  foreach ( $this->watermark_positions['y'] as $position_y ) {
@@ -224,6 +244,9 @@ class Image_Watermark_Settings {
224
  $input['image_protection']['draganddrop'] = isset( $_POST['iw_options']['image_protection']['draganddrop'] ) ? ((bool) $_POST['iw_options']['image_protection']['draganddrop'] == 1 ? true : false) : Image_Watermark()->defaults['options']['image_protection']['draganddrop'];
225
  $input['image_protection']['forlogged'] = isset( $_POST['iw_options']['image_protection']['forlogged'] ) ? ((bool) $_POST['iw_options']['image_protection']['forlogged'] == 1 ? true : false) : Image_Watermark()->defaults['options']['image_protection']['forlogged'];
226
 
 
 
 
227
  add_settings_error( 'iw_settings_errors', 'iw_settings_saved', __( 'Settings saved.', 'image-watermark' ), 'updated' );
228
  } elseif ( isset( $_POST['reset_image_watermark_options'] ) ) {
229
 
@@ -423,9 +446,9 @@ class Image_Watermark_Settings {
423
  }
424
  ?>
425
  <div class="iw_watermark_image">
426
- <input id="upload_image" type="hidden" name="iw_options[watermark_image][url]" value="<?php echo (int) Image_Watermark()->options['watermark_image']['url']; ?>" />
427
- <input id="upload_image_button" type="button" class="button button-secondary" value="<?php echo __( 'Select image', 'image-watermark' ); ?>" />
428
- <input id="turn_off_image_button" type="button" class="button button-secondary" value="<?php echo __( 'Remove image', 'image-watermark' ); ?>" <?php if ( $image_selected === false ) echo 'disabled="disabled"'; ?>/>
429
  <p class="description"><?php _e( 'You have to save changes after the selection or removal of the image.', 'image-watermark' ); ?></p>
430
  </div>
431
  <?php
@@ -604,4 +627,69 @@ class Image_Watermark_Settings {
604
  </label>
605
  <?php
606
  }
607
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  add_settings_field( 'iw_protection_right_click', __( 'Right click', 'image-watermark' ), array( $this, 'iw_protection_right_click' ), 'image_watermark_options', 'image_watermark_protection' );
81
  add_settings_field( 'iw_protection_drag_drop', __( 'Drag and drop', 'image-watermark' ), array( $this, 'iw_protection_drag_drop' ), 'image_watermark_options', 'image_watermark_protection' );
82
  add_settings_field( 'iw_protection_logged', __( 'Logged-in users', 'image-watermark' ), array( $this, 'iw_protection_logged' ), 'image_watermark_options', 'image_watermark_protection' );
83
+
84
+ // Backup
85
+ add_settings_section( 'image_watermark_backup', __( 'Image backup', 'image-watermark' ), '', 'image_watermark_options' );
86
+ add_settings_field( 'iw_backup_image', __( 'Backup full size image', 'image-watermark' ), array( $this, 'iw_backup_image' ), 'image_watermark_options', 'image_watermark_backup' );
87
+ add_settings_field( 'iw_backup_image_quality', __( 'Backup image quality', 'image-watermark' ), array( $this, 'iw_backup_image_quality' ), 'image_watermark_options', 'image_watermark_backup' );
88
  }
89
 
90
  /**
109
  <h2>' . __( 'Image Watermark', 'image-watermark' ) . '</h2>';
110
 
111
  echo '
112
+ <div class="image-watermark-settings metabox-holder">
113
  <div class="df-sidebar">
114
  <div class="df-credits">
115
  <h3 class="hndle">' . __( 'Image Watermark', 'image-watermark' ) . ' ' . Image_Watermark()->defaults['version'] . '</h3>
132
  <p class="df-link inner">' . __( 'Created by', 'image-watermark' ) . ' <a href="http://www.dfactory.eu/?utm_source=image-watermark-settings&utm_medium=link&utm_campaign=created-by" target="_blank" title="dFactory - Quality plugins for WordPress"><img src="' . plugins_url( '../images/logo-dfactory.png', __FILE__ ) . '" title="dFactory - Quality plugins for WordPress" alt="dFactory - Quality plugins for WordPress" /></a></p>
133
  </div>
134
  </div>
135
+ </div>
136
+ <form action="options.php" method="post">
137
+ <div id="main-sortables" class="meta-box-sortables ui-sortable">';
138
  settings_fields( 'image_watermark_options' );
139
+ $this->do_settings_sections( 'image_watermark_options' );
140
 
141
  echo '
142
  <p class="submit">';
148
 
149
  echo '
150
  </p>
151
+ </div>
152
  </form>
153
  </div>
154
  <div class="clear"></div>
155
  </div>';
156
+ ?>
157
+ <script type="text/javascript">
158
+ //<![CDATA[
159
+ jQuery(document).ready( function ($) {
160
+ // close postboxes that should be closed
161
+ $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
162
+ // postboxes setup
163
+ postboxes.add_postbox_toggles('watermark-options');
164
+ });
165
+ //]]>
166
+ </script>
167
+ <?php
168
  }
169
 
170
  /**
219
  $input['watermark_image']['frontend_active'] = isset( $_POST['iw_options']['watermark_image']['frontend_active'] ) ? ((bool) $_POST['iw_options']['watermark_image']['frontend_active'] == 1 ? true : false) : Image_Watermark()->defaults['options']['watermark_image']['frontend_active'];
220
  $input['watermark_image']['deactivation_delete'] = isset( $_POST['iw_options']['watermark_image']['deactivation_delete'] ) ? ((bool) $_POST['iw_options']['watermark_image']['deactivation_delete'] == 1 ? true : false) : Image_Watermark()->defaults['options']['watermark_image']['deactivation_delete'];
221
 
222
+
223
  $positions = array();
224
 
225
  foreach ( $this->watermark_positions['y'] as $position_y ) {
244
  $input['image_protection']['draganddrop'] = isset( $_POST['iw_options']['image_protection']['draganddrop'] ) ? ((bool) $_POST['iw_options']['image_protection']['draganddrop'] == 1 ? true : false) : Image_Watermark()->defaults['options']['image_protection']['draganddrop'];
245
  $input['image_protection']['forlogged'] = isset( $_POST['iw_options']['image_protection']['forlogged'] ) ? ((bool) $_POST['iw_options']['image_protection']['forlogged'] == 1 ? true : false) : Image_Watermark()->defaults['options']['image_protection']['forlogged'];
246
 
247
+ $input['backup']['backup_image'] = isset( $_POST['iw_options']['backup']['backup_image'] );
248
+ $input['backup']['backup_quality'] = isset( $_POST['iw_options']['backup']['backup_quality'] ) ? (int) $_POST['iw_options']['backup']['backup_quality'] : Image_Watermark()->defaults['options']['backup']['backup_quality'];
249
+
250
  add_settings_error( 'iw_settings_errors', 'iw_settings_saved', __( 'Settings saved.', 'image-watermark' ), 'updated' );
251
  } elseif ( isset( $_POST['reset_image_watermark_options'] ) ) {
252
 
446
  }
447
  ?>
448
  <div class="iw_watermark_image">
449
+ <input id="iw_upload_image" type="hidden" name="iw_options[watermark_image][url]" value="<?php echo (int) Image_Watermark()->options['watermark_image']['url']; ?>" />
450
+ <input id="iw_upload_image_button" type="button" class="button button-secondary" value="<?php echo __( 'Select image', 'image-watermark' ); ?>" />
451
+ <input id="iw_turn_off_image_button" type="button" class="button button-secondary" value="<?php echo __( 'Remove image', 'image-watermark' ); ?>" <?php if ( $image_selected === false ) echo 'disabled="disabled"'; ?>/>
452
  <p class="description"><?php _e( 'You have to save changes after the selection or removal of the image.', 'image-watermark' ); ?></p>
453
  </div>
454
  <?php
627
  </label>
628
  <?php
629
  }
630
+
631
+ /**
632
+ * Backup the original image
633
+ */
634
+ public function iw_backup_image() {
635
+ ?>
636
+ <label for="iw_backup_size_full">
637
+ <input id="iw_backup_size_full" type="checkbox" <?php checked( ! empty( Image_Watermark()->options['backup']['backup_image'] ), true, true ); ?> value="1" name="iw_options[backup][backup_image]">
638
+ <?php echo __( 'Backup the full size image.', 'image-watermark' ); ?>
639
+ </label>
640
+ <?php
641
+ }
642
+
643
+ /**
644
+ * Image backup quality option.
645
+ */
646
+ public function iw_backup_image_quality() {
647
+ ?>
648
+ <fieldset id="iw_backup_image_quality">
649
+ <div>
650
+ <input type="text" id="iw_backup_quality_input" maxlength="3" class="hide-if-js" name="iw_options[backup][backup_quality]" value="<?php echo Image_Watermark()->options['backup']['backup_quality']; ?>" />
651
+ <div class="wplike-slider">
652
+ <span class="left hide-if-no-js">0</span><span class="middle" id="iw_backup_quality_span" title="<?php echo Image_Watermark()->options['backup']['backup_quality']; ?>"></span><span class="right hide-if-no-js">100</span>
653
+ </div>
654
+ </div>
655
+ </fieldset>
656
+ <p class="description"><?php _e( 'Set output image quality.', 'image-watermark' ); ?></p>
657
+ <?php
658
+ }
659
+
660
+ /**
661
+ * This function is similar to the function in the Settings API, only the output HTML is changed.
662
+ * Print out the settings fields for a particular settings section
663
+ *
664
+ * @global $wp_settings_fields Storage array of settings fields and their pages/sections
665
+ *
666
+ * @since 0.1
667
+ *
668
+ * @param string $page Slug title of the admin page who's settings fields you want to show.
669
+ * @param string $section Slug title of the settings section who's fields you want to show.
670
+ */
671
+ function do_settings_sections( $page ) {
672
+ global $wp_settings_sections, $wp_settings_fields;
673
+
674
+ if ( ! isset( $wp_settings_sections[$page] ) )
675
+ return;
676
+
677
+ foreach ( (array) $wp_settings_sections[$page] as $section ) {
678
+ echo '<div id="" class="stuffbox postbox '.$section['id'].'">';
679
+ echo '<button type="button" class="handlediv button-link" aria-expanded="true"><span class="screen-reader-text">' . __('Toggle panel', 'image-watermark') . '</span><span class="toggle-indicator" aria-hidden="true"></span></button>';
680
+ if ( $section['title'] )
681
+ echo "<h3 class=\"hndle\"><span>{$section['title']}</span></h3>\n";
682
+
683
+ if ( $section['callback'] )
684
+ call_user_func( $section['callback'], $section );
685
+
686
+ if ( ! isset( $wp_settings_fields ) || !isset( $wp_settings_fields[$page] ) || !isset( $wp_settings_fields[$page][$section['id']] ) )
687
+ continue;
688
+ echo '<div class="inside"><table class="form-table">';
689
+ do_settings_fields( $page, $section['id'] );
690
+ echo '</table></div>';
691
+ echo '</div>';
692
+ }
693
+ }
694
+
695
+ }
index.php CHANGED
@@ -1,2 +1,2 @@
1
- <?php
2
  // Silence is golden.
1
+ <?php
2
  // Silence is golden.
js/admin-image-actions.js ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ jQuery( document ).ready( function ( $ ) {
3
+
4
+ /**
5
+ * wp_localize_script object: iwImageActionArgs
6
+ *
7
+ * Params:
8
+ *
9
+ * _nonce
10
+ * __applied_none => 'Watermark could not be applied to selected files or no valid images (JPEG, PNG) were selected.'
11
+ * __applied_one => 'Watermark was succesfully applied to 1 image.
12
+ * __applied_multi => 'Watermark was succesfully applied to %s images.'
13
+ * __removed_none => 'Watermark could not be removed from selected files or no valid images (JPEG, PNG) were selected.'
14
+ * __removed_one => 'Watermark was succesfully removed from 1 image.'
15
+ * __removed_multi => 'Watermark was succesfully removed from %s images.'
16
+ * __skipped => 'Skipped files'
17
+ * __running => 'Bulk action is currently running, please wait.'
18
+ * __dismiss => 'Dismiss this notice.' // Wordpress default string
19
+ *
20
+ */
21
+
22
+ watermarkImageActions = {
23
+ running: false,
24
+ action_location: '',
25
+ action: '',
26
+ response: '',
27
+ selected: [],
28
+ successCount: 0,
29
+ skippedCount: 0,
30
+
31
+ init: function() {
32
+
33
+ // Normal (list) mode
34
+ $(document).on('click', '.bulkactions input#doaction', function(e) {
35
+ // Get the selected bulk action
36
+ action = $(this).parent().children('select').val();
37
+
38
+ if ( ! iwImageActionArgs.backup_image && action === 'removewatermark' ) {
39
+ return;
40
+ }
41
+
42
+ // Validate action
43
+ if ( 'applywatermark' == action || 'removewatermark' == action ) {
44
+ // Stop default
45
+ e.preventDefault();
46
+
47
+ // Is this script running?
48
+ if ( false === watermarkImageActions.running ) {
49
+ // No! set it on running
50
+ watermarkImageActions.running = true;
51
+
52
+ // store current action
53
+ watermarkImageActions.action = action;
54
+
55
+ // store current location where the action was fired
56
+ watermarkImageActions.action_location = 'upload-list';
57
+
58
+ // store selected attachment id's
59
+ $('.wp-list-table .check-column input:checkbox:checked').each(function(){
60
+ watermarkImageActions.selected.push( $(this).val() );
61
+ });
62
+
63
+ // remove current notices
64
+ $('.iw-notice').slideUp('fast', function() {
65
+ $(this).remove();
66
+ });
67
+
68
+ // begin the update!
69
+ watermarkImageActions.post_loop();
70
+
71
+ } else {
72
+ // script is running, can't run two at the same time
73
+ watermarkImageActions.notice( 'iw-notice error', iwImageActionArgs.__running, false );
74
+ }
75
+
76
+ }
77
+ });
78
+
79
+ // Media modal or edit attachment screen mode
80
+ $(document).on('click', '#image_watermark_buttons a.iw-watermark-action', function(e) {
81
+ // Get the selected bulk action
82
+ action = $(this).attr('data-action');
83
+ id = $(this).attr('data-id');
84
+
85
+ // Validate action
86
+ if ( 'applywatermark' == action || 'removewatermark' == action && ! isNaN( id ) ) {
87
+ // Stop default
88
+ e.preventDefault();
89
+
90
+ // store current action
91
+ watermarkImageActions.action = action;
92
+
93
+ // Is this script running?
94
+ if ( false === watermarkImageActions.running ) {
95
+ // No! set it on running
96
+ watermarkImageActions.running = true;
97
+
98
+ // store current action
99
+ watermarkImageActions.action = action;
100
+
101
+ // store current location where the action was fired
102
+ if ( $(this).parents('.media-modal ').length ) {
103
+ watermarkImageActions.action_location = 'media-modal';
104
+ } else {
105
+ watermarkImageActions.action_location = 'edit';
106
+ }
107
+
108
+ // store attachment id
109
+ watermarkImageActions.selected.push( id );
110
+
111
+ // remove current notices
112
+ $('.iw-notice').slideUp( 'fast', function() {
113
+ $( this ).remove();
114
+ });
115
+
116
+ // begin the update!
117
+ watermarkImageActions.post_loop();
118
+ } else {
119
+ // script is running, can't run two at the same time
120
+ watermarkImageActions.notice( 'iw-notice error', iwMediaModal.__running, false );
121
+ }
122
+ }
123
+ });
124
+
125
+ // Since these are added later we'll need to enable dismissing again
126
+ $(document).on('click', '.iw-notice.is-dismissible .notice-dismiss', function() {
127
+ $(this).parents('.iw-notice').slideUp( 'fast', function() {
128
+ $(this).remove();
129
+ } );
130
+ });
131
+
132
+ },
133
+
134
+ post_loop: function() {
135
+ // do we have selected attachments?
136
+ if ( watermarkImageActions.selected.length ) {
137
+
138
+ // take the first id
139
+ id = watermarkImageActions.selected[ 0 ];
140
+
141
+ // check for a valid ID (needs to be numeric)
142
+ if ( ! isNaN( id ) ) {
143
+
144
+ // Show loading icon
145
+ watermarkImageActions.row_image_feedback( 'loading', id );
146
+
147
+ // post data
148
+ data = {
149
+ '_iw_nonce': iwImageActionArgs._nonce,
150
+ 'action': 'iw_watermark_bulk_action',
151
+ 'iw-action': watermarkImageActions.action,
152
+ 'attachment_id': id
153
+ };
154
+
155
+ // the ajax post!
156
+ $.post( ajaxurl, data, function( response ) {
157
+ // show result
158
+ watermarkImageActions.result( response, id );
159
+ // remove this ID/key from the selected attachments
160
+ watermarkImageActions.selected.splice( 0, 1 );
161
+ // Redo this function
162
+ watermarkImageActions.post_loop();
163
+
164
+ $('.iw-overlay').first().each( function() {
165
+ $(this).fadeOut( 'fast', function() {
166
+ $(this).remove();
167
+
168
+ if ( response.data === 'watermarked' ) {
169
+ $( '#image_watermark_buttons .value' ).append( '<span class="dashicons dashicons-yes" style="font-size: 24px;float: none;min-width: 28px;padding: 0;margin: 0; display: none;"></span>' );
170
+ $( '#image_watermark_buttons .value .dashicons' ).fadeIn( 'fast' );
171
+ } else if ( response.data === 'watermarkremoved' ) {
172
+ $( '#image_watermark_buttons .value' ).append( '<span class="dashicons dashicons-yes" style="font-size: 24px;float: none;min-width: 28px;padding: 0;margin: 0; display: none;"></span>' );
173
+ $( '#image_watermark_buttons .value .dashicons' ).fadeIn( 'fast' );
174
+ }
175
+
176
+ $( '#image_watermark_buttons .value .dashicons' ).delay( 1500 ).fadeOut( 'fast', function() {
177
+ $( this ).remove();
178
+ } );
179
+ } );
180
+ } );
181
+ } );
182
+
183
+ } else {
184
+ // ID is not valid so remove this key from the selected attachments
185
+ watermarkImageActions.selected.splice( 0, 1 );
186
+ // Redo this function
187
+ watermarkImageActions.post_loop();
188
+ }
189
+ } else {
190
+ // All is done, reset this "class"
191
+ watermarkImageActions.reset();
192
+ }
193
+ },
194
+
195
+ result: function( response, id ) {
196
+
197
+ // Was the ajax post successful?
198
+ if ( true === response.success ) {
199
+
200
+ // defaults
201
+ type = false;
202
+ message = '';
203
+ // store response data
204
+ watermarkImageActions.response = response.data;
205
+
206
+ // Check what kind of action is done (watermarked, watermarkremoved or skipped)
207
+ switch ( response.data ) {
208
+ case 'watermarked':
209
+ // The css classes for the notice
210
+ type = 'iw-notice updated iw-watermarked';
211
+ // another successful update
212
+ watermarkImageActions.successCount += 1;
213
+ // did we have more success updates?
214
+ if ( 1 < watermarkImageActions.successCount ) {
215
+ //yes
216
+ message = iwImageActionArgs.__applied_multi.replace( '%s', watermarkImageActions.successCount );
217
+ } else {
218
+ //no
219
+ message = iwImageActionArgs.__applied_one;
220
+ }
221
+ // update the row feedback
222
+ watermarkImageActions.row_image_feedback( 'success', id );
223
+ // reload the image
224
+ watermarkImageActions.reload_image( id );
225
+ break;
226
+ case 'watermarkremoved':
227
+ // The css classes for the notice
228
+ type = 'iw-notice updated iw-watermarkremoved';
229
+ // another successful update
230
+ watermarkImageActions.successCount += 1;
231
+ // did we have more success updates?
232
+ if ( 1 < watermarkImageActions.successCount ) {
233
+ //yes
234
+ message = iwImageActionArgs.__removed_multi.replace( '%s', watermarkImageActions.successCount );
235
+ } else {
236
+ //no
237
+ message = iwImageActionArgs.__removed_one;
238
+ }
239
+ // update the row feedback
240
+ watermarkImageActions.row_image_feedback( 'success', id );
241
+ // reload the image
242
+ watermarkImageActions.reload_image( id );
243
+ break;
244
+ case 'skipped':
245
+ // The css classes for the notice
246
+ type = 'iw-notice error iw-skipped';
247
+ // another skipped update
248
+ watermarkImageActions.skippedCount += 1;
249
+ // adjust the message with the number of skipped updates
250
+ message = iwImageActionArgs.__skipped + ': ' + watermarkImageActions.skippedCount;
251
+ // update the row feedback
252
+ watermarkImageActions.row_image_feedback( 'error', id );
253
+ break;
254
+ }
255
+ if ( false !== type ) {
256
+ // we have a valid terun type, show the notice! (Overwrite current notice if available)
257
+ watermarkImageActions.notice( type, message, true );
258
+ }
259
+ } else {
260
+ // No success...
261
+ watermarkImageActions.notice( 'iw-notice error', response.data, false );
262
+ // update the row feedback
263
+ watermarkImageActions.row_image_feedback( 'error', id );
264
+ }
265
+
266
+ },
267
+
268
+ row_image_feedback: function( type, id ) {
269
+ var css = {},
270
+ cssinner = {},
271
+ container_selector;
272
+
273
+ switch ( watermarkImageActions.action_location ) {
274
+ case 'upload-list':
275
+ container_selector = '.wp-list-table #post-'+id+' .media-icon';
276
+ css = {
277
+ display: 'table',
278
+ width: $(container_selector).width() + 'px',
279
+ height: $(container_selector).height() + 'px',
280
+ top: '0',
281
+ left: '0',
282
+ position: 'absolute',
283
+ font: 'normal normal normal dashicons',
284
+ background: 'rgba(255,255,255,0.75)',
285
+ content: ''
286
+ };
287
+ cssinner = {
288
+ 'vertical-align': 'middle',
289
+ 'text-align': 'center',
290
+ display: 'table-cell',
291
+ width: '100%',
292
+ height: '100%',
293
+ };
294
+ break;
295
+
296
+ case 'edit':
297
+ container_selector = '.wp_attachment_holder #thumbnail-head-'+id+'';
298
+ css = {
299
+ display: 'table',
300
+ width: $(container_selector+' img').width() + 'px',
301
+ height: $(container_selector+' img').height() + 'px',
302
+ top: '0',
303
+ left: '0',
304
+ position: 'absolute',
305
+ font: 'normal normal normal dashicons',
306
+ background: 'rgba(255,255,255,0.75)',
307
+ content: ''
308
+ };
309
+ cssinner = {
310
+ 'vertical-align': 'middle',
311
+ 'text-align': 'center',
312
+ display: 'table-cell',
313
+ width: '100%',
314
+ height: '100%',
315
+ };
316
+ break;
317
+
318
+ case 'media-modal':
319
+ container_selector = '.media-modal #image_watermark_buttons[data-id="'+id+'"] .value';
320
+ css = {
321
+ 'float': 'none'
322
+ };
323
+ cssinner = {
324
+ 'float': 'none'
325
+ };
326
+ break;
327
+
328
+ default:
329
+ return false;
330
+ }
331
+
332
+ // css rules
333
+ $( container_selector ).css( 'position', 'relative' );
334
+
335
+ // Only create the element if it doesn't exist
336
+ if ( ! $( container_selector + ' .iw-overlay').length ) {
337
+ $( container_selector ).append( '<span class="iw-overlay"><span class="iw-overlay-inner"></span></span>' );
338
+ }
339
+
340
+ // Overwrite with new data
341
+ $( container_selector + ' .iw-overlay' ).css( css );
342
+ $( container_selector + ' .iw-overlay .iw-overlay-inner' ).css( cssinner );
343
+ $( container_selector + ' .iw-overlay .iw-overlay-inner' ).html( '<span class="spinner is-active"></span>' );
344
+
345
+ if ( watermarkImageActions.action_location === 'media-modal' ) {
346
+ $( container_selector + ' .iw-overlay .iw-overlay-inner .spinner' ).css( { 'float': 'none', 'padding': 0, 'margin': '-4px 0 0 10px' } );
347
+ }
348
+ },
349
+
350
+ notice: function( type, message, overwrite ) {
351
+
352
+ if ( watermarkImageActions.action_location === 'media-modal' ) {
353
+ return;
354
+ }
355
+
356
+ type += ' notice is-dismissible';
357
+
358
+ // Get the prefix based on the action location
359
+ switch ( watermarkImageActions.action_location ) {
360
+ case 'upload-list': prefix = '.wrap > h1'; break;
361
+ default: prefix = '#image_watermark_buttons'; break;
362
+ }
363
+
364
+ // Overwrite the current notice?
365
+ if ( true === overwrite ) {
366
+ selector = false;
367
+
368
+ // Get the selector based on the response
369
+ switch ( watermarkImageActions.response ) {
370
+ case 'watermarked': selector = '.iw-notice.iw-watermarked'; break;
371
+ case 'watermarkremoved': selector = '.iw-notice.iw-watermarkremoved'; break;
372
+ case 'skipped': selector = '.iw-notice.iw-skipped'; break;
373
+ }
374
+ // Do we have a selector and can we find it? If not, just create a new notice
375
+ if ( selector && $('.wrap '+selector+' > p').length ) {
376
+
377
+ // Get the selector based on the action location (not not forget the ending space)
378
+ switch ( watermarkImageActions.action_location ) {
379
+ case 'upload-list': prefix = '.wrap '; break;
380
+ default: prefix = '#image_watermark_buttons '; break;
381
+ }
382
+ $(prefix+selector+' > p').html( message );
383
+ } else {
384
+ $(prefix).after('<div class="' + type + '" style="display: none;"><p>' + message + '</p><button type="button" class="notice-dismiss"><span class="screen-reader-text">' + iwImageActionArgs.__dismiss + '</span></button></div>');
385
+ $('.iw-notice').slideDown('fast');
386
+ }
387
+ } else {
388
+ // create a new notice
389
+ $(prefix).after('<div class="' + type + '" style="display: none;"><p>' + message + '</p><button type="button" class="notice-dismiss"><span class="screen-reader-text">' + iwImageActionArgs.__dismiss + '</span></button></div>');
390
+ $('.iw-notice').slideDown('fast');
391
+ }
392
+
393
+ },
394
+
395
+ reset: function() {
396
+ watermarkImageActions.running = false;
397
+ watermarkImageActions.action = '';
398
+ watermarkImageActions.response = '';
399
+ watermarkImageActions.selected = [];
400
+ watermarkImageActions.successCount = 0;
401
+ watermarkImageActions.skippedCount = 0;
402
+
403
+ // remove the overlay
404
+ setTimeout( function() {
405
+ $( '.iw-overlay' ).each( function() {
406
+ $(this).fadeOut('fast', function() {
407
+ $(this).remove();
408
+ });
409
+ });
410
+ }, 100 );
411
+ },
412
+
413
+ reload_image: function( id ) {
414
+ // reload the images
415
+ time = new Date().getTime();
416
+ selector = false;
417
+ // Get the selector based on the action location
418
+ switch ( watermarkImageActions.action_location ) {
419
+ case 'upload-list': selector = '.wp-list-table #post-'+id+' .image-icon img'; break;
420
+ case 'media-modal': selector = '.attachment-details[data-id="'+id+'"] img, .attachment[data-id="'+id+'"] img'; break;
421
+ case 'edit': selector = '.wp_attachment_holder img'; break;
422
+ }
423
+
424
+ if ( selector ) {
425
+ image = $( selector );
426
+ image.each( function () {
427
+ // Remove the responsive metadata, this prevents reloading the image
428
+ $(this).removeAttr('srcset');
429
+ $(this).removeAttr('sizes');
430
+ // Reload the image (actually a browser hack by adding a time parameter to the image)
431
+ $(this).attr('src', watermarkImageActions.replace_url_param( $(this).attr('src'), 't', time ) );
432
+ });
433
+ }
434
+ },
435
+
436
+ rotate_icon: function( icon ) {
437
+ // This function accepts selectors and objects
438
+ if ( typeof icon == 'string') {
439
+ icon = $( icon );
440
+ }
441
+ // Check for the length of the selected object.
442
+ if ( $( icon.selector ).length ) {
443
+ // Set rotation to 0
444
+ icon.css({
445
+ '-webkit-transform': 'rotate(0deg)',
446
+ '-ms-transform': 'rotate(0deg)',
447
+ 'transform': 'rotate(0deg)',
448
+ 'borderSpacing': '0',
449
+ });
450
+ // Do animation (one rotation)
451
+ icon.animate(
452
+ { borderSpacing: 360 },
453
+ {
454
+ duration: 1000,
455
+ step: function(now, fx) {
456
+ $(this).css('-webkit-transform', 'rotate('+now+'deg)');
457
+ $(this).css('-ms-transform', 'rotate('+now+'deg)');
458
+ $(this).css('transform', 'rotate('+now+'deg)');
459
+ if (now == 360) {
460
+ // Animation finished, stop loop and restart
461
+ icon.stop();
462
+ watermarkImageActions.rotate_icon( icon );
463
+ }
464
+ },
465
+ }
466
+ );
467
+ }
468
+ },
469
+
470
+ replace_url_param: function( url, paramName, paramValue ) {
471
+ var pattern = new RegExp('\\b('+paramName+'=).*?(&|$)');
472
+ if(url.search(pattern)>=0){
473
+ return url.replace(pattern,'$1' + paramValue + '$2');
474
+ }
475
+ return url + (url.indexOf('?')>0 ? '&' : '?') + paramName + '=' + paramValue;
476
+ },
477
+ };
478
+
479
+ // We need that nonce!
480
+ if ( typeof iwImageActionArgs._nonce != 'undefined' ) {
481
+ watermarkImageActions.init();
482
+ }
483
+
484
+ } );
js/admin-settings.js CHANGED
@@ -52,4 +52,17 @@ jQuery( document ).ready( function ( $ ) {
52
  }
53
  } );
54
 
55
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
  } );
54
 
55
+ // quality slider
56
+ $( '#iw_backup_quality_span' ).slider( {
57
+ value: $( '#iw_backup_quality_input' ).val(),
58
+ min: 0,
59
+ max: 100,
60
+ step: 1,
61
+ orientation: 'horizontal',
62
+ slide: function ( e, ui ) {
63
+ $( '#iw_backup_quality_input' ).attr( 'value', ui.value );
64
+ $( '#iw_backup_quality_span' ).attr( 'title', ui.value );
65
+ }
66
+ } );
67
+
68
+ } );
js/admin-upload.js CHANGED
@@ -23,7 +23,7 @@ jQuery( document ).ready( function ( $ ) {
23
 
24
  if ( jQuery.inArray( attachment.attributes.mime, ['image/gif', 'image/jpg', 'image/jpeg', 'image/png'] ) !== -1 ) {
25
 
26
- $( '#upload_image' ).val( attachment.attributes.id );
27
 
28
  if ( $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src' ) !== '' ) {
29
  $( 'div#previewImg_imageDiv img#previewImg_image' ).replaceWith( '<img id="previewImg_image" src="' + attachment.attributes.url + '" alt="" width="300" />' );
@@ -31,7 +31,7 @@ jQuery( document ).ready( function ( $ ) {
31
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', attachment.attributes.url );
32
  }
33
 
34
- $( '#turn_off_image_button' ).removeAttr( 'disabled' );
35
  $( 'div#previewImg_imageDiv img#previewImg_image' ).show();
36
 
37
  var img = new Image();
@@ -43,15 +43,15 @@ jQuery( document ).ready( function ( $ ) {
43
 
44
  } else {
45
 
46
- $( '#turn_off_image_button' ).attr( 'disabled', 'true' );
47
- $( '#upload_image' ).val( 0 );
48
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', '' ).hide();
49
  $( 'p#previewImageInfo' ).html( '<strong>' + iwUploadArgs.notAllowedImg + '</strong>' );
50
 
51
  }
52
  },
53
  init: function () {
54
- $( '#wpbody' ).on( 'click', 'input#upload_image_button', function ( e ) {
55
  e.preventDefault();
56
  watermarkFileUpload.frame().open();
57
  } );
@@ -60,9 +60,9 @@ jQuery( document ).ready( function ( $ ) {
60
 
61
  watermarkFileUpload.init();
62
 
63
- $( document ).on( 'click', '#turn_off_image_button', function ( event ) {
64
  $( this ).attr( 'disabled', 'true' );
65
- $( '#upload_image' ).val( 0 );
66
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', '' ).hide();
67
  $( 'p#previewImageInfo' ).html( iwUploadArgs.noSelectedImg );
68
  } );
23
 
24
  if ( jQuery.inArray( attachment.attributes.mime, ['image/gif', 'image/jpg', 'image/jpeg', 'image/png'] ) !== -1 ) {
25
 
26
+ $( '#iw_upload_image' ).val( attachment.attributes.id );
27
 
28
  if ( $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src' ) !== '' ) {
29
  $( 'div#previewImg_imageDiv img#previewImg_image' ).replaceWith( '<img id="previewImg_image" src="' + attachment.attributes.url + '" alt="" width="300" />' );
31
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', attachment.attributes.url );
32
  }
33
 
34
+ $( '#iw_turn_off_image_button' ).removeAttr( 'disabled' );
35
  $( 'div#previewImg_imageDiv img#previewImg_image' ).show();
36
 
37
  var img = new Image();
43
 
44
  } else {
45
 
46
+ $( '#iw_turn_off_image_button' ).attr( 'disabled', 'true' );
47
+ $( '#iw_upload_image' ).val( 0 );
48
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', '' ).hide();
49
  $( 'p#previewImageInfo' ).html( '<strong>' + iwUploadArgs.notAllowedImg + '</strong>' );
50
 
51
  }
52
  },
53
  init: function () {
54
+ $( '#wpbody' ).on( 'click', 'input#iw_upload_image_button', function ( e ) {
55
  e.preventDefault();
56
  watermarkFileUpload.frame().open();
57
  } );
60
 
61
  watermarkFileUpload.init();
62
 
63
+ $( document ).on( 'click', '#iw_turn_off_image_button', function ( event ) {
64
  $( this ).attr( 'disabled', 'true' );
65
+ $( '#iw_upload_image' ).val( 0 );
66
  $( 'div#previewImg_imageDiv img#previewImg_image' ).attr( 'src', '' ).hide();
67
  $( 'p#previewImageInfo' ).html( iwUploadArgs.noSelectedImg );
68
  } );
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: dfactory
3
  Donate link: http://www.dfactory.eu/
4
  Tags: image, images, picture, photo, watermark, watermarking, protection, image protection, image security, plugin
5
  Requires at least: 3.5
6
- Tested up to: 4.5.2
7
- Stable tag: 1.5.6
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
@@ -53,6 +53,10 @@ No questions yet.
53
 
54
  == Changelog ==
55
 
 
 
 
 
56
  = 1.5.6 =
57
  * New: PHP image processing library option, if more than one available.
58
  * Fix: Manual / Media library watermarking not working.
@@ -157,7 +161,6 @@ Initial release
157
 
158
  == Upgrade Notice ==
159
 
160
- = 1.5.6 =
161
- * New: PHP image processing library option, if more than one available.
162
- * Fix: Manual / Media library watermarking not working.
163
- * Fix: Image sizes not being generated proparly in GD library.
3
  Donate link: http://www.dfactory.eu/
4
  Tags: image, images, picture, photo, watermark, watermarking, protection, image protection, image security, plugin
5
  Requires at least: 3.5
6
+ Tested up to: 4.6
7
+ Stable tag: 1.6.0
8
  License: MIT License
9
  License URI: http://opensource.org/licenses/MIT
10
 
53
 
54
  == Changelog ==
55
 
56
+ = 1.6.0 =
57
+ * New: Image backup functionality, thanks to [JoryHogeveen](https://github.com/JoryHogeveen)
58
+ * New: Option to remove watermark (if backup is available)
59
+
60
  = 1.5.6 =
61
  * New: PHP image processing library option, if more than one available.
62
  * Fix: Manual / Media library watermarking not working.
161
 
162
  == Upgrade Notice ==
163
 
164
+ = 1.6.0 =
165
+ * New: Image backup functionality, thanks to [JoryHogeveen](https://github.com/JoryHogeveen)
166
+ * New: Option to remove watermark (if backup is available)