Skip to content

Commit 4c33314

Browse files
author
Jacob Middag
committed
Improved bulk compression
1 parent 7db683d commit 4c33314

15 files changed

Lines changed: 307 additions & 39 deletions

src/class-tiny-metadata.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Tiny_Metadata {
2525
private $id;
2626
private $values;
2727
private $filenames;
28+
private $urls;
2829

2930
public function __construct($id, $wp_metadata=null) {
3031
$this->id = $id;
@@ -41,21 +42,26 @@ public function __construct($id, $wp_metadata=null) {
4142

4243
private function parse_wp_metadata($wp_metadata) {
4344
$this->filenames = array();
45+
$this->urls = array();
4446
if (!is_array($wp_metadata)) {
4547
return;
4648
}
4749

4850
$path_info = pathinfo($wp_metadata['file']);
4951
$upload_dir = wp_upload_dir();
50-
$prefix = $upload_dir['basedir'] . '/';
52+
$path_prefix = $upload_dir['basedir'] . '/';
53+
$url_prefix = $upload_dir['baseurl'] . '/';
5154
if (isset($path_info['dirname'])) {
52-
$prefix .= $path_info['dirname'] .'/';
55+
$path_prefix .= $path_info['dirname'] .'/';
56+
$url_prefix .= $path_info['dirname'] .'/';
5357
}
5458

55-
$this->filenames[self::ORIGINAL] = "$prefix${path_info['basename']}";
59+
$this->filenames[self::ORIGINAL] = "$path_prefix${path_info['basename']}";
60+
$this->urls[self::ORIGINAL] = "$url_prefix${path_info['basename']}";
5661
if (isset($wp_metadata['sizes']) && is_array($wp_metadata['sizes'])) {
5762
foreach ($wp_metadata['sizes'] as $size => $info) {
58-
$this->filenames[$size] = "$prefix${info['file']}";
63+
$this->filenames[$size] = "$path_prefix${info['file']}";
64+
$this->urls[$size] = "$url_prefix${info['file']}";
5965
}
6066
}
6167
}
@@ -84,6 +90,10 @@ public function get_filename($size=self::ORIGINAL) {
8490
return isset($this->filenames[$size]) ? $this->filenames[$size] : null;
8591
}
8692

93+
public function get_url($size=self::ORIGINAL) {
94+
return isset($this->urls[$size]) ? $this->urls[$size] : null;
95+
}
96+
8797
public function get_value($size=self::ORIGINAL) {
8898
return isset($this->values[$size]) ? $this->values[$size] : null;
8999
}

src/class-tiny-notices.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ public function dismiss() {
106106
exit();
107107
}
108108

109-
public function show($name, $message, $dismissable=true) {
109+
public function show($name, $message, $klass='error', $dismissable=true) {
110110
$link = $dismissable ? "&nbsp;<a href=\"#\" data-name=\"$name\" class=\"tiny-dismiss\">" . self::translate_escape('Dismiss') . '</a>' : '';
111-
add_action('admin_notices', create_function('', "echo '<div class=\"updated\"><p>Compress JPEG & PNG images: $message$link</p></div>';"));
111+
add_action('admin_notices', create_function('', "echo '<div class=\"$klass\"><p>Compress JPEG & PNG images: $message$link</p></div>';"));
112112
}
113113
}

src/class-tiny-plugin.php

Lines changed: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public static function jpeg_quality() {
3131
public function __construct() {
3232
parent::__construct();
3333
$this->settings = new Tiny_Settings();
34+
if (is_admin()) {
35+
add_action('admin_menu', $this->get_method('admin_menu'));
36+
}
3437
}
3538

3639
public function set_compressor($compressor) {
@@ -52,6 +55,14 @@ public function admin_init() {
5255
add_action('admin_enqueue_scripts', $this->get_method('enqueue_scripts'));
5356
}
5457

58+
public function admin_menu() {
59+
add_management_page(
60+
self::translate('Compress JPEG & PNG Images'), self::translate('Compress all images'),
61+
'upload_files', 'tiny-bulk-compress', $this->get_method('bulk_compress_page')
62+
);
63+
64+
}
65+
5566
public function enqueue_scripts($hook) {
5667
wp_enqueue_style(self::NAME .'_admin', plugins_url('/styles/admin.css', __FILE__),
5768
array(), self::plugin_version());
@@ -63,54 +74,81 @@ public function enqueue_scripts($hook) {
6374
// Wordpress < 3.3 does not handle multi dimensional arrays
6475
wp_localize_script($handle, 'tinyCompress', array(
6576
'nonce' => wp_create_nonce('tiny-compress'),
66-
'L10nBulkAction' => self::translate('Compress all uncompressed sizes'),
77+
'L10nAllDone' => self::translate('All images are processed'),
78+
'L10nBulkAction' => self::translate('Compress all'),
79+
'L10nCompressing' => self::translate('Compressing'),
80+
'L10nError' => self::translate('Error'),
81+
'L10nInternalError' => self::translate('Internal error'),
82+
'L10nOutOf' => self::translate('out of'),
83+
'L10nWaiting' => self::translate('Waiting'),
6784
));
6885
wp_enqueue_script($handle);
6986
}
7087

71-
public function compress_attachment($metadata, $attachment_id) {
88+
private function compress($metadata, $attachment_id) {
7289
$mime_type = get_post_mime_type($attachment_id);
7390
$tiny_metadata = new Tiny_Metadata($attachment_id, $metadata);
7491

7592
if ($this->settings->get_compressor() === null || strpos($mime_type, 'image/') !== 0) {
7693
return $metadata;
7794
}
7895

96+
$success = 0;
97+
$failed = 0;
98+
7999
$compressor = $this->settings->get_compressor();
80100
$sizes = $this->settings->get_tinify_sizes();
81101
foreach ($tiny_metadata->get_missing_sizes($sizes) as $size) {
82102
try {
83103
$response = $compressor->compress_file($tiny_metadata->get_filename($size));
84104
$tiny_metadata->add_response($response, $size);
105+
$success++;
85106
} catch (Tiny_Exception $e) {
86107
$tiny_metadata->add_exception($e, $size);
108+
$failed++;
87109
}
88110
}
89-
90111
$tiny_metadata->update();
112+
113+
return array($tiny_metadata, array('success' => $success, 'failed' => $failed));
114+
}
115+
116+
public function compress_attachment($metadata, $attachment_id) {
117+
$this->compress($metadata, $attachment_id);
91118
return $metadata;
92119
}
93120

94121
public function compress_image() {
95122
if (!$this->check_ajax_referer()) {
96123
exit();
97124
}
125+
$json = !empty($_POST['json']) && $_POST['json'];
98126
if (!current_user_can('upload_files')) {
99-
echo self::translate("You don't have permission to work with uploaded files") . '.';
127+
$message = self::translate("You don't have permission to work with uploaded files") . '.';
128+
echo $json ? json_encode(array('error' => $message)) : $message;
100129
exit();
101130
}
102131
if (empty($_POST['id'])) {
103-
echo self::translate("Not a valid media file") . '.';
132+
$message = self::translate("Not a valid media file") . '.';
133+
echo $json ? json_encode(array('error' => $message)) : $message;
104134
exit();
105135
}
106136
$id = intval($_POST['id']);
107137
$metadata = wp_get_attachment_metadata($id);
108138
if (!is_array($metadata)) {
109-
echo self::translate("Could not find metadata of media file") . '.';
139+
$message = self::translate("Could not find metadata of media file") . '.';
140+
echo $json ? json_encode(array('error' => $message)) : $message;
141+
exit;
110142
}
111143

112-
$this->compress_attachment($metadata, $id);
113-
$this->render_media_column(self::MEDIA_COLUMN, $id);
144+
list($tiny_metadata, $result) = $this->compress($metadata, $id);
145+
if ($json) {
146+
$result['status'] = $this->settings->get_status();
147+
$result['thumbnail'] = $tiny_metadata->get_url('thumbnail');
148+
echo json_encode($result);
149+
} else {
150+
echo $this->render_media_column(self::MEDIA_COLUMN, $id);
151+
}
114152

115153
exit();
116154
}
@@ -122,12 +160,13 @@ public function bulk_compress() {
122160
return;
123161
}
124162

125-
foreach ($_REQUEST['media'] as $id) {
126-
$metadata = wp_get_attachment_metadata($id);
127-
if (is_array($metadata)) {
128-
$this->compress_attachment($metadata, $id);
129-
}
130-
}
163+
$ids = implode('-', array_map('intval', $_REQUEST['media']));
164+
wp_redirect(add_query_arg(
165+
'_wpnonce',
166+
wp_create_nonce('tiny-bulk-compress'),
167+
admin_url("tools.php?page=tiny-bulk-compress&ids=$ids")
168+
));
169+
exit();
131170
}
132171

133172
public function add_media_columns($columns) {
@@ -162,4 +201,48 @@ public function render_media_column($column, $id) {
162201
}
163202
}
164203
}
204+
205+
public function bulk_compress_page() {
206+
echo '<div class="wrap" id="tiny-bulk-compress">';
207+
echo '<h2>' . self::translate('Compress JPEG & PNG Images') . '</h2>';
208+
if (empty($_POST['tiny-bulk-compress']) && empty($_REQUEST['ids'])) {
209+
echo '<p>' . self::translate_escape("Use this tool to compress all images via the Tiny API service") . '.</p>';
210+
echo '<p>' . self::translate_escape("To begin, just press the button below") . '.</p>';
211+
212+
echo '<form method="POST" action="?page=tiny-bulk-compress">';
213+
echo '<input type="hidden" name="_wpnonce" value="' . wp_create_nonce('tiny-bulk-compress') . '">';
214+
echo '<input type="hidden" name="tiny-bulk-compress" value="1">';
215+
echo '<p><button class="button" type="submit">'. self::translate_escape('Compress all images') .'</p>';
216+
echo '</form>';
217+
} else {
218+
check_admin_referer('tiny-bulk-compress');
219+
220+
if (!empty($_REQUEST['ids'])) {
221+
$ids = implode(',', array_map('intval', explode('-', $_REQUEST['ids'])));
222+
$cond = "AND ID IN($ids)";
223+
} else {
224+
$cond = "";
225+
}
226+
227+
global $wpdb;
228+
// Get all ids and names of the images and not the whole objects which will only fill memory
229+
$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);
230+
231+
echo '<p>';
232+
echo self::translate_escape("Please be patient while the images are being compressed") . '. ';
233+
echo self::translate_escape("This can take a while if you have many images") . '. ';
234+
echo self::translate_escape("Do not navigate away from this page because it will stop the process") . '. ';
235+
echo self::translate_escape("You will be notified via this page when the processing is done") . '.';
236+
echo "</p>";
237+
238+
echo '<div id="tiny-status"><p>'. self::translate_escape('Compressions this month') . sprintf(' <span>%d</span></p></div>', $this->settings->get_status());
239+
echo '<div id="tiny-progress"><p>'. self::translate_escape('Processing') . ': <span>0</span> ' . self::translate_escape('out of') . sprintf(' %d </p></div>', count($items));
240+
echo '<div id="tiny-images">';
241+
echo '</div>';
242+
243+
echo '<script type="text/javascript">jQuery(function() { tinyBulkCompress('. json_encode($items) . ')})</script>';
244+
}
245+
246+
echo '</div>';
247+
}
165248
}

src/class-tiny-settings.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@ public function __construct() {
3232
}
3333

3434
public function admin_init() {
35+
if (current_user_can('manage_options') && empty($this->get_api_key())) {
36+
$link = sprintf('<a href="options-media.php#%s">%s</a>', self::NAME,
37+
self::translate_escape('Please fill in an API key to start compressing images'));
38+
$this->notices->show('setting', $link, 'error', false);
39+
}
3540
try {
3641
$this->compressor = Tiny_Compress::get_compressor($this->get_api_key(), $this->get_method('after_compress_callback'));
3742
} catch (Tiny_Exception $e) {
38-
$this->notices->show('compressor_exception', self::translate_escape($e->getMessage()), false);
43+
$this->notices->show('compressor_exception', self::translate_escape($e->getMessage()), 'error', false);
3944
}
4045

4146
$section = self::get_prefixed_name('settings');
@@ -53,10 +58,10 @@ public function admin_init() {
5358
register_setting('media', $field);
5459
add_settings_field($field, self::translate('Connection status'), $this->get_method('render_pending_status'), 'media', $section);
5560

56-
add_action('wp_ajax_tiny_compress_status', $this->get_method('get_status'));
61+
add_action('wp_ajax_tiny_compress_status', $this->get_method('connection_status'));
5762
}
5863

59-
public function get_status() {
64+
public function connection_status() {
6065
$this->render_status();
6166
exit();
6267
}
@@ -69,6 +74,10 @@ public function set_compressor($compressor) {
6974
$this->compressor = $compressor;
7075
}
7176

77+
public function get_status() {
78+
return intval(get_option(self::get_prefixed_name('status')));
79+
}
80+
7281
protected function get_api_key() {
7382
if (defined('TINY_API_KEY')) {
7483
return TINY_API_KEY;
@@ -140,6 +149,7 @@ public function get_tinify_sizes() {
140149
}
141150

142151
public function render_section() {
152+
echo '<span id="' . self::NAME . '"></span>';
143153
}
144154

145155
public function render_api_key() {
@@ -208,7 +218,12 @@ public function after_compress_callback($details, $headers) {
208218

209219
public function render_status() {
210220
$details = null;
211-
$status = $this->compressor->get_status($details);
221+
try {
222+
$status = $this->compressor->get_status($details);
223+
} catch (Tiny_Exception $e) {
224+
$status = false;
225+
$details = array('message' => $e->getMessage());
226+
}
212227
if ($status) {
213228
echo '<p><img src="images/yes.png"> ' . self::translate_escape('API connection successful') . '</p>';
214229
} else {

src/class-tiny-wp-base.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ protected static function translate_escape($phrase) {
4646

4747
public function __construct() {
4848
add_action('init', $this->get_method('init'));
49-
add_action('admin_init', $this->get_method('admin_init'));
49+
if (is_admin()) {
50+
add_action('admin_init', $this->get_method('admin_init'));
51+
}
5052
}
5153

5254
protected function get_method($name) {

src/config/tiny-config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php
22

33
class Tiny_Config {
4-
const URL = 'http://webservice/shrink';
4+
const URL = 'https://api.tinypng.com/shrink';
55
}
1.35 KB
Binary file not shown.

0 commit comments

Comments
 (0)