Compress JPEG & PNG images - Version 1.5.0

Version Description

  • Resize original images when compressing. Set a maximum width and/or height and your original images will be scaled down in case they are bigger.
  • Added support for the mobile WordPress app (thanks to David Goodwin).
Download this release

Release Info

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

Code changes from version 1.4.0 to 1.5.0

RELEASE CHANGED
@@ -2,15 +2,16 @@ In order to release a new version of the plugin to wordpress.org, perform the fo
2
 
3
  1. Update the version in tiny-compress-images.php
4
  2. Change the 'Stable tag' in readme.txt to the new release number.
5
- 3. If you've changed the plugin to work with newer version of wordpress add that to the readme as well.
6
- 4. Commit and push to GitHub.
7
- 5. Create a new release in GitHub and pull it in.
8
- 6. Locally, checkout the new tag: `git checkout <tagged version>`.
9
- 7. If not already done so, checkout the plugin's Subversion repository: `svn co http://plugins.svn.wordpress.org/tiny-compress-images`.
10
- 8. Update svn:ignore property of trunk when .gitignore is updated: `svn propedit svn:ignore trunk`.
11
- 9. Delete everything in trunk `rm -rf <path-to-local-svn-repo/trunk/*`.
12
- 10. Manually copy the Git release to the local Subversion repo: `git ls-files | xargs tar c | tar x -C <path-to-local-svn-repo>/trunk/`.
13
- 11. Add new files `svn st | awk '/^\?/ { print $2; }' | xargs svn add`.
14
- 12. Delete deleted files: `svn st | awk '/^!/ { print $2; }' | xargs svn rm`.
15
- 13. Commit the trunk to Subversion: `svn ci -m "<message>"`.
16
- 14. Tag the new release in Subversion and commit: `svn cp trunk tags/<version> && svn ci -m "<message>"`.
 
2
 
3
  1. Update the version in tiny-compress-images.php
4
  2. Change the 'Stable tag' in readme.txt to the new release number.
5
+ 3. Add release notes to readme.txt.
6
+ 4. If you've changed the plugin to work with newer version of wordpress add that to the readme as well.
7
+ 5. Commit and push to GitHub.
8
+ 6. Create a new release in GitHub and pull it in.
9
+ 7. Locally, checkout the new tag: `git checkout <tagged version>`.
10
+ 8. If not already done so, checkout the plugin's Subversion repository: `svn co http://plugins.svn.wordpress.org/tiny-compress-images`.
11
+ 9. Update svn:ignore property of trunk when .gitignore is updated: `svn propedit svn:ignore trunk`.
12
+ 10. Delete everything in trunk `rm -rf <path-to-local-svn-repo/trunk/*`.
13
+ 11. Manually copy the Git release to the local Subversion repo: `git ls-files | xargs tar c | tar x -C <path-to-local-svn-repo>/trunk/`.
14
+ 12. Add new files `svn st | awk '/^\?/ { print $2; }' | xargs svn add`.
15
+ 13. Delete deleted files: `svn st | awk '/^!/ { print $2; }' | xargs svn rm`.
16
+ 14. Commit the trunk to Subversion: `svn ci -m "<message>"`.
17
+ 15. Tag the new release in Subversion and commit: `svn cp trunk tags/<version> && svn ci -m "<message>"`.
bin/docker-functions CHANGED
@@ -50,7 +50,7 @@ run_mysql() {
50
  then
51
  docker start "mysql-wordpress"
52
  else
53
- docker run --name mysql-wordpress -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql
54
  fi
55
  fi
56
  }
50
  then
51
  docker start "mysql-wordpress"
52
  else
53
+ docker run --name mysql-wordpress -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:5.5
54
  fi
55
  fi
56
  }
bin/integration-tests CHANGED
@@ -10,7 +10,7 @@ my $dir = dirname($0);
10
 
11
  my $hostip;
12
  if (`which docker-machine`) {
13
- $hostip = `docker-machine ip default`;
14
  } else {
15
  $hostip = `boot2docker ip`;
16
  }
10
 
11
  my $hostip;
12
  if (`which docker-machine`) {
13
+ $hostip = `docker-machine ip $ENV{'DOCKER_MACHINE_NAME'}`;
14
  } else {
15
  $hostip = `boot2docker ip`;
16
  }
bin/restore-wordpress CHANGED
@@ -21,10 +21,14 @@ export WORDPRESS_DATABASE=wordpress_$version
21
  export MYSQL_ROOT_PASSWORD=root
22
 
23
  if hash docker-machine 2>/dev/null; then
24
- export HOST_IP=$(docker-machine ip default)
25
  else
26
  export HOST_IP=$(boot2docker ip)
27
  fi
 
 
 
 
28
 
29
  export MYSQL_DUMP_FILE=tmp/mysqldump_wordpress_$version.sql.gz
30
 
21
  export MYSQL_ROOT_PASSWORD=root
22
 
23
  if hash docker-machine 2>/dev/null; then
24
+ export HOST_IP=$(docker-machine ip $DOCKER_MACHINE_NAME)
25
  else
26
  export HOST_IP=$(boot2docker ip)
27
  fi
28
+ if [ -z "$HOST_IP" ]; then
29
+ echo "Could not find docker machine ip"
30
+ exit 2
31
+ fi
32
 
33
  export MYSQL_DUMP_FILE=tmp/mysqldump_wordpress_$version.sql.gz
34
 
bin/test-wordpress CHANGED
@@ -28,10 +28,14 @@ export WORDPRESS_DATABASE=wordpress_$version
28
  export MYSQL_ROOT_PASSWORD=root
29
 
30
  if hash docker-machine 2>/dev/null; then
31
- export HOST_IP=$(docker-machine ip default)
32
  else
33
  export HOST_IP=$(boot2docker ip)
34
  fi
 
 
 
 
35
 
36
  export HOST_PORT=80$version
37
  export WORDPRESS_URL=http://$HOST_IP:$HOST_PORT
28
  export MYSQL_ROOT_PASSWORD=root
29
 
30
  if hash docker-machine 2>/dev/null; then
31
+ export HOST_IP=$(docker-machine ip $DOCKER_MACHINE_NAME)
32
  else
33
  export HOST_IP=$(boot2docker ip)
34
  fi
35
+ if [ -z "$HOST_IP" ]; then
36
+ echo "Could not find docker machine ip"
37
+ exit 2
38
+ fi
39
 
40
  export HOST_PORT=80$version
41
  export WORDPRESS_URL=http://$HOST_IP:$HOST_PORT
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Compress JPEG & PNG images ===
2
  Contributors: TinyPNG
3
  Donate link: https://tinypng.com/
4
- Tags: compress, optimize, shrink, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, faster, performance, panda
5
  Requires at least: 3.0.6
6
  Tested up to: 4.4
7
- Stable tag: 1.4.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -16,16 +16,17 @@ Make your website faster by compressing your JPEG and PNG images. This plugin au
16
 
17
  = Features =
18
 
19
- * Automatically compress new images.
20
- * Easy bulk compression of your existing media library.
21
  * Compress individual images already in your media library.
 
 
22
  * Multisite support with a single API key.
23
  * Color profiles are translated to the standard RGB color space.
24
  * See your usage directly from the media settings and during bulk compression.
25
- * Select which thumbnail sizes of an image may be compressed.
26
- * Converts from CMYK to RGB to save more space and maximize compatibility.
27
- * Automatic detection of images that can be recompressed.
28
- * No file size limit.
29
 
30
  = How does it work? =
31
 
@@ -98,29 +99,34 @@ A: Yes! After installing the plugin, go to Tools > Compress JPEG & PNG images, a
98
 
99
  == Changelog ==
100
 
 
 
 
 
101
  = 1.4.0 =
102
- * Added indication of number of images you can compress for free each month.
103
- * Added link to settings page from the plugin listing.
104
- * Added clarification that by checking the original image size your original images will be overwritten.
105
 
106
  = 1.3.2 =
107
- * In some cases a user would have different file sizes defined in Settings > Media which have the exact same pixel dimensions. Compressing images could then occasionally result in compressing the same image multiple times without being seen as 'compressed'. We now detect duplicate file sizes and don't compress them again.
108
 
109
  = 1.3.1 =
110
- * Media library now shows when files are in the process of being compressed.
111
 
112
  = 1.3.0 =
113
- * Improved bulk compressions from media library. You can now also bulk compress your whole media library in one step.
114
- * Intelligent detection if file is already compressed or was altered by another plugin and should be recompressed.
 
115
 
116
  = 1.2.1 =
117
- * Bugfix that prevents recompressing the original when no additional image sizes can be found in the metadata. (introduced in 1.2.0)
118
 
119
  = 1.2.0 =
120
  * Display connection status and number of compressions this month on the settings page. This also allows you to check if you entered a valid API key.
121
- * Show a notice to administrators when reaching the monthly compression limit (in case you're on a fixed or free plan).
122
- * The plugin will now work when php's parse_ini_file is disabled on your host.
123
- * Bugfix that avoids a warning when no additional image sizes can be found in the metadata.
124
 
125
  = 1.1.0 =
126
  * The API key can now be set with the TINY_API_KEY constant in wp-config.php. This will work for normal and multisite WordPress installations.
1
  === Compress JPEG & PNG images ===
2
  Contributors: TinyPNG
3
  Donate link: https://tinypng.com/
4
+ Tags: compress, optimize, shrink, resize, fit, scale, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, faster, performance, panda, wordpress app
5
  Requires at least: 3.0.6
6
  Tested up to: 4.4
7
+ Stable tag: 1.5.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
16
 
17
  = Features =
18
 
19
+ * Automatically compress new images on upload.
20
+ * Resize large original images by setting a maximum width and/or height.
21
  * Compress individual images already in your media library.
22
+ * Easy bulk compression of your existing media library.
23
+ * Select which thumbnail sizes of an image may be compressed.
24
  * Multisite support with a single API key.
25
  * Color profiles are translated to the standard RGB color space.
26
  * See your usage directly from the media settings and during bulk compression.
27
+ * Convert CMYK to RGB to save more space and maximize compatibility.
28
+ * Compress and resize uploads with the WordPress mobile app.
29
+ * No file size limits.
 
30
 
31
  = How does it work? =
32
 
99
 
100
  == Changelog ==
101
 
102
+ = 1.5.0 =
103
+ * Resize original images when compressing. Set a maximum width and/or height and your original images will be scaled down in case they are bigger.
104
+ * Added support for the mobile WordPress app (thanks to David Goodwin).
105
+
106
  = 1.4.0 =
107
+ * Indication of the number of images you can compress for free each month.
108
+ * Link to the settings page from the plugin listing.
109
+ * Clarification that original images will be overwritten when compressed.
110
 
111
  = 1.3.2 =
112
+ * Detect different thumbnail sizes with the same dimensions so they will not be compressed again.
113
 
114
  = 1.3.1 =
115
+ * Media library shows files that are in the process of compression.
116
 
117
  = 1.3.0 =
118
+ * Improved bulk compression from media library. Bulk compress your whole media library in one step.
119
+ * Better indication of image sizes that have been compressed.
120
+ * Detection of image sizes modified after compression by other plugins.
121
 
122
  = 1.2.1 =
123
+ * Prevent compressing the original image if it is the only selected image size.
124
 
125
  = 1.2.0 =
126
  * Display connection status and number of compressions this month on the settings page. This also allows you to check if you entered a valid API key.
127
+ * Show a notice to administrators when the limit of the fixed and free plans is reached.
128
+ * The plugin now works when php's parse_ini_file is disabled on your host.
129
+ * Avoids warnings when no image sizes have been selected.
130
 
131
  = 1.1.0 =
132
  * The API key can now be set with the TINY_API_KEY constant in wp-config.php. This will work for normal and multisite WordPress installations.
src/class-tiny-compress-curl.php CHANGED
@@ -63,22 +63,32 @@ class Tiny_Compress_Curl extends Tiny_Compress {
63
  return array(self::decode(substr($response, $header_size)), $headers, $status_code);
64
  }
65
 
66
- protected function output_options($url) {
67
- return array(
68
  CURLOPT_URL => $url,
69
  CURLOPT_RETURNTRANSFER => true,
 
70
  CURLOPT_CAINFO => self::get_ca_file(),
71
  CURLOPT_SSL_VERIFYPEER => true
72
  );
 
 
 
 
 
 
73
  }
74
 
75
- protected function output($url) {
76
  $request = curl_init();
77
- curl_setopt_array($request, $this->output_options($url));
 
78
 
79
  $response = curl_exec($request);
 
 
80
  curl_close($request);
81
 
82
- return $response;
83
  }
84
  }
63
  return array(self::decode(substr($response, $header_size)), $headers, $status_code);
64
  }
65
 
66
+ protected function output_options($url, $resize) {
67
+ $options = array(
68
  CURLOPT_URL => $url,
69
  CURLOPT_RETURNTRANSFER => true,
70
+ CURLOPT_HEADER => true,
71
  CURLOPT_CAINFO => self::get_ca_file(),
72
  CURLOPT_SSL_VERIFYPEER => true
73
  );
74
+ if ($resize) {
75
+ $options[CURLOPT_USERPWD] = 'api:' . $this->api_key;
76
+ $options[CURLOPT_HTTPHEADER] = array('Content-Type: application/json');
77
+ $options[CURLOPT_POSTFIELDS] = json_encode(array('resize' => $resize));
78
+ }
79
+ return $options;
80
  }
81
 
82
+ protected function output($url, $resize) {
83
  $request = curl_init();
84
+ $options = $this->output_options($url, $resize);
85
+ curl_setopt_array($request, $options);
86
 
87
  $response = curl_exec($request);
88
+ $header_size = curl_getinfo($request, CURLINFO_HEADER_SIZE);
89
+ $headers = self::parse_headers(substr($response, 0, $header_size));
90
  curl_close($request);
91
 
92
+ return array(substr($response, $header_size), $headers);
93
  }
94
  }
src/class-tiny-compress-fopen.php CHANGED
@@ -51,6 +51,7 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
51
 
52
  if (!$request) {
53
  $headers = self::parse_headers($http_response_header);
 
54
  return array(array(
55
  'error' => 'FopenError',
56
  'message' => 'Could not compress, enable cURL for detailed error',
@@ -66,8 +67,8 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
66
  return array(self::decode($response), $headers, $status_code);
67
  }
68
 
69
- protected function output_options() {
70
- return array(
71
  'http' => array(
72
  'method' => 'GET',
73
  ),
@@ -76,19 +77,29 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
76
  'verify_peer' => true
77
  )
78
  );
 
 
 
 
 
 
 
 
79
  }
80
 
81
- protected function output($url) {
82
- $context = stream_context_create($this->output_options());
83
  $request = @fopen($url, 'rb', false, $context);
84
 
85
  if ($request) {
86
  $response = stream_get_contents($request);
 
 
87
  fclose($request);
88
  } else {
89
  $response = '';
 
90
  }
91
-
92
- return $response;
93
  }
94
  }
51
 
52
  if (!$request) {
53
  $headers = self::parse_headers($http_response_header);
54
+
55
  return array(array(
56
  'error' => 'FopenError',
57
  'message' => 'Could not compress, enable cURL for detailed error',
67
  return array(self::decode($response), $headers, $status_code);
68
  }
69
 
70
+ protected function output_options($resize) {
71
+ $options = array(
72
  'http' => array(
73
  'method' => 'GET',
74
  ),
77
  'verify_peer' => true
78
  )
79
  );
80
+ if ($resize) {
81
+ $options['http']['header'] = array(
82
+ 'Authorization: Basic ' . base64_encode('api:' . $this->api_key),
83
+ 'Content-Type: application/json'
84
+ );
85
+ $options['http']['content'] = json_encode(array('resize' => $resize));
86
+ }
87
+ return $options;
88
  }
89
 
90
+ protected function output($url, $resize) {
91
+ $context = stream_context_create($this->output_options($resize));
92
  $request = @fopen($url, 'rb', false, $context);
93
 
94
  if ($request) {
95
  $response = stream_get_contents($request);
96
+ $meta_data = stream_get_meta_data($request);
97
+ $headers = self::parse_headers($meta_data['wrapper_data']);
98
  fclose($request);
99
  } else {
100
  $response = '';
101
+ $headers = array();
102
  }
103
+ return array($response, $headers);
 
104
  }
105
  }
src/class-tiny-compress.php CHANGED
@@ -41,7 +41,7 @@ abstract class Tiny_Compress {
41
  }
42
 
43
  abstract protected function shrink($input);
44
- abstract protected function output($url);
45
 
46
  public function get_status(&$details) {
47
  list($details, $headers, $status_code) = $this->shrink(null);
@@ -54,7 +54,7 @@ abstract class Tiny_Compress {
54
  }
55
  }
56
 
57
- public function compress($input) {
58
  list($details, $headers) = $this->shrink($input);
59
  $this->call_after_compress_callback($details, $headers);
60
  $outputUrl = isset($headers['location']) ? $headers['location'] : null;
@@ -63,19 +63,31 @@ abstract class Tiny_Compress {
63
  } else if ($outputUrl === null) {
64
  throw new Tiny_Exception('Could not find output url', 'OutputNotFound');
65
  }
66
- $output = $this->output($outputUrl);
 
67
  if (strlen($output) == 0) {
68
  throw new Tiny_Exception('Could not download output', 'OutputError');
69
  }
 
70
  return array($output, $details);
71
  }
72
 
73
- public function compress_file($file) {
74
  if (!file_exists($file)) {
75
  throw new Tiny_Exception('File does not exist', 'FileError');
76
  }
77
- list($output, $details) = $this->compress(file_get_contents($file));
 
 
 
 
 
78
  file_put_contents($file, $output);
 
 
 
 
 
79
  return $details;
80
  }
81
 
@@ -109,5 +121,26 @@ abstract class Tiny_Compress {
109
  }
110
  return $result;
111
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
 
41
  }
42
 
43
  abstract protected function shrink($input);
44
+ abstract protected function output($url, $resize);
45
 
46
  public function get_status(&$details) {
47
  list($details, $headers, $status_code) = $this->shrink(null);
54
  }
55
  }
56
 
57
+ public function compress($input, $resize_options) {
58
  list($details, $headers) = $this->shrink($input);
59
  $this->call_after_compress_callback($details, $headers);
60
  $outputUrl = isset($headers['location']) ? $headers['location'] : null;
63
  } else if ($outputUrl === null) {
64
  throw new Tiny_Exception('Could not find output url', 'OutputNotFound');
65
  }
66
+ list($output, $headers) = $this->output($outputUrl, $resize_options);
67
+ $this->call_after_compress_callback(null, $headers);
68
  if (strlen($output) == 0) {
69
  throw new Tiny_Exception('Could not download output', 'OutputError');
70
  }
71
+
72
  return array($output, $details);
73
  }
74
 
75
+ public function compress_file($file, $resize_options) {
76
  if (!file_exists($file)) {
77
  throw new Tiny_Exception('File does not exist', 'FileError');
78
  }
79
+
80
+ if (!self::needs_resize($file, $resize_options)) {
81
+ $resize_options = false;
82
+ }
83
+
84
+ list($output, $details) = $this->compress(file_get_contents($file), $resize_options);
85
  file_put_contents($file, $output);
86
+
87
+ if ($resize_options) {
88
+ $details['output'] = self::update_details($file, $details) + $details['output'];
89
+ }
90
+
91
  return $details;
92
  }
93
 
121
  }
122
  return $result;
123
  }
124
+
125
+ protected static function needs_resize($file, $resize_options) {
126
+ if (!$resize_options) {
127
+ return false;
128
+ }
129
+
130
+ list($width, $height) = getimagesize($file);
131
+ return $width > $resize_options['width'] || $height > $resize_options['height'];
132
+ }
133
+
134
+ protected static function update_details($file, $details) {
135
+ $size = filesize($file);
136
+ list($width, $height) = getimagesize($file);
137
+ return array(
138
+ 'size' => $size,
139
+ 'width' => $width,
140
+ 'height' => $height,
141
+ 'ratio' => round($size / $details['input']['size'], 4),
142
+ 'resized' => true
143
+ );
144
+ }
145
  }
146
 
src/class-tiny-metadata.php CHANGED
@@ -73,17 +73,22 @@ class Tiny_Metadata {
73
  }
74
  }
75
 
 
 
 
 
 
 
 
 
 
76
  public function update() {
77
  update_post_meta($this->id, self::META_KEY, $this->values);
78
  }
79
 
80
  public function add_response($response, $size=self::ORIGINAL) {
81
- $data = array(
82
- 'input' => array('size' => $response['input']['size']),
83
- 'output' => array('size' => $response['output']['size']),
84
- 'end' => time()
85
- );
86
- $this->values[$size] = array_merge($this->values[$size], $data);
87
  }
88
 
89
  public function add_request($size=self::ORIGINAL) {
@@ -171,4 +176,8 @@ class Tiny_Metadata {
171
  }
172
  return $result;
173
  }
 
 
 
 
174
  }
73
  }
74
  }
75
 
76
+ public function update_wp_metadata($wp_metadata) {
77
+ $tiny_metadata = $this->get_value();
78
+ if (isset($tiny_metadata) && isset($tiny_metadata['output']) && isset($tiny_metadata['output']['width']) && isset($tiny_metadata['output']['height'])) {
79
+ $wp_metadata['width'] = $tiny_metadata['output']['width'];
80
+ $wp_metadata['height'] = $tiny_metadata['output']['height'];
81
+ }
82
+ return $wp_metadata;
83
+ }
84
+
85
  public function update() {
86
  update_post_meta($this->id, self::META_KEY, $this->values);
87
  }
88
 
89
  public function add_response($response, $size=self::ORIGINAL) {
90
+ $response['end'] = time();
91
+ $this->values[$size] = array_merge($this->values[$size], $response);
 
 
 
 
92
  }
93
 
94
  public function add_request($size=self::ORIGINAL) {
176
  }
177
  return $result;
178
  }
179
+
180
+ public function is_resizable($size) {
181
+ return $size === self::ORIGINAL;
182
+ }
183
  }
src/class-tiny-plugin.php CHANGED
@@ -102,7 +102,7 @@ class Tiny_Plugin extends Tiny_WP_Base {
102
  $tiny_metadata = new Tiny_Metadata($attachment_id, $metadata);
103
 
104
  if ($this->settings->get_compressor() === null || strpos($mime_type, 'image/') !== 0) {
105
- return $metadata;
106
  }
107
 
108
  $success = 0;
@@ -116,9 +116,8 @@ class Tiny_Plugin extends Tiny_WP_Base {
116
  try {
117
  $tiny_metadata->add_request($uncompressed_size);
118
  $tiny_metadata->update();
119
- $response = $compressor->compress_file($tiny_metadata->get_filename($uncompressed_size));
120
- $responses[$uncompressed_size] = $response;
121
-
122
  $tiny_metadata->add_response($response, $uncompressed_size);
123
  $success++;
124
  } catch (Tiny_Exception $e) {
@@ -132,8 +131,8 @@ class Tiny_Plugin extends Tiny_WP_Base {
132
  }
133
 
134
  public function compress_attachment($metadata, $attachment_id) {
135
- $this->compress($metadata, $attachment_id);
136
- return $metadata;
137
  }
138
 
139
  public function compress_image() {
@@ -160,6 +159,8 @@ class Tiny_Plugin extends Tiny_WP_Base {
160
  }
161
 
162
  list($tiny_metadata, $result) = $this->compress($metadata, $id);
 
 
163
  if ($json) {
164
  $result['message'] = $tiny_metadata->get_latest_error();
165
  $result['status'] = $this->settings->get_status();
@@ -211,6 +212,11 @@ class Tiny_Plugin extends Tiny_WP_Base {
211
 
212
  if (count($missing) > 0) {
213
  printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
 
 
 
 
 
214
  echo '<br/>';
215
  if (($error = $tiny_metadata->get_latest_error())) {
216
  echo '<span class="error">' . self::translate_escape('Latest error') . ': '. self::translate_escape($error) .'</span><br/>';
@@ -222,6 +228,11 @@ class Tiny_Plugin extends Tiny_WP_Base {
222
  printf(self::translate_escape('Compressing %d sizes...'), count($this->settings->get_active_tinify_sizes()));
223
  } else {
224
  printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
 
 
 
 
 
225
  $savings = $tiny_metadata->get_savings();
226
  if ($savings['count'] > 0) {
227
  echo '<br/>';
@@ -238,12 +249,14 @@ class Tiny_Plugin extends Tiny_WP_Base {
238
  echo '<h2>' . self::translate('Compress JPEG & PNG Images') . '</h2>';
239
  if (empty($_POST['tiny-bulk-compress']) && empty($_REQUEST['ids'])) {
240
  $result = $wpdb->get_results("SELECT COUNT(*) AS `count` FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC", ARRAY_A);
241
- $count = $result[0]['count'];
 
242
 
243
  echo '<p>' . self::translate_escape("Use this tool to compress all images in your media library") . '. ';
244
  echo self::translate_escape("Only images that have not been compressed will be compressed") . '.</p>';
245
- echo '<p>' . sprintf(self::translate_escape("We have found %d images in your media library"), $count) . '. ';
246
- echo self::translate_escape("To begin, just press the button below") . '.</p>';
 
247
 
248
  echo '<form method="POST" action="?page=tiny-bulk-compress">';
249
  echo '<input type="hidden" name="_wpnonce" value="' . wp_create_nonce('tiny-bulk-compress') . '">';
102
  $tiny_metadata = new Tiny_Metadata($attachment_id, $metadata);
103
 
104
  if ($this->settings->get_compressor() === null || strpos($mime_type, 'image/') !== 0) {
105
+ return array($tiny_metadata, null);
106
  }
107
 
108
  $success = 0;
116
  try {
117
  $tiny_metadata->add_request($uncompressed_size);
118
  $tiny_metadata->update();
119
+ $resize = $tiny_metadata->is_resizable($uncompressed_size) ? $this->settings->get_resize_options() : false;
120
+ $response = $compressor->compress_file($tiny_metadata->get_filename($uncompressed_size), $resize);
 
121
  $tiny_metadata->add_response($response, $uncompressed_size);
122
  $success++;
123
  } catch (Tiny_Exception $e) {
131
  }
132
 
133
  public function compress_attachment($metadata, $attachment_id) {
134
+ list($tiny_metadata, $result) = $this->compress($metadata, $attachment_id);
135
+ return $tiny_metadata->update_wp_metadata($metadata);
136
  }
137
 
138
  public function compress_image() {
159
  }
160
 
161
  list($tiny_metadata, $result) = $this->compress($metadata, $id);
162
+ wp_update_attachment_metadata($id, $tiny_metadata->update_wp_metadata($metadata));
163
+
164
  if ($json) {
165
  $result['message'] = $tiny_metadata->get_latest_error();
166
  $result['status'] = $this->settings->get_status();
212
 
213
  if (count($missing) > 0) {
214
  printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
215
+ $original = $tiny_metadata->get_value();
216
+ if (isset($original['output']['resized'])) {
217
+ echo '<br/>';
218
+ printf(self::translate_escape('Resized original to %dx%d'), $original['output']['width'], $original['output']['height']);
219
+ }
220
  echo '<br/>';
221
  if (($error = $tiny_metadata->get_latest_error())) {
222
  echo '<span class="error">' . self::translate_escape('Latest error') . ': '. self::translate_escape($error) .'</span><br/>';
228
  printf(self::translate_escape('Compressing %d sizes...'), count($this->settings->get_active_tinify_sizes()));
229
  } else {
230
  printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
231
+ $original = $tiny_metadata->get_value();
232
+ if (isset($original['output']['resized'])) {
233
+ echo '<br/>';
234
+ printf(self::translate_escape('Resized original to %dx%d'), $original['output']['width'], $original['output']['height']);
235
+ }
236
  $savings = $tiny_metadata->get_savings();
237
  if ($savings['count'] > 0) {
238
  echo '<br/>';
249
  echo '<h2>' . self::translate('Compress JPEG & PNG Images') . '</h2>';
250
  if (empty($_POST['tiny-bulk-compress']) && empty($_REQUEST['ids'])) {
251
  $result = $wpdb->get_results("SELECT COUNT(*) AS `count` FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC", ARRAY_A);
252
+ $image_count = $result[0]['count'];
253
+ $sizes_count = count($this->settings->get_active_tinify_sizes());
254
 
255
  echo '<p>' . self::translate_escape("Use this tool to compress all images in your media library") . '. ';
256
  echo self::translate_escape("Only images that have not been compressed will be compressed") . '.</p>';
257
+ echo '<p>' . sprintf(self::translate_escape("We have found %d images in your media library and for each image %d sizes will be compressed"), $image_count, $sizes_count) . '. ';
258
+ echo sprintf(self::translate_escape('This results in %d compressions at most'), $image_count*$sizes_count) . '.</p>';
259
+ echo '<p>' . self::translate_escape("To begin, just press the button below") . '.</p>';
260
 
261
  echo '<form method="POST" action="?page=tiny-bulk-compress">';
262
  echo '<input type="hidden" name="_wpnonce" value="' . wp_create_nonce('tiny-bulk-compress') . '">';
src/class-tiny-settings.php CHANGED
@@ -32,14 +32,25 @@ class Tiny_Settings extends Tiny_WP_Base {
32
  $this->notices = new Tiny_Notices();
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
35
  public function admin_init() {
36
  if (current_user_can('manage_options') && !$this->get_api_key()) {
37
  $link = sprintf('<a href="options-media.php#%s">%s</a>', self::NAME,
38
  self::translate_escape('Please fill in an API key to start compressing images'));
39
  $this->notices->show('setting', $link, 'error', false);
40
  }
41
- try {
42
- $this->compressor = Tiny_Compress::get_compressor($this->get_api_key(), $this->get_method('after_compress_callback'));
43
  } catch (Tiny_Exception $e) {
44
  $this->notices->show('compressor_exception', self::translate_escape($e->getMessage()), 'error', false);
45
  }
@@ -55,6 +66,10 @@ class Tiny_Settings extends Tiny_WP_Base {
55
  register_setting('media', $field);
56
  add_settings_field($field, self::translate('File compression'), $this->get_method('render_sizes'), 'media', $section);
57
 
 
 
 
 
58
  $field = self::get_prefixed_name('status');
59
  register_setting('media', $field);
60
  add_settings_field($field, self::translate('Connection status'), $this->get_method('render_pending_status'), 'media', $section);
@@ -64,7 +79,7 @@ class Tiny_Settings extends Tiny_WP_Base {
64
  }
65
 
66
  public function image_sizes_notice() {
67
- $this->render_image_sizes_notice($_GET["image_sizes_selected"]);
68
  exit();
69
  }
70
 
@@ -155,6 +170,32 @@ class Tiny_Settings extends Tiny_WP_Base {
155
  return $this->tinify_sizes;
156
  }
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  public function render_section() {
159
  echo '<span id="' . self::NAME . '"></span>';
160
  }
@@ -187,7 +228,7 @@ class Tiny_Settings extends Tiny_WP_Base {
187
  }
188
 
189
  echo '<div id="tiny-image-sizes-notice">';
190
- $this->render_image_sizes_notice(count(self::get_active_tinify_sizes()));
191
  echo '</div>';
192
  }
193
 
@@ -204,22 +245,57 @@ class Tiny_Settings extends Tiny_WP_Base {
204
  <?php
205
  }
206
 
207
- public function render_image_sizes_notice($active_image_sizes_count) {
208
- echo '<br/>';
209
- if ($active_image_sizes_count < 1) {
210
- echo '<p>' . self::translate_escape('With these settings no images will be compressed') . '.</p>';
 
 
211
  }
212
- else {
 
 
213
  $free_images_per_month = floor(self::MONTHLY_FREE_COMPRESSIONS / $active_image_sizes_count);
214
-
215
- echo '<p>';
216
  echo self::translate_escape('With these settings you can compress');
217
  echo ' <strong>';
218
- printf(self::translate_escape('%s images'), $free_images_per_month);
219
  echo '</strong> ';
220
  echo self::translate_escape('for free each month') . '.';
221
- echo '</p>';
222
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  }
224
 
225
  public function get_compression_count() {
32
  $this->notices = new Tiny_Notices();
33
  }
34
 
35
+ private function init_compressor() {
36
+ $this->compressor = Tiny_Compress::get_compressor($this->get_api_key(), $this->get_method('after_compress_callback'));
37
+ }
38
+
39
+ public function xmlrpc_init() {
40
+ try {
41
+ $this->init_compressor();
42
+ } catch (Tiny_Exception $e) {
43
+ }
44
+ }
45
+
46
  public function admin_init() {
47
  if (current_user_can('manage_options') && !$this->get_api_key()) {
48
  $link = sprintf('<a href="options-media.php#%s">%s</a>', self::NAME,
49
  self::translate_escape('Please fill in an API key to start compressing images'));
50
  $this->notices->show('setting', $link, 'error', false);
51
  }
52
+ try {
53
+ $this->init_compressor();
54
  } catch (Tiny_Exception $e) {
55
  $this->notices->show('compressor_exception', self::translate_escape($e->getMessage()), 'error', false);
56
  }
66
  register_setting('media', $field);
67
  add_settings_field($field, self::translate('File compression'), $this->get_method('render_sizes'), 'media', $section);
68
 
69
+ $field = self::get_prefixed_name('resize_original');
70
+ register_setting('media', $field);
71
+ add_settings_field($field, self::translate('Resize original'), $this->get_method('render_resize'), 'media', $section);
72
+
73
  $field = self::get_prefixed_name('status');
74
  register_setting('media', $field);
75
  add_settings_field($field, self::translate('Connection status'), $this->get_method('render_pending_status'), 'media', $section);
79
  }
80
 
81
  public function image_sizes_notice() {
82
+ $this->render_image_sizes_notice($_GET["image_sizes_selected"], isset($_GET["resize_original"]));
83
  exit();
84
  }
85
 
170
  return $this->tinify_sizes;
171
  }
172
 
173
+ public function get_resize_enabled() {
174
+ $setting = get_option(self::get_prefixed_name('resize_original'));
175
+ return isset($setting['enabled']) && $setting['enabled'] === 'on';
176
+ }
177
+
178
+ public function get_resize_options() {
179
+ $setting = get_option(self::get_prefixed_name('resize_original'));
180
+ if (!$this->get_resize_enabled()) {
181
+ return false;
182
+ }
183
+
184
+ $width = intval($setting['width']);
185
+ $height = intval($setting['height']);
186
+ $method = $width > 0 && $height > 0 ? 'fit' : 'scale';
187
+
188
+ $options['method'] = $method;
189
+ if ($width > 0) {
190
+ $options['width'] = $width;
191
+ }
192
+ if ($height > 0) {
193
+ $options['height'] = $height;
194
+ }
195
+
196
+ return sizeof($options) >= 2 ? $options : false;
197
+ }
198
+
199
  public function render_section() {
200
  echo '<span id="' . self::NAME . '"></span>';
201
  }
228
  }
229
 
230
  echo '<div id="tiny-image-sizes-notice">';
231
+ $this->render_image_sizes_notice(count(self::get_active_tinify_sizes()), self::get_resize_enabled());
232
  echo '</div>';
233
  }
234
 
245
  <?php
246
  }
247
 
248
+ public function render_image_sizes_notice($active_image_sizes_count, $resize_original_enabled) {
249
+ echo '<br>';
250
+ echo '<p>' . self::translate_escape('Each selected size counts as a compression') . '. ';
251
+
252
+ if ($resize_original_enabled) {
253
+ $active_image_sizes_count++;
254
  }
255
+ if ($active_image_sizes_count < 1) {
256
+ echo self::translate_escape('With these settings no images will be compressed') . '.';
257
+ } else {
258
  $free_images_per_month = floor(self::MONTHLY_FREE_COMPRESSIONS / $active_image_sizes_count);
 
 
259
  echo self::translate_escape('With these settings you can compress');
260
  echo ' <strong>';
261
+ printf(self::translate_escape('at least %s images'), $free_images_per_month);
262
  echo '</strong> ';
263
  echo self::translate_escape('for free each month') . '.';
 
264
  }
265
+ echo '</p>';
266
+ }
267
+
268
+ public function render_resize() {
269
+ echo '<p class="tiny-resize-unavailable" style="display: none">' . self::translate_escape("Enable the compression of the original image size to configure resizing") . '.</p>';
270
+
271
+ $id = self::get_prefixed_name("resize_original_enabled");
272
+ $field = self::get_prefixed_name("resize_original[enabled]");
273
+ $label = self::translate_escape('Resize and compress orginal images to fit within');
274
+
275
+ echo '<p class="tiny-resize-available">';
276
+ ?>
277
+ <input type="checkbox" id="<?php echo $id ?>" name="<?php echo $field ?>" value="on" <?php if ($this->get_resize_enabled()) { echo ' checked="checked"'; } ?>/>
278
+ <label for="<?php echo $id; ?>"><?php echo $label; ?>:</label><br>
279
+ <?php
280
+
281
+ echo '</p>';
282
+ echo '<p class="tiny-resize-available tiny-resize-resolution">';
283
+
284
+ printf("%s: ", self::translate_escape('Max Width'));
285
+ $this->render_resize_input('width');
286
+ printf("%s: ", self::translate_escape('Max Height'));
287
+ $this->render_resize_input('height');
288
+ echo '</p>';
289
+
290
+ echo '<p class="tiny-resize-available">' . sprintf(self::translate_escape("Resizing takes %s per image larger than the specified resolution"), '<strong>' . self::translate_escape('1 additional compression') . '</strong>') . '.</p>';
291
+ }
292
+
293
+ public function render_resize_input($name) {
294
+ $id = sprintf(self::get_prefixed_name('resize_original_%s'), $name);
295
+ $field = sprintf(self::get_prefixed_name('resize_original[%s]'), $name);
296
+ $settings = get_option(self::get_prefixed_name('resize_original'));
297
+ $value = isset($settings[$name]) ? $settings[$name] : "2048";
298
+ echo '<input type="number" id="'. $id .'" name="' . $field . '" value="' . $value . '" size="5" />';
299
  }
300
 
301
  public function get_compression_count() {
src/class-tiny-wp-base.php CHANGED
@@ -42,6 +42,10 @@ abstract class Tiny_WP_Base {
42
  return floatval(self::wp_version()) >= $version;
43
  }
44
 
 
 
 
 
45
  public static function plugin_version() {
46
  if (is_null(self::$plugin_version)) {
47
  $plugin_data = get_plugin_data(dirname(__FILE__) . '/../tiny-compress-images.php');
@@ -68,7 +72,9 @@ abstract class Tiny_WP_Base {
68
 
69
  public function __construct() {
70
  add_action('init', $this->get_method('init'));
71
- if (is_admin()) {
 
 
72
  add_action('admin_init', $this->get_method('admin_init'));
73
  }
74
  }
@@ -92,6 +98,9 @@ abstract class Tiny_WP_Base {
92
  public function init() {
93
  }
94
 
 
 
 
95
  public function admin_init() {
96
  }
97
  }
42
  return floatval(self::wp_version()) >= $version;
43
  }
44
 
45
+ protected function is_xmlrpc_request() {
46
+ return defined('XMLRPC_REQUEST') && XMLRPC_REQUEST;
47
+ }
48
+
49
  public static function plugin_version() {
50
  if (is_null(self::$plugin_version)) {
51
  $plugin_data = get_plugin_data(dirname(__FILE__) . '/../tiny-compress-images.php');
72
 
73
  public function __construct() {
74
  add_action('init', $this->get_method('init'));
75
+ if (self::is_xmlrpc_request()) {
76
+ add_action('init', $this->get_method('xmlrpc_init'));
77
+ } elseif (is_admin()) {
78
  add_action('admin_init', $this->get_method('admin_init'));
79
  }
80
  }
98
  public function init() {
99
  }
100
 
101
+ public function xmlrpc_init() {
102
+ }
103
+
104
  public function admin_init() {
105
  }
106
  }
src/languages/tiny-compress-images-nl_NL.mo CHANGED
Binary file
src/languages/tiny-compress-images-nl_NL.po CHANGED
@@ -133,11 +133,14 @@ msgstr "Als je meer afbeeldingen wilt comprimeren kun je je %s aanpassen"
133
  msgid "Upgrade your %s if you like to compress more images"
134
  msgstr "Upgrade je %s als je meer afbeeldingen wilt comprimeren"
135
 
 
 
 
136
  msgid "With these settings you can compress"
137
  msgstr "Met deze instellingen kun je elke maand"
138
 
139
- msgid "%s images"
140
- msgstr "%s afbeeldingen"
141
 
142
  msgid "for free each month"
143
  msgstr "gratis comprimeren"
@@ -184,8 +187,11 @@ msgstr "Deze tool comprimeert alle afbeeldingen in je media-bibliotheek"
184
  msgid "Only images that have not been compressed will be compressed"
185
  msgstr "Dit geldt alleen voor de afbeeldingen die nog niet zijn gecomprimeerd"
186
 
187
- msgid "We have found %d images in your media library"
188
- msgstr "We hebben %d afbeeldingen in de media-bibliotheek gevonden"
 
 
 
189
 
190
  msgid "To begin, just press the button below"
191
  msgstr "Druk op de knop om te starten"
@@ -204,3 +210,27 @@ msgstr "Je wordt genotificeerd op deze pagina bij voltooing"
204
 
205
  msgid "Settings"
206
  msgstr "Instellingen"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  msgid "Upgrade your %s if you like to compress more images"
134
  msgstr "Upgrade je %s als je meer afbeeldingen wilt comprimeren"
135
 
136
+ msgid "Each selected size counts as a compression"
137
+ msgstr "Elke geselecteerde afmeting telt als een compressie"
138
+
139
  msgid "With these settings you can compress"
140
  msgstr "Met deze instellingen kun je elke maand"
141
 
142
+ msgid "at least %s images"
143
+ msgstr "minimaal %s afbeeldingen"
144
 
145
  msgid "for free each month"
146
  msgstr "gratis comprimeren"
187
  msgid "Only images that have not been compressed will be compressed"
188
  msgstr "Dit geldt alleen voor de afbeeldingen die nog niet zijn gecomprimeerd"
189
 
190
+ msgid "We have found %d images in your media library and for each image %d sizes will be compressed"
191
+ msgstr "We hebben %d afbeeldingen in de media-bibliotheek gevonden en voor elke afbeelding worden %d afmetingen gecomprimeerd"
192
+
193
+ msgid "This results in %d compressions at most"
194
+ msgstr "Dit resulteert in een maximaal verbruik van %d compressies"
195
 
196
  msgid "To begin, just press the button below"
197
  msgstr "Druk op de knop om te starten"
210
 
211
  msgid "Settings"
212
  msgstr "Instellingen"
213
+
214
+ msgid "Resize original"
215
+ msgstr "Orgineel verkleinen"
216
+
217
+ msgid "Enable the compression of the original image size to configure resizing"
218
+ msgstr "Schakel de compressie van het originele formaat in om het origineel te verkleinen"
219
+
220
+ msgid "Resize and compress orginal images to fit within"
221
+ msgstr "Verklein en comprimeer het origineel in"
222
+
223
+ msgid "Resizing takes %s per image larger than the specified resolution"
224
+ msgstr "Verkleinen gebruikt %s per afbeelding die groter is dan de opgegeven resolutie"
225
+
226
+ msgid "1 additional compression"
227
+ msgstr "1 extra compressie"
228
+
229
+ msgid "Resized original to %dx%d"
230
+ msgstr "Origineel verkleind tot %dx%d"
231
+
232
+ msgid "Max Width"
233
+ msgstr "Maximale breedte"
234
+
235
+ msgid "Max Height"
236
+ msgstr "Maximale hoogte"
src/scripts/admin.js CHANGED
@@ -156,11 +156,32 @@
156
  if (adminpage === "options-media-php") {
157
  jQuery('#tiny-compress-status').load(ajaxurl + '?action=tiny_compress_status')
158
 
159
- jQuery('input[name*="tinypng_sizes"]').on("click", function() {
160
  // Unfortunately, we need some additional information to display the correct notice.
161
  totalSelectedSizes = jQuery('input[name*="tinypng_sizes"]:checked').length
162
- jQuery('#tiny-image-sizes-notice').load(ajaxurl + '?action=tiny_image_sizes_notice&image_sizes_selected=' + totalSelectedSizes)
 
 
 
 
163
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  }
165
 
166
  jQuery('.tiny-notice a.tiny-dismiss').click(dismiss_notice)
@@ -169,4 +190,4 @@
169
  })
170
 
171
  window.tinyBulkCompress = bulk_compress
172
- }).call()
156
  if (adminpage === "options-media-php") {
157
  jQuery('#tiny-compress-status').load(ajaxurl + '?action=tiny_compress_status')
158
 
159
+ jQuery('input[name*="tinypng_sizes"], input#tinypng_resize_original_enabled').on("click", function() {
160
  // Unfortunately, we need some additional information to display the correct notice.
161
  totalSelectedSizes = jQuery('input[name*="tinypng_sizes"]:checked').length
162
+ var image_count_url = ajaxurl + '?action=tiny_image_sizes_notice&image_sizes_selected=' + totalSelectedSizes
163
+ if (jQuery('input#tinypng_resize_original_enabled').prop('checked') && jQuery('input#tinypng_sizes_0').prop('checked')) {
164
+ image_count_url += '&resize_original=true'
165
+ }
166
+ jQuery('#tiny-image-sizes-notice').load(image_count_url)
167
  })
168
+
169
+ function update_resize_settings() {
170
+ if (jQuery('#tinypng_sizes_0').prop('checked')) {
171
+ jQuery('.tiny-resize-available').show()
172
+ jQuery('.tiny-resize-unavailable').hide()
173
+ } else {
174
+ jQuery('.tiny-resize-available').hide()
175
+ jQuery('.tiny-resize-unavailable').show()
176
+ }
177
+
178
+ var elements = jQuery('#tinypng_resize_original_width, #tinypng_resize_original_height')
179
+ for (var i = 0; i < elements.length; i++) {
180
+ elements[i].disabled = !jQuery('#tinypng_resize_original_enabled').prop('checked')
181
+ }
182
+ }
183
+ update_resize_settings()
184
+ jQuery('#tinypng_sizes_0, #tinypng_resize_original_enabled').click(update_resize_settings)
185
  }
186
 
187
  jQuery('.tiny-notice a.tiny-dismiss').click(dismiss_notice)
190
  })
191
 
192
  window.tinyBulkCompress = bulk_compress
193
+ }).call()
src/styles/admin.css CHANGED
@@ -51,3 +51,15 @@
51
  box-shadow: 0px 1px 0px #DFDFDF;
52
  padding: 5px;
53
  }
 
 
 
 
 
 
 
 
 
 
 
 
51
  box-shadow: 0px 1px 0px #DFDFDF;
52
  padding: 5px;
53
  }
54
+
55
+ p.tiny-resize-resolution {
56
+ margin-left: 24px;
57
+ }
58
+
59
+ p.tiny-resize-resolution input {
60
+ margin-right: 6px;
61
+ }
62
+
63
+ input[type=number][name*="tinypng_resize_original"] {
64
+ width: 65px;
65
+ }
test/fixtures/input-large.jpg ADDED
Binary file
test/helpers/wordpress.php CHANGED
@@ -176,7 +176,12 @@ class WordPressStubs {
176
  }
177
 
178
  public function getTestMetadata($path='14/01', $name='test') {
179
- $metadata = array('file' => "$path/$name.png", 'sizes' => array());
 
 
 
 
 
180
 
181
  $regex = '#^' . preg_quote($name) .'-([^.]+)[.](png|jpe?g)$#';
182
  $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
176
  }
177
 
178
  public function getTestMetadata($path='14/01', $name='test') {
179
+ $metadata = array(
180
+ 'file' => "$path/$name.png",
181
+ 'width' => 4000,
182
+ 'height' => 3000,
183
+ 'sizes' => array()
184
+ );
185
 
186
  $regex = '#^' . preg_quote($name) .'-([^.]+)[.](png|jpe?g)$#';
187
  $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
test/integration/CompressIntegrationTest.php CHANGED
@@ -80,4 +80,51 @@ class CompressIntegrationTest extends IntegrationTestCase {
80
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
81
  WebDriverBy::cssSelector('td.tiny-compress-images'), 'JSON: Syntax error [4]'));
82
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
80
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
81
  WebDriverBy::cssSelector('td.tiny-compress-images'), 'JSON: Syntax error [4]'));
82
  }
83
+
84
+ public function testResizeFit() {
85
+ $this->set_api_key('JPG123');
86
+ $this->enable_resize(300, 200);
87
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-large.jpg');
88
+ $this->assertContains('Resized original to 300x200',
89
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
90
+ $this->view_edit_image();
91
+ $this->assertContains('Dimensions: 300 × 200',
92
+ self::$driver->findElement(WebDriverBy::cssSelector('div.misc-pub-dimensions'))->getText());
93
+ }
94
+
95
+ public function testResizeScale() {
96
+ $this->set_api_key('JPG123');
97
+ $this->enable_resize(0, 200);
98
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-large.jpg');
99
+ $this->assertContains('Resized original to 300x200',
100
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
101
+ $this->view_edit_image();
102
+ $this->assertContains('Dimensions: 300 × 200',
103
+ self::$driver->findElement(WebDriverBy::cssSelector('div.misc-pub-dimensions'))->getText());
104
+ }
105
+
106
+ public function testResizeNotNeeded()
107
+ {
108
+ $this->set_api_key('JPG123');
109
+ $this->enable_resize(30000, 20000);
110
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-large.jpg');
111
+ $this->assertNotContains('Resized original',
112
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
113
+ $this->view_edit_image();
114
+ $this->assertContains('Dimensions: 1080 × 330',
115
+ self::$driver->findElement(WebDriverBy::cssSelector('div.misc-pub-dimensions'))->getText());
116
+ }
117
+
118
+ public function testResizeDisabled()
119
+ {
120
+ $this->set_api_key('JPG123');
121
+ $this->enable_resize(300, 200);
122
+ $this->disable_resize();
123
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-large.jpg');
124
+ $this->assertNotContains('Resized original',
125
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
126
+ $this->view_edit_image();
127
+ $this->assertContains('Dimensions: 1080 × 330',
128
+ self::$driver->findElement(WebDriverBy::cssSelector('div.misc-pub-dimensions'))->getText());
129
+ }
130
  }
test/integration/IntegrationTestCase.php CHANGED
@@ -62,4 +62,43 @@ abstract class IntegrationTestCase extends PHPUnit_Framework_TestCase {
62
  }
63
  self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
64
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
62
  }
63
  self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
64
  }
65
+
66
+ protected function enable_resize($width, $height) {
67
+ $url = wordpress('/wp-admin/options-media.php');
68
+ if (self::$driver->getCurrentUrl() != $url) {
69
+ self::$driver->get($url);
70
+ }
71
+ $element = self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_enabled'));
72
+ if (!$element->getAttribute('checked')) {
73
+ $element->click();
74
+ }
75
+ self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_width'))->clear()->sendKeys($width);
76
+ self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_height'))->clear()->sendKeys($height);
77
+ self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
78
+ }
79
+
80
+ protected function disable_resize() {
81
+ $url = wordpress('/wp-admin/options-media.php');
82
+ if (self::$driver->getCurrentUrl() != $url) {
83
+ self::$driver->get($url);
84
+ }
85
+ $element = self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_enabled'));
86
+ if ($element->getAttribute('checked')) {
87
+ $element->click();
88
+ }
89
+ self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
90
+ }
91
+
92
+ protected function view_edit_image($image_title = 'input-large') {
93
+ $url = wordpress('/wp-admin/upload.php');
94
+ if (self::$driver->getCurrentUrl() != $url) {
95
+ self::$driver->get($url);
96
+ }
97
+ if (wordpress_version() >= 43) {
98
+ $selector = "//span[text()='" . $image_title . "']";
99
+ } else {
100
+ $selector = "//a[contains(text(),'" . $image_title . "')]";
101
+ }
102
+ self::$driver->findElement(WebDriverBy::xpath($selector))->click();
103
+ }
104
  }
test/integration/SettingsIntegrationTest.php CHANGED
@@ -89,7 +89,7 @@ class SettingsIntegrationTest extends IntegrationTestCase {
89
  public function testShouldShowTotalImagesInfo() {
90
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
91
  $statuses = array_map('innerText', $elements);
92
- $this->assertContains('With these settings you can compress 100 images for free each month.', $statuses);
93
  }
94
 
95
  public function testShouldUpdateTotalImagesInfo() {
@@ -97,11 +97,11 @@ class SettingsIntegrationTest extends IntegrationTestCase {
97
  WebDriverBy::xpath('//input[@type="checkbox" and @name="tinypng_sizes[0]" and @checked="checked"]'));
98
  $element->click();
99
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
100
- WebDriverBy::cssSelector('#tiny-image-sizes-notice'), 'With these settings you can compress 125 images for free each month.'));
101
  // Not really necessary anymore to assert this.
102
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
103
  $statuses = array_map('innerText', $elements);
104
- $this->assertContains('With these settings you can compress 125 images for free each month.', $statuses);
105
  }
106
 
107
  public function testShouldShowCorrectNoImageSizesInfo() {
@@ -111,11 +111,43 @@ class SettingsIntegrationTest extends IntegrationTestCase {
111
  $element->click();
112
  }
113
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
114
- WebDriverBy::cssSelector('#tiny-image-sizes-notice'), 'With these settings no images will be compressed.'));
115
  // Not really necessary anymore to assert this.
116
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
117
  $statuses = array_map('innerText', $elements);
118
- $this->assertContains('With these settings no images will be compressed.', $statuses);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
 
121
  public function testStatusPresenceOK() {
89
  public function testShouldShowTotalImagesInfo() {
90
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
91
  $statuses = array_map('innerText', $elements);
92
+ $this->assertContains('Each selected size counts as a compression. With these settings you can compress at least 100 images for free each month.', $statuses);
93
  }
94
 
95
  public function testShouldUpdateTotalImagesInfo() {
97
  WebDriverBy::xpath('//input[@type="checkbox" and @name="tinypng_sizes[0]" and @checked="checked"]'));
98
  $element->click();
99
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
100
+ WebDriverBy::cssSelector('#tiny-image-sizes-notice'), 'Each selected size counts as a compression. With these settings you can compress at least 125 images for free each month.'));
101
  // Not really necessary anymore to assert this.
102
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
103
  $statuses = array_map('innerText', $elements);
104
+ $this->assertContains('Each selected size counts as a compression. With these settings you can compress at least 125 images for free each month.', $statuses);
105
  }
106
 
107
  public function testShouldShowCorrectNoImageSizesInfo() {
111
  $element->click();
112
  }
113
  self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
114
+ WebDriverBy::cssSelector('#tiny-image-sizes-notice'), 'Each selected size counts as a compression. With these settings no images will be compressed.'));
115
  // Not really necessary anymore to assert this.
116
  $elements = self::$driver->findElement(WebDriverBy::id('tiny-image-sizes-notice'))->findElements(WebDriverBy::tagName('p'));
117
  $statuses = array_map('innerText', $elements);
118
+ $this->assertContains('Each selected size counts as a compression. With these settings no images will be compressed.', $statuses);
119
+ }
120
+
121
+ public function testShouldShowResizingWhenOriginalEnabled() {
122
+ $element = self::$driver->findElement(WebDriverBy::id('tinypng_sizes_0'));
123
+ if (!$element->getAttribute('checked')) {
124
+ $element->click();
125
+ }
126
+ $labels = self::$driver->findElements(WebDriverBy::tagName('label'));
127
+ $texts = array_map('innerText', $labels);
128
+ $this->assertContains('Resize and compress orginal images to fit within:', $texts);
129
+ $paragraphs = self::$driver->findElements(WebDriverBy::tagName('p'));
130
+ $texts = array_map('innerText', $paragraphs);
131
+ $this->assertNotContains('Enable the compression of the original image size to configure resizing.', $texts);
132
+ }
133
+
134
+ public function testShouldNotShowResizingWhenOriginalDisabled() {
135
+ $element = self::$driver->findElement(WebDriverBy::id('tinypng_sizes_0'));
136
+ if ($element->getAttribute('checked')) {
137
+ $element->click();
138
+ }
139
+ $labels = self::$driver->findElements(WebDriverBy::tagName('label'));
140
+ $texts = array_map('innerText', $labels);
141
+ $this->assertNotContains('Resize and compress orginal images to fit within:', $texts);
142
+ $paragraphs = self::$driver->findElements(WebDriverBy::tagName('p'));
143
+ $texts = array_map('innerText', $paragraphs);
144
+ $this->assertContains('Enable the compression of the original image size to configure resizing.', $texts);
145
+ }
146
+
147
+ public function testShouldPersistResizingSettings() {
148
+ $this->enable_resize(123, 456);
149
+ $this->assertEquals('123', self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_width'))->getAttribute('value'));
150
+ $this->assertEquals('456', self::$driver->findElement(WebDriverBy::id('tinypng_resize_original_height'))->getAttribute('value'));
151
  }
152
 
153
  public function testStatusPresenceOK() {
test/mock-tinypng-webservice/common.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ define('SESSION_FILE', '/tmp/session.dat');
4
+
5
+ if (file_exists(SESSION_FILE)) {
6
+ $session = unserialize(file_get_contents(SESSION_FILE));
7
+ } else {
8
+ $session = array('Compression-Count' => 0);
9
+ }
10
+
11
+ function save_session() {
12
+ global $session;
13
+ if ($session) {
14
+ file_put_contents(SESSION_FILE, serialize($session));
15
+ } elseif (file_exists(SESSION_FILE)) {
16
+ unlink(SESSION_FILE);
17
+ }
18
+ }
19
+ register_shutdown_function('save_session');
20
+
21
+ function get_api_key() {
22
+ $request_headers = apache_request_headers();
23
+ if (!isset($request_headers['Authorization'])) {
24
+ return null;
25
+ }
26
+ $basic_auth = base64_decode(str_replace('Basic ', '', $request_headers['Authorization']));
27
+ return next(explode(':', $basic_auth));
28
+ }
29
+
30
+ function get_json_body() {
31
+ return json_decode(file_get_contents("php://input"));
32
+ }
33
+
34
+ function mock_invalid_response() {
35
+ global $session;
36
+
37
+ header('HTTP/1.1 401 Unauthorized');
38
+ header("Content-Type: application/json; charset=utf-8");
39
+
40
+ $response = array(
41
+ "error" => "Unauthorized",
42
+ "message" => "Credentials are invalid"
43
+ );
44
+ return json_encode($response);
45
+ }
test/mock-tinypng-webservice/output-resized.jpg ADDED
Binary file
test/mock-tinypng-webservice/output.php CHANGED
@@ -1,13 +1,33 @@
1
  <?php
2
  ob_start();
3
 
 
 
4
  if (preg_match('#output/.+[.](png|jpg)$#', $_SERVER['REQUEST_URI'], $match)) {
5
  $file = str_replace('/', '-', $match[0]);
 
6
  $mime = $match[1] == 'jpg' ? 'image/jpeg' : "image/$ext";
7
  } else {
8
  $file = null;
9
  }
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if ($file && file_exists($file)) {
12
  header("Content-Type: $mime");
13
  header('Content-Disposition: attachment');
@@ -16,4 +36,4 @@ if ($file && file_exists($file)) {
16
  header("HTTP/1.1 404 Not Found");
17
  }
18
 
19
- ob_end_flush();
1
  <?php
2
  ob_start();
3
 
4
+ require_once('common.php');
5
+
6
  if (preg_match('#output/.+[.](png|jpg)$#', $_SERVER['REQUEST_URI'], $match)) {
7
  $file = str_replace('/', '-', $match[0]);
8
+ $ext = $match[1];
9
  $mime = $match[1] == 'jpg' ? 'image/jpeg' : "image/$ext";
10
  } else {
11
  $file = null;
12
  }
13
 
14
+ $api_key = get_api_key();
15
+ if (!is_null($api_key)) {
16
+ $data = get_json_body();
17
+ if (is_null($data) || $api_key != 'JPG123') {
18
+ mock_invalid_response();
19
+ ob_end_flush();
20
+ exit();
21
+ }
22
+
23
+ $resize = $data->resize;
24
+ if ($resize->method) {
25
+ $file = "output-resized.$ext";
26
+ header("Image-Width: {$resize->width}");
27
+ header("Image-Height: {$resize->height}");
28
+ }
29
+ }
30
+
31
  if ($file && file_exists($file)) {
32
  header("Content-Type: $mime");
33
  header('Content-Disposition: attachment');
36
  header("HTTP/1.1 404 Not Found");
37
  }
38
 
39
+ ob_end_flush();
test/mock-tinypng-webservice/reset.php CHANGED
@@ -1,7 +1,4 @@
1
  <?php
2
 
3
- define('SESSION_FILE', '/tmp/session.dat');
4
-
5
- if (file_exists(SESSION_FILE)) {
6
- unlink(SESSION_FILE);
7
- }
1
  <?php
2
 
3
+ require('common.php');
4
+ $session = null;
 
 
 
test/mock-tinypng-webservice/shrink.php CHANGED
@@ -1,13 +1,7 @@
1
  <?php
2
  ob_start();
3
 
4
- define('SESSION_FILE', '/tmp/session.dat');
5
-
6
- if (file_exists(SESSION_FILE)) {
7
- $session = unserialize(file_get_contents(SESSION_FILE));
8
- } else {
9
- $session = array('Compression-Count' => 0);
10
- }
11
 
12
  function mock_png_response() {
13
  global $session;
@@ -15,10 +9,11 @@ function mock_png_response() {
15
  $session['Compression-Count'] += 1;
16
  header('HTTP/1.1 201 Created');
17
  header("Location: http://webservice/output/example.png");
 
18
  header("Compression-Count: {$session['Compression-Count']}");
19
  $response = array(
20
  "input" => array("size" => 161885, "type" => "image/png"),
21
- "output" => array("size" => 151021, "type" => "image.png", "ratio" => 0.933)
22
  );
23
  return json_encode($response);
24
  }
@@ -29,6 +24,7 @@ function mock_jpg_response() {
29
  $session['Compression-Count'] += 1;
30
  header('HTTP/1.1 201 Created');
31
  header("Location: http://webservice/output/example.jpg");
 
32
  header("Compression-Count: {$session['Compression-Count']}");
33
 
34
  $response = array(
@@ -44,6 +40,7 @@ function mock_large_response() {
44
  $session['Compression-Count'] += 1;
45
  header('HTTP/1.1 201 Created');
46
  header("Location: http://webservice/output/large.png");
 
47
  header("Compression-Count: {$session['Compression-Count']}");
48
 
49
  $response = array(
@@ -53,19 +50,6 @@ function mock_large_response() {
53
  return json_encode($response);
54
  }
55
 
56
- function mock_invalid_response() {
57
- global $session;
58
-
59
- header('HTTP/1.1 401 Unauthorized');
60
- header("Content-Type: application/json; charset=utf-8");
61
-
62
- $response = array(
63
- "error" => "Unauthorized",
64
- "message" => "Credentials are invalid"
65
- );
66
- return json_encode($response);
67
- }
68
-
69
  function mock_empty_response() {
70
  global $session;
71
 
@@ -100,17 +84,12 @@ function mock_invalid_json_response() {
100
  $session['Compression-Count'] += 1;
101
  header('HTTP/1.1 201 Created');
102
  header("Location: http://webservice/output/example.png");
 
103
  header("Compression-Count: {$session['Compression-Count']}");
104
  return '{invalid: json}';
105
  }
106
 
107
- $request_headers = apache_request_headers();
108
- $basic_auth = base64_decode(str_replace('Basic ', '', $request_headers['Authorization']));
109
- $api_key_elements = explode(':', $basic_auth);
110
- $api_key = $api_key_elements[1];
111
-
112
- header("Content-Type: application/json; charset=utf-8");
113
-
114
  if ($api_key == 'PNG123') {
115
  if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
116
  echo mock_empty_response();
@@ -127,7 +106,7 @@ if ($api_key == 'PNG123') {
127
  if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
128
  echo mock_empty_response();
129
  } else {
130
- echo mock_invald_json_response();
131
  }
132
  } else if ($api_key == 'LIMIT123') {
133
  echo mock_limit_reached_response();
@@ -135,6 +114,4 @@ if ($api_key == 'PNG123') {
135
  echo mock_invalid_response();
136
  }
137
 
138
- file_put_contents(SESSION_FILE, serialize($session));
139
-
140
- ob_end_flush();
1
  <?php
2
  ob_start();
3
 
4
+ require_once('common.php');
 
 
 
 
 
 
5
 
6
  function mock_png_response() {
7
  global $session;
9
  $session['Compression-Count'] += 1;
10
  header('HTTP/1.1 201 Created');
11
  header("Location: http://webservice/output/example.png");
12
+ header("Content-Type: application/json; charset=utf-8");
13
  header("Compression-Count: {$session['Compression-Count']}");
14
  $response = array(
15
  "input" => array("size" => 161885, "type" => "image/png"),
16
+ "output" => array("size" => 151021, "type" => "image/png", "ratio" => 0.933)
17
  );
18
  return json_encode($response);
19
  }
24
  $session['Compression-Count'] += 1;
25
  header('HTTP/1.1 201 Created');
26
  header("Location: http://webservice/output/example.jpg");
27
+ header("Content-Type: application/json; charset=utf-8");
28
  header("Compression-Count: {$session['Compression-Count']}");
29
 
30
  $response = array(
40
  $session['Compression-Count'] += 1;
41
  header('HTTP/1.1 201 Created');
42
  header("Location: http://webservice/output/large.png");
43
+ header("Content-Type: application/json; charset=utf-8");
44
  header("Compression-Count: {$session['Compression-Count']}");
45
 
46
  $response = array(
50
  return json_encode($response);
51
  }
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  function mock_empty_response() {
54
  global $session;
55
 
84
  $session['Compression-Count'] += 1;
85
  header('HTTP/1.1 201 Created');
86
  header("Location: http://webservice/output/example.png");
87
+ header("Content-Type: application/json; charset=utf-8");
88
  header("Compression-Count: {$session['Compression-Count']}");
89
  return '{invalid: json}';
90
  }
91
 
92
+ $api_key = get_api_key();
 
 
 
 
 
 
93
  if ($api_key == 'PNG123') {
94
  if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
95
  echo mock_empty_response();
106
  if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
107
  echo mock_empty_response();
108
  } else {
109
+ echo mock_invalid_json_response();
110
  }
111
  } else if ($api_key == 'LIMIT123') {
112
  echo mock_limit_reached_response();
114
  echo mock_invalid_response();
115
  }
116
 
117
+ ob_end_flush();
 
 
test/unit/TinyMetadataTest.php CHANGED
@@ -38,4 +38,22 @@ class Tiny_Metadata_Test extends TinyTestCase {
38
  $uncompressed_sizes = array(Tiny_Metadata::ORIGINAL, "custom-size");
39
  $this->assertEquals($uncompressed_sizes, $this->subject->get_uncompressed_sizes($tinify_sizes));
40
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
38
  $uncompressed_sizes = array(Tiny_Metadata::ORIGINAL, "custom-size");
39
  $this->assertEquals($uncompressed_sizes, $this->subject->get_uncompressed_sizes($tinify_sizes));
40
  }
41
+
42
+ public function testUpdateWpMetadataShouldNotUpdateWithNoResizedOriginal() {
43
+ $wp_metadata = array(
44
+ 'width' => 2000,
45
+ 'height' => 1000
46
+ );
47
+ $this->assertEquals(array('width' => 2000, 'height' => 1000), $this->subject->update_wp_metadata($wp_metadata));
48
+ }
49
+
50
+ public function testUpdateWpMetadataShouldUpdateWithResizedOriginal() {
51
+ $wp_metadata = array(
52
+ 'width' => 2000,
53
+ 'height' => 1000
54
+ );
55
+ $this->subject->add_request();
56
+ $this->subject->add_response(array('output' => array('width' => 200, 'height' => 100)));
57
+ $this->assertEquals(array('width' => 200, 'height' => 100), $this->subject->update_wp_metadata($wp_metadata));
58
+ }
59
  }
test/unit/TinyPluginTest.php CHANGED
@@ -34,19 +34,32 @@ class Tiny_Plugin_Test extends TinyTestCase {
34
  $input = filesize($file);
35
  switch ($key) {
36
  case "thumbnail":
37
- $output = 81; break;
 
 
 
38
  case "medium":
39
- $output = 768; break;
 
 
 
40
  case "large":
41
- $output = 6789; break;
 
 
 
42
  case "post-thumbnail":
43
- $output = 1000; break;
 
 
 
44
  default:
45
  $output = 10000;
 
 
46
  }
47
  $this->vfs->getChild(vfsStream::path($file))->truncate($output);
48
- return array('input' => array('size' => $input), 'output' => array('size' => $output));
49
-
50
  }
51
 
52
  public function testInitShouldAddFilters() {
@@ -120,9 +133,9 @@ class Tiny_Plugin_Test extends TinyTestCase {
120
  unset($metadata[$key]['start']);
121
  }
122
  $this->assertEquals(array(
123
- 0 => array('input' => array('size' => 12345), 'output' => array('size' => 10000)),
124
- 'large' => array('input' => array('size' => 10000), 'output' => array('size' => 6789)),
125
- 'post-thumbnail' => array('input' => array('size' => 1234), 'output' => array('size' => 1000)),
126
  ), $metadata);
127
  }
128
 
@@ -186,4 +199,4 @@ class Tiny_Plugin_Test extends TinyTestCase {
186
  $this->subject->compress_attachment($testmeta, 1);
187
  $this->assertEquals(2, count($this->wp->getCalls('update_post_meta')));
188
  }
189
- }
34
  $input = filesize($file);
35
  switch ($key) {
36
  case "thumbnail":
37
+ $output = 81;
38
+ $width = '150';
39
+ $height = '150';
40
+ break;
41
  case "medium":
42
+ $output = 768;
43
+ $width = '300';
44
+ $height = '300';
45
+ break;
46
  case "large":
47
+ $output = 6789;
48
+ $width = '1024';
49
+ $height = '1024';
50
+ break;
51
  case "post-thumbnail":
52
+ $output = 1000;
53
+ $width = '800';
54
+ $height = '500';
55
+ break;
56
  default:
57
  $output = 10000;
58
+ $width = '4000';
59
+ $height = '3000';
60
  }
61
  $this->vfs->getChild(vfsStream::path($file))->truncate($output);
62
+ return array('input' => array('size' => $input), 'output' => array('size' => $output, 'width' => $width, 'height' => $height));
 
63
  }
64
 
65
  public function testInitShouldAddFilters() {
133
  unset($metadata[$key]['start']);
134
  }
135
  $this->assertEquals(array(
136
+ 0 => array('input' => array('size' => 12345), 'output' => array('size' => 10000, 'width' => 4000, 'height' => 3000)),
137
+ 'large' => array('input' => array('size' => 10000), 'output' => array('size' => 6789, 'width' => 1024, 'height' => 1024)),
138
+ 'post-thumbnail' => array('input' => array('size' => 1234), 'output' => array('size' => 1000, 'width' => 800, 'height' => 500)),
139
  ), $metadata);
140
  }
141
 
199
  $this->subject->compress_attachment($testmeta, 1);
200
  $this->assertEquals(2, count($this->wp->getCalls('update_post_meta')));
201
  }
202
+ }
test/unit/TinySettingsTest.php CHANGED
@@ -14,6 +14,7 @@ class Tiny_Settings_Test extends TinyTestCase {
14
  $this->assertEquals(array(
15
  array('media', 'tinypng_api_key'),
16
  array('media', 'tinypng_sizes'),
 
17
  array('media', 'tinypng_status')
18
  ), $this->wp->getCalls('register_setting'));
19
  }
@@ -28,6 +29,7 @@ class Tiny_Settings_Test extends TinyTestCase {
28
  $this->assertEquals(array(
29
  array('tinypng_api_key', 'TinyPNG API key', array($this->subject, 'render_api_key'), 'media', 'tinypng_settings', array('label_for' => 'tinypng_api_key')),
30
  array('tinypng_sizes', 'File compression', array($this->subject, 'render_sizes'), 'media', 'tinypng_settings'),
 
31
  array('tinypng_status', 'Connection status', array($this->subject, 'render_pending_status'), 'media', 'tinypng_settings')
32
  ), $this->wp->getCalls('add_settings_field'));
33
  }
@@ -99,4 +101,49 @@ class Tiny_Settings_Test extends TinyTestCase {
99
  array('width' => 0, 'height' => 888, 'tinify' => true),
100
  $sizes["additional_size_no_width"]);
101
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
14
  $this->assertEquals(array(
15
  array('media', 'tinypng_api_key'),
16
  array('media', 'tinypng_sizes'),
17
+ array('media', 'tinypng_resize_original'),
18
  array('media', 'tinypng_status')
19
  ), $this->wp->getCalls('register_setting'));
20
  }
29
  $this->assertEquals(array(
30
  array('tinypng_api_key', 'TinyPNG API key', array($this->subject, 'render_api_key'), 'media', 'tinypng_settings', array('label_for' => 'tinypng_api_key')),
31
  array('tinypng_sizes', 'File compression', array($this->subject, 'render_sizes'), 'media', 'tinypng_settings'),
32
+ array('tinypng_resize_original', 'Resize original', array($this->subject, 'render_resize'), 'media', 'tinypng_settings'),
33
  array('tinypng_status', 'Connection status', array($this->subject, 'render_pending_status'), 'media', 'tinypng_settings')
34
  ), $this->wp->getCalls('add_settings_field'));
35
  }
101
  array('width' => 0, 'height' => 888, 'tinify' => true),
102
  $sizes["additional_size_no_width"]);
103
  }
104
+
105
+ public function testShouldReturnResizeEnabled() {
106
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on'));
107
+ $this->assertEquals(true, $this->subject->get_resize_enabled());
108
+ }
109
+
110
+ public function testShouldReturnResizeNotEnabledWithoutConfiguration() {
111
+ $this->wp->addOption("tinypng_resize_original", array());
112
+ $this->assertEquals(false, $this->subject->get_resize_enabled());
113
+ }
114
+
115
+ public function testShouldReturnResizeOptionsWithWidthAndHeight() {
116
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '800', 'height' => '600'));
117
+ $this->assertEquals(array('method' => 'fit', 'width' => 800, 'height' => 600), $this->subject->get_resize_options());
118
+ }
119
+
120
+ public function testShouldReturnResizeOptionsWithoutWidth() {
121
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '', 'height' => '600'));
122
+ $this->assertEquals(array('method' => 'scale', 'height' => 600), $this->subject->get_resize_options());
123
+ }
124
+
125
+ public function testShouldReturnResizeOptionsWithoutHeight() {
126
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '800', 'height' => '',));
127
+ $this->assertEquals(array('method' => 'scale', 'width' => 800), $this->subject->get_resize_options());
128
+ }
129
+
130
+ public function testShouldReturnResizeOptionsWithInvaledWidth() {
131
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '-1', 'height' => '600'));
132
+ $this->assertEquals(array('method' => 'scale', 'height' => 600), $this->subject->get_resize_options());
133
+ }
134
+
135
+ public function testShouldReturnResizeOptionsWithInvaledHeight() {
136
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '800', 'height' => '-1'));
137
+ $this->assertEquals(array('method' => 'scale', 'width' => 800), $this->subject->get_resize_options());
138
+ }
139
+
140
+ public function testShouldNotReturnResizeOptionsWithoutWithAndHeight() {
141
+ $this->wp->addOption("tinypng_resize_original", array('enabled' => 'on', 'width' => '', 'height' => ''));
142
+ $this->assertEquals(false, $this->subject->get_resize_options());
143
+ }
144
+
145
+ public function testShouldNotReturnResizeOptionsWhenNotEnabled() {
146
+ $this->wp->addOption("tinypng_resize_original", array('width' => '800', 'height' => '600'));
147
+ $this->assertEquals(false, $this->subject->get_resize_options());
148
+ }
149
  }
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: 1.4.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * License: GPLv2 or later
@@ -24,4 +24,4 @@ $tiny_plugin = new Tiny_Plugin();
24
 
25
  if (!defined('TINY_DEBUG')) {
26
  define('TINY_DEBUG', null);
27
- }
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: 1.5.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * License: GPLv2 or later
24
 
25
  if (!defined('TINY_DEBUG')) {
26
  define('TINY_DEBUG', null);
27
+ }