Compress JPEG & PNG images - Version 3.1.0

Version Description

  • Remaining free compressions shown in settings page.
  • Easier way to upgrade a free account.
  • WPML and WPML Media compatibility in collaboration with the authors of WPML. Make sure to upgrade WPML to version 4.1.
  • Added a notice to the Bulk Optimization page for free accounts with not enough available free compressions.
  • Added a new hook after compression of an image useful for CDN cache flushing.
Download this release

Release Info

Developer TinyPNG
Plugin Icon 128x128 Compress JPEG & PNG images
Version 3.1.0
Comparing to
See all releases

Code changes from version 3.0.1 to 3.1.0

NOTES ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ Note the following when making changes to the plugin:
2
+
3
+ 1. XML-RPC
4
+
5
+ Wordpress can either be used via the web interface or through the official
6
+ Wordpress apps for mobile devices. Wordpress uses XML-RPC internally to
7
+ communicate between the app and the Wordpress admin. Make sure therefore
8
+ that when developing functionality that is linked to functionality available
9
+ in the mobile app that it also works over XML-RPC.
composer.lock CHANGED
@@ -1433,12 +1433,12 @@
1433
  "source": {
1434
  "type": "git",
1435
  "url": "https://github.com/tinify/tinify-php.git",
1436
- "reference": "ce0b3fe4b7490604604294992f41d8ccd91f6cf6"
1437
  },
1438
  "dist": {
1439
  "type": "zip",
1440
- "url": "https://api.github.com/repos/tinify/tinify-php/zipball/ce0b3fe4b7490604604294992f41d8ccd91f6cf6",
1441
- "reference": "ce0b3fe4b7490604604294992f41d8ccd91f6cf6",
1442
  "shasum": ""
1443
  },
1444
  "require": {
@@ -1485,7 +1485,7 @@
1485
  "source": "https://github.com/tinify/tinify-php/tree/create-key",
1486
  "issues": "https://github.com/tinify/tinify-php/issues"
1487
  },
1488
- "time": "2017-07-19 12:34:08"
1489
  },
1490
  {
1491
  "name": "wp-coding-standards/wpcs",
1433
  "source": {
1434
  "type": "git",
1435
  "url": "https://github.com/tinify/tinify-php.git",
1436
+ "reference": "cb76e97b93ef7646c9a24a461687defe1a4d212e"
1437
  },
1438
  "dist": {
1439
  "type": "zip",
1440
+ "url": "https://api.github.com/repos/tinify/tinify-php/zipball/cb76e97b93ef7646c9a24a461687defe1a4d212e",
1441
+ "reference": "cb76e97b93ef7646c9a24a461687defe1a4d212e",
1442
  "shasum": ""
1443
  },
1444
  "require": {
1485
  "source": "https://github.com/tinify/tinify-php/tree/create-key",
1486
  "issues": "https://github.com/tinify/tinify-php/issues"
1487
  },
1488
+ "time": "2018-11-07T11:13:32+00:00"
1489
  },
1490
  {
1491
  "name": "wp-coding-standards/wpcs",
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: TinyPNG
3
  Donate link: https://tinypng.com/
4
  Tags: optimize, compress, shrink, resize, faster, fit, scale, improve, images, picture, pictures, photo, photos, image, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, performance, panda, george, wordpress app, SEO, lossy, wp compress, sitespeed, shortpixel, kraken, PageRank, cheetaho, s3
5
  Requires at least: 3.4
6
- Tested up to: 4.9
7
- Stable tag: 3.0.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -20,20 +20,21 @@ Make your website faster by optimizing your JPEG and PNG images. This plugin aut
20
  * Advanced background optimization to speed up your workflow.
21
  * Optimize individual images already in your media library.
22
  * Easy bulk optimization of your existing media library.
23
- * Resize large original images by setting a maximum width and/or height.
24
  * Display JPEG images more quickly with progressive JPEG encoding.
25
- * Preserve copyright metadata, creation date and GPS location in the original images.
26
  * Supports compression of animated PNG.
27
  * Select which thumbnail sizes of an image may be optimized.
28
  * Multisite support with a single API key.
 
29
  * WooCommerce compatible.
30
  * WP Retina 2x compatible.
31
  * WP Offload S3 compatible.
32
- * See your usage from the media settings and during bulk optimization.
33
- * Color profiles are automatically translated to the standard RGB color space.
34
- * Convert CMYK to RGB to save more space and maximize compatibility.
35
- * Optimize and resize uploads with the WordPress mobile app.
36
  * Dashboard widget with your total savings.
 
37
  * No file size limits.
38
 
39
  = How does it work? =
@@ -42,15 +43,15 @@ After you upload an image to your WordPress site, each resized image is uploaded
42
 
43
  = Getting started =
44
 
45
- Install this plugin and follow the instructions to set up your account. With a regular WordPress installation you can optimize **roughly 100 images each month** for free. The exact total depends on the number of thumbnail sizes that are in use in your WordPress installation. You can change which of the generated thumbnail sizes should be optimized in the *Settings > Compress JPEG & PNG images* page. Once installed you can also switch to a [paid account](https://tinypng.com/dashboard/api) to remove the limits and optimize as many images as you like.
46
 
47
  = Optimizing all your images =
48
 
49
- You can optimize all your JPEG and PNG images at once by going to *Media > Bulk Optimization*. Clicking on the big button will start optimizing all unoptimized images in your media library.
50
 
51
  = Multisite support =
52
 
53
- The plugin is fully multisite compatible and you can set the API key for all sites at once by defining it in the *wp-config.php* file. View the installation instructions for more information.
54
 
55
  = Contact us =
56
 
@@ -128,6 +129,13 @@ A: Yes! After installing the plugin, go to *Media > Bulk Optimization*, and clic
128
  A: You can upgrade to a paid account by adding your *Payment details* on your [account dashboard](https://tinypng.com/dashboard/api). Additional compressions above 500 will then be charged at the end of each month as a one-time fee.
129
 
130
  == Changelog ==
 
 
 
 
 
 
 
131
  = 3.0.1 =
132
  * Fixed bug that caused an error when registering a new account.
133
  * No longer use create_function, which is deprecated in PHP 7.2. The plugin no longer supports PHP 5.2.
3
  Donate link: https://tinypng.com/
4
  Tags: optimize, compress, shrink, resize, faster, fit, scale, improve, images, picture, pictures, photo, photos, image, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, performance, panda, george, wordpress app, SEO, lossy, wp compress, sitespeed, shortpixel, kraken, PageRank, cheetaho, s3
5
  Requires at least: 3.4
6
+ Tested up to: 5.0
7
+ Stable tag: 3.1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
20
  * Advanced background optimization to speed up your workflow.
21
  * Optimize individual images already in your media library.
22
  * Easy bulk optimization of your existing media library.
23
+ * Automatically resize huge image uploads by setting a maximum width and/or height for more reasonable browser display.
24
  * Display JPEG images more quickly with progressive JPEG encoding.
25
+ * Chose to preserve copyright metadata, creation date and GPS location in your original images.
26
  * Supports compression of animated PNG.
27
  * Select which thumbnail sizes of an image may be optimized.
28
  * Multisite support with a single API key.
29
+ * WPML compatible.
30
  * WooCommerce compatible.
31
  * WP Retina 2x compatible.
32
  * WP Offload S3 compatible.
33
+ * See your usage on the settings page and during bulk optimization.
34
+ * Color profiles are automatically translated to standard RGB color.
35
+ * Convert CMYK to RGB to save more space and add compatibility.
 
36
  * Dashboard widget with your total savings.
37
+ * Optimize and resize uploads with the WordPress mobile app.
38
  * No file size limits.
39
 
40
  = How does it work? =
43
 
44
  = Getting started =
45
 
46
+ Install this plugin and follow the instructions to set up your account. With a regular WordPress installation you can optimize **roughly 100 images each month** for free. The exact total depends on the number of thumbnail sizes that are in use in your WordPress installation. You can change which of the generated thumbnail sizes should be optimized on the *Settings > Compress JPEG & PNG images* page. Once installed you can also switch to a [paid account](https://tinypng.com/dashboard/api) which removes the limits and allows you to optimize as many images as you like.
47
 
48
  = Optimizing all your images =
49
 
50
+ You can optimize your existing JPEG and PNG images all at once by going to *Media > Bulk Optimization*. Clicking on the big button will start optimizing all unoptimized images in your media library.
51
 
52
  = Multisite support =
53
 
54
+ The plugin is fully multisite compatible and you can set the API key for all sites by defining the key in your *wp-config.php* file. View the installation instructions for more information.
55
 
56
  = Contact us =
57
 
129
  A: You can upgrade to a paid account by adding your *Payment details* on your [account dashboard](https://tinypng.com/dashboard/api). Additional compressions above 500 will then be charged at the end of each month as a one-time fee.
130
 
131
  == Changelog ==
132
+ = 3.1.0 =
133
+ * Remaining free compressions shown in settings page.
134
+ * Easier way to upgrade a free account.
135
+ * WPML and WPML Media compatibility in collaboration with the authors of WPML. Make sure to upgrade WPML to version 4.1.
136
+ * Added a notice to the Bulk Optimization page for free accounts with not enough available free compressions.
137
+ * Added a new hook after compression of an image useful for CDN cache flushing.
138
+
139
  = 3.0.1 =
140
  * Fixed bug that caused an error when registering a new account.
141
  * No longer use create_function, which is deprecated in PHP 7.2. The plugin no longer supports PHP 5.2.
src/class-tiny-compress-client.php CHANGED
@@ -50,20 +50,27 @@ class Tiny_Compress_Client extends Tiny_Compress {
50
  return \Tinify\getCompressionCount();
51
  }
52
 
53
- public function get_key() {
54
- return \Tinify\getKey();
 
 
 
 
 
 
 
 
55
  }
56
 
57
- public function limit_reached() {
58
- return 429 == $this->last_error_code;
59
  }
60
 
61
  protected function validate() {
62
  try {
63
  $this->last_error_code = 0;
64
- $this->set_request_options( \Tinify\Tinify::getClient() );
65
-
66
- \Tinify\Tinify::getClient()->request( 'post', '/shrink' );
67
  return true;
68
 
69
  } catch ( \Tinify\Exception $err ) {
50
  return \Tinify\getCompressionCount();
51
  }
52
 
53
+ public function get_remaining_credits() {
54
+ return \Tinify\remainingCredits();
55
+ }
56
+
57
+ public function get_paying_state() {
58
+ return \Tinify\payingState();
59
+ }
60
+
61
+ public function get_email_address() {
62
+ return \Tinify\emailAddress();
63
  }
64
 
65
+ public function get_key() {
66
+ return \Tinify\getKey();
67
  }
68
 
69
  protected function validate() {
70
  try {
71
  $this->last_error_code = 0;
72
+ $this->set_request_options( \Tinify\Tinify::getClient( \Tinify\Tinify::ANONYMOUS ) );
73
+ \Tinify\Tinify::getClient()->request( 'get', '/keys/' . $this->get_key() );
 
74
  return true;
75
 
76
  } catch ( \Tinify\Exception $err ) {
src/class-tiny-compress-fopen.php CHANGED
@@ -21,6 +21,9 @@
21
  class Tiny_Compress_Fopen extends Tiny_Compress {
22
  private $last_error_code = 0;
23
  private $compression_count;
 
 
 
24
  private $api_key;
25
 
26
  protected static function identifier() {
@@ -41,19 +44,28 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
41
  return $this->compression_count;
42
  }
43
 
44
- public function get_key() {
45
- return $this->api_key;
 
 
 
 
46
  }
47
 
48
- public function limit_reached() {
49
- return 429 == $this->last_error_code;
 
 
 
 
50
  }
51
 
52
  protected function validate() {
53
- $params = $this->request_options( 'POST' );
54
- list($details, $headers, $status_code) = $this->request( $params );
 
55
 
56
- if ( 429 == $status_code || 400 == $status_code ) {
57
  return true;
58
  } elseif ( is_array( $details ) && isset( $details['error'] ) ) {
59
  throw new Tiny_Exception(
@@ -135,7 +147,7 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
135
  return array( $output, $meta );
136
  }
137
 
138
- private function request( $params, $url = Tiny_Config::URL ) {
139
  $context = stream_context_create( $params );
140
  $request = fopen( $url, 'rb', false, $context );
141
 
@@ -159,6 +171,18 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
159
  $this->compression_count = intval( $headers['compression-count'] );
160
  }
161
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  $this->last_error_code = $status_code;
163
 
164
  $response = stream_get_contents( $request );
21
  class Tiny_Compress_Fopen extends Tiny_Compress {
22
  private $last_error_code = 0;
23
  private $compression_count;
24
+ private $remaining_credits;
25
+ private $paying_state;
26
+ private $email_address;
27
  private $api_key;
28
 
29
  protected static function identifier() {
44
  return $this->compression_count;
45
  }
46
 
47
+ public function get_remaining_credits() {
48
+ return $this->remaining_credits;
49
+ }
50
+
51
+ public function get_paying_state() {
52
+ return $this->paying_state;
53
  }
54
 
55
+ public function get_email_address() {
56
+ return $this->email_address;
57
+ }
58
+
59
+ public function get_key() {
60
+ return $this->api_key;
61
  }
62
 
63
  protected function validate() {
64
+ $params = $this->request_options( 'GET' );
65
+ $url = Tiny_Config::KEYS_URL . '/' . $this->get_key();
66
+ list($details, $headers, $status_code) = $this->request( $params, $url );
67
 
68
+ if ( 429 == $status_code || 400 == $status_code || 200 == $status_code ) {
69
  return true;
70
  } elseif ( is_array( $details ) && isset( $details['error'] ) ) {
71
  throw new Tiny_Exception(
147
  return array( $output, $meta );
148
  }
149
 
150
+ private function request( $params, $url = Tiny_Config::SHRINK_URL ) {
151
  $context = stream_context_create( $params );
152
  $request = fopen( $url, 'rb', false, $context );
153
 
171
  $this->compression_count = intval( $headers['compression-count'] );
172
  }
173
 
174
+ if ( isset( $headers['compression-count-remaining'] ) ) {
175
+ $this->remaining_credits = intval( $headers['compression-count-remaining'] );
176
+ }
177
+
178
+ if ( isset( $headers['paying-state'] ) ) {
179
+ $this->paying_state = $headers['paying-state'];
180
+ }
181
+
182
+ if ( isset( $headers['email-address'] ) ) {
183
+ $this->email_address = $headers['email-address'];
184
+ }
185
+
186
  $this->last_error_code = $status_code;
187
 
188
  $response = stream_get_contents( $request );
src/class-tiny-compress.php CHANGED
@@ -54,8 +54,14 @@ abstract class Tiny_Compress {
54
 
55
  public abstract function can_create_key();
56
  public abstract function get_compression_count();
 
 
 
57
  public abstract function get_key();
58
- public abstract function limit_reached();
 
 
 
59
 
60
  public function get_status() {
61
  if ( $this->get_key() == null ) {
@@ -71,7 +77,7 @@ abstract class Tiny_Compress {
71
  try {
72
  $result = $this->validate();
73
  } catch ( Tiny_Exception $err ) {
74
- if ( $err->get_status() == 401 ) {
75
  $message = 'The key that you have entered is not valid';
76
  } else {
77
  list( $message ) = explode( ' (HTTP', $err->getMessage(), 2 );
54
 
55
  public abstract function can_create_key();
56
  public abstract function get_compression_count();
57
+ public abstract function get_remaining_credits();
58
+ public abstract function get_paying_state();
59
+ public abstract function get_email_address();
60
  public abstract function get_key();
61
+
62
+ public function limit_reached() {
63
+ return $this->get_remaining_credits() === 0;
64
+ }
65
 
66
  public function get_status() {
67
  if ( $this->get_key() == null ) {
77
  try {
78
  $result = $this->validate();
79
  } catch ( Tiny_Exception $err ) {
80
+ if ( $err->get_status() == 404 ) {
81
  $message = 'The key that you have entered is not valid';
82
  } else {
83
  list( $message ) = explode( ' (HTTP', $err->getMessage(), 2 );
src/class-tiny-image.php CHANGED
@@ -223,6 +223,13 @@ class Tiny_Image {
223
  $this->update_tiny_post_meta();
224
  }
225
  }
 
 
 
 
 
 
 
226
  return array(
227
  'success' => $success,
228
  'failed' => $failed,
@@ -284,6 +291,11 @@ class Tiny_Image {
284
  $tiny_metadata[ $size_name ] = $size->meta;
285
  }
286
  update_post_meta( $this->id, Tiny_Config::META_KEY, $tiny_metadata );
 
 
 
 
 
287
  }
288
 
289
  public function get_image_sizes() {
@@ -366,7 +378,7 @@ class Tiny_Image {
366
  if ( isset( $size->meta['error'] ) && isset( $size->meta['message'] ) ) {
367
  if ( null === $last_timestamp || $last_timestamp < $size->meta['timestamp'] ) {
368
  $last_timestamp = $size->meta['timestamp'];
369
- $error_message = $size->meta['message'];
370
  }
371
  }
372
  }
223
  $this->update_tiny_post_meta();
224
  }
225
  }
226
+
227
+ /*
228
+ Other plugins can hook into this action to execute custom logic
229
+ after the image sizes have been compressed, ie. cache flushing.
230
+ */
231
+ do_action( 'tiny_image_after_compression', $this->id, $success );
232
+
233
  return array(
234
  'success' => $success,
235
  'failed' => $failed,
291
  $tiny_metadata[ $size_name ] = $size->meta;
292
  }
293
  update_post_meta( $this->id, Tiny_Config::META_KEY, $tiny_metadata );
294
+ /*
295
+ This action is being used by WPML:
296
+ https://gist.github.com/srdjan-jcc/5c47685cda4da471dff5757ba3ce5ab1
297
+ */
298
+ do_action( 'updated_tiny_postmeta', $this->id, Tiny_Config::META_KEY, $tiny_metadata );
299
  }
300
 
301
  public function get_image_sizes() {
378
  if ( isset( $size->meta['error'] ) && isset( $size->meta['message'] ) ) {
379
  if ( null === $last_timestamp || $last_timestamp < $size->meta['timestamp'] ) {
380
  $last_timestamp = $size->meta['timestamp'];
381
+ $error_message = mb_strimwidth( $size->meta['message'], 0 , 140, '...' );
382
  }
383
  }
384
  }
src/class-tiny-plugin.php CHANGED
@@ -18,7 +18,7 @@
18
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
  */
20
  class Tiny_Plugin extends Tiny_WP_Base {
21
- const VERSION = '3.0.1';
22
  const MEDIA_COLUMN = self::NAME;
23
  const DATETIME_FORMAT = 'Y-m-d G:i:s';
24
 
@@ -61,6 +61,8 @@ class Tiny_Plugin extends Tiny_WP_Base {
61
  10, 2
62
  );
63
 
 
 
64
  add_filter( 'wp_ajax_nopriv_tiny_rpc',
65
  $this->get_method( 'process_rpc_request' )
66
  );
@@ -138,6 +140,8 @@ class Tiny_Plugin extends Tiny_WP_Base {
138
  10, 2
139
  );
140
 
 
 
141
  add_thickbox();
142
  }
143
 
@@ -165,6 +169,12 @@ class Tiny_Plugin extends Tiny_WP_Base {
165
  return array_merge( $additional, $current_links );
166
  }
167
 
 
 
 
 
 
 
168
  public function compress_retina_image( $attachment_id, $path, $size_name ) {
169
  if ( $this->settings->compress_wr2x_images() ) {
170
  $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
@@ -602,7 +612,13 @@ class Tiny_Plugin extends Tiny_WP_Base {
602
  );
603
  $admin_colors = self::retrieve_admin_colors();
604
 
 
 
 
605
  $active_tinify_sizes = $this->settings->get_active_tinify_sizes();
 
 
 
606
 
607
  include( dirname( __FILE__ ) . '/views/bulk-optimization.php' );
608
  }
18
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
  */
20
  class Tiny_Plugin extends Tiny_WP_Base {
21
+ const VERSION = '3.1.0';
22
  const MEDIA_COLUMN = self::NAME;
23
  const DATETIME_FORMAT = 'Y-m-d G:i:s';
24
 
61
  10, 2
62
  );
63
 
64
+ /* When touching any functionality linked to image compressions when
65
+ uploading images make sure it also works with XML-RPC. See NOTES. */
66
  add_filter( 'wp_ajax_nopriv_tiny_rpc',
67
  $this->get_method( 'process_rpc_request' )
68
  );
140
  10, 2
141
  );
142
 
143
+ $this->tiny_compatibility();
144
+
145
  add_thickbox();
146
  }
147
 
169
  return array_merge( $additional, $current_links );
170
  }
171
 
172
+ public function tiny_compatibility() {
173
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
174
+ $tiny_wpml_compatibility = new Tiny_WPML();
175
+ }
176
+ }
177
+
178
  public function compress_retina_image( $attachment_id, $path, $size_name ) {
179
  if ( $this->settings->compress_wr2x_images() ) {
180
  $tiny_image = new Tiny_Image( $this->settings, $attachment_id );
612
  );
613
  $admin_colors = self::retrieve_admin_colors();
614
 
615
+ /* This makes sure that up to date information is retrieved from the API. */
616
+ $this->settings->get_compressor()->get_status();
617
+
618
  $active_tinify_sizes = $this->settings->get_active_tinify_sizes();
619
+ $remaining_credits = $this->settings->get_remaining_credits();
620
+ $is_on_free_plan = $this->settings->is_on_free_plan();
621
+ $email_address = $this->settings->get_email_address();
622
 
623
  include( dirname( __FILE__ ) . '/views/bulk-optimization.php' );
624
  }
src/class-tiny-settings.php CHANGED
@@ -712,12 +712,12 @@ class Tiny_Settings extends Tiny_WP_Base {
712
  'strong' => array(),
713
  );
714
 
715
- echo '<p class="tiny-resize-unavailable" style="display: none">';
716
  esc_html_e(
717
  'Enable compression of the original image size for more options.',
718
  'tiny-compress-images'
719
  );
720
- echo '</p>';
721
 
722
  $id = self::get_prefixed_name( 'resize_original_enabled' );
723
  $name = self::get_prefixed_name( 'resize_original[enabled]' );
@@ -844,14 +844,50 @@ class Tiny_Settings extends Tiny_WP_Base {
844
  return $this->compressor->limit_reached();
845
  }
846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
  public function after_compress_callback( $compressor ) {
848
  $count = $compressor->get_compression_count();
849
  if ( ! is_null( $count ) ) {
850
  $field = self::get_prefixed_name( 'status' );
851
  update_option( $field, $count );
852
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  if ( $compressor->limit_reached() ) {
854
- $link = '<a href="https://tinypng.com/dashboard/api" target="_blank">' .
 
 
855
  esc_html__( 'TinyPNG API account', 'tiny-compress-images' ) . '</a>';
856
 
857
  $this->notices->add('limit-reached',
712
  'strong' => array(),
713
  );
714
 
715
+ echo '<div class="tiny-resize-unavailable" style="display: none">';
716
  esc_html_e(
717
  'Enable compression of the original image size for more options.',
718
  'tiny-compress-images'
719
  );
720
+ echo '</div>';
721
 
722
  $id = self::get_prefixed_name( 'resize_original_enabled' );
723
  $name = self::get_prefixed_name( 'resize_original[enabled]' );
844
  return $this->compressor->limit_reached();
845
  }
846
 
847
+ public function get_remaining_credits() {
848
+ $field = self::get_prefixed_name( 'remaining_credits' );
849
+ return get_option( $field );
850
+ }
851
+
852
+ public function get_paying_state() {
853
+ $field = self::get_prefixed_name( 'paying_state' );
854
+ return get_option( $field );
855
+ }
856
+
857
+ public function is_on_free_plan() {
858
+ return self::get_paying_state() === 'free';
859
+ }
860
+
861
+ public function get_email_address() {
862
+ $field = self::get_prefixed_name( 'email_address' );
863
+ return get_option( $field );
864
+ }
865
+
866
  public function after_compress_callback( $compressor ) {
867
  $count = $compressor->get_compression_count();
868
  if ( ! is_null( $count ) ) {
869
  $field = self::get_prefixed_name( 'status' );
870
  update_option( $field, $count );
871
  }
872
+ $remaining_credits = $compressor->get_remaining_credits();
873
+ if ( ! is_null( $remaining_credits ) ) {
874
+ $field = self::get_prefixed_name( 'remaining_credits' );
875
+ update_option( $field, $remaining_credits );
876
+ }
877
+ $paying_state = $compressor->get_paying_state();
878
+ if ( ! is_null( $paying_state ) ) {
879
+ $field = self::get_prefixed_name( 'paying_state' );
880
+ update_option( $field, $paying_state );
881
+ }
882
+ $email_address = $compressor->get_email_address();
883
+ if ( ! is_null( $email_address ) ) {
884
+ $field = self::get_prefixed_name( 'email_address' );
885
+ update_option( $field, $email_address );
886
+ }
887
  if ( $compressor->limit_reached() ) {
888
+ $encoded_email = str_replace( '%20', '%2B', rawurlencode( $email_address ) );
889
+ $url = 'https://tinypng.com/dashboard/api?type=upgrade&mail=' . $encoded_email;
890
+ $link = '<a href="' . $url . '" target="_blank">' .
891
  esc_html__( 'TinyPNG API account', 'tiny-compress-images' ) . '</a>';
892
 
893
  $this->notices->add('limit-reached',
src/compatibility/wpml/class-tiny-wpml.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Tiny Compress Images - WordPress plugin.
4
+ * Copyright (C) 2015-2018 Tinify B.V.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify it
7
+ * under the terms of the GNU General Public License as published by the Free
8
+ * Software Foundation; either version 2 of the License, or (at your option)
9
+ * any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
+ * more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along
17
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
18
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ */
20
+
21
+ class Tiny_WPML {
22
+
23
+ public function __construct() {
24
+ $this->add_hooks();
25
+ }
26
+
27
+ private function add_hooks() {
28
+ // When WPML duplicates an attachment in other languages.
29
+ add_action( 'wpml_after_duplicate_attachment',
30
+ array( $this, 'copy_tiny_postmeta' ), 10, 2
31
+ );
32
+
33
+ // When you add a missing translation text or restore an image
34
+ // on the WPML media tranlation popup.
35
+ add_action( 'wpml_after_copy_attached_file_postmeta',
36
+ array( $this, 'after_copy_attached_file' ), 10, 2
37
+ );
38
+
39
+ // When adding an alternative image on the WPML media translation popup.
40
+ add_action( 'wpml_updated_attached_file', array( $this, 'updated_attached_file' ) );
41
+ }
42
+
43
+ public function copy_tiny_postmeta( $post_id, $duplicate_post_id ) {
44
+ $original_tiny_postmeta = get_post_meta( $post_id, Tiny_Config::META_KEY, true );
45
+ update_post_meta( $duplicate_post_id, Tiny_Config::META_KEY, $original_tiny_postmeta );
46
+ }
47
+
48
+ public function after_copy_attached_file( $original_post_id, $post_id ) {
49
+ $original_tiny_postmeta = get_post_meta( $original_post_id, Tiny_Config::META_KEY, true );
50
+ update_post_meta( $post_id, Tiny_Config::META_KEY, $original_tiny_postmeta );
51
+ }
52
+
53
+ public function updated_attached_file( $post_id ) {
54
+ delete_post_meta( $post_id, Tiny_Config::META_KEY );
55
+ }
56
+ }
src/config/class-tiny-config.php CHANGED
@@ -6,7 +6,8 @@ if ( ! defined( 'TINY_DEBUG' ) ) {
6
 
7
  class Tiny_Config {
8
  /* URL is only used by fopen driver. */
9
- const URL = 'https://api.tinify.com/shrink';
 
10
  const MONTHLY_FREE_COMPRESSIONS = 500;
11
  const META_KEY = 'tiny_compress_images';
12
  }
6
 
7
  class Tiny_Config {
8
  /* URL is only used by fopen driver. */
9
+ const SHRINK_URL = 'https://api.tinify.com/shrink';
10
+ const KEYS_URL = 'https://api.tinify.com/keys';
11
  const MONTHLY_FREE_COMPRESSIONS = 500;
12
  const META_KEY = 'tiny_compress_images';
13
  }
src/css/admin.css CHANGED
@@ -8,18 +8,28 @@ div.tiny-account-status {
8
  box-sizing: border-box;
9
  display: table-cell;
10
  width: 500px;
11
- padding: 22px 28px;
12
  border: 1px solid #e1e1e1;
13
  background-color: white;
14
  }
15
 
 
 
 
 
 
 
16
  div.tiny-account-status div.status {
17
  box-sizing: border-box;
18
- padding-left: 26px;
 
 
 
 
19
  position: relative;
 
20
  }
21
 
22
- div.tiny-account-status div.status:before {
23
  box-sizing: border-box;
24
  position: absolute;
25
  width: 20px;
@@ -30,31 +40,51 @@ div.tiny-account-status div.status:before {
30
  font-style: normal;
31
  }
32
 
33
- div.tiny-account-status div.status-failure:before {
34
- left: -6px;
35
- top: -6px;
36
- color: #d54e21;
37
- content: "\f158";
 
 
 
 
 
38
  }
39
 
40
- div.tiny-account-status div.status-success:before {
41
- left: -6px;
42
- top: -6px;
43
  color: #30d030;
44
  content: "\f147";
45
  }
46
 
47
- div.tiny-account-status div.status-pending:before {
48
- left: -6px;
49
- top: -4px;
 
 
 
 
 
 
 
50
  color: #0086ba;
51
  font-size: 24px;
52
  content: "\f466";
53
  }
54
 
 
 
 
 
 
55
  div.tiny-account-status div.status-loading:before {
56
- left: -2px;
57
- top: 0;
 
 
 
58
  background: url("../images/spinner.gif") no-repeat center;
59
  background-size: 20px 20px;
60
  content: "";
@@ -92,6 +122,27 @@ div.tiny-account-status p.status {
92
  font-weight: bold;
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  div.tiny-account-status.wide {
96
  width: auto;
97
  max-width: 700px;
@@ -107,13 +158,14 @@ div.tiny-account-status div.failure p.message {
107
 
108
  div.tiny-account-status div.update {
109
  width: 380px;
 
110
  }
111
 
112
  div.tiny-account-status.wide div.create {
113
  box-sizing: border-box;
114
  display: table-cell;
115
  width: 50%;
116
- padding-right: 30px;
117
  border-right: 1px solid #e5e5e5;
118
  }
119
 
@@ -128,7 +180,6 @@ div.tiny-account-status.wide div.update {
128
  div.tiny-account-status.wide div.create {
129
  display: block;
130
  width: auto;
131
- padding-right: 0;
132
  padding-bottom: 20px;
133
  border-right: 0;
134
  border-bottom: 1px solid #e5e5e5;
@@ -138,22 +189,24 @@ div.tiny-account-status.wide div.update {
138
  display: block;
139
  width: auto;
140
  padding-top: 29px;
141
- padding-left: 0;
142
  }
143
  }
144
 
145
- div.tiny-account-status.wide div.create input, div.tiny-account-status.wide div.update input {
 
146
  width: 100%;
147
  margin-bottom: 8px;
148
  }
149
 
150
- div.tiny-account-status.wide div.create button, div.tiny-account-status.wide div.update button {
 
151
  width: 100%;
152
  margin-top: 4px;
153
  margin-bottom: 4px;
154
  }
155
 
156
- div.tiny-account-status.wide div.create button.loading, div.tiny-account-status.wide div.update button.loading {
 
157
  background-image: url(../images/button-spinner.gif) !important;
158
  background-size: 16px 16px !important;
159
  background-position: 95% 50% !important;
@@ -161,7 +214,8 @@ div.tiny-account-status.wide div.create button.loading, div.tiny-account-status.
161
  }
162
 
163
  @media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {
164
- div.tiny-account-status.wide div.create button.loading, div.tiny-account-status.wide div.update button.loading {
 
165
  background-image: url("../images/button-spinner-2x.gif") !important;
166
  }
167
  }
@@ -187,10 +241,11 @@ table.tinify-settings p.intro {
187
  }
188
 
189
  table.tinify-settings div.sizes {
190
- margin: 20px 0;
191
  }
192
 
193
- table.tinify-settings input[type="checkbox"], table.tinify-settings input[type="radio"] {
 
194
  margin-right: 12px;
195
  }
196
 
@@ -212,7 +267,8 @@ p.tiny-radio span.description {
212
  }
213
  }
214
 
215
- p.tiny-radio.disabled label, p.tiny-radio.disabled span.description {
 
216
  opacity: 0.5;
217
  }
218
 
@@ -227,7 +283,7 @@ p.tiny-radio span {
227
  }
228
 
229
  div.tiny-resize-available {
230
- margin-top: 10px;
231
  }
232
 
233
  div.tiny-resize-resolution {
8
  box-sizing: border-box;
9
  display: table-cell;
10
  width: 500px;
 
11
  border: 1px solid #e1e1e1;
12
  background-color: white;
13
  }
14
 
15
+ @media only screen and (max-width: 800px) {
16
+ div.tiny-account-status {
17
+ max-width: 100%;
18
+ }
19
+ }
20
+
21
  div.tiny-account-status div.status {
22
  box-sizing: border-box;
23
+ padding: 22px 28px 22px 56px;
24
+ position: relative;
25
+ }
26
+
27
+ div.tiny-account-status p.status span {
28
  position: relative;
29
+ margin-right: 30px;
30
  }
31
 
32
+ div.tiny-account-status p.status span:after {
33
  box-sizing: border-box;
34
  position: absolute;
35
  width: 20px;
40
  font-style: normal;
41
  }
42
 
43
+ div.tiny-account-status div.status-success,
44
+ div.tiny-account-status div.status-failure,
45
+ div.tiny-account-status div.status-pending {
46
+ padding-left: 28px;
47
+ }
48
+
49
+ div.tiny-account-status div.status-success p {
50
+ display: inline-block;
51
+ position: relative;
52
+ margin-bottom: 10px;
53
  }
54
 
55
+ div.tiny-account-status div.status-success p.status span:after {
56
+ right: -18px;
57
+ top: -11px;
58
  color: #30d030;
59
  content: "\f147";
60
  }
61
 
62
+ div.tiny-account-status div.status-failure p.status span:after {
63
+ right: -20px;
64
+ top: -11px;
65
+ color: #d54e21;
66
+ content: "\f158";
67
+ }
68
+
69
+ div.tiny-account-status div.status-pending p.status span:after {
70
+ right: -24px;
71
+ top: -11px;
72
  color: #0086ba;
73
  font-size: 24px;
74
  content: "\f466";
75
  }
76
 
77
+ div.tiny-account-status p.status a {
78
+ text-decoration: none;
79
+ font-weight: 400;
80
+ }
81
+
82
  div.tiny-account-status div.status-loading:before {
83
+ position: absolute;
84
+ left: 26px;
85
+ top: 22px;
86
+ height: 20px;
87
+ width: 20px;
88
  background: url("../images/spinner.gif") no-repeat center;
89
  background-size: 20px 20px;
90
  content: "";
122
  font-weight: bold;
123
  }
124
 
125
+ div.tiny-account-status div.upgrade {
126
+ display: flex;
127
+ padding: 22px 28px;
128
+ background-color: #F5F9FA;
129
+ }
130
+
131
+ div.tiny-account-status div.upgrade p {
132
+ width: 400px;
133
+ margin-right: 20px;
134
+ }
135
+
136
+ @media only screen and (max-width: 800px) {
137
+ div.tiny-account-status div.upgrade p {
138
+ width: auto;
139
+ }
140
+ }
141
+
142
+ div.tiny-account-status div.upgrade div.button-container {
143
+ display: inline-block;
144
+ }
145
+
146
  div.tiny-account-status.wide {
147
  width: auto;
148
  max-width: 700px;
158
 
159
  div.tiny-account-status div.update {
160
  width: 380px;
161
+ padding: 22px 28px;
162
  }
163
 
164
  div.tiny-account-status.wide div.create {
165
  box-sizing: border-box;
166
  display: table-cell;
167
  width: 50%;
168
+ padding: 22px 28px;
169
  border-right: 1px solid #e5e5e5;
170
  }
171
 
180
  div.tiny-account-status.wide div.create {
181
  display: block;
182
  width: auto;
 
183
  padding-bottom: 20px;
184
  border-right: 0;
185
  border-bottom: 1px solid #e5e5e5;
189
  display: block;
190
  width: auto;
191
  padding-top: 29px;
 
192
  }
193
  }
194
 
195
+ div.tiny-account-status.wide div.create input,
196
+ div.tiny-account-status.wide div.update input {
197
  width: 100%;
198
  margin-bottom: 8px;
199
  }
200
 
201
+ div.tiny-account-status.wide div.create button,
202
+ div.tiny-account-status.wide div.update button {
203
  width: 100%;
204
  margin-top: 4px;
205
  margin-bottom: 4px;
206
  }
207
 
208
+ div.tiny-account-status.wide div.create button.loading,
209
+ div.tiny-account-status.wide div.update button.loading {
210
  background-image: url(../images/button-spinner.gif) !important;
211
  background-size: 16px 16px !important;
212
  background-position: 95% 50% !important;
214
  }
215
 
216
  @media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {
217
+ div.tiny-account-status.wide div.create button.loading,
218
+ div.tiny-account-status.wide div.update button.loading {
219
  background-image: url("../images/button-spinner-2x.gif") !important;
220
  }
221
  }
241
  }
242
 
243
  table.tinify-settings div.sizes {
244
+ margin: 20px 0 5px;
245
  }
246
 
247
+ table.tinify-settings input[type="checkbox"],
248
+ table.tinify-settings input[type="radio"] {
249
  margin-right: 12px;
250
  }
251
 
267
  }
268
  }
269
 
270
+ p.tiny-radio.disabled label,
271
+ p.tiny-radio.disabled span.description {
272
  opacity: 0.5;
273
  }
274
 
283
  }
284
 
285
  div.tiny-resize-available {
286
+ margin-top: 5px;
287
  }
288
 
289
  div.tiny-resize-resolution {
src/css/bulk-optimization.css CHANGED
@@ -330,3 +330,23 @@ div.tiny-bulk-optimization table.whitebox tr.no-action button.toggle-row:before
330
  div.tiny-bulk-optimization table.whitebox tr.failed.is-expanded span.icon {
331
  display: none;
332
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  div.tiny-bulk-optimization table.whitebox tr.failed.is-expanded span.icon {
331
  display: none;
332
  }
333
+
334
+ div.tiny-bulk-optimization div.upgrade-account-notice {
335
+ padding: 22px 28px;
336
+ background-color: #F5F9FA;
337
+ text-align: center;
338
+ }
339
+
340
+ div.tiny-bulk-optimization div.upgrade-account-notice div.introduction {
341
+ padding-bottom: 10px;
342
+ }
343
+
344
+ div.tiny-bulk-optimization div.upgrade-account-notice p {
345
+ margin: 5px 0;
346
+ }
347
+
348
+ div.tiny-bulk-optimization div.upgrade-account-notice p a {
349
+ display: block;
350
+ margin-top: 10px;
351
+ color: #858A93;
352
+ }
src/js/admin.js CHANGED
@@ -61,6 +61,13 @@
61
  });
62
  }
63
 
 
 
 
 
 
 
 
64
  function submitKey(event) {
65
  event.preventDefault();
66
  jQuery(event.target).attr({disabled: true}).addClass('loading');
@@ -94,7 +101,7 @@
94
  },
95
  success: function(json) {
96
  var status = jQuery.parseJSON(json);
97
-
98
  if (status.ok) {
99
  var target = jQuery('#tiny-account-status');
100
  if (target.length) {
@@ -244,6 +251,8 @@
244
 
245
  eventOn('click', '[data-tiny-action=create-key]', submitKey);
246
  eventOn('click', '[data-tiny-action=update-key]', submitKey);
 
 
247
 
248
  var target = jQuery('#tiny-account-status[data-state=pending]');
249
  if (target.length) {
61
  });
62
  }
63
 
64
+ function toggleChangeKey(event) {
65
+ jQuery('div.tiny-account-status div.update').toggle();
66
+ jQuery('div.tiny-account-status div.status').toggle();
67
+ jQuery('div.tiny-account-status div.upgrade').toggle();
68
+ return false;
69
+ }
70
+
71
  function submitKey(event) {
72
  event.preventDefault();
73
  jQuery(event.target).attr({disabled: true}).addClass('loading');
101
  },
102
  success: function(json) {
103
  var status = jQuery.parseJSON(json);
104
+
105
  if (status.ok) {
106
  var target = jQuery('#tiny-account-status');
107
  if (target.length) {
251
 
252
  eventOn('click', '[data-tiny-action=create-key]', submitKey);
253
  eventOn('click', '[data-tiny-action=update-key]', submitKey);
254
+ eventOn('click', '#change-key', toggleChangeKey);
255
+ eventOn('click', '#cancel-change-key', toggleChangeKey);
256
 
257
  var target = jQuery('#tiny-account-status[data-state=pending]');
258
  if (target.length) {
src/js/bulk-optimization.js CHANGED
@@ -202,6 +202,11 @@
202
  jQuery('div#bulk-optimization-actions input#id-cancelling').addClass('visible');
203
  }
204
 
 
 
 
 
 
205
  jQuery('div#bulk-optimization-actions input').click(function() {
206
  if ((jQuery(this).attr('id') === 'id-start') && jQuery(this).hasClass('visible')) {
207
  jQuery('div#bulk-optimization-actions input#id-start').removeClass('visible');
202
  jQuery('div#bulk-optimization-actions input#id-cancelling').addClass('visible');
203
  }
204
 
205
+ jQuery('.tiny-bulk-optimization .upgrade-account-notice a#hide-warning').click(function() {
206
+ jQuery('.tiny-bulk-optimization .upgrade-account-notice').hide();
207
+ jQuery('.tiny-bulk-optimization .optimize').children().show();
208
+ });
209
+
210
  jQuery('div#bulk-optimization-actions input').click(function() {
211
  if ((jQuery(this).attr('id') === 'id-start') && jQuery(this).hasClass('visible')) {
212
  jQuery('div#bulk-optimization-actions input#id-start').removeClass('visible');
src/vendor/tinify/Tinify.php CHANGED
@@ -13,6 +13,9 @@ class Tinify {
13
  private static $proxy = NULL;
14
 
15
  private static $compressionCount = NULL;
 
 
 
16
 
17
  private static $client = NULL;
18
 
@@ -49,6 +52,30 @@ class Tinify {
49
  self::$compressionCount = $compressionCount;
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  public static function getClient($mode = self::AUTHENTICATED) {
53
  if ($mode == self::AUTHENTICATED && !self::$key) {
54
  throw new AccountException("Provide an API key with Tinify\setKey(...)");
@@ -94,6 +121,18 @@ function compressionCount() {
94
  return Tinify::getCompressionCount();
95
  }
96
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  function fromFile($path) {
98
  return Source::fromFile($path);
99
  }
@@ -108,7 +147,8 @@ function fromUrl($string) {
108
 
109
  function validate() {
110
  try {
111
- Tinify::getClient()->request("post", "/shrink");
 
112
  } catch (AccountException $err) {
113
  if ($err->status == 429) return true;
114
  throw $err;
13
  private static $proxy = NULL;
14
 
15
  private static $compressionCount = NULL;
16
+ private static $remainingCredits = NULL;
17
+ private static $payingState = NULL;
18
+ private static $emailAddress = NULL;
19
 
20
  private static $client = NULL;
21
 
52
  self::$compressionCount = $compressionCount;
53
  }
54
 
55
+ public static function getRemainingCredits() {
56
+ return self::$remainingCredits;
57
+ }
58
+
59
+ public static function setRemainingCredits($remainingCredits) {
60
+ self::$remainingCredits = $remainingCredits;
61
+ }
62
+
63
+ public static function getPayingState() {
64
+ return self::$payingState;
65
+ }
66
+
67
+ public static function setPayingState($payingState) {
68
+ self::$payingState = $payingState;
69
+ }
70
+
71
+ public static function getEmailAddress() {
72
+ return self::$emailAddress;
73
+ }
74
+
75
+ public static function setEmailAddress($emailAddress) {
76
+ self::$emailAddress = $emailAddress;
77
+ }
78
+
79
  public static function getClient($mode = self::AUTHENTICATED) {
80
  if ($mode == self::AUTHENTICATED && !self::$key) {
81
  throw new AccountException("Provide an API key with Tinify\setKey(...)");
121
  return Tinify::getCompressionCount();
122
  }
123
 
124
+ function remainingCredits() {
125
+ return Tinify::getRemainingCredits();
126
+ }
127
+
128
+ function payingState() {
129
+ return Tinify::getPayingState();
130
+ }
131
+
132
+ function emailAddress() {
133
+ return Tinify::getEmailAddress();
134
+ }
135
+
136
  function fromFile($path) {
137
  return Source::fromFile($path);
138
  }
147
 
148
  function validate() {
149
  try {
150
+ Tinify::getClient()->request("get", "/keys/" . Tinify::getKey());
151
+ return true;
152
  } catch (AccountException $err) {
153
  if ($err->status == 429) return true;
154
  throw $err;
src/vendor/tinify/Tinify/Client.php CHANGED
@@ -118,6 +118,18 @@ class Client {
118
  Tinify::setCompressionCount(intval($headers["compression-count"]));
119
  }
120
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  $isJson = false;
122
  if (isset($headers["content-type"])) {
123
  /* Parse JSON response bodies. */
@@ -144,7 +156,12 @@ class Client {
144
 
145
  if ($isError) {
146
  if ($retries > 0 && $status >= 500) continue;
147
- throw Exception::create($body->message, $body->error, $status);
 
 
 
 
 
148
  }
149
 
150
  return (object) array("body" => $body, "headers" => $headers);
118
  Tinify::setCompressionCount(intval($headers["compression-count"]));
119
  }
120
 
121
+ if ( isset( $headers["compression-count-remaining"] ) ) {
122
+ Tinify::setRemainingCredits( intval( $headers["compression-count-remaining"] ) );
123
+ }
124
+
125
+ if ( isset( $headers["paying-state"] ) ) {
126
+ Tinify::setPayingState( $headers["paying-state"] );
127
+ }
128
+
129
+ if ( isset( $headers["email-address"] ) ) {
130
+ Tinify::setEmailAddress( $headers["email-address"] );
131
+ }
132
+
133
  $isJson = false;
134
  if (isset($headers["content-type"])) {
135
  /* Parse JSON response bodies. */
156
 
157
  if ($isError) {
158
  if ($retries > 0 && $status >= 500) continue;
159
+ /* When the key doesn't exist a 404 response is given. */
160
+ if ($status == 404) {
161
+ throw Exception::create(null, null, $status);
162
+ } else {
163
+ throw Exception::create($body->message, $body->error, $status);
164
+ }
165
  }
166
 
167
  return (object) array("body" => $body, "headers" => $headers);
src/vendor/tinify/Tinify/Exception.php CHANGED
@@ -6,7 +6,7 @@ class Exception extends \Exception {
6
  public $status;
7
 
8
  public static function create($message, $type, $status) {
9
- if ($status == 401 || $status == 403 || $status == 429) {
10
  $klass = "Tinify\AccountException";
11
  } else if($status >= 400 && $status <= 499) {
12
  $klass = "Tinify\ClientException";
6
  public $status;
7
 
8
  public static function create($message, $type, $status) {
9
+ if ($status == 401 || $status == 403 || $status == 404 || $status == 429) {
10
  $klass = "Tinify\AccountException";
11
  } else if($status >= 400 && $status <= 499) {
12
  $klass = "Tinify\ClientException";
src/views/account-status-connected.php CHANGED
@@ -1,33 +1,42 @@
1
  <div class="tiny-account-status" id="tiny-account-status" data-state="complete">
2
  <div class="status <?php echo $status->ok ? ( $status->pending ? 'status-pending' : 'status-success' ) : 'status-failure'; ?>">
3
- <p class="status"><?php
4
  if ( $status->ok ) {
5
  if ( isset( $status->message ) ) {
6
  echo esc_html( $status->message, 'tiny-compress-images' );
 
7
  } else {
8
  echo esc_html__( 'Your account is connected', 'tiny-compress-images' );
 
 
 
 
 
9
  }
10
  } else {
11
  echo esc_html__( 'Connection unsuccessful', 'tiny-compress-images' );
 
 
 
 
 
 
12
  }
13
  ?></p>
14
  <p><?php
15
  if ( $status->ok ) {
 
 
 
16
  $compressions = self::get_compression_count();
17
- /* It is not possible to check if a subscription is free or flexible. */
18
- if ( self::limit_reached() ) {
19
- $link = '<a href="https://tinypng.com/dashboard/api" target="_blank">' . esc_html__( 'TinyPNG API account', 'tiny-compress-images' ) . '</a>';
20
- esc_html_e(
21
- 'You have reached your free limit this month.',
22
- 'tiny-compress-images'
23
- );
24
- echo '<br>';
25
- /* translators: %s: link saying TinyPNG API account */
26
- printf( esc_html__(
27
- 'If you need to compress more images you can upgrade your %s.',
28
  'tiny-compress-images'
29
- ), $link );
30
- } else {
31
  /* translators: %s: number of compressions */
32
  printf( esc_html__(
33
  'You have made %s compressions this month.',
@@ -44,7 +53,7 @@
44
  'tiny-compress-images'
45
  );
46
  }
47
- }
48
  ?></p>
49
  <p><?php
50
  if ( defined( 'TINY_API_KEY' ) ) {
@@ -53,10 +62,6 @@
53
  'The API key has been configured in %s',
54
  'tiny-compress-images'
55
  ), 'wp-config.php' );
56
- } else {
57
- echo '<a href="#" onclick="jQuery(\'div.tiny-account-status div.update\').toggle(); jQuery(\'div.tiny-account-status div.status\').toggle(); return false">';
58
- echo esc_html__( 'Change API key', 'tiny-compress-images' );
59
- echo '</a>';
60
  }
61
  ?></p>
62
  </div>
@@ -84,8 +89,26 @@
84
 
85
  <p class="message"></p>
86
 
87
- <p><a href="#" onclick="jQuery('div.tiny-account-status div.update').toggle(); jQuery('div.tiny-account-status div.status').toggle(); return false"><?php
88
  echo esc_html__( 'Cancel' );
89
  ?></a></p>
90
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </div>
1
  <div class="tiny-account-status" id="tiny-account-status" data-state="complete">
2
  <div class="status <?php echo $status->ok ? ( $status->pending ? 'status-pending' : 'status-success' ) : 'status-failure'; ?>">
3
+ <p class="status"><span><?php
4
  if ( $status->ok ) {
5
  if ( isset( $status->message ) ) {
6
  echo esc_html( $status->message, 'tiny-compress-images' );
7
+ echo '</span>';
8
  } else {
9
  echo esc_html__( 'Your account is connected', 'tiny-compress-images' );
10
+ if ( ! defined( 'TINY_API_KEY' ) ) {
11
+ echo '</span><a href="#" id="change-key">';
12
+ echo esc_html__( 'change key', 'tiny-compress-images' );
13
+ echo '</a>';
14
+ }
15
  }
16
  } else {
17
  echo esc_html__( 'Connection unsuccessful', 'tiny-compress-images' );
18
+ echo '</span>';
19
+ if ( ! defined( 'TINY_API_KEY' ) ) {
20
+ echo '<a href="#" id="change-key">';
21
+ echo esc_html__( 'change key', 'tiny-compress-images' );
22
+ echo '</a>';
23
+ }
24
  }
25
  ?></p>
26
  <p><?php
27
  if ( $status->ok ) {
28
+ $strong = array(
29
+ 'strong' => array(),
30
+ );
31
  $compressions = self::get_compression_count();
32
+ $remaining_credits = self::get_remaining_credits();
33
+ if ( self::is_on_free_plan() ) {
34
+ /* translators: %s: number of remaining credits */
35
+ printf( wp_kses( __(
36
+ 'You are on a <strong>free plan</strong> with <strong>%s compressions left</strong> this month.', // WPCS: Needed for proper translation.
 
 
 
 
 
 
37
  'tiny-compress-images'
38
+ ), $strong ), $remaining_credits );
39
+ } elseif ( ! $status->pending ) {
40
  /* translators: %s: number of compressions */
41
  printf( esc_html__(
42
  'You have made %s compressions this month.',
53
  'tiny-compress-images'
54
  );
55
  }
56
+ } // End if().
57
  ?></p>
58
  <p><?php
59
  if ( defined( 'TINY_API_KEY' ) ) {
62
  'The API key has been configured in %s',
63
  'tiny-compress-images'
64
  ), 'wp-config.php' );
 
 
 
 
65
  }
66
  ?></p>
67
  </div>
89
 
90
  <p class="message"></p>
91
 
92
+ <p><a href="#" id="cancel-change-key"><?php
93
  echo esc_html__( 'Cancel' );
94
  ?></a></p>
95
+ </div><?php
96
+ if ( self::is_on_free_plan() ) { ?>
97
+ <div class="upgrade">
98
+ <p>
99
+ <?php echo esc_html__(
100
+ 'Remove all limitations? Visit your TinyPNG dashboard to upgrade your account.',
101
+ 'tiny-compress-images'
102
+ ); ?>
103
+ </p>
104
+ <div class="button-container">
105
+ <div class="box">
106
+ <?php $encoded_email = str_replace( '%20', '%2B', rawurlencode( self::get_email_address() ) ); ?>
107
+ <a href="https://tinypng.com/dashboard/api?type=upgrade&mail=<?php echo $encoded_email; ?>" target="_blank" class="button button-primary upgrade-account">
108
+ <?php echo esc_html__( 'Upgrade account', 'tiny-compress-images' ); ?>
109
+ </a>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ <?php } ?>
114
  </div>
src/views/bulk-optimization-form.php CHANGED
@@ -1,4 +1,4 @@
1
- <div id="bulk-optimization-actions" class="optimization-buttons">
2
  <?php
3
  $button_start_visibility = ' visible';
4
  $button_optimizing_visibility = '';
1
+ <div id="bulk-optimization-actions" class="optimization-buttons" style="<?php echo $show_notice ? 'display:none;' : '' ?>">
2
  <?php
3
  $button_start_visibility = ' visible';
4
  $button_optimizing_visibility = '';
src/views/bulk-optimization-upgrade-notice.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="upgrade-account-notice">
2
+ <div class="introduction">
3
+ <p><?php
4
+ $strong = array(
5
+ 'strong' => array(),
6
+ );
7
+ /* translators: %s: number of remaining credits */
8
+ printf( wp_kses( __(
9
+ 'You are on a <strong>free plan</strong> with <strong>%s compressions left</strong> this month.', // WPCS: Needed for proper translation.
10
+ 'tiny-compress-images'
11
+ ), $strong ), $remaining_credits );
12
+ ?></p>
13
+ <p><?php
14
+ echo esc_html__(
15
+ 'Upgrade your account now to compress your entire media library.',
16
+ 'tiny-compress-images'
17
+ );
18
+ ?></p>
19
+ </div>
20
+ <?php $encoded_email = str_replace( '%20', '%2B', rawurlencode( $email_address ) ); ?>
21
+ <a href="https://tinypng.com/dashboard/api?type=upgrade&mail=<?php echo $encoded_email; ?>" target="_blank" class="button button-primary button-hero upgrade-account">
22
+ <?php echo esc_html__( 'Upgrade account', 'tiny-compress-images' ); ?>
23
+ </a><?php
24
+ if ( $remaining_credits > 0 ) { ?>
25
+ <p>
26
+ <a id="hide-warning" href="#">
27
+ <?php echo esc_html__( 'No thanks, continue anyway', 'tiny-compress-images' ); ?>
28
+ </a>
29
+ </p><?php
30
+ } ?>
31
+ </div>
src/views/bulk-optimization.php CHANGED
@@ -170,7 +170,7 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
170
  'a' => array(
171
  'href' => array(),
172
  ),
173
- ) ), Tiny_Config::MONTHLY_FREE_COMPRESSIONS, esc_html__( 'image sizes', 'tiny-compress-images' ), '<a href="https://tinypng.com/dashboard/api">' . esc_html__( ' upgrade here', 'tiny-compress-images' ) . '</a>' );
174
  ?></p>
175
  </div>
176
  </div>
@@ -226,8 +226,9 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
226
  </div>
227
  </div>
228
  </div>
 
229
  <div class="optimize">
230
- <div class="progressbar" id="compression-progress-bar" data-number-to-optimize="<?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?>" data-amount-optimized="0">
231
  <div id="progress-size" class="progress">
232
  </div>
233
  <div class="numbers" >
@@ -243,7 +244,12 @@ div.tiny-bulk-optimization div.dashboard div.optimize div.progressbar div.progre
243
  }
244
  ?>
245
  </div>
246
- </div>
 
 
 
 
 
247
  <script type="text/javascript">
248
  <?php echo 'jQuery(function() { bulkOptimization(' . json_encode( $stats['available-for-optimization'] ) . ')})'; ?>
249
  </script>
170
  'a' => array(
171
  'href' => array(),
172
  ),
173
+ ) ), Tiny_Config::MONTHLY_FREE_COMPRESSIONS, esc_html__( 'image sizes', 'tiny-compress-images' ), '<a target="_blank" href="https://tinypng.com/dashboard/api?type=upgrade&mail=' . str_replace( '%20', '%2B', rawurlencode( $email_address ) ) . '">' . esc_html__( ' upgrade here', 'tiny-compress-images' ) . '</a>' );
174
  ?></p>
175
  </div>
176
  </div>
226
  </div>
227
  </div>
228
  </div>
229
+ <?php $show_notice = $is_on_free_plan && $stats['available-unoptimised-sizes'] > $remaining_credits; ?>
230
  <div class="optimize">
231
+ <div class="progressbar" id="compression-progress-bar" data-number-to-optimize="<?php echo $stats['optimized-image-sizes'] + $stats['available-unoptimised-sizes'] ?>" data-amount-optimized="0" style="<?php echo $show_notice ? 'display:none;' : '' ?>">
232
  <div id="progress-size" class="progress">
233
  </div>
234
  <div class="numbers" >
244
  }
245
  ?>
246
  </div>
247
+ <?php
248
+ if ( $show_notice ) {
249
+ require_once dirname( __FILE__ ) . '/bulk-optimization-upgrade-notice.php';
250
+ }
251
+ ?>
252
+ </div>
253
  <script type="text/javascript">
254
  <?php echo 'jQuery(function() { bulkOptimization(' . json_encode( $stats['available-for-optimization'] ) . ')})'; ?>
255
  </script>
tiny-compress-images.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
- * Version: 3.0.1
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * Text Domain: tiny-compress-images
@@ -20,6 +20,7 @@ require dirname( __FILE__ ) . '/src/class-tiny-image.php';
20
  require dirname( __FILE__ ) . '/src/class-tiny-settings.php';
21
  require dirname( __FILE__ ) . '/src/class-tiny-plugin.php';
22
  require dirname( __FILE__ ) . '/src/class-tiny-notices.php';
 
23
 
24
  if ( Tiny_PHP::client_supported() ) {
25
  require dirname( __FILE__ ) . '/src/class-tiny-compress-client.php';
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
+ * Version: 3.1.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * Text Domain: tiny-compress-images
20
  require dirname( __FILE__ ) . '/src/class-tiny-settings.php';
21
  require dirname( __FILE__ ) . '/src/class-tiny-plugin.php';
22
  require dirname( __FILE__ ) . '/src/class-tiny-notices.php';
23
+ require dirname( __FILE__ ) . '/src/compatibility/wpml/class-tiny-wpml.php';
24
 
25
  if ( Tiny_PHP::client_supported() ) {
26
  require dirname( __FILE__ ) . '/src/class-tiny-compress-client.php';