PluginProbe ʕ •ᴥ•ʔ
TinyPNG – JPEG, PNG & WebP image compression / 1.6.0
TinyPNG – JPEG, PNG & WebP image compression v1.6.0
3.7.0 3.6.14 trunk 1.0.0 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.4.0 1.5.0 1.6.0 1.7.0 1.7.1 1.7.2 2.0.0 2.0.1 2.0.2 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.0.0 3.0.1 3.1.0 3.2.0 3.2.1 3.3 3.4 3.4.1 3.4.2 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.6.0 3.6.1 3.6.10 3.6.11 3.6.12 3.6.13 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
tiny-compress-images / src / class-tiny-plugin.php
tiny-compress-images / src Last commit date
config 10 years ago languages 10 years ago scripts 10 years ago styles 10 years ago views 10 years ago cacert.pem 11 years ago class-tiny-compress-curl.php 10 years ago class-tiny-compress-fopen.php 10 years ago class-tiny-compress.php 10 years ago class-tiny-exception.php 11 years ago class-tiny-metadata.php 10 years ago class-tiny-notices.php 11 years ago class-tiny-php.php 11 years ago class-tiny-plugin.php 10 years ago class-tiny-settings.php 10 years ago class-tiny-wp-base.php 10 years ago
class-tiny-plugin.php
289 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015 Voormedia 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_Plugin extends Tiny_WP_Base {
22 const MEDIA_COLUMN = self::NAME;
23 const MEDIA_COLUMN_HEADER = 'Compression';
24 const DATETIME_FORMAT = 'Y-m-d G:i:s';
25
26 private $settings;
27 private $twig;
28
29 public static function jpeg_quality() {
30 return 95;
31 }
32
33 public function __construct() {
34 parent::__construct();
35
36 $this->settings = new Tiny_Settings();
37 if (is_admin()) {
38 add_action('admin_menu', $this->get_method('admin_menu'));
39 }
40 }
41
42 public function set_compressor($compressor) {
43 $this->settings->set_compressor($compressor);
44 }
45
46 public function init() {
47 add_filter('jpeg_quality', $this->get_static_method('jpeg_quality'));
48 add_filter('wp_editor_set_quality', $this->get_static_method('jpeg_quality'));
49 add_filter('wp_generate_attachment_metadata', $this->get_method('compress_attachment'), 10, 2);
50 load_plugin_textdomain(self::NAME, false, dirname(plugin_basename(__FILE__)) . '/languages');
51 }
52
53 public function admin_init() {
54 add_filter('manage_media_columns', $this->get_method('add_media_columns'));
55 add_action('manage_media_custom_column', $this->get_method('render_media_column'), 10, 2);
56 add_action('wp_ajax_tiny_compress_image', $this->get_method('compress_image'));
57 add_action('admin_action_tiny_bulk_compress', $this->get_method('bulk_compress'));
58 add_action('admin_enqueue_scripts', $this->get_method('enqueue_scripts'));
59 $plugin = plugin_basename(dirname(dirname(__FILE__)) . '/tiny-compress-images.php');
60 add_filter("plugin_action_links_$plugin", $this->get_method('add_plugin_links'));
61 add_thickbox();
62 }
63
64 public function admin_menu() {
65 add_media_page(
66 self::translate('Compress JPEG & PNG Images'), self::translate('Compress All Images'),
67 'upload_files', 'tiny-bulk-compress', $this->get_method('bulk_compress_page')
68 );
69 }
70
71 public function add_plugin_links($current_links) {
72 $additional[] = sprintf('<a href="options-media.php#%s">%s</a>', self::NAME,
73 self::translate_escape('Settings'));
74 return array_merge($additional, $current_links);
75 }
76
77 public function enqueue_scripts($hook) {
78 wp_enqueue_style(self::NAME .'_admin', plugins_url('/styles/admin.css', __FILE__),
79 array(), self::plugin_version());
80
81 $handle = self::NAME .'_admin';
82 wp_register_script($handle, plugins_url('/scripts/admin.js', __FILE__),
83 array(), self::plugin_version(), true);
84
85 // WordPress < 3.3 does not handle multidimensional arrays
86 wp_localize_script($handle, 'tinyCompress', array(
87 'nonce' => wp_create_nonce('tiny-compress'),
88 'wpVersion' => self::wp_version(),
89 'pluginVersion' => self::plugin_version(),
90 'L10nAllDone' => self::translate('All images are processed'),
91 'L10nBulkAction' => self::translate('Compress Images'),
92 'L10nCompressing' => self::translate('Compressing'),
93 'L10nCompressions' => self::translate('compressions'),
94 'L10nError' => self::translate('Error'),
95 'L10nInternalError' => self::translate('Internal error'),
96 'L10nOutOf' => self::translate('out of'),
97 'L10nWaiting' => self::translate('Waiting'),
98 ));
99 wp_enqueue_script($handle);
100 }
101
102 private function compress($metadata, $attachment_id) {
103 $mime_type = get_post_mime_type($attachment_id);
104 $tiny_metadata = new Tiny_Metadata($attachment_id, $metadata);
105
106 if ($this->settings->get_compressor() === null || strpos($mime_type, 'image/') !== 0) {
107 return array($tiny_metadata, null);
108 }
109
110 $success = 0;
111 $failed = 0;
112
113 $compressor = $this->settings->get_compressor();
114 $active_tinify_sizes = $this->settings->get_active_tinify_sizes();
115 $uncompressed_sizes = $tiny_metadata->get_uncompressed_sizes($active_tinify_sizes);
116
117 foreach ($uncompressed_sizes as $uncompressed_size) {
118 try {
119 $tiny_metadata->add_request($uncompressed_size);
120 $tiny_metadata->update();
121
122 $resize = $tiny_metadata->is_resizable($uncompressed_size) ? $this->settings->get_resize_options() : false;
123 $response = $compressor->compress_file($tiny_metadata->get_filename($uncompressed_size), $resize);
124
125 $tiny_metadata->add_response($response, $uncompressed_size);
126 $tiny_metadata->update();
127 $success++;
128 } catch (Tiny_Exception $e) {
129 $tiny_metadata->add_exception($e, $uncompressed_size);
130 $tiny_metadata->update();
131 $failed++;
132 }
133 }
134
135 return array($tiny_metadata, array('success' => $success, 'failed' => $failed));
136 }
137
138 public function compress_attachment($metadata, $attachment_id) {
139 if (!empty($metadata)) {
140 list($tiny_metadata, $result) = $this->compress($metadata, $attachment_id);
141 return $tiny_metadata->update_wp_metadata($metadata);
142 }
143 }
144
145 public function compress_image() {
146 if (!$this->check_ajax_referer()) {
147 exit();
148 }
149 $json = !empty($_POST['json']) && $_POST['json'];
150 if (!current_user_can('upload_files')) {
151 $message = self::translate("You don't have permission to work with uploaded files") . '.';
152 echo $json ? json_encode(array('error' => $message)) : $message;
153 exit();
154 }
155 if (empty($_POST['id'])) {
156 $message = self::translate("Not a valid media file") . '.';
157 echo $json ? json_encode(array('error' => $message)) : $message;
158 exit();
159 }
160 $id = intval($_POST['id']);
161 $metadata = wp_get_attachment_metadata($id);
162 if (!is_array($metadata)) {
163 $message = self::translate("Could not find metadata of media file") . '.';
164 echo $json ? json_encode(array('error' => $message)) : $message;
165 exit;
166 }
167
168 list($tiny_metadata, $result) = $this->compress($metadata, $id);
169 wp_update_attachment_metadata($id, $tiny_metadata->update_wp_metadata($metadata));
170
171 if ($json) {
172 $result['message'] = $tiny_metadata->get_latest_error();
173 $result['status'] = $this->settings->get_status();
174 $result['thumbnail'] = $tiny_metadata->get_url('thumbnail');
175 echo json_encode($result);
176 } else {
177 echo $this->render_compress_details($tiny_metadata);
178 }
179
180 exit();
181 }
182
183 public function bulk_compress() {
184 check_admin_referer('bulk-media');
185
186 if (empty($_REQUEST['media']) || !is_array( $_REQUEST['media'])) {
187 return;
188 }
189
190 $ids = implode('-', array_map('intval', $_REQUEST['media']));
191 wp_redirect(add_query_arg(
192 '_wpnonce',
193 wp_create_nonce('tiny-bulk-compress'),
194 admin_url("upload.php?page=tiny-bulk-compress&ids=$ids")
195 ));
196 exit();
197 }
198
199 public function add_media_columns($columns) {
200 $columns[self::MEDIA_COLUMN] = self::translate(self::MEDIA_COLUMN_HEADER);
201 return $columns;
202 }
203
204 public function render_media_column($column, $id) {
205 if ($column === self::MEDIA_COLUMN) {
206 $this->render_compress_details(new Tiny_Metadata($id));
207 }
208 }
209
210 private function render_compress_details($tiny_metadata) {
211 $active = $this->settings->get_active_tinify_sizes();
212 $uncompressed = $tiny_metadata->get_uncompressed_sizes($active);
213 $not_compressed_active = count($tiny_metadata->get_not_compressed_active_sizes($active));
214 $savings = $tiny_metadata->get_savings();
215 $error = $tiny_metadata->get_latest_error();
216 $missing = $tiny_metadata->get_missing_count();
217 $modified = $tiny_metadata->get_modified_count();
218 $compressing = (count($uncompressed) > 0) ? count($uncompressed) : count($active);
219
220 if ($tiny_metadata->get_in_progress_count() > 0) {
221 include(dirname(__FILE__) . '/views/compress-details-processing.php');
222 } else {
223 include(dirname(__FILE__) . '/views/compress-details.php');
224 }
225 }
226
227 public function bulk_compress_page() {
228 global $wpdb;
229
230 echo '<div class="wrap" id="tiny-bulk-compress">';
231 echo '<h2>' . self::translate('Compress JPEG & PNG Images') . '</h2>';
232 if (empty($_POST['tiny-bulk-compress']) && empty($_REQUEST['ids'])) {
233 $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);
234 $image_count = $result[0]['count'];
235 $sizes_count = count($this->settings->get_active_tinify_sizes());
236
237 echo '<p>';
238 echo self::translate_escape("Use this tool to compress all images in your media library") . '. ';
239 echo self::translate_escape("Only images that have not been compressed will be compressed") . '. ';
240 echo '</p>';
241 echo '<p>';
242 echo 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) . '. ';
243 echo sprintf(self::translate_escape('This results in %d compressions at most'), $image_count*$sizes_count) . '. ';
244 echo '</p>';
245 echo '<p>';
246 echo self::translate_escape("To begin, just press the button below") . '. ';
247 echo '</p>';
248
249 echo '<form method="POST" action="?page=tiny-bulk-compress">';
250 echo '<input type="hidden" name="_wpnonce" value="' . wp_create_nonce('tiny-bulk-compress') . '">';
251 echo '<input type="hidden" name="tiny-bulk-compress" value="1">';
252 echo '<p>';
253 echo '<button class="button button-primary button-large" type="submit">';
254 echo self::translate_escape('Compress All Images');
255 echo '</button>';
256 echo '</p>';
257 echo '</form>';
258 } else {
259 check_admin_referer('tiny-bulk-compress');
260
261 if (!empty($_REQUEST['ids'])) {
262 $ids = implode(',', array_map('intval', explode('-', $_REQUEST['ids'])));
263 $cond = "AND ID IN($ids)";
264 } else {
265 $cond = "";
266 }
267
268 // Get all ids and names of the images and not the whole objects which will only fill memory
269 $items = $wpdb->get_results("SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' $cond ORDER BY ID DESC", ARRAY_A);
270
271 echo '<p>';
272 echo self::translate_escape("Please be patient while the images are being compressed") . '. ';
273 echo self::translate_escape("This can take a while if you have many images") . '. ';
274 echo self::translate_escape("Do not navigate away from this page because it will stop the process") . '. ';
275 echo self::translate_escape("You will be notified via this page when the processing is done") . '.';
276 echo "</p>";
277
278 echo '<div id="tiny-status"><p>'. self::translate_escape('Compressions this month') . sprintf(' <span>%d</span></p></div>', $this->settings->get_status());
279 echo '<div id="tiny-progress"><p>'. self::translate_escape('Processing') . ' <span>0</span> ' . self::translate_escape('out of') . sprintf(' %d </p></div>', count($items));
280 echo '<div id="media-items">';
281 echo '</div>';
282
283 echo '<script type="text/javascript">jQuery(function() { tinyBulkCompress('. json_encode($items) . ')})</script>';
284 }
285
286 echo '</div>';
287 }
288 }
289