Plugin Directory

source: kraken-image-optimizer/tags/2.6.6/kraken.php

Last change on this file was 2802730, checked in by karim79, 2 years ago

tagging version 2.6.6

  • Property svn:executable set to *
File size: 54.1 KB
Line 
1<?php
2/*
3        Copyright 2015  Karim Salman  (email : ksalman@kraken.io)
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2, as
7    published by the Free Software Foundation.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17*/
18
19/*
20 * Plugin Name: Kraken Image Optimizer
21 * Plugin URI: http://wordpress.org/plugins/kraken-image-optimizer/
22 * Description: This plugin allows you to optimize your WordPress images through the Kraken API, the world's most advanced image optimization solution.
23 * Author: Karim Salman
24 * Version: 2.6.6
25 * Requires at least: 3.0.1
26 * Requires PHP: 5.0.0
27 * Stable Tag: 2.6.6
28 * Author URI: https://kraken.io
29 * License GPL2
30 */
31
32
33if ( !class_exists( 'Wp_Kraken' ) ) {
34
35        define( 'KRAKEN_DEV_MODE', false );
36        class Wp_Kraken {
37
38                private $id;
39
40                private $kraken_settings = array();
41
42                private $thumbs_data = array();
43
44                private $optimization_type = 'lossy';
45
46                public static $kraken_plugin_version = '2.6.4';
47
48                function __construct() {
49                        $plugin_dir_path = dirname( __FILE__ );
50                        require_once( $plugin_dir_path . '/lib/Kraken.php' );
51                        $this->kraken_settings = get_option( '_kraken_options' );
52                        $this->optimization_type = $this->kraken_settings['api_lossy'];
53                        add_action( 'admin_enqueue_scripts', array( &$this, 'my_enqueue' ) );
54                        add_action( 'wp_ajax_kraken_reset', array( &$this, 'kraken_media_library_reset' ) );
55                        add_action( 'wp_ajax_kraken_optimize', array( &$this, 'kraken_optimize' ) );
56                        add_action( 'wp_ajax_kraken_request', array( &$this, 'kraken_media_library_ajax_callback' ) );
57                        add_action( 'wp_ajax_kraken_reset_all', array( &$this, 'kraken_media_library_reset_all' ) );
58                        add_action( 'manage_media_custom_column', array( &$this, 'fill_media_columns' ), 10, 2 );
59                        add_filter( 'manage_media_columns', array( &$this, 'add_media_columns') );
60                        add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), array( &$this, 'add_settings_link' ) );
61
62                        if ( ( !empty( $this->kraken_settings ) && !empty( $this->kraken_settings['auto_optimize'] ) ) || !isset( $this->kraken_settings['auto_optimize'] ) ) {
63                                add_action( 'add_attachment', array( &$this, 'kraken_media_uploader_callback' ) );                     
64                                add_filter( 'wp_generate_attachment_metadata', array( &$this, 'optimize_thumbnails' ) );
65                        }
66
67                        // in case settings were not resaved after update
68                        if ( !isset( $this->kraken_settings["optimize_main_image"] ) ) {
69                                $this->kraken_settings["optimize_main_image"] = 1;
70                        }
71
72                        // in case settings were not resaved after update
73                        if ( !isset( $this->kraken_settings["chroma"] ) ) {
74                                $this->kraken_settings["chroma"] = '4:2:0';
75                        }
76
77                        add_action( 'admin_menu', array( &$this, 'kraken_menu' ) );     
78                }
79
80                function preg_array_key_exists( $pattern, $array ) {
81                    $keys = array_keys( $array );   
82                    return (int) preg_grep( $pattern,$keys );
83                }
84
85                function isApiActive() {
86                        $settings = $this->kraken_settings;
87                        $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
88                        $api_secret = isset( $settings['api_secret'] ) ? $settings['api_secret'] : '';
89                        if ( empty( $api_key ) || empty( $api_secret) ) {
90                                return false;
91                        }
92                        return true;                   
93                }
94
95                function kraken_menu() {
96                        add_options_page( 'Kraken Image Optimizer Settings', 'Kraken.io', 'manage_options', 'wp-krakenio', array( &$this, 'kraken_settings_page' ) );
97                }
98
99                function add_settings_link ( $links ) {
100                        $mylinks = array(
101                                '<a href="' . admin_url( 'options-general.php?page=wp-krakenio' ) . '">Settings</a>',
102                        );
103                        return array_merge( $links, $mylinks );
104                }
105
106                function kraken_settings_page() {
107
108                        if ( !empty( $_POST ) && isset( $_POST['settings_form_nonce'] ) && wp_verify_nonce( $_POST['settings_form_nonce'], 'settings_form_nonce' ) ) {
109                                $options = $_POST['_kraken_options'];
110                                $result = $this->validate_options( $options );
111                                update_option( '_kraken_options', $result['valid'] );
112                        }
113
114                        $form_nonce = wp_create_nonce( 'settings_form_nonce' );
115                        $settings = get_option( '_kraken_options' );
116                        $lossy = isset( $settings['api_lossy'] ) ? $settings['api_lossy'] : 'lossy';
117                        $auto_optimize = isset( $settings['auto_optimize'] ) ? $settings['auto_optimize'] : 1;
118                        $optimize_main_image = isset( $settings['optimize_main_image'] ) ? $settings['optimize_main_image'] : 1;
119                        $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
120                        $api_secret = isset( $settings['api_secret'] ) ? $settings['api_secret'] : '';
121                        $show_reset = isset( $settings['show_reset'] ) ? $settings['show_reset'] : 0;
122                        $bulk_async_limit = isset( $settings['bulk_async_limit'] ) ? $settings['bulk_async_limit'] : 4;
123                        $preserve_meta_date = isset( $settings['preserve_meta_date'] ) ? $settings['preserve_meta_date'] : 0;
124                        $preserve_meta_copyright = isset( $settings['preserve_meta_copyright'] ) ? $settings['preserve_meta_copyright'] : 0;
125                        $preserve_meta_geotag = isset( $settings['preserve_meta_geotag'] ) ? $settings['preserve_meta_geotag'] : 0;
126                        $preserve_meta_orientation = isset( $settings['preserve_meta_orientation'] ) ? $settings['preserve_meta_orientation'] : 0;
127                        $preserve_meta_profile = isset( $settings['preserve_meta_profile'] ) ? $settings['preserve_meta_profile'] : 0;
128                        $auto_orient = isset( $settings['auto_orient'] ) ? $settings['auto_orient'] : 1;
129                        $resize_width = isset( $settings['resize_width'] ) ? $settings['resize_width'] : 0;
130                        $resize_height = isset( $settings['resize_height'] ) ? $settings['resize_height'] : 0;
131                        $jpeg_quality = isset( $settings['jpeg_quality'] ) ? $settings['jpeg_quality'] : 0;
132                        $chroma_subsampling = isset( $settings['chroma'] ) ? $settings['chroma'] : '4:2:0';
133               
134                        $sizes = array_keys($this->get_image_sizes());
135                        foreach ($sizes as $size) {
136                                $valid['include_size_' . $size] = isset( $settings['include_size_' . $size]) ? $settings['include_size_' . $size] : 1;
137                        }
138
139                        $status = $this->get_api_status( $api_key, $api_secret );
140
141                        $icon_url = admin_url() . 'images/';
142                        if ( $status !== false && isset( $status['active'] ) && $status['active'] === true ) {
143                                $icon_url .= 'yes.png';
144                                $status_html = '<p class="apiStatus">Your credentials are valid <span class="apiValid" style="background:url(' . "'$icon_url') no-repeat 0 0" . '"></span></p>';
145                        } else {
146                                $icon_url .= 'no.png';
147                                $status_html = '<p class="apiStatus">There is a problem with your credentials <span class="apiInvalid" style="background:url(' . "'$icon_url') no-repeat 0 0" . '"></span></p>';
148                        }
149
150                        ?>      <h1 class="kraken-admin-section-title">Kraken.io Settings</h1>
151                                        <?php if ( isset( $result['error'] ) ) { ?>
152                                                <div class="kraken error settings-error">
153                                                <?php foreach( $result['error'] as $error ) { ?>
154                                                        <p><?php echo $error; ?></p>
155                                                <?php } ?>
156                                                </div>
157                                        <?php } else if ( isset( $result['success'] ) ) { ?>
158                                                <div class="kraken updated settings-error">
159                                                        <p>Settings saved.</p>
160                                                </div>
161                                        <?php } ?>
162
163                                        <?php if ( !function_exists( 'curl_init' ) ) { ?>
164                                                <p class="curl-warning"><strong>Warning: </strong>CURL is not available. Please install CURL before using this plugin</p>
165                                        <?php } ?>
166
167                                        <form id="krakenSettings" method="post">
168                                                <a href="http://kraken.io/account" target="_blank" title="Log in to your Kraken.io account">Kraken.io</a> API settings
169                                                <table class="form-table">
170                                                    <tbody>
171                                                        <tr>
172                                                            <th scope="row">API Key:</th>
173                                                            <td>
174                                                                <input id="kraken_api_key" name="_kraken_options[api_key]" type="text" value="<?php echo esc_attr( $api_key ); ?>" size="50">
175                                                            </td>
176                                                        </tr>
177                                                        <tr>
178                                                            <th scope="row">API Secret:</th>
179                                                            <td>
180                                                                <input id="kraken_api_secret" name="_kraken_options[api_secret]" type="text" value="<?php echo esc_attr( $api_secret ); ?>" size="50">
181                                                            </td>
182                                                        </tr>
183                                                        <tr>
184                                                            <th scope="row">API status:</th>
185                                                            <td>
186                                                                <?php echo $status_html ?>
187                                                            </td>
188                                                        </tr>
189                                                        <tr class="with-tip">
190                                                            <th scope="row">Optimization mode:</th>
191                                                            <td>
192                                                                <input type="radio" id="kraken_lossy" name="_kraken_options[api_lossy]" value="lossy" <?php checked( 'lossy', $lossy, true ); ?>/>
193                                                                <label for="kraken_lossy">Intelligent Lossy</label>
194                                                                <input style="margin-left:10px;" type="radio" id="kraken_lossless" name="_kraken_options[api_lossy]" value="lossless" <?php checked( 'lossless', $lossy, true ) ?>/>
195                                                                <label for="kraken_lossless">Lossless</label>
196                                                            </td>
197                                                        </tr>
198                                                        <tr class="tip">
199                                                                <td colspan="2">
200                                                                        <div>
201                                                                                The <strong>Intelligent Lossy</strong> mode will yield the greatest savings without perceivable reducing the quality of your images, and so we recommend this setting to users.<br />
202                                                                                The <strong>Lossless</strong> mode will result in an unchanged image, however, will yield reduced savings as the image will not be recompressed.
203                                                                        </div>
204                                                                </td>
205                                                        </tr>
206                                                        <tr class="with-tip">
207                                                            <th scope="row">Automatically optimize uploads:</th>
208                                                            <td>
209                                                                <input type="checkbox" id="auto_optimize" name="_kraken_options[auto_optimize]" value="1" <?php checked( 1, $auto_optimize, true ); ?>/>
210                                                            </td>
211                                                        </tr>
212                                                        <tr class="tip">
213                                                                <td colspan="2">
214                                                                        <div>
215                                                                                Enabled by default. This setting causes images uploaded through the Media Uploader to be optimized on-the-fly.<br />
216                                                                                If you do not wish to do this, or wish to optimize images later, disable this setting by unchecking the box.
217                                                                        </div>
218                                                                </td>
219                                                        </tr>
220                                                        <tr class="with-tip">
221                                                            <th scope="row">Optimize main image:</th>
222                                                            <td>
223                                                                <input type="checkbox" id="optimize_main_image" name="_kraken_options[optimize_main_image]" value="1" <?php checked( 1, $optimize_main_image, true ); ?>/>
224                                                            </td>
225                                                        </tr>
226                                                        <tr class="tip">
227                                                                <td colspan="2">
228                                                                        <div>
229                                                                                Enabled by default. This option causes the image uploaded by the user to get optimized, as well as all sizes generated by WordPress.<br />
230                                                                                Disabling this option results in faster uploading, since the main image is not sent to our system for optimization.<br />
231                                                                                Disable this option if you never use the "main" image upload in your posts, or speed of image uploading is an issue.
232                                                                        </div>
233                                                                </td>
234                                                        </tr>
235                                                        <tr class="with-tip">
236                                                                <th scope="row">Resize main image:</th>
237                                                                <td>
238                                                                        Max Width (px):&nbsp;&nbsp;<input type="text" id="kraken_maximum_width" name="_kraken_options[resize_width]" value="<?php echo esc_attr( $resize_width ); ?>" style="width:50px;" />&nbsp;&nbsp;&nbsp;Max Height (px):&nbsp;<input type="text" id="kraken_maximum_height" name="_kraken_options[resize_height]" value="<?php echo esc_attr( $resize_height ); ?>" style="width:50px;" />
239                                                                </td>
240                                                        </tr>
241                                                        <tr class="tip">
242                                                                <td colspan="2">
243                                                                        <div>
244                                                                                You can restrict the maximum dimensions of image uploads by width and/or height.<br />
245                                                                                It is especially useful if you wish to prevent unnecessarily large photos with extremely high resolutions from being uploaded, for example, <br />
246                                                                                photos shot with a recent-model iPhone. Note: you can restrict the dimenions by width, height, or both. A value of zero disables.
247                                                                        </div>
248                                                                </td>
249                                                        </tr>
250                                                        <tr class="with-tip">
251                                                                <th scope="row">JPEG quality setting:</th>
252                                                                <td>
253                                                                                <select name="_kraken_options[jpeg_quality]">
254                                                                                        <?php $i = 0 ?>
255                                                                                        <?php foreach ( range(100, 25) as $number ) { ?>
256                                                                                                <?php if ( $i === 0 ) { ?>
257                                                                                                        <?php echo '<option value="0">Intelligent lossy (recommended)</option>'; ?>
258                                                                                                <?php } ?>
259                                                                                                <?php if ($i > 0) { ?>
260                                                                                                        <option value="<?php echo $number ?>" <?php selected( $jpeg_quality, $number, true); ?>>
261                                                                                                        <?php echo $number; ?>
262                                                                                                <?php } ?>
263                                                                                                        </option>
264                                                                                                <?php $i++ ?>
265                                                                                        <?php } ?>
266                                                                                </select>
267                                                                </td>
268                                                        </tr>
269                                                        <tr class="tip">
270                                                                <td colspan="2">
271                                                                        <div>
272                                                                                Advanced users can force the quality of JPEG images to a discrete "q" value between 25 and 100 using this setting <br />
273                                                                                For example, forcing the quality to 60 or 70 might yield greater savings, but the resulting quality might be affected, depending on the image. <br />
274                                                                                We therefore recommend keeping the <strong>Intelligent Lossy</strong> setting, which will not allow a resulting image of unacceptable quality.<br />
275                                                                                This setting will be ignored when using the <strong>lossless</strong> optimization mode.
276                                                                        </div>
277                                                                </td>
278                                                        </tr>
279                                                        <tr class="with-tip">
280                                                            <th scope="row">Chroma subsampling scheme:</th>
281                                                            <td>
282                                                                <input type="radio" id="kraken_chroma_420" name="_kraken_options[chroma]" value="4:2:0" <?php checked( '4:2:0', $chroma_subsampling, true ); ?>/>
283                                                                <label for="kraken_chroma_420">4:2:0 (default)</label>
284                                                                <input style="margin-left:10px;" type="radio" id="kraken_chroma_422" name="_kraken_options[chroma]" value="4:2:2" <?php checked( '4:2:2', $chroma_subsampling, true ) ?>/>
285                                                                <label for="kraken_chroma_422">4:2:2</label>
286                                                                <input style="margin-left:10px;" type="radio" id="kraken_chroma_444" name="_kraken_options[chroma]" value="4:4:4" <?php checked( '4:4:4', $chroma_subsampling, true ) ?>/>
287                                                                <label for="kraken_chroma_444">4:4:4 (no subsampling)</label>                                                       
288                                                            </td>
289                                                        </tr>
290                                                        <tr class="tip">
291                                                                <td colspan="2">
292                                                                        <div>
293                                                                                Advanced users can also set the resolution at which colour is encoded for JPEG images. In short, the default setting of <strong>4:2:0</strong> is suitable for most images,<br />
294                                                                                and will result in the lowest possible optimized file size. Images containing high contrast text or bright red areas on flat backgrounds might benefit from disabling chroma subsampling<br />
295                                                                                (by setting it to <strong>4:4:4</strong>). More information can be found in our <a href="https://kraken.io/docs/chroma-subsampling" target="_blank">documentation</a>.
296                                                                        </div>
297                                                                </td>
298                                                        </tr>                                                                                                 
299                                                        <tr class="no-border">
300                                                                <td class="krakenAdvancedSettings"><h3><span class="kraken-advanced-settings-label">Advanced Settings</span></h3></td>
301                                                        </tr>
302                                                        <tr class="kraken-advanced-settings">
303                                                                <td colspan="2" class="krakenAdvancedSettingsDescription"><small>We recommend that you leave these settings at their default values</td>
304                                                        </tr>
305                                                        <tr class="kraken-advanced-settings">
306                                                            <th scope="row">Image Sizes to Krak:</th>
307                                                                        <td>
308                                                                <?php $size_count = count($sizes); ?>
309                                                                <?php $i = 0; ?>
310                                                                <?php foreach($sizes as $size) { ?>
311                                                                <?php $size_checked = isset( $valid['include_size_' . $size] ) ? $valid['include_size_' . $size] : 1; ?>
312                                                                <label for="<?php echo "kraken_size_$size" ?>"><input type="checkbox" id="kraken_size_<?php echo $size ?>" name="_kraken_options[include_size_<?php echo $size ?>]" value="1" <?php checked( 1, $size_checked, true ); ?>/>&nbsp;<?php echo $size ?></label>&nbsp;&nbsp;&nbsp;&nbsp;
313                                                                <?php $i++ ?>
314                                                                <?php if ($i % 3 == 0) { ?>
315                                                                        <br />
316                                                                <?php } ?>
317                                                                <?php } ?>
318                                                            </td>
319                                                        </tr>                                                   
320                                                        <tr class="kraken-advanced-settings">
321                                                            <th scope="row">Preserve EXIF Metadata:</th>
322                                                            <td>
323                                                                <label for="preserve_meta_date"><input type="checkbox" id="preserve_meta_date" name="_kraken_options[preserve_meta_date]" value="1" <?php checked( 1, $preserve_meta_date, true ); ?>/>&nbsp;Date</label>&nbsp;&nbsp;&nbsp;&nbsp;
324                                                                <label for="preserve_meta_copyright"><input type="checkbox" id="preserve_meta_copyright" name="_kraken_options[preserve_meta_copyright]" value="1" <?php checked( 1, $preserve_meta_copyright, true ); ?>/>&nbsp;Copyright</label>&nbsp;&nbsp;&nbsp;&nbsp;
325                                                                <label for="preserve_meta_geotag"><input type="checkbox" id="preserve_meta_geotag" name="_kraken_options[preserve_meta_geotag]" value="1" <?php checked( 1, $preserve_meta_geotag, true ); ?>/>&nbsp;Geotag</label>&nbsp;&nbsp;&nbsp;&nbsp;
326                                                            <label for="preserve_meta_orientation"><input type="checkbox" id="preserve_meta_orientation" name="_kraken_options[preserve_meta_orientation]" value="1" <?php checked( 1, $preserve_meta_orientation, true ); ?>/>&nbsp;Orientation</label>&nbsp;&nbsp;&nbsp;&nbsp;
327                                                                <label for="preserve_meta_profile"><input type="checkbox" id="preserve_meta_profile" name="_kraken_options[preserve_meta_profile]" value="1" <?php checked( 1, $preserve_meta_profile, true ); ?>/>&nbsp;Profile</label>&nbsp;&nbsp;&nbsp;&nbsp;
328                                                            </td>
329                                                        </tr>
330                                                        <tr class="kraken-advanced-settings with-tip">
331                                                            <th scope="row">Automatically Orient Images:</th>
332                                                            <td>
333                                                                <input type="checkbox" id="auto_orient" name="_kraken_options[auto_orient]" value="1" <?php checked( 1, $auto_orient, true ); ?>/>
334                                                            </td>
335                                                        </tr>
336                                                        <tr class="tip">
337                                                                <td colspan="2">
338                                                                        <div>
339                                                                                This setting will rotate the JPEG image according to its <strong>Orientation</strong> EXIF metadata such that it will always be correctly displayed in Web Browsers.<br />
340                                                                                Enable this setting if many of your image uploads come from smart phones or digital cameras which set the orientation based on how they are held at the time of shooting.
341                                                                        </div>
342                                                                </td>
343                                                        </tr>
344                                                    <tr class="kraken-advanced-settings with-tip">
345                                                            <th scope="row">Show metadata reset per image:</th>
346                                                            <td>
347                                                                <input type="checkbox" id="kraken_show_reset" name="_kraken_options[show_reset]" value="1" <?php checked( 1, $show_reset, true ); ?>/>
348                                                                &nbsp;&nbsp;&nbsp;&nbsp;<span class="kraken-reset-all enabled">Reset All Images</span>
349                                                            </td>
350                                                        </tr>
351                                                        <tr class="tip">
352                                                                <td colspan="2">
353                                                                        <div>
354                                                                                Checking this option will add a Reset button in the "Show Details" popup in the Kraken Stats column for each optimized image.<br />
355                                                                                Resetting an image will remove the Kraken.io metadata associated with it, effectively making your blog forget that it had been optimized in the first place, allowing further optimization in some cases.<br />
356                                                                                If an image has been optimized using the lossless setting, lossless optimization will not yield any greater savings. If in doubt, please contact support@kraken.io
357                                                                        </div>
358                                                                </td>
359                                                        </tr>
360                                                        <tr class="kraken-advanced-settings with-tip">
361                                                                <th scope="row">Bulk Concurrency:</th>
362                                                                <td>
363                                                                                <select name="_kraken_options[bulk_async_limit]">
364                                                                                        <?php foreach ( range(1, 10) as $number ) { ?>
365                                                                                                <option value="<?php echo $number ?>" <?php selected( $bulk_async_limit, $number, true); ?>>
366                                                                                                        <?php echo $number ?>
367                                                                                                </option>
368                                                                                        <?php } ?>
369                                                                                </select>
370                                                                </td>
371                                                        </tr>
372                                                        <tr class="tip">
373                                                                <td colspan="2">
374                                                                        <div>
375                                                                                This settings defines how many images can be processed at the same time using the bulk optimizer. The recommended (and default) value is 4. <br />
376                                                                                For blogs on very small hosting plans, or with reduced connectivity, a lower number might be necessary to avoid hitting request limits.
377                                                                        </div>
378                                                                </td>
379                                                        </tr>
380                                                    </tbody>
381                                                </table>
382                                 <input type="hidden"  name="settings_form_nonce" value="<?php echo $form_nonce; ?>" />
383                             <input type="submit" name="kraken_save" id="kraken_save" class="button button-primary" value="Save All"/>
384                          </form>
385                        <?php
386                }
387
388                function validate_options( $input ) {
389                        $valid = array();
390                        $error = array();
391                        $valid['api_lossy'] = $input['api_lossy'];
392                        $valid['auto_optimize'] = isset( $input['auto_optimize'] )? 1 : 0;
393                        $valid['optimize_main_image'] = isset( $input['optimize_main_image'] ) ? 1 : 0;
394                        $valid['preserve_meta_date'] = isset( $input['preserve_meta_date'] ) ? $input['preserve_meta_date'] : 0;
395                        $valid['preserve_meta_copyright'] = isset( $input['preserve_meta_copyright'] ) ? $input['preserve_meta_copyright'] : 0;
396                        $valid['preserve_meta_geotag'] = isset( $input['preserve_meta_geotag'] ) ? $input['preserve_meta_geotag'] : 0;
397                        $valid['preserve_meta_orientation'] = isset( $input['preserve_meta_orientation'] ) ? $input['preserve_meta_orientation'] : 0;
398                        $valid['preserve_meta_profile'] = isset( $input['preserve_meta_profile'] ) ? $input['preserve_meta_profile'] : 0;
399                        $valid['auto_orient'] = isset( $input['auto_orient'] ) ? $input['auto_orient'] : 0;
400                        $valid['show_reset'] = isset( $input['show_reset'] ) ? 1 : 0;
401                        $valid['bulk_async_limit'] = isset( $input['bulk_async_limit'] ) ? $input['bulk_async_limit'] : 4;
402                        $valid['resize_width'] = isset( $input['resize_width'] ) ? (int) $input['resize_width'] : 0;
403                        $valid['resize_height'] = isset( $input['resize_height'] ) ? (int) $input['resize_height'] : 0;
404                        $valid['jpeg_quality'] = isset( $input['jpeg_quality'] ) ? (int) $input['jpeg_quality'] : 0;
405                        $valid['chroma'] = isset( $input['chroma'] ) ? $input['chroma'] : '4:2:0';
406
407
408                        $sizes = get_intermediate_image_sizes();
409                        foreach ($sizes as $size) {
410                                $valid['include_size_' . $size] = isset( $input['include_size_' . $size] ) ? 1 : 0;
411                        }
412
413                        if ( $valid['show_reset'] ) {
414                                $valid['show_reset'] = $input['show_reset'];
415                        }
416
417                        if ( empty( $input['api_key']) || empty( $input['api_secret'] ) ) {
418                                $error[] = 'API Credentials must not be left blank.';
419                        } else {
420                       
421                                $status = $this->get_api_status( $input['api_key'], $input['api_secret'] );
422
423                                if ( $status !== false ) {
424
425                                        if ( isset($status['active']) && $status['active'] === true ) {
426                                                if ( $status['plan_name'] === 'Developers' ) {
427                                                        $error[] = 'Developer API credentials cannot be used with this plugin.';
428                                                } else {
429                                                        $valid['api_key'] = $input['api_key'];
430                                                        $valid['api_secret'] = $input['api_secret'];
431                                                }
432                                        } else {
433                                                $error[] = 'There is a problem with your credentials. Please check them from your Kraken.io account.';
434                                        }
435
436                                } else {
437                                        $error[] = 'Please enter a valid Kraken.io API key and secret.';
438                                }                       
439                        }
440
441                        if ( !empty( $error ) ) {
442                                return array( 'success' => false, 'error' => $error, 'valid' => $valid );
443                        } else {
444                                return array( 'success' => true, 'valid' => $valid );
445                        }
446                }
447
448                function my_enqueue( $hook ) {
449
450                        if ( $hook == 'options-media.php' || $hook == 'upload.php' || $hook == 'settings_page_wp-krakenio' ) {
451                                wp_enqueue_script( 'jquery' );
452                                if ( KRAKEN_DEV_MODE === true ) {
453                                        wp_enqueue_script( 'async-js', plugins_url( '/js/async.js', __FILE__ ) );
454                                        wp_enqueue_script( 'tipsy-js', plugins_url( '/js/jquery.tipsy.js', __FILE__ ), array( 'jquery' ) );
455                                        wp_enqueue_script( 'modal-js', plugins_url( '/js/jquery.modal.min.js', __FILE__ ), array( 'jquery' ) );
456                                        wp_enqueue_script( 'ajax-script', plugins_url( '/js/ajax.js', __FILE__ ), array( 'jquery' ) );
457                                        wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
458                                        wp_localize_script( 'ajax-script', 'kraken_settings', $this->kraken_settings );
459                                        wp_enqueue_style( 'kraken_admin_style', plugins_url( 'css/admin.css', __FILE__ ) );
460                                        wp_enqueue_style( 'tipsy-style', plugins_url( 'css/tipsy.css', __FILE__ ) );
461                                        wp_enqueue_style( 'modal-style', plugins_url( 'css/jquery.modal.css', __FILE__ ) );
462                                } else {
463                                        wp_enqueue_script( 'kraken-js', plugins_url( '/js/dist/kraken.min.js', __FILE__ ), array( 'jquery' ) );
464                                        wp_localize_script( 'kraken-js', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
465                                        wp_localize_script( 'kraken-js', 'kraken_settings', $this->kraken_settings );
466                                        wp_enqueue_style( 'kraken-css', plugins_url( 'css/dist/kraken.min.css', __FILE__ ) );                                   
467                                }
468                        }
469                }
470
471                function get_api_status( $api_key, $api_secret ) {
472
473                        if ( !empty( $api_key ) && !empty( $api_secret ) ) {
474                                $kraken = new Kraken( $api_key, $api_secret );
475                                $status = $kraken->status();
476                                return $status;
477                        }
478                        return false;
479                }
480
481                /**
482                 *      Converts an deserialized API result array into an array
483                 *      which this plugin will consume
484                 */
485                function get_result_arr( $result, $image_id ) {
486                        $rv = array();
487                        $rv['original_size'] = $result['original_size'];
488                        $rv['kraked_size'] = $result['kraked_size'];
489                        $rv['saved_bytes'] = $result['saved_bytes'];
490                        $savings_percentage = $result['saved_bytes'] / $result['original_size'] * 100;
491                        $rv['savings_percent'] = round( $savings_percentage, 2 ) . '%';
492                        $rv['type'] = $result['type'];
493                        if ( !empty( $result['kraked_width'] ) && !empty( $result['kraked_height'] ) ) {
494                                $rv['kraked_width'] = $result['kraked_width'];
495                                $rv['kraked_height'] = $result['kraked_height'];
496                        }
497                        $rv['success'] = $result['success'];
498                        $rv['meta'] = wp_get_attachment_metadata( $image_id );
499                        return $rv;             
500                }
501
502
503                /**
504                 *  Handles optimizing already-uploaded images in the  Media Library
505                 */
506                function kraken_media_library_ajax_callback() {
507                        $image_id = (int) $_POST['id'];
508                        $type = false;
509
510                        if ( isset( $_POST['type'] ) ) {
511                                $type = $_POST['type'];
512                                $this->optimization_type = $type;
513                        }
514
515                        $this->id = $image_id;
516
517                        if ( wp_attachment_is_image( $image_id ) ) {
518
519                                $settings = $this->kraken_settings;
520
521                                $image_path = get_attached_file( $image_id );
522                                $optimize_main_image = !empty( $settings['optimize_main_image'] );
523                                $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
524                                $api_secret = isset( $settings['api_secret'] ) ? $settings['api_secret'] : '';
525
526                                $data = array();
527
528                                if ( empty( $api_key ) && empty( $api_secret ) ) {
529                                        $data['error'] = 'There is a problem with your credentials. Please check them in the Kraken.io settings section of Media Settings, and try again.';
530                                        update_post_meta( $image_id, '_kraken_size', $data );
531                                        echo json_encode( array( 'error' => $data['error'] ) );
532                                        exit;
533                                }
534
535                                if ( $optimize_main_image ) {
536
537                                        // check if thumbs already optimized
538                                        $thumbs_optimized = false;
539                                        $kraked_thumbs_data = get_post_meta( $image_id, '_kraked_thumbs', true );
540                                       
541                                        if ( !empty ( $kraked_thumbs_data ) ) {
542                                                $thumbs_optimized = true;
543                                        }
544
545                                        // get metadata for thumbnails
546                                        $image_data = wp_get_attachment_metadata( $image_id );
547
548                                        if ( !$thumbs_optimized ) {
549                                                $this->optimize_thumbnails( $image_data );
550                                        } else {
551
552                                                // re-optimize thumbs if mode has changed
553                                                $kraked_thumbs_mode = $kraked_thumbs_data[0]['type'];                                           
554                                                if ( strcmp( $kraked_thumbs_mode, $this->optimization_type ) !== 0 ) {
555                                                        wp_generate_attachment_metadata( $image_id, $image_path );
556                                                        $this->optimize_thumbnails( $image_data );
557                                                }
558                                        }
559
560                                        $resize = false;
561                                        if ( !empty( $settings['resize_width'] ) || !empty( $settings['resize_height'] ) ) {
562                                                $resize = true;
563                                        }
564
565                                        $api_result = $this->optimize_image( $image_path, $type, $resize );
566
567                                        if ( !empty( $api_result ) && !empty( $api_result['success'] ) ) {
568                                                $data = $this->get_result_arr( $api_result, $image_id );
569                                                if ( $this->replace_image( $image_path, $api_result['kraked_url'] ) ) {
570
571                                                        if ( !empty( $data['kraked_width'] ) && !empty( $data['kraked_height'] ) ) {
572                                                                $image_data = wp_get_attachment_metadata( $image_id );
573                                                                $image_data['width'] = $data['kraked_width'];
574                                                                $image_data['height'] = $data['kraked_height'];
575                                                                wp_update_attachment_metadata( $image_id, $image_data );
576                                                        }
577
578                                                        // store kraked info to DB
579                                                        update_post_meta( $image_id, '_kraken_size', $data );
580
581                                                        // krak thumbnails, store that data too. This can be unset when there are no thumbs
582                                                        $kraked_thumbs_data = get_post_meta( $image_id, '_kraked_thumbs', true );
583                                                        if ( !empty( $kraked_thumbs_data ) ) {
584                                                                $data['thumbs_data'] = $kraked_thumbs_data;
585                                                                $data['success'] = true;
586                                                        }
587
588                                                        $data['html'] = $this->generate_stats_summary( $image_id );
589                                                        echo json_encode( $data );
590                                               
591                                                } else {
592                                                        echo json_encode( array( 'error' => 'Could not overwrite original file. Please ensure that your files are writable by plugins.' ) );
593                                                        exit;
594                                                }       
595
596                                        } else {
597                                                // error or no optimization
598                                                if ( file_exists( $image_path ) ) {
599                                                        update_post_meta( $image_id, '_kraken_size', $data );
600                                                } else {
601                                                        // file not found
602                                                }
603                                                echo json_encode( array( 'error' => $api_result['message'], '' ) );
604                                        }
605                                } else {
606                                        // get metadata for thumbnails
607                                        $image_data = wp_get_attachment_metadata( $image_id );
608                                        $this->optimize_thumbnails( $image_data );
609
610                                        // krak thumbnails, store that data too. This can be unset when there are no thumbs
611                                        $kraked_thumbs_data = get_post_meta( $image_id, '_kraked_thumbs', true );
612
613                                        if ( !empty( $kraked_thumbs_data ) ) {
614                                                $data['thumbs_data'] = $kraked_thumbs_data;
615                                                $data['success'] = true;
616                                        }
617                                        $data['html'] = $this->generate_stats_summary( $image_id );
618
619                                        echo json_encode( $data );
620                                }
621                        }
622                        wp_die();
623                }
624
625
626                function is_successful( $response ) {}
627
628                /**
629                 *  Handles optimizing images uploaded through any of the media uploaders.
630                 */
631                function kraken_media_uploader_callback( $image_id ) {
632
633                        $this->id = $image_id;
634
635                        if ( empty( $this->kraken_settings['optimize_main_image'] ) ) {
636                                return;
637                        }
638
639                        $settings = $this->kraken_settings;
640                        $type = $settings['api_lossy'];
641
642                        if ( !$this->isApiActive() ) {
643                                remove_filter( 'wp_generate_attachment_metadata', array( &$this, 'optimize_thumbnails') );
644                                remove_action( 'add_attachment', array( &$this, 'kraken_media_uploader_callback' ) );
645                                return;
646                        }
647
648                        if ( wp_attachment_is_image( $image_id ) ) {
649
650                                $image_path = get_attached_file( $image_id );
651                                $image_backup_path = $image_path . '_kraken_' . md5( $image_path );
652                                $backup_created = false;
653
654                                if ( copy( $image_path, $image_backup_path ) ) {
655                                        $backup_created = true;
656                                }
657
658                                $resize = false;
659                                if ( !empty( $settings['resize_width'] ) || !empty( $settings['resize_height'] ) ) {
660                                        $resize = true;
661                                }
662
663                                // optimize backup image
664                                if ( $backup_created ) {
665                                        $api_result = $this->optimize_image( $image_backup_path, $type, $resize );
666                                } else {
667                                        $api_result = $this->optimize_image( $image_path, $type, $resize );
668                                }                               
669
670                                $data = array();
671
672                                if ( !empty( $api_result ) && !empty( $api_result['success'] ) ) {
673                                        $data = $this->get_result_arr( $api_result, $image_id );
674                                       
675                                        if ( $backup_created ) {
676                                                $data['optimized_backup_file'] = $image_backup_path;
677                                                if ( $data['saved_bytes'] > 0 ) {
678                                                        if ( $this->replace_image( $image_backup_path, $api_result['kraked_url'] ) ) {
679                                                        } else {
680                                                                error_log('Kraken.io: Could not replace local image with optimized image.');
681                                                        }                                               
682                                                }                                               
683                                        } else {
684                                                if ( $data['saved_bytes'] > 0 ) {
685                                                        if ( $this->replace_image( $image_path, $api_result['kraked_url'] ) ) {
686                                                        } else {
687                                                                error_log('Kraken.io: Could not replace local image with optimized image.');
688                                                        }                                               
689                                                }
690                                        }
691                                        update_post_meta( $image_id, '_kraken_size', $data );
692
693                                } else {
694                                        // error or no optimization
695                                        if ( file_exists( $image_path ) ) {
696
697                                                $data['original_size'] = filesize( $image_path );
698                                                $data['error'] = $api_result['message'];
699                                                $data['type'] = $api_result['type'];
700                                                update_post_meta( $image_id, '_kraken_size', $data );
701
702                                        } else {
703                                                // file not found
704                                        }
705                                }
706                        }
707                }
708
709                function kraken_media_library_reset() {
710                        $image_id = (int) $_POST['id'];
711                        $image_meta = get_post_meta( $image_id, '_kraken_size', true );
712                        $original_size = self::formatBytes( filesize( get_attached_file( $image_id ) ) );
713                        delete_post_meta( $image_id, '_kraken_size' );
714                        delete_post_meta( $image_id, '_kraked_thumbs' );                       
715                        echo json_encode( array( 'success' => true, 'original_size' => $original_size, 'html' => $this->optimize_button_html( $image_id ) ) );
716                        wp_die();
717                }
718
719                function kraken_media_library_reset_all() {
720                        $result = null;
721                        delete_post_meta_by_key( '_kraked_thumbs' );
722                        delete_post_meta_by_key( '_kraken_size' );
723                        $result = json_encode( array( 'success' => true ) );
724                        echo $result;
725                        wp_die();
726                }
727
728
729                function optimize_button_html( $id )  {
730                        $image_url = wp_get_attachment_url( $id );
731                        $filename = basename( $image_url );
732
733$html = <<<EOD
734        <div class="buttonWrap">
735                <button type="button"
736                                data-setting="$this->optimization_type"
737                                class="kraken_req"
738                                data-id="$id"
739                                id="krakenid-$id"
740                                data-filename="$filename"
741                                data-url="<$image_url">
742                        Optimize This Image
743                </button>
744                <small class="krakenOptimizationType" style="display:none">$this->optimization_type</small>
745                <span class="krakenSpinner"></span>
746        </div>
747EOD;
748
749                        return $html;
750                }
751
752
753                function show_credentials_validity() {
754
755                        $settings = $this->kraken_settings;
756                        $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
757                        $api_secret = isset( $settings['api_secret'] ) ? $settings['api_secret'] : '';
758
759                        $status = $this->get_api_status( $api_key, $api_secret );
760                        $url = admin_url() . 'images/';
761
762                        if ( $status !== false && isset( $status['active'] ) && $status['active'] === true ) {
763                                $url .= 'yes.png';
764                                echo '<p class="apiStatus">Your credentials are valid <span class="apiValid" style="background:url(' . "'$url') no-repeat 0 0" . '"></span></p>';
765                        } else {
766                                $url .= 'no.png';
767                                echo '<p class="apiStatus">There is a problem with your credentials <span class="apiInvalid" style="background:url(' . "'$url') no-repeat 0 0" . '"></span></p>';
768                        }
769                }
770
771                function show_kraken_image_optimizer() {
772                        echo '<a href="http://kraken.io" title="Visit Kraken.io Homepage">Kraken.io</a> API settings';
773                }
774
775                function show_api_key() {
776                        $settings = $this->kraken_settings;
777                        $value = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
778                        ?>
779                                <input id='kraken_api_key' name='_kraken_options[api_key]'
780                                 type='text' value='<?php echo esc_attr( $value ); ?>' size="50"/>
781                        <?php
782                }
783
784                function show_api_secret() {
785                        $settings = $this->kraken_settings;
786                        $value = isset( $settings['api_secret'] ) ? $settings['api_secret'] : '';
787                        ?>
788                                <input id='kraken_api_secret' name='_kraken_options[api_secret]'
789                                 type='text' value='<?php echo esc_attr( $value ); ?>' size="50"/>
790                        <?php
791                }
792
793                function show_lossy() {
794                        $options = get_option( '_kraken_options' );
795                        $value = isset( $options['api_lossy'] ) ? $options['api_lossy'] : 'lossy';
796
797                        $html = '<input type="radio" id="kraken_lossy" name="_kraken_options[api_lossy]" value="lossy"' . checked( 'lossy', $value, false ) . '/>';
798                        $html .= '<label for="kraken_lossy">Lossy</label>';
799
800                        $html .= '<input style="margin-left:10px;" type="radio" id="kraken_lossless" name="_kraken_options[api_lossy]" value="lossless"' . checked( 'lossless', $value, false ) . '/>';
801                        $html .= '<label for="kraken_lossless">Lossless</label>';
802
803                        echo $html;
804                }
805
806                function show_auto_optimize() {
807                        $options = get_option( '_kraken_options' );
808                        $auto_optimize = isset( $options['auto_optimize'] ) ? $options['auto_optimize'] : 1;
809                        ?>
810                        <input type="checkbox" id="auto_optimize" name="_kraken_options[auto_optimize]" value="1" <?php checked( 1, $auto_optimize, true ); ?>/>
811                        <?php
812                }
813
814                function show_reset_field() {
815                        $options = get_option( '_kraken_options' );
816                        $show_reset = isset( $options['show_reset'] ) ? $options['show_reset'] : 0;
817                        ?>
818                        <input type="checkbox" id="show_reset" name="_kraken_options[show_reset]" value="1" <?php checked( 1, $show_reset, true ); ?>/>
819                        <span class="kraken-reset-all enabled">Reset All Images</span>
820                        <?php
821                }
822
823                function show_bulk_async_limit() {
824                        $options = get_option( '_kraken_options' );
825                        $bulk_limit = isset( $options['bulk_async_limit'] ) ? $options['bulk_async_limit'] : 4;
826                        ?>
827                        <select name="_kraken_options[bulk_async_limit]">
828                                <?php foreach ( range(1, 10) as $number ) { ?>
829                                        <option value="<?php echo $number ?>" <?php selected( $bulk_limit, $number, true); ?>>
830                                                <?php echo $number ?>
831                                        </option>
832                                <?php } ?>
833                        </select>
834                        <?php
835                }
836
837                function add_media_columns( $columns ) {
838                        $columns['original_size'] = 'Original Size';
839                        $columns['kraked_size'] = 'Kraken.io Stats';
840                        return $columns;
841                }
842
843
844                static function KBStringToBytes( $str ) {
845                        $temp = floatVal( $str );
846                        $rv = false;
847                        if ( 0 == $temp ) {
848                                $rv = '0 bytes';
849                        } else {
850                                $rv = self::formatBytes( ceil( floatval( $str) * 1024 ) );
851                        }
852                        return $rv;
853                }
854
855
856                static function calculate_savings( $meta ) {
857
858                        if ( isset( $meta['original_size'] ) ) {
859
860                                $saved_bytes = isset( $meta['saved_bytes'] ) ? $meta['saved_bytes'] : '';
861                                $savings_percentage = $meta['savings_percent'];
862
863                                // convert old data format, where applicable
864                                if ( stripos( $saved_bytes, 'kb' ) !== false ) {
865                                        $saved_bytes = self::KBStringToBytes( $saved_bytes );
866                                } else {
867                                        if ( !$saved_bytes ) {
868                                                $saved_bytes = '0 bytes';
869                                        } else {
870                                                $saved_bytes = self::formatBytes( $saved_bytes );
871                                        }
872                                }
873
874                                return array( 
875                                        'saved_bytes' => $saved_bytes,
876                                        'savings_percentage' => $savings_percentage 
877                                );
878                       
879                        } else if ( !empty( $meta ) ) {
880                                $thumbs_count = count( $meta );
881                                $total_thumb_byte_savings = 0;
882                                $total_thumb_size = 0;
883                                $thumbs_savings_percentage = '';
884                                $total_thumbs_savings = '';
885
886                                foreach ( $meta as $k => $v ) {
887                                        $total_thumb_size += $v['original_size'];
888                                        $thumb_byte_savings = $v['original_size'] - $v['kraked_size'];
889                                        $total_thumb_byte_savings += $thumb_byte_savings;
890                                }
891
892                                $thumbs_savings_percentage = round( ( $total_thumb_byte_savings / $total_thumb_size * 100 ), 2 ) . '%';
893                                if ( $total_thumb_byte_savings ) {
894                                        $total_thumbs_savings = self::formatBytes( $total_thumb_byte_savings );
895                                } else {
896                                        $total_thumbs_savings = '0 bytes';
897                                }
898                                return array( 
899                                        'savings_percentage' => $thumbs_savings_percentage,
900                                        'total_savings' => $total_thumbs_savings 
901                                );
902                        }
903                }
904
905                function generate_stats_summary( $id ) {
906                        $image_meta = get_post_meta( $id, '_kraken_size', true );
907                        $thumbs_meta = get_post_meta( $id, '_kraked_thumbs', true );
908
909                        $total_original_size = 0;
910                        $total_kraked_size = 0;
911                        $total_saved_bytes = 0;
912                       
913                        $total_savings_percentage = 0;
914
915                        // crap for backward compat
916                        if ( isset( $image_meta['original_size'] ) ) {
917
918                                $original_size = $image_meta['original_size'];
919
920                                if ( stripos( $original_size, 'kb' ) !== false ) {
921                                        $total_original_size = ceil( floatval( $original_size ) * 1024 );
922                                } else {
923                                        $total_original_size = (int) $original_size;
924                                }
925
926                                if ( isset( $image_meta['saved_bytes'] ) ) {
927                                        $saved_bytes = $image_meta['saved_bytes'];
928                                        if ( is_string( $saved_bytes ) ) {
929                                                $total_saved_bytes = (int) ceil( floatval( $saved_bytes ) * 1024 );
930                                        } else {
931                                                $total_saved_bytes = $saved_bytes;
932                                        }
933                                }
934
935                                $total_kraked_size = $total_original_size - $total_saved_bytes;
936                        } 
937
938                        if ( !empty( $thumbs_meta ) ) {
939                                $thumb_saved_bytes = 0;
940                                $total_thumb_byte_savings = 0;
941                                $total_thumb_size = 0;
942
943                                foreach ( $thumbs_meta as $k => $v ) {
944                                        $total_original_size += $v['original_size'];
945                                        $thumb_saved_bytes = $v['original_size'] - $v['kraked_size'];
946                                        $total_saved_bytes += $thumb_saved_bytes;
947                                }
948
949                        }
950                        $total_savings_percentage = round( ( $total_saved_bytes / $total_original_size * 100 ), 2 ) . '%';
951                        $summary_string = '';
952                        if ( !$total_saved_bytes ) {
953                                $summary_string = 'No savings';
954                        } else {
955                                $total_savings = self::formatBytes( $total_saved_bytes );
956                                $detailed_results_html = $this->results_html( $id );
957                                $summary_string = '<div class="kraken-result-wrap">' . "Saved $total_savings_percentage ($total_savings)";
958                                $summary_string .= '<br /><small class="kraken-item-details" data-id="' . $id . '" original-title="' . htmlspecialchars($detailed_results_html) .'">Show details</small></div>';
959                        }
960                        return $summary_string;
961                }
962
963                function results_html( $id ) {
964
965                        $settings = $this->kraken_settings;
966                        $optimize_main_image = !empty( $settings['optimize_main_image'] ); 
967
968                        // get meta data for main post and thumbs
969                        $image_meta = get_post_meta( $id, '_kraken_size', true );
970                        $thumbs_meta = get_post_meta( $id, '_kraked_thumbs', true );
971                        $main_image_optimized = !empty( $image_meta ) && isset( $image_meta['type'] );
972                        $thumbs_optimized = !empty( $thumbs_meta ) && count( $thumbs_meta ) && isset( $thumbs_meta[0]['type'] );
973
974                        $type = '';
975                        $kraked_size = '';
976                        $savings_percentage = '';
977
978                        if ( $main_image_optimized ) {
979                                $type = $image_meta['type'];
980                                $kraked_size = isset( $image_meta['kraked_size'] ) ? $image_meta['kraked_size'] : '';
981                                $savings_percentage = $image_meta['savings_percent'];
982                                $main_image_kraked_stats = self::calculate_savings( $image_meta );
983                        } 
984
985                        if ( $thumbs_optimized ) {
986                                $type = $thumbs_meta[0]['type'];
987                                $thumbs_kraked_stats = self::calculate_savings( $thumbs_meta );
988                                $thumbs_count = count( $thumbs_meta );
989                        }
990                       
991                        ob_start();
992                        ?>
993                                <?php if ( $main_image_optimized ) { ?>
994                                <div class="kraken_detailed_results_wrap">
995                                <span class=""><strong>Main image savings:</strong></span>
996                                <br />
997                                <span style="display:inline-block;margin-bottom:5px"><?php echo $main_image_kraked_stats['saved_bytes']; ?> (<?php echo $main_image_kraked_stats['savings_percentage']; ?> saved)</span>
998                                <?php } ?>
999                                <?php if ( $main_image_optimized && $thumbs_optimized ) { ?>
1000                                <br />
1001                                <?php } ?>
1002                                <?php if ( $thumbs_optimized ) { ?>
1003                                        <span><strong>Savings on <?php echo $thumbs_count; ?> thumbnails:</strong></span>
1004                                        <br />
1005                                        <span style="display:inline-block;margin-bottom:5px"><?php echo $thumbs_kraked_stats['total_savings']; ?> (<?php echo $thumbs_kraked_stats['savings_percentage']; ?> saved)</span>
1006                                <?php } ?>
1007                                <br />
1008                                <span><strong>Optimization mode:</strong></span>
1009                                <br />
1010                                <span><?php echo ucfirst($type); ?></span>     
1011                                <?php if ( !empty( $this->kraken_settings['show_reset'] ) ) { ?>
1012                                        <br />
1013                                        <small
1014                                                class="krakenReset" data-id="<?php echo $id; ?>"
1015                                                title="Removes Kraken metadata associated with this image">
1016                                                Reset
1017                                        </small>
1018                                        <span class="krakenSpinner"></span>
1019                                </div>
1020                                <?php } ?>
1021                        <?php   
1022                        $html = ob_get_clean();
1023                        return $html;
1024                }
1025
1026                function fill_media_columns( $column_name, $id ) {
1027
1028                        $settings = $this->kraken_settings;
1029                        $optimize_main_image = !empty( $settings['optimize_main_image'] ); 
1030
1031                        $file = get_attached_file( $id );
1032                        $original_size = filesize( $file );
1033
1034                        // handle the case where file does not exist
1035                        if ( $original_size === 0 || $original_size === false ) {
1036                                echo '0 bytes';
1037                                return;
1038                        } else {
1039                                $original_size = self::formatBytes( $original_size );                           
1040                        }
1041                       
1042                        $type = isset( $settings['api_lossy'] ) ? $settings['api_lossy'] : 'lossy';
1043
1044                        if ( strcmp( $column_name, 'original_size' ) === 0 ) {
1045                                if ( wp_attachment_is_image( $id ) ) {
1046
1047                                        $meta = get_post_meta( $id, '_kraken_size', true );
1048
1049                                        if ( isset( $meta['original_size'] ) ) {
1050
1051                                                if ( stripos( $meta['original_size'], 'kb' ) !== false ) {
1052                                                        echo self::formatBytes( ceil( floatval( $meta['original_size']) * 1024 ) );
1053                                                } else {
1054                                                        echo self::formatBytes( $meta['original_size'] );
1055                                                }
1056                                               
1057                                        } else {
1058                                                echo $original_size;
1059                                        }
1060                                } else {
1061                                        echo $original_size;
1062                                }
1063                        } else if ( strcmp( $column_name, 'kraked_size' ) === 0 ) {
1064                                echo '<div class="kraken-wrap">';
1065                                $image_url = wp_get_attachment_url( $id );
1066                                $filename = basename( $image_url );
1067                                if ( wp_attachment_is_image( $id ) ) {
1068
1069                                        $meta = get_post_meta( $id, '_kraken_size', true );
1070                                        $thumbs_meta = get_post_meta( $id, '_kraked_thumbs', true );
1071
1072                                        // Is it optimized? Show some stats
1073                                        if ( ( isset( $meta['kraked_size'] ) && empty( $meta['no_savings'] ) ) || !empty( $thumbs_meta ) ) {
1074                                                if ( !isset( $meta['kraked_size'] ) && $optimize_main_image ) {
1075                                                        echo '<div class="buttonWrap"><button data-setting="' . $type . '" type="button" class="kraken_req" data-id="' . $id . '" id="krakenid-' . $id .'" data-filename="' . $filename . '" data-url="' . $image_url . '">Optimize Main Image</button><span class="krakenSpinner"></span></div>';
1076                                                }
1077                                                echo $this->generate_stats_summary( $id );
1078
1079                                        // Were there no savings, or was there an error?
1080                                        } else {
1081                                                echo '<div class="buttonWrap"><button data-setting="' . $type . '" type="button" class="kraken_req" data-id="' . $id . '" id="krakenid-' . $id .'" data-filename="' . $filename . '" data-url="' . $image_url . '">Optimize This Image</button><span class="krakenSpinner"></span></div>';
1082                                                if ( !empty( $meta['no_savings'] ) ) {
1083                                                        echo '<div class="noSavings"><strong>No savings found</strong><br /><small>Type:&nbsp;' . $meta['type'] . '</small></div>';
1084                                                } else if ( isset( $meta['error'] ) ) {
1085                                                        $error = $meta['error'];
1086                                                        echo '<div class="krakenErrorWrap"><a class="krakenError" title="' . $error . '">Failed! Hover here</a></div>';
1087                                                }
1088                                        }
1089                                } else {
1090                                        echo 'n/a';
1091                                }
1092                                echo '</div>';
1093                        }
1094                }
1095
1096                function replace_image( $image_path, $kraked_url ) {
1097                        $rv = false;
1098                        $ch =  curl_init( $kraked_url );
1099                        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
1100                curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
1101                curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
1102                curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 0 ); 
1103                curl_setopt( $ch, CURLOPT_TIMEOUT, 120 );                     
1104            curl_setopt( $ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36' );
1105                        $result = curl_exec( $ch );
1106
1107                        if ( $result ) {
1108                                $rv = file_put_contents( $image_path, $result );
1109                        }
1110                        return $rv !== false;
1111                }
1112
1113                function optimize_image( $image_path, $type, $resize = false ) {
1114                        $settings = $this->kraken_settings;
1115                        $kraken = new Kraken( $settings['api_key'], $settings['api_secret'] );
1116
1117                        if ( !empty( $type ) ) {
1118                                $lossy = $type === 'lossy';
1119                        } else {
1120                                $lossy = $settings['api_lossy'] === 'lossy';
1121                        }
1122
1123                        $params = array(
1124                                'file' => $image_path,
1125                                'wait' => true,
1126                                'lossy' => $lossy,
1127                                'origin' => 'wp'
1128                        );
1129
1130                        $preserve_meta_arr = array();
1131                        if ( $settings['preserve_meta_date'] ) {
1132                                $preserve_meta_arr[] = 'date';
1133                        }
1134                        if ( $settings['preserve_meta_copyright'] ) {
1135                                $preserve_meta_arr[] = 'copyright';
1136                        }
1137                        if ( $settings['preserve_meta_geotag'] ) {
1138                                $preserve_meta_arr[] = 'geotag';
1139                        }
1140                        if ( $settings['preserve_meta_orientation'] ) {
1141                                $preserve_meta_arr[] = 'orientation';
1142                        }
1143                        if ( $settings['preserve_meta_profile'] ) {
1144                                $preserve_meta_arr[] = 'profile';
1145                        }
1146                        if ( $settings['chroma'] ) {
1147                                $params['sampling_scheme'] = $settings['chroma'];
1148                        }
1149
1150                        if ( count( $preserve_meta_arr ) ) {
1151                                $params['preserve_meta'] = $preserve_meta_arr;
1152                        }
1153
1154                        if ( $settings['auto_orient'] ) {
1155                                $params['auto_orient'] = true;
1156                        }
1157
1158                        if ( $resize ) {
1159                                $width = (int) $settings['resize_width'];
1160                                $height = (int) $settings['resize_height'];
1161                                if ( $width && $height ) {
1162                                        $params['resize'] = array('strategy' => 'auto', 'width' => $width, 'height' => $height );
1163                                } elseif ( $width && !$height ) {
1164                                        $params['resize'] = array('strategy' => 'landscape', 'width' => $width );
1165                                } elseif ( $height && !$width ) {
1166                                        $params['resize'] = array('strategy' => 'portrait', 'height' => $height );
1167                                }
1168                        }
1169
1170                        if ( isset( $settings['jpeg_quality'] ) && $settings['jpeg_quality'] > 0 ) {
1171                                $params['quality'] = (int) $settings['jpeg_quality'];
1172                        }
1173                       
1174                        set_time_limit(400);
1175                        $data = $kraken->upload( $params );
1176                        $data['type'] = !empty( $type ) ? $type : $settings['api_lossy'];
1177                        return $data;
1178                }
1179
1180                function get_sizes_to_krak() {
1181                        $settings = $this->kraken_settings;
1182                        $rv = array();
1183
1184                        foreach( $settings as $key => $value ) {
1185                                if ( strpos( $key, 'include_size' ) === 0 && !empty( $value ) ) {
1186                                        $rv[] = $key;
1187                                }
1188                        }
1189                        return $rv;
1190                }
1191
1192                function optimize_thumbnails( $image_data ) {
1193
1194                        $image_id = $this->id;
1195                        if ( empty( $image_id ) ) {
1196                                global $wpdb;
1197                                $post = $wpdb->get_row( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_value = %s LIMIT 1", $image_data['file'] ) );
1198                                $image_id = $post->post_id;
1199                        }
1200
1201                        $kraken_meta = get_post_meta( $image_id, '_kraken_size', true );
1202                        $image_backup_path = isset( $kraken_meta['optimized_backup_file'] ) ? $kraken_meta['optimized_backup_file'] : '';
1203                       
1204                        if ( $image_backup_path ) {
1205                                $original_image_path = get_attached_file( $image_id );                         
1206                                if ( copy( $image_backup_path, $original_image_path ) ) {
1207                                        unlink( $image_backup_path );
1208                                        unset( $kraken_meta['optimized_backup_file'] );
1209                                        update_post_meta( $image_id, '_kraken_size', $kraken_meta );
1210                                }
1211                        }
1212
1213                        if ( !$this->preg_array_key_exists( '/^include_size_/', $this->kraken_settings ) ) {
1214                               
1215                                global $_wp_additional_image_sizes;
1216                                $sizes = array();
1217
1218                                foreach ( get_intermediate_image_sizes() as $_size ) {
1219                                        if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) {
1220                                                $sizes[ $_size ]['width']  = get_option( "{$_size}_size_w" );
1221                                                $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
1222                                                $sizes[ $_size ]['crop']   = (bool) get_option( "{$_size}_crop" );
1223                                        } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
1224                                                $sizes[ $_size ] = array(
1225                                                        'width'  => $_wp_additional_image_sizes[ $_size ]['width'],
1226                                                        'height' => $_wp_additional_image_sizes[ $_size ]['height'],
1227                                                        'crop'   => $_wp_additional_image_sizes[ $_size ]['crop'],
1228                                                );
1229                                        }
1230                                }
1231                                $sizes = array_keys( $sizes );
1232                                foreach ($sizes as $size) {
1233                                        $this->kraken_settings['include_size_' . $size] = 1;
1234                                }
1235                        }                       
1236
1237                        // when resizing has taken place via API, update the post metadata accordingly
1238                        if ( !empty( $kraken_meta['kraked_width'] ) && !empty( $kraken_meta['kraked_height'] ) ) {
1239                                $image_data['width'] = $kraken_meta['kraked_width'];
1240                                $image_data['height'] = $kraken_meta['kraked_height'];
1241                        }
1242
1243
1244                        $path_parts = pathinfo( $image_data['file'] );
1245
1246                        // e.g. 04/02, for use in getting correct path or URL
1247                        $upload_subdir = $path_parts['dirname'];
1248
1249                        $upload_dir = wp_upload_dir();
1250
1251                        // all the way up to /uploads
1252                        $upload_base_path = $upload_dir['basedir'];
1253                        $upload_full_path = $upload_base_path . '/' . $upload_subdir;
1254
1255                        $sizes = array();
1256
1257                        if ( isset( $image_data['sizes'] ) ) {
1258                                $sizes = $image_data['sizes'];
1259                        }
1260
1261                        if ( !empty( $sizes ) ) {
1262
1263                                $sizes_to_krak = $this->get_sizes_to_krak();
1264                                $thumb_path = '';
1265                                $thumbs_optimized_store = array();
1266                                $this_thumb = array();
1267
1268                                foreach ( $sizes as $key => $size ) {
1269
1270                                        if ( !in_array("include_size_$key", $sizes_to_krak) ) {
1271                                                continue;
1272                                        }
1273
1274                                        $thumb_path = $upload_full_path . '/' . $size['file'];
1275                                       
1276                                        if ( file_exists( $thumb_path ) !== false ) {
1277                                                $result = $this->optimize_image( $thumb_path, $this->optimization_type );
1278                                                if ( !empty( $result ) && isset( $result['success'] ) && isset( $result['kraked_url'] ) ) {
1279                                                        $kraked_url = $result['kraked_url'];
1280                                                        if ( (int) $result['saved_bytes'] !== 0 ) {
1281                                                                if ( $this->replace_image( $thumb_path, $kraked_url ) ) {
1282                                                                        $this_thumb = array( 'thumb' => $key, 'file' => $size['file'], 'original_size' => $result['original_size'], 'kraked_size' => $result['kraked_size'], 'type' => $this->optimization_type );
1283                                                                        $thumbs_optimized_store [] = $this_thumb;
1284                                                                }
1285                                                        } else {
1286                                                                $this_thumb = array( 'thumb' => $key, 'file' => $size['file'], 'original_size' => $result['original_size'], 'kraked_size' => $result['original_size'], 'type' => $this->optimization_type );
1287                                                                $thumbs_optimized_store [] = $this_thumb;                                                               
1288                                                        }
1289                                                } 
1290                                        }
1291                                }
1292                        }
1293                        if ( !empty( $thumbs_optimized_store ) ) {
1294                                update_post_meta( $image_id, '_kraked_thumbs', $thumbs_optimized_store, false );
1295                        }
1296                        return $image_data;
1297                }
1298
1299                function get_image_sizes() {
1300                        global $_wp_additional_image_sizes;
1301
1302                        $sizes = array();
1303
1304                        foreach ( get_intermediate_image_sizes() as $_size ) {
1305                                if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) {
1306                                        $sizes[ $_size ]['width']  = get_option( "{$_size}_size_w" );
1307                                        $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
1308                                        $sizes[ $_size ]['crop']   = (bool) get_option( "{$_size}_crop" );
1309                                } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
1310                                        $sizes[ $_size ] = array(
1311                                                'width'  => $_wp_additional_image_sizes[ $_size ]['width'],
1312                                                'height' => $_wp_additional_image_sizes[ $_size ]['height'],
1313                                                'crop'   => $_wp_additional_image_sizes[ $_size ]['crop'],
1314                                        );
1315                                }
1316                        }
1317
1318                        return $sizes;
1319                }
1320
1321
1322                static function formatBytes( $size, $precision = 2 ) {
1323                    $base = log( $size, 1024 );
1324                    $suffixes = array( ' bytes', 'KB', 'MB', 'GB', 'TB' );   
1325                    return round( pow( 1024, $base - floor( $base ) ), $precision ) . $suffixes[floor( $base )];
1326                }
1327        }
1328}
1329
1330new Wp_Kraken();
Note: See TracBrowser for help on using the repository browser.