PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 3.1.1
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v3.1.1
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / inc / admin.php

admin.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 3.1.1, at inc/admin.php

920 lines 44.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin class.
4 *
5 * Author: Andrei Baicus <andrei@themeisle.com>
6 * Created on: 19/07/2018
7 *
8 * @soundtrack Somewhere Else - Marillion
9 * @package \Optimole\Inc
10 * @author Optimole <friends@optimole.com>
11 */
12
13 /**
14 * Class Optml_Admin
15 */
16 class Optml_Admin {
17
18 /**
19 * Hold the settings object.
20 *
21 * @var Optml_Settings Settings object.
22 */
23 public $settings;
24
25 /**
26 * Optml_Admin constructor.
27 */
28 public function __construct() {
29 $this->settings = new Optml_Settings();
30 add_action( 'plugin_action_links_' . plugin_basename( OPTML_BASEFILE ), [ $this, 'add_action_links' ] );
31 add_action( 'admin_menu', [ $this, 'add_dashboard_page' ] );
32 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], PHP_INT_MIN );
33 add_action( 'admin_notices', [ $this, 'add_notice' ] );
34 add_action( 'admin_notices', [ $this, 'add_notice_upgrade' ] );
35 add_filter( 'admin_body_class', [ $this, 'add_body_class' ] );
36 add_action( 'optml_daily_sync', [ $this, 'daily_sync' ] );
37 add_action( 'admin_init', [ $this, 'maybe_redirect' ] );
38 if ( ! is_admin() && $this->settings->is_connected() && ! wp_next_scheduled( 'optml_daily_sync' ) ) {
39 wp_schedule_event( time() + 10, 'daily', 'optml_daily_sync', [] );
40 }
41 add_action( 'optml_after_setup', [ $this, 'register_public_actions' ], 999999 );
42
43 }
44
45 /**
46 * Adds Optimole tag to admin bar
47 */
48 public function add_report_menu() {
49 global $wp_admin_bar;
50
51 $wp_admin_bar->add_node(
52 [
53 'id' => 'optml_report_script',
54 'href' => '#',
55 'title' => '<span class="ab-icon"></span>Optimole ' . __( 'debugger', 'optimole-wp' ),
56 ]
57 );
58 $wp_admin_bar->add_menu(
59 [
60 'id' => 'optml_status',
61 'title' => __( 'Troubleshoot this page', 'optimole-wp' ),
62 'parent' => 'optml_report_script',
63 ]
64 );
65 }
66
67 /**
68 * Adds Optimole css to admin bar
69 */
70 public function print_report_css() {
71 ?>
72 <style type="text/css">
73 li#wp-admin-bar-optml_report_script > div :hover {
74 cursor: pointer;
75 color: #00b9eb !important;
76 text-decoration: underline;
77 }
78
79 #wpadminbar #wp-admin-bar-optml_report_script .ab-icon:before {
80 content: "\f227";
81 top: 3px;
82 }
83
84 /* The Modal (background) */
85 .optml-modal {
86 display: none; /* Hidden by default */
87 position: fixed; /* Stay in place */
88 z-index: 2147483641; /* Sit on top */
89 padding-top: 100px; /* Location of the box */
90 left: 0;
91 top: 0;
92 width: 100%; /* Full width */
93 height: 100%; /* Full height */
94 overflow: auto; /* Enable scroll if needed */
95 background-color: rgb(0, 0, 0); /* Fallback color */
96 background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
97 }
98
99 /* Modal Content */
100 .optml-modal-content {
101 background-color: #fefefe;
102 margin: auto;
103 padding: 20px;
104 border: 1px solid #888;
105 width: 80%;
106 }
107
108 /* The Close Button */
109 .optml-close {
110 color: #aaaaaa;
111 float: right;
112 font-size: 28px;
113 font-weight: bold;
114 }
115
116 .optml-modal-content ul {
117 list-style: none;
118 font-size: 80%;
119 margin-top: 50px;
120 }
121
122 .optml-close:hover,
123 .optml-close:focus {
124 color: #000;
125 text-decoration: none;
126 cursor: pointer;
127 }
128 </style>
129 <?php
130 }
131
132 /**
133 * Register public actions.
134 */
135 public function register_public_actions() {
136 add_action( 'wp_head', [ $this, 'generator' ] );
137 add_filter( 'wp_resource_hints', [ $this, 'add_dns_prefetch' ], 10, 2 );
138
139 if ( Optml_Manager::should_ignore_image_tags() ) {
140 return;
141 }
142 if ( ! is_admin() && $this->settings->get( 'report_script' ) === 'enabled' && current_user_can( 'manage_options' ) ) {
143
144 add_action( 'wp_head', [ $this, 'print_report_css' ] );
145 add_action( 'wp_before_admin_bar_render', [ $this, 'add_report_menu' ] );
146 add_action( 'wp_enqueue_scripts', [ $this, 'add_diagnosis_script' ] );
147 }
148 if ( ! $this->settings->use_lazyload() ) {
149 return;
150 }
151 add_action( 'wp_enqueue_scripts', [ $this, 'frontend_scripts' ] );
152 add_action( 'wp_head', [ $this, 'inline_bootstrap_script' ] );
153
154 add_filter( 'optml_additional_html_classes', [ $this, 'add_no_js_class_to_html_tag' ], 10, 1 );
155 }
156
157 /**
158 * Use filter to add additional class to html tag.
159 *
160 * @param array $classes The classes to be added.
161 *
162 * @return array
163 */
164 public function add_no_js_class_to_html_tag( $classes ) {
165 // we need the space padding since some plugins might not target correctly with js there own classes
166 // this causes some issues if they concat directly, this way we can protect against that since no matter what
167 // there will be an extra space padding so that classes can be easily identified
168 return array_merge( $classes, [ ' optml_no_js ' ] );
169 }
170
171 /**
172 * Adds script for lazyload/js replacement.
173 */
174 public function inline_bootstrap_script() {
175
176 $domain = 'https://' . $this->settings->get_cdn_url() . '/js-lib';
177
178 $min = ! OPTML_DEBUG ? '.min' : '';
179 $bgclasses = Optml_Lazyload_Replacer::get_lazyload_bg_classes();
180 $watcher_classes = Optml_Lazyload_Replacer::get_watcher_lz_classes();
181 $lazyload_bg_selectors = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
182 foreach ( $bgclasses as $key ) {
183 $lazyload_bg_selectors[] = '.' . $key;
184 }
185 $lazyload_bg_selectors = empty( $lazyload_bg_selectors ) ? '' : sprintf( '%s', implode( ', ', (array) $lazyload_bg_selectors ) );
186 $bgclasses = empty( $bgclasses ) ? '' : sprintf( '"%s"', implode( '","', (array) $bgclasses ) );
187 $watcher_classes = empty( $watcher_classes ) ? '' : sprintf( '"%s"', implode( '","', (array) $watcher_classes ) );
188 $default_network = ( $this->settings->get( 'network_optimization' ) === 'enabled' );
189 $retina_ready = ! ( $this->settings->get( 'retina_images' ) === 'enabled' );
190 $scale_is_disabled = ( $this->settings->get( 'scale' ) === 'enabled' );
191 $native_lazy_enabled = ( $this->settings->get( 'native_lazyload' ) === 'enabled' );
192 $output = sprintf(
193 '
194 <style type="text/css">
195 img[data-opt-src]:not([data-opt-lazy-loaded]) {
196 transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
197 -webkit-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
198 -moz-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
199 -o-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
200 }
201 img[data-opt-src]:not([data-opt-lazy-loaded]) {
202 opacity: .75;
203 -webkit-filter: blur(8px);
204 -moz-filter: blur(8px);
205 -o-filter: blur(8px);
206 -ms-filter: blur(8px);
207 filter: blur(8px);
208 transform: scale(1.04);
209 animation: 0.1s ease-in;
210 -webkit-transform: translate3d(0, 0, 0);
211 }
212 %s
213 </style>
214 <script type="application/javascript">
215 document.documentElement.className = document.documentElement.className.replace(/\boptml_no_js\b/g, "");
216 (function(w, d){
217 var b = d.getElementsByTagName("head")[0];
218 var s = d.createElement("script");
219 var v = ("IntersectionObserver" in w && "isIntersecting" in w.IntersectionObserverEntry.prototype) ? "_no_poly" : "";
220 s.async = true;
221 s.src = "%s/v2/latest/optimole_lib" + v + "%s.js";
222 b.appendChild(s);
223 w.optimoleData = {
224 lazyloadOnly: "optimole-lazy-only",
225 backgroundReplaceClasses: [%s],
226 nativeLazyload : %s,
227 scalingDisabled: %s,
228 watchClasses: [%s],
229 backgroundLazySelectors: "%s",
230 network_optimizations: %s,
231 ignoreDpr: %s,
232 quality: %d
233 }
234 }(window, document));
235 document.addEventListener( "DOMContentLoaded", function() {
236
237 if ( "loading" in HTMLImageElement.prototype && Object.prototype.hasOwnProperty.call( optimoleData, "nativeLazyload" ) && optimoleData.nativeLazyload === true ) {
238 const images = document.querySelectorAll(\'img[loading="lazy"]\');
239 images.forEach( function (img) {
240 if ( !img.dataset.optSrc) {
241 return;
242 }
243 img.src = img.dataset.optSrc;
244 delete img.dataset.optSrc;
245 });
246 }
247 } );
248 </script>',
249 Optml_Lazyload_Replacer::IFRAME_TEMP_COMMENT,
250 esc_url( $domain ),
251 $min,
252 $bgclasses,
253 $native_lazy_enabled ? 'true' : 'false',
254 $scale_is_disabled ? 'true' : 'false',
255 $watcher_classes,
256 addcslashes( $lazyload_bg_selectors, '"' ),
257 defined( 'OPTML_NETWORK_ON' ) && constant( 'OPTML_NETWORK_ON' ) ? ( OPTML_NETWORK_ON ? 'true' : 'false' ) : ( $default_network ? 'true' : 'false' ),
258 $retina_ready ? 'true' : 'false',
259 $this->settings->get_numeric_quality()
260 );
261 echo $output;
262 }
263
264 /**
265 * Adds script for lazyload/js replacement.
266 */
267 public function add_diagnosis_script() {
268
269 wp_enqueue_script( 'optml-report', OPTML_URL . 'assets/js/report_script.js' );
270 $ignored_domains = [ 'gravatar.com', 'instagram.com', 'fbcdn' ];
271 $report_script = [
272 'optmlCdn' => $this->settings->get_cdn_url(),
273 'restUrl' => untrailingslashit( rest_url( OPTML_NAMESPACE . '/v1' ) ) . '/check_redirects',
274 'nonce' => wp_create_nonce( 'wp_rest' ),
275 'ignoredDomains' => $ignored_domains,
276 'wait' => __( 'We are checking the current page for any issues with optimized images ...', 'optimole-wp' ),
277 'description' => __( 'Optimole page analyzer', 'optimole-wp' ),
278 ];
279 wp_localize_script( 'optml-report', 'reportScript', $report_script );
280 }
281
282 /**
283 * Add settings links in the plugin listing page.
284 *
285 * @param array $links Old plugin links.
286 *
287 * @return array Altered links.
288 */
289 function add_action_links( $links ) {
290 if ( ! is_array( $links ) ) {
291 return $links;
292 }
293
294 return array_merge(
295 $links,
296 [
297 '<a href="' . admin_url( 'upload.php?page=optimole' ) . '">' . __( 'Settings', 'optimole-wp' ) . '</a>',
298 ]
299 );
300 }
301
302 /**
303 * Adds optimole optin class.
304 *
305 * @return string Optimole class.
306 */
307 public function add_body_class( $classes ) {
308
309 if ( ! $this->should_show_notice() ) {
310 return $classes;
311 }
312
313 return $classes . ' optimole-optin-show ';
314 }
315
316 /**
317 * Check if we should show the notice.
318 *
319 * @return bool Should show?
320 */
321 public function should_show_notice() {
322
323 $current_screen = get_current_screen();
324 if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
325 is_network_admin() ||
326 $this->settings->is_connected() ||
327 empty( $current_screen )
328 ) {
329 return false;
330 }
331
332 static $allowed_base = [
333 'plugins' => true,
334 'upload' => true,
335 'media' => true,
336 'themes' => true,
337 'appearance_page_tgmpa-install-plugins' => true,
338 ];
339
340 $screen_slug = '';
341 if ( isset( $current_screen->base ) ) {
342 $screen_slug = $current_screen->base;
343 }
344
345 if ( isset( $current_screen->parent_base ) ) {
346 $screen_slug = $current_screen->parent_base;
347 }
348
349 if ( empty( $screen_slug ) ||
350 ( ! isset( $allowed_base[ $screen_slug ] ) ) ||
351 ! current_user_can( 'manage_options' ) ||
352 ( get_option( 'optml_notice_optin', 'no' ) === 'yes' )
353 ) {
354 return false;
355 }
356
357 return true;
358 }
359
360 /**
361 * Show upgrade notice.
362 */
363 public function add_notice_upgrade() {
364 if ( ! $this->should_show_upgrade() ) {
365 return;
366 }
367 ?>
368 <div class="notice notice-warning optml-notice-optin">
369 <p> <?php printf( __( 'It seems your are close to the %1$s5.0000%2$s visits limit with %3$sOptiMole%4$s for this month. You might want to check the upgrade plans for a larger quota. %5$s %6$s What happens if i exceed the quota ?%7$s We will need to deliver back your original %8$sun-optimized%9$s images which might decrease your site speed perfomance.', 'optimole-wp' ), '<strong>', '</strong>', '<strong>', '</strong>', '<br/><br/>', '<i>', '</i >', '<strong>', '</strong>' ); ?></p>
370 <p>
371 <a href="https://optimole.com/pricing" target="_blank" class="button button-primary"><span
372 class="dashicons dashicons-external"></span><?php _e( 'Check upgrade plans', 'optimole-wp' ); ?>
373 </a>
374 <a class="button"
375 href="<?php echo wp_nonce_url( add_query_arg( [ 'optml_hide_upg' => 'yes' ] ), 'hide_nonce', 'optml_nonce' ); ?>"><?php _e( 'I\'ve done this', 'optimole-wp' ); ?></a>
376 </p>
377 </div>
378 <?php
379 }
380
381 /**
382 * Check if we should show the upgrade notice to users.
383 *
384 * @return bool Should we show it?
385 */
386 public function should_show_upgrade() {
387 $current_screen = get_current_screen();
388 if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
389 is_network_admin() ||
390 ! current_user_can( 'manage_options' ) ||
391 ! $this->settings->is_connected() ||
392 empty( $current_screen )
393 ) {
394 return false;
395 }
396 if ( get_option( 'optml_notice_hide_upg', 'no' ) === 'yes' ) {
397 return false;
398 }
399 if ( isset( $current_screen->base ) && $current_screen->base !== 'upload' ) {
400 return false;
401 }
402 $service_data = $this->settings->get( 'service_data' );
403 if ( ! isset( $service_data['plan'] ) ) {
404 return false;
405 }
406 if ( $service_data['plan'] !== 'free' ) {
407 return false;
408 }
409 $visitors_limit = isset( $service_data['visitors_limit'] ) ? (int) $service_data['visitors_limit'] : 0;
410 $visitors_left = isset( $service_data['visitors_left'] ) ? (int) $service_data['visitors_left'] : 0;
411 if ( $visitors_limit === 0 ) {
412 return false;
413 }
414 if ( $visitors_left > 2000 ) {
415 return false;
416 }
417
418 return true;
419 }
420
421 /**
422 * Adds opt in notice.
423 */
424 public function add_notice() {
425 if ( ! $this->should_show_notice() ) {
426 return;
427 }
428 ?>
429 <div class="notice notice-success optml-notice-optin">
430 <p> <?php printf( __( 'Welcome to %1$sOptiMole%2$s, the easiest way to optimize your website images. Your users will enjoy a %3$sfaster%4$s website after you connect it with our service.', 'optimole-wp' ), '<strong>', '</strong>', '<strong>', '</strong>' ); ?></p>
431 <p>
432 <a href="<?php echo esc_url( admin_url( 'upload.php?page=optimole' ) ); ?>"
433 class="button button-primary"><?php _e( 'Connect to OptiMole', 'optimole-wp' ); ?></a>
434 <a class="button"
435 href="<?php echo wp_nonce_url( add_query_arg( [ 'optml_hide_optin' => 'yes' ] ), 'hide_nonce', 'optml_nonce' ); ?>"><?php _e( 'I will do it later', 'optimole-wp' ); ?></a>
436 </p>
437 </div>
438 <?php
439 }
440
441 /**
442 * Add style classes for lazy loading background images.
443 */
444 protected function get_background_lazy_css() {
445
446 $watchers = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
447
448 $css = [];
449 foreach ( $watchers as $selector ) {
450 $css[] = 'html ' . $selector . ':not(.optml-bg-lazyloaded)';
451 }
452 if ( empty( $css ) ) {
453 return '';
454 }
455 $css = implode( ",\n", $css ) . ' { background-image: none !important; } ';
456
457 return strip_tags( $css );
458 }
459
460 /**
461 * Enqueue frontend scripts.
462 */
463 public function frontend_scripts() {
464
465 $bg_css = $this->get_background_lazy_css();
466
467 wp_register_style( 'optm_lazyload_noscript_style', false );
468 wp_enqueue_style( 'optm_lazyload_noscript_style' );
469 wp_add_inline_style( 'optm_lazyload_noscript_style', "html.optml_no_js img[data-opt-src] { display: none !important; } \n " . $bg_css );
470 }
471
472 /**
473 * Maybe redirect to dashboard page.
474 */
475 public function maybe_redirect() {
476
477 if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_optin'] ) && $_GET['optml_hide_optin'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
478 update_option( 'optml_notice_optin', 'yes' );
479 }
480
481 if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_upg'] ) && $_GET['optml_hide_upg'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
482 update_option( 'optml_notice_hide_upg', 'yes' );
483 }
484
485 if ( ! get_transient( 'optml_fresh_install' ) ) {
486 return;
487 }
488
489 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
490 return;
491 }
492
493 delete_transient( 'optml_fresh_install' );
494
495 if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
496 return;
497 }
498
499 if ( $this->settings->is_connected() ) {
500 return;
501 }
502 wp_safe_redirect( admin_url( 'upload.php?page=optimole' ) );
503 exit;
504 }
505
506 /**
507 * Output Generator tag.
508 */
509 public function generator() {
510 if ( ! $this->settings->is_connected() ) {
511 return;
512 }
513 if ( ! $this->settings->is_enabled() ) {
514 return;
515 }
516 echo '<meta name="generator" content="Optimole ' . esc_attr( OPTML_VERSION ) . '">';
517 }
518
519 /**
520 * Update daily the quota routine.
521 */
522 function daily_sync() {
523
524 $api_key = $this->settings->get( 'api_key' );
525 if ( empty( $api_key ) ) {
526 return;
527 }
528
529 $request = new Optml_Api();
530 $data = $request->get_user_data( $api_key );
531 if ( $data === false || is_wp_error( $data ) ) {
532 return;
533 }
534
535 $this->settings->update( 'service_data', $data );
536
537 }
538
539 /**
540 * Adds cdn url for prefetch.
541 *
542 * @param array $hints Hints array.
543 * @param string $relation_type Type of relation.
544 *
545 * @return array Altered hints array.
546 */
547 public function add_dns_prefetch( $hints, $relation_type ) {
548 if ( 'dns-prefetch' !== $relation_type &&
549 'preconnect' !== $relation_type
550 ) {
551 return $hints;
552 }
553 if ( ! $this->settings->is_connected() ) {
554 return $hints;
555 }
556 if ( ! $this->settings->is_enabled() ) {
557 return $hints;
558 }
559 $hints[] = sprintf( 'https://%s', $this->settings->get_cdn_url() );
560
561 return $hints;
562 }
563
564 /**
565 * Add the dashboard page.
566 */
567 public function add_dashboard_page() {
568 if ( defined( 'OPTIOMLE_HIDE_ADMIN_AREA' ) && OPTIOMLE_HIDE_ADMIN_AREA ) {
569 return;
570 }
571 add_media_page( 'Optimole', 'Optimole', 'manage_options', 'optimole', [ $this, 'render_dashboard_page' ] );
572 }
573
574 /**
575 * Render dashboard page.
576 */
577 public function render_dashboard_page() {
578 if ( get_option( 'optml_notice_optin', 'no' ) !== 'yes' ) {
579 update_option( 'optml_notice_optin', 'yes' );
580 }
581 ?>
582
583 <div id="optimole-app">
584 <app></app>
585 </div>
586 <?php
587 }
588
589 /**
590 * Enqueue scripts needed for admin functionality.
591 *
592 * @codeCoverageIgnore
593 */
594 public function enqueue() {
595
596 $current_screen = get_current_screen();
597 if ( ! isset( $current_screen->id ) ) {
598 return;
599 }
600 if ( $current_screen->id !== 'media_page_optimole' ) {
601 return;
602 }
603 wp_register_script( OPTML_NAMESPACE . '-admin', OPTML_URL . 'assets/js/bundle' . ( ! OPTML_DEBUG ? '.min' : '' ) . '.js', [], OPTML_VERSION );
604 wp_localize_script( OPTML_NAMESPACE . '-admin', 'optimoleDashboardApp', $this->localize_dashboard_app() );
605 wp_enqueue_script( OPTML_NAMESPACE . '-admin' );
606 }
607
608 /**
609 * Localize the dashboard app.
610 *
611 * @codeCoverageIgnore
612 * @return array
613 */
614 private function localize_dashboard_app() {
615
616 global $wp_version;
617 $is_offload_media_available = 'no';
618 if ( version_compare( $wp_version, '5.3', '>=' ) ) {
619 $is_offload_media_available = 'yes';
620 }
621 $api_key = $this->settings->get( 'api_key' );
622 $service_data = $this->settings->get( 'service_data' );
623 $user = get_userdata( get_current_user_id() );
624
625 return [
626 'strings' => $this->get_dashboard_strings(),
627 'assets_url' => OPTML_URL . 'assets/',
628 'connection_status' => empty( $service_data ) ? 'no' : 'yes',
629 'has_application' => isset( $service_data['app_count'] ) && $service_data['app_count'] >= 1 ? 'yes' : 'no',
630 'user_status' => isset( $service_data['status'] ) && $service_data['status'] === 'inactive' ? 'inactive' : 'active',
631 'available_apps' => isset( $service_data['available_apps'] ) ? $service_data['available_apps'] : null,
632 'api_key' => $api_key,
633 'root' => untrailingslashit( rest_url( OPTML_NAMESPACE . '/v1' ) ),
634 'nonce' => wp_create_nonce( 'wp_rest' ),
635 'user_data' => $service_data,
636 'remove_latest_images' => defined( 'OPTML_REMOVE_LATEST_IMAGES' ) && constant( 'OPTML_REMOVE_LATEST_IMAGES' ) ? ( OPTML_REMOVE_LATEST_IMAGES ? 'yes' : 'no' ) : 'no',
637 'current_user' => [
638 'email' => $user->user_email,
639 ],
640 'site_settings' => $this->settings->get_site_settings(),
641 'home_url' => home_url(),
642 'is_offload_media_available' => $is_offload_media_available,
643 ];
644 }
645
646 /**
647 * Get all dashboard strings.
648 *
649 * @codeCoverageIgnore
650 * @return array
651 */
652 private function get_dashboard_strings() {
653 return [
654 'optimole' => 'Optimole',
655 'version' => OPTML_VERSION,
656 'terms_menu' => __( 'Terms', 'optimole-wp' ),
657 'privacy_menu' => __( 'Privacy', 'optimole-wp' ),
658 'testdrive_menu' => __( 'Test Optimole', 'optimole-wp' ),
659 'service_details' => __( 'Image optimization service', 'optimole-wp' ),
660 'connect_btn' => __( 'Connect to OptiMole Service', 'optimole-wp' ),
661 'disconnect_btn' => __( 'Disconnect', 'optimole-wp' ),
662 'refresh_stats_cta' => __( 'Refresh stats', 'optimole-wp' ),
663 'updating_stats_cta' => __( 'Updating stats', 'optimole-wp' ),
664 'api_key_placeholder' => __( 'API Key', 'optimole-wp' ),
665 'account_needed_heading' => __( 'Sign-up for API key', 'optimole-wp' ),
666 'invalid_key' => __( 'Invalid API Key', 'optimole-wp' ),
667 'status' => __( 'Status', 'optimole-wp' ),
668 'email_address_label' => __( 'Your email address', 'optimole-wp' ),
669 'register_btn' => __( 'Register & Email API key', 'optimole-wp' ),
670 'step_one_api_title' => __( 'Enter your API key.', 'optimole-wp' ),
671 'step_one_api_desc' => sprintf( __( 'Copy the API key you have received via email or you can get it from %1$s Optimole dashboard%2$s. <br/>', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/" target="_blank"> ', '</a>' ),
672 'step_two_api_title' => __( 'Connect to Optimole.', 'optimole-wp' ),
673 'step_two_api_desc' => __( 'Fill in the upper API key field and connect to Optimole service.', 'optimole-wp' ),
674 'step_three_api_title' => __( 'Select your domain', 'optimole-wp' ),
675 'step_three_api_desc' => __( 'If your account has multiple domains select the one you want to use.', 'optimole-wp' ),
676 'api_exists' => __( 'I already have an API key.', 'optimole-wp' ),
677 'back_to_register' => __( 'Register account', 'optimole-wp' ),
678 'back_to_connect' => __( 'Connect account', 'optimole-wp' ),
679 'error_register' => sprintf( __( 'Error registering account. You can try again %1$shere%2$s ', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/register" target="_blank"> ', '</a>' ),
680 'connected' => __( 'Connected', 'optimole-wp' ),
681 'not_connected' => __( 'Not connected', 'optimole-wp' ),
682 'usage' => __( 'Monthly Usage', 'optimole-wp' ),
683 'quota' => __( 'Monthly Quota', 'optimole-wp' ),
684 'logged_in_as' => __( 'Logged in as', 'optimole-wp' ),
685 'private_cdn_url' => __( 'Images domain', 'optimole-wp' ),
686 'notification_message_register' => __( 'We have sent you an email with the API key. Please copy and paste the key in the field below.', 'optimole-wp' ),
687 'account_needed_title' => sprintf(
688 __( 'In order to get access to free image optimization service you will need an API key from %s.', 'optimole-wp' ),
689 ' <a href="https://dashboard.optimole.com/register" target="_blank">optimole.com</a>'
690 ),
691 'account_needed_subtitle_1' => sprintf(
692 __( 'You will get access to our image optimization service for %1$sFREE%2$s in the limit of %3$s5k%4$s %5$svisitors%6$s per month. ', 'optimole-wp' ),
693 '<strong>',
694 '</strong>',
695 '<strong>',
696 '</strong>',
697 '<a href="https://docs.optimole.com/article/1134-how-optimole-counts-the-number-of-visitors" target="_blank">',
698 '</a>'
699 ),
700 'account_needed_subtitle_3' => sprintf(
701 __( 'Here’s %1$show%2$s to install Optimole on your WordPress site in 3 steps.', 'optimole-wp' ),
702 '<a target="_blank" href="https://docs.optimole.com/article/1173-how-to-get-started-with-optimole-in-just-3-steps">',
703 '</a>'
704 ),
705 'account_needed_subtitle_2' => sprintf(
706 __( 'Bonus, if you dont use a CDN, we got you covered, we will serve the images using CloudFront CDN from 200 locations.', 'optimole-wp' )
707 ),
708 'notice_just_activated' => ! $this->settings->is_connected() ?
709 sprintf( __( '%1$sImage optimisation is currently running.%2$s <br/> Your visitors will now view the best image for their device automatically, all served from the Optimole Cloud Service on the fly. You might see for the very first image request being redirected to the original URL while we do the optimization in the background.<br/> You can relax, we\'ll take it from here.', 'optimole-wp' ), '<strong>', '</strong>' )
710 : '',
711 'notice_api_not_working' => __(
712 'It seems there is an issue with your WordPress configuration and the core REST API functionality is not available. This is crucial as Optimole relies on this functionality in order to work.<br/>
713 The root cause might be either a security plugin which blocks this feature or some faulty server configuration which constrain this WordPress feature.You can try to disable any of the security plugins that you use in order to see if the issue persists or ask the hosting company to further investigate.',
714 'optimole-wp'
715 ),
716 'notice_disabled_account' => sprintf( __( 'Your account has been disabled due to exceeding quota. All images are being redirected to the original unoptimized URL. Please %1$supgrade%2$s to re-activate the account.', 'optimole-wp' ), '<a href="https://optimole.com/pricing">', '</a>' ),
717 'dashboard_menu_item' => __( 'Dashboard', 'optimole-wp' ),
718 'settings_menu_item' => __( 'Settings', 'optimole-wp' ),
719 'settings_exclusions_menu_item' => __( 'Exclusions', 'optimole-wp' ),
720 'settings_resize_menu_item' => __( 'Resize', 'optimole-wp' ),
721 'settings_compression_menu_item' => __( 'Compression', 'optimole-wp' ),
722 'advanced_settings_menu_item' => __( 'Advanced', 'optimole-wp' ),
723 'general_settings_menu_item' => __( 'General', 'optimole-wp' ),
724 'lazyload_settings_menu_item' => __( 'Lazyload', 'optimole-wp' ),
725 'offload_media_settings_menu_item' => __( 'Cloud Integration', 'optimole-wp' ),
726 'watermarks_menu_item' => __( 'Watermark', 'optimole-wp' ),
727 'conflicts_menu_item' => __( 'Possible issues', 'optimole-wp' ),
728 'conflicts' => [
729 'title' => __( 'We might have some possible conflicts with the plugins that you use. In order to benefit from Optimole\'s full potential you will need to address this issues.', 'optimole-wp' ),
730 'message' => __( 'Details', 'optimole-wp' ),
731 'conflict_close' => __( 'I\'ve done this.', 'optimole-wp' ),
732 'no_conflicts_found' => __( 'No conflicts found. We are all peachy now. 🍑', 'optimole-wp' ),
733 ],
734 'upgrade' => [
735 'title' => __( 'Upgrade to Pro', 'optimole-wp' ),
736 'reason_1' => __( 'Priority & Live Chat support', 'optimole-wp' ),
737 'reason_2' => __( 'Extend visits limit', 'optimole-wp' ),
738 'reason_3' => __( 'Custom domain', 'optimole-wp' ),
739 'reason_4' => __( 'Site audit', 'optimole-wp' ),
740 'cta' => __( 'View plans', 'optimole-wp' ),
741 ],
742 'neve' => [
743 'is_active' => defined( 'NEVE_VERSION' ) ? 'yes' : 'no',
744 'byline' => __( 'Fast, perfomance built-in WordPress theme.', 'optimole-wp' ),
745 'reason_1' => __( 'Lightweight, 25kB in page-weight.', 'optimole-wp' ),
746 'reason_2' => __( '100+ Starter Sites available.', 'optimole-wp' ),
747 'reason_3' => __( 'AMP/Mobile ready.', 'optimole-wp' ),
748 'reason_4' => __( 'Lots of customizations options.', 'optimole-wp' ),
749 'reason_5' => __( 'Fully compatible with Optimole.', 'optimole-wp' ),
750 ],
751 'options_strings' => [
752 'add_filter' => __( 'Add filter', 'optimole-wp' ),
753 'add_site' => __( 'Add site', 'optimole-wp' ),
754 'admin_bar_desc' => __( 'Show in the WordPress admin bar the available quota from Optimole service.', 'optimole-wp' ),
755 'auto_q_title' => __( 'Auto', 'optimole-wp' ),
756 'cache_desc' => __( 'Clear all cached resources(images,js,css) by Optimole from this site. Useful if you updated them and Optimole shows the old version.', 'optimole-wp' ),
757 'cache_title' => __( 'Clear cached resources', 'optimole-wp' ),
758 'clear_cache' => __( 'Clear cached resources', 'optimole-wp' ),
759 'connect_step_0' => __( 'Connecting your site to the Optimole service.', 'optimole-wp' ),
760 'connect_step_1' => __( 'Checking for possible conflicts.', 'optimole-wp' ),
761 'connect_step_2' => __( 'Inspecting the images from your site.', 'optimole-wp' ),
762 'connect_step_3' => __( 'All done, Optimole is currently optimizing your site.', 'optimole-wp' ),
763 'disabled' => __( 'Disabled', 'optimole-wp' ),
764 'enable_bg_lazyload_desc' => __( 'Lazyload images used as CSS backgrounds.', 'optimole-wp' ),
765 'enable_bg_lazyload_title' => __( 'Enable lazyload for background images', 'optimole-wp' ),
766 'enable_video_lazyload_desc' => __( 'Lazyload iframes/videos', 'optimole-wp' ),
767 'enable_video_lazyload_title' => __( 'Enable lazyload for embedded videos and iframes.', 'optimole-wp' ),
768 'enable_gif_replace_title' => __( 'Enable Gif to Video conversion', 'optimole-wp' ),
769 'enable_report_title' => __( 'Enable error diagnosis tool', 'optimole-wp' ),
770 'enable_report_desc' => __( 'Provides a troubleshooting mechanism which should help you identify any possible issues with your site using Optimole.', 'optimole-wp' ),
771 'enable_offload_media_title' => __( 'Enable offloading images', 'optimole-wp' ),
772 'enable_offload_media_desc' => __( 'Offload your new images automatically to Optimole Cloud. You will no longer store them on your server and you can restore them back anytime.', 'optimole-wp' ),
773 'enable_cloud_images_title' => __( 'Enable cloud library browsing', 'optimole-wp' ),
774 'enable_cloud_images_desc' => __( 'Allow access from this site to all images from your Optimole account. More details', 'optimole-wp' ),
775 'enable_image_replace' => __( 'Enable image replacement', 'optimole-wp' ),
776 'enable_lazyload_placeholder_desc' => __( 'Enabling this might affect the user experience in some cases, however it will reduce the number of total requests and page weight. Try it out and see how works best for you!', 'optimole-wp' ),
777 'enable_lazyload_placeholder_title' => __( 'Enable generic lazyload placeholder', 'optimole-wp' ),
778 'enable_network_opt_desc' => __( 'Optimole provides an option to automatically downgrade the image quality when it detects a slower network.', 'optimole-wp' ),
779 'enable_network_opt_title' => __( 'Enable network based optimizations', 'optimole-wp' ),
780 'enable_resize_smart_desc' => __( 'Detects the most interesting section of the image and considers it as the center of the resulting image.', 'optimole-wp' ),
781 'enable_resize_smart_title' => __( 'Enable Smart Cropping', 'optimole-wp' ),
782 'enable_retina_desc' => __( 'Deliver retina ready images to your visitors', 'optimole-wp' ),
783 'enable_retina_title' => __( 'Enable Retina images', 'optimole-wp' ),
784 'enabled' => __( 'Enabled', 'optimole-wp' ),
785 'exclude_class_desc' => __( 'Image tag contains class', 'optimole-wp' ),
786 'exclude_ext_desc' => __( 'Image extension is', 'optimole-wp' ),
787 'exclude_filename_desc' => __( 'Image filename contains', 'optimole-wp' ),
788 'exclude_title_lazyload' => __( 'Don\'t lazyload images if', 'optimole-wp' ),
789 'exclude_title_optimize' => __( 'Don\'t optimize images if', 'optimole-wp' ),
790 'exclude_url_desc' => __( 'Page url contains', 'optimole-wp' ),
791 'exclude_first_images_title' => __( 'Exclude first <number> of images from lazyload', 'optimole-wp' ),
792 'exclude_first_images_desc' => __( 'Exclude the first <number> images from lazyload on every page to avoid lazy load on above the fold images. Use 0 to disable this.', 'optimole-wp' ),
793 'filter_class' => __( 'Image class', 'optimole-wp' ),
794 'filter_ext' => __( 'Image extension', 'optimole-wp' ),
795 'filter_filename' => __( 'Image filename', 'optimole-wp' ),
796 'filter_operator_contains' => __( 'contains', 'optimole-wp' ),
797 'filter_operator_is' => __( 'is', 'optimole-wp' ),
798 'filter_url' => __( 'Page URL', 'optimole-wp' ),
799 'gif_replacer_desc' => __( 'Automatically convert GIF images to Video files(MP4 and WebM)', 'optimole-wp' ),
800 'height_field' => __( 'Height', 'optimole-wp' ),
801 'here' => __( ' here.', 'optimole-wp' ),
802 'hide' => __( 'Hide', 'optimole-wp' ),
803 'high_q_title' => __( 'High', 'optimole-wp' ),
804 'image_1_label' => __( 'Original', 'optimole-wp' ),
805 'image_2_label' => __( 'Optimized', 'optimole-wp' ),
806 'lazyload_desc' => __( 'We will generate images size based on your visitor\'s screen using javascript and render them without blocking the page execution via lazyload .', 'optimole-wp' ),
807 'scale_desc' => __( 'When this option is off, we disable the automatic scaling of images on lazyload.', 'optimole-wp' ),
808 'low_q_title' => __( 'Low', 'optimole-wp' ),
809 'medium_q_title' => __( 'Medium', 'optimole-wp' ),
810 'no_images_found' => __( 'You dont have any images in your Media Library. Add one and check how the Optimole will perform.', 'optimole-wp' ),
811 'native_desc' => __( 'Use browser native lazyload if supported, fallback to classic lazyload otherwise. When using browser native lazyload the auto scale feature is disabled', 'optimole-wp' ),
812 'option_saved' => __( 'Option saved.', 'optimole-wp' ),
813 'quality_desc' => __( 'Lower image quality might not always be perceived by users and would result in a boost of your loading speed by lowering the page size. Try experimenting with the setting, then click the View sample image link to see what option works best for you.', 'optimole-wp' ),
814 'quality_selected_value' => __( 'Selected value', 'optimole-wp' ),
815 'quality_slider_desc' => __( 'See one sample image which will help you choose the right quality of the compression.', 'optimole-wp' ),
816 'quality_title' => __( 'Image quality', 'optimole-wp' ),
817 'replacer_desc' => __( 'Replace all the image urls from your website with the ones optimized by Optimole.', 'optimole-wp' ),
818 'sample_image_loading' => __( 'Loading a sample image. ', 'optimole-wp' ),
819 'save_changes' => __( 'Save changes', 'optimole-wp' ),
820 'show' => __( 'Show', 'optimole-wp' ),
821 'selected_sites_title' => __( 'Show images only from these sites: ', 'optimole-wp' ),
822 'selected_sites_desc' => __( 'Site: ', 'optimole-wp' ),
823 'selected_all_sites_desc' => __( 'Currently viewing images from all sites ', 'optimole-wp' ),
824 'select_all_sites_desc' => __( 'View images from all sites ', 'optimole-wp' ),
825 'size_desc' => __( 'We resize all images with sizes greater than the values defined here. Changing this option is not recommended unless large images are not being processed correctly. This does NOT affect the scaling of images on the frontend.', 'optimole-wp' ),
826 'size_title' => __( 'Resize large images original source.', 'optimole-wp' ),
827 'select_site' => __( 'Select a site', 'optimole-wp' ),
828 'cloud_site_title' => __( 'Select the sites from which to view images.', 'optimole-wp' ),
829 'cloud_site_desc' => __( 'Only the images from the selected sites will be displayed on this site.', 'optimole-wp' ),
830 'toggle_ab_item' => __( 'Admin bar status', 'optimole-wp' ),
831 'toggle_lazyload' => __( 'Scale images & Lazy load', 'optimole-wp' ),
832 'toggle_scale' => __( 'Scale Images', 'optimole-wp' ),
833 'toggle_native' => __( 'Use native lazyload', 'optimole-wp' ),
834 'on_toggle' => __( 'On', 'optimole-wp' ),
835 'off_toggle' => __( 'Off', 'optimole-wp' ),
836 'view_sample_image' => __( 'View sample image', 'optimole-wp' ),
837 'watch_desc_lazyload' => __( 'You can add each CSS selector on a new line or separated by comma(,).', 'optimole-wp' ),
838 'watch_title_lazyload' => __( 'Lazyload background images for selectors:', 'optimole-wp' ),
839 'width_field' => __( 'Width', 'optimole-wp' ),
840 'toggle_cdn' => __( 'Serve CSS & JS through Optimole', 'optimole-wp' ),
841 'cdn_desc' => __( 'Useful when you have images into CSS/JS files. Optimole will optimize the images from them and serve the CSS/JS through the CDN.', 'optimole-wp' ),
842 'enable_css_minify_title' => __( 'Minify CSS files', 'optimole-wp' ),
843 'css_minify_desc' => __( 'Once Optimole will serve your CSS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
844 'enable_js_minify_title' => __( 'Minify JS files', 'optimole-wp' ),
845 'js_minify_desc' => __( 'Once Optimole will serve your JS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
846 'sync_title' => __( 'Offload existing images', 'optimole-wp' ),
847 'rollback_title' => __( 'Restore offloaded images', 'optimole-wp' ),
848 'sync_desc' => __( 'Right now all the new images uploaded to your site are moved automatically to Optimole Cloud. In order to offload the existing ones, please click Sync images and wait for the process to finish. You can rollback anytime.', 'optimole-wp' ),
849 'rollback_desc' => __( 'Pull all the offloaded images to Optimole Cloud back to your server.', 'optimole-wp' ),
850 'sync_media' => __( 'Sync images', 'optimole-wp' ),
851 'rollback_media' => __( 'Rollback images', 'optimole-wp' ),
852 'sync_media_progress' => __( 'We are currently offloading your images to Optimole, please wait', 'optimole-wp' ),
853 'rollback_media_progress' => __( 'We are currently moving images to your media library, please wait', 'optimole-wp' ),
854 'rollback_media_error' => __( 'An unexpected error occured while pulling the offloaded back to your site', 'optimole-wp' ),
855 'rollback_media_error_desc' => __( 'You can try again to pull back the rest of the images.', 'optimole-wp' ),
856 'remove_notice' => __( 'Remove notice', 'optimole-wp' ),
857 'sync_media_error' => __( 'An unexpected error occured while offloading all existing images from your site to Optimole ', 'optimole-wp' ),
858 'sync_media_error_desc' => __( 'You can try again to offload the rest of the images to Optimole.', 'optimole-wp' ),
859 'offload_disable_warning_title' => __( 'Please read carrefully the following notice', 'optimole-wp' ),
860 'offload_disable_warning_desc' => __( 'If you disable this option you will not be able to see the images in the media library without restoring the images first, do you want to restore the images to your site upon disabling the option ?', 'optimole-wp' ),
861 'select' => __( 'Please select one ...', 'optimole-wp' ),
862 'yes' => __( 'Yes', 'optimole-wp' ),
863 'no' => __( 'No', 'optimole-wp' ),
864
865 ],
866 'watermarks' => [
867 'image' => __( 'Image', 'optimole-wp' ),
868 'loading_remove_watermark' => __( 'Removing watermark resource ...', 'optimole-wp' ),
869 'max_allowed' => __( 'You are allowed to save maximum 5 images.', 'optimole-wp' ),
870 'list_header' => __( 'Possible watermarks', 'optimole-wp' ),
871 'settings_header' => __( 'Watermarks position settings', 'optimole-wp' ),
872 'no_images_found' => __( 'No images available for watermark. Please upload one.', 'optimole-wp' ),
873 'id' => __( 'ID', 'optimole-wp' ),
874 'name' => __( 'Name', 'optimole-wp' ),
875 'type' => __( 'Type', 'optimole-wp' ),
876 'action' => __( 'Action', 'optimole-wp' ),
877 'upload' => __( 'Upload', 'optimole-wp' ),
878 'add_desc' => __( 'Add new watermark', 'optimole-wp' ),
879 'wm_title' => __( 'Active watermark', 'optimole-wp' ),
880 'wm_desc' => __( 'The active watermark to use from the list of uploaded watermarks.', 'optimole-wp' ),
881 'opacity_field' => __( 'Opacity', 'optimole-wp' ),
882 'opacity_title' => __( 'Watermark opacity', 'optimole-wp' ),
883 'opacity_desc' => __( 'A value between 0 and 100 for the opacity level. If set to 0 it will disable the watermark.', 'optimole-wp' ),
884 'position_title' => __( 'Watermark position', 'optimole-wp' ),
885 'position_desc' => __( 'The place relative to the image where the watermark should be placed.', 'optimole-wp' ),
886 'pos_nowe_title' => __( 'North-West', 'optimole-wp' ),
887 'pos_no_title' => __( 'North', 'optimole-wp' ),
888 'pos_noea_title' => __( 'North-East', 'optimole-wp' ),
889 'pos_we_title' => __( 'West', 'optimole-wp' ),
890 'pos_ce_title' => __( 'Center', 'optimole-wp' ),
891 'pos_ea_title' => __( 'East', 'optimole-wp' ),
892 'pos_sowe_title' => __( 'South-West', 'optimole-wp' ),
893 'pos_so_title' => __( 'South', 'optimole-wp' ),
894 'pos_soea_title' => __( 'South-East', 'optimole-wp' ),
895 'offset_x_field' => __( 'Offset X', 'optimole-wp' ),
896 'offset_y_field' => __( 'Offset Y', 'optimole-wp' ),
897 'offset_title' => __( 'Watermark offset', 'optimole-wp' ),
898 'offset_desc' => __( 'Offset the watermark from set position on X and Y axis. Values can be positive or negative.', 'optimole-wp' ),
899 'scale_field' => __( 'Scale', 'optimole-wp' ),
900 'scale_title' => __( 'Watermark scale', 'optimole-wp' ),
901 'scale_desc' => __( 'A value between 0 and 300 for the scale of the watermark (100 is the original size and 300 is 3x the size) relative to the resulting image size. If set to 0 it will default to the original size.', 'optimole-wp' ),
902 'save_changes' => __( 'Save changes', 'optimole-wp' ),
903 ],
904 'latest_images' => [
905 'image' => __( 'Image', 'optimole-wp' ),
906 'no_images_found' => sprintf( __( 'We are currently optimizing your images. Meanwhile you can visit your %1$shomepage%2$s and check how our plugin performs. ', 'optimole-wp' ), '<a href="' . esc_url( home_url() ) . '" target="_blank" >', '</a>' ),
907 'compression' => __( 'Optimization', 'optimole-wp' ),
908 'loading_latest_images' => __( 'Loading your optimized images...', 'optimole-wp' ),
909 'last' => __( 'Last', 'optimole-wp' ),
910 'optimized_images' => __( 'optimized images', 'optimole-wp' ),
911 'same_size' => __( '🙉 We couldn\'t do better, this image is already optimized at maximum. ', 'optimole-wp' ),
912 'small_optimization' => __( '😬 Not that much, just <strong>{ratio}</strong> smaller.', 'optimole-wp' ),
913 'medium_optimization' => __( '🤓 We are on the right track, <strong>{ratio}</strong> squeezed.', 'optimole-wp' ),
914 'big_optimization' => __( '❤️❤️❤️ Our moles just nailed it, this one is <strong>{ratio}</strong> smaller. ', 'optimole-wp' ),
915 ],
916 ];
917 }
918
919 }
920