PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 1.0.4
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v1.0.4
4.2.14 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 All 135 releases
← All changes | inc/admin.php +133 -1434 3.12.11.0.4 View file →
@@ -13,13 +13,9 @@
13 13 /**
14 14 * Class Optml_Admin
15 15 */
16 16 class Optml_Admin {
17 - use Optml_Normalizer;
18 17
19 - const IMAGE_DATA_COLLECTED = 'optml_image_data_collected';
20 -
21 - const IMAGE_DATA_COLLECTED_BATCH = 100;
22 18 /**
23 19 * Hold the settings object.
24 20 *
25 21 * @var Optml_Settings Settings object.
@@ -26,850 +22,31 @@
26 22 */
27 23 public $settings;
28 24
29 25 /**
30 - * Hold the plugin conflict object.
31 - *
32 - * @var Optml_Conflicting_Plugins Settings object.
33 - */
34 - public $conflicting_plugins;
35 -
36 - const NEW_USER_DEFAULTS_UPDATED = 'optml_defaults_updated';
37 - const OLD_USER_ENABLED_LD = 'optml_enabled_limit_dimensions';
38 - const OLD_USER_ENABLED_CL = 'optml_enabled_cloud_sites';
39 -
40 - /**
41 26 * Optml_Admin constructor.
42 27 */
43 28 public function __construct() {
44 29 $this->settings = new Optml_Settings();
45 - $this->conflicting_plugins = new Optml_Conflicting_Plugins();
46 30
47 - add_filter( 'plugin_action_links_' . plugin_basename( OPTML_BASEFILE ), [ $this, 'add_action_links' ] );
48 - add_action( 'admin_menu', [ $this, 'add_dashboard_page' ] );
49 - add_action( 'admin_menu', [ $this, 'add_settings_subpage' ], 99 );
50 - add_action( 'admin_enqueue_scripts', [ $this, 'menu_icon_style' ] );
51 - add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], PHP_INT_MIN );
52 - add_action( 'admin_notices', [ $this, 'add_notice' ] );
53 - add_action( 'admin_notices', [ $this, 'add_notice_upgrade' ] );
54 - add_action( 'admin_notices', [ $this, 'add_notice_conflicts' ] );
55 - add_action( 'optml_daily_sync', [ $this, 'daily_sync' ] );
56 - add_action( 'admin_init', [ $this, 'redirect_old_dashboard' ] );
57 -
58 - if ( $this->settings->is_connected() ) {
59 - add_action( 'init', [$this, 'check_domain_change'] );
60 - add_action( 'optml_pull_image_data_init', [$this, 'pull_image_data_init'] );
61 - add_action( 'optml_pull_image_data', [$this, 'pull_image_data'] );
62 -
63 - // Backwards compatibility for older versions of WordPress < 6.0.0 requiring 3 parameters for this specific filter.
64 - $below_6_0_0 = version_compare( get_bloginfo( 'version' ), '6.0.0', '<' );
65 - if ( $below_6_0_0 ) {
66 - add_filter( 'wp_insert_attachment_data', [$this, 'legacy_detect_image_title_changes'], 10, 3 );
67 - } else {
68 - add_filter( 'wp_insert_attachment_data', [$this, 'detect_image_title_changes'], 10, 4 );
31 + add_action( 'admin_menu', array( $this, 'add_dashboard_page' ) );
32 + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
33 + add_action( 'admin_bar_menu', array( $this, 'add_traffic_node' ), 9999 );
34 + add_filter( 'wp_resource_hints', array( $this, 'add_dns_prefetch' ), 10, 2 );
35 + add_action( 'optml_daily_sync', array( $this, 'daily_sync' ) );
36 + add_action( 'wp_head', array( $this, 'generator' ) );
37 + add_action( 'admin_init', array( $this, 'maybe_redirect' ) );
38 + if ( ! is_admin() && $this->settings->is_connected() ) {
39 + if ( ! wp_next_scheduled( 'optml_daily_sync' ) ) {
40 + wp_schedule_event( time() + 10, 'daily', 'optml_daily_sync', array() );
69 41 }
70 -
71 - add_action( 'updated_post_meta', [$this, 'detect_image_alt_change' ], 10, 4 );
72 - add_action( 'added_post_meta', [$this, 'detect_image_alt_change'], 10, 4 );
73 - add_action( 'init', [ $this, 'schedule_data_enhance_cron' ] );
74 42 }
75 - add_action( 'init', [ $this, 'update_default_settings' ] );
76 - add_action( 'init', [ $this, 'update_limit_dimensions' ] );
77 - add_action( 'init', [ $this, 'update_cloud_sites_default' ] );
78 - add_action( 'admin_init', [ $this, 'maybe_redirect' ] );
79 - add_action( 'admin_init', [ $this, 'init_no_script' ] );
80 - if ( ! is_admin() && $this->settings->is_connected() && ! wp_next_scheduled( 'optml_daily_sync' ) ) {
81 - wp_schedule_event( time() + 10, 'daily', 'optml_daily_sync', [] );
82 - }
83 - add_action( 'optml_after_setup', [ $this, 'register_public_actions' ], 999999 );
84 -
85 - if ( ! function_exists( 'is_wpcom_vip' ) ) {
86 - add_filter( 'upload_mimes', [ $this, 'allow_meme_types' ] ); // phpcs:ignore WordPressVIPMinimum.Hooks.RestrictedHooks.upload_mimes
87 - }
88 43 }
89 - /**
90 - * Schedules the hourly cron that starts the querying for images alt/title attributes
91 - *
92 - * @uses action: init
93 - */
94 - public function schedule_data_enhance_cron() {
95 - if ( ! wp_next_scheduled( 'optml_pull_image_data_init' ) ) {
96 - wp_schedule_event( time(), 'hourly', 'optml_pull_image_data_init' );
97 - }
98 - }
99 44
100 45 /**
101 - * Query the database for images and extract the alt/title to send them to the API
102 - *
103 - * @uses action: optml_pull_image_data
104 - */
105 - public function pull_image_data() {
106 - // Get all image attachments that are not processed
107 - $args = [
108 - 'post_type' => 'attachment',
109 - 'post_mime_type' => 'image',
110 - 'posts_per_page' => self::IMAGE_DATA_COLLECTED_BATCH,
111 - 'meta_query' => [
112 - 'relation' => 'AND',
113 - [
114 - 'key' => self::IMAGE_DATA_COLLECTED,
115 - 'compare' => 'NOT EXISTS',
116 - ],
117 - ],
118 - ];
119 - $attachments = get_posts( $args );
120 -
121 - $image_data = [];
122 -
123 - foreach ( $attachments as $attachment ) {
124 - // Get image URL, alt, and title
125 - $image_url = wp_get_attachment_url( $attachment->ID );
126 - $image_alt = get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true );
127 - $image_title = $attachment->post_title;
128 - $image_data[ $image_url ] = [];
129 -
130 - if ( ! empty( $image_alt ) ) {
131 - $image_data[ $image_url ]['alt'] = $image_alt;
132 - }
133 - if ( ! empty( $image_title ) ) {
134 - $image_data[ $image_url ]['title'] = $image_title;
135 - }
136 - if ( empty( $image_data[ $image_url ] ) ) {
137 - unset( $image_data[ $image_url ] );
138 - }
139 -
140 - // Mark the image as processed
141 - update_post_meta( $attachment->ID, self::IMAGE_DATA_COLLECTED, 'yes' );
142 - }
143 -
144 - if ( ! empty( $image_data ) ) {
145 - $api = new Optml_Api();
146 - $api->call_data_enrich_api( $image_data );
147 - }
148 - if ( ! empty( $attachments ) ) {
149 - wp_schedule_single_event( time() + 5, 'optml_pull_image_data' );
150 - }
151 - }
152 -
153 - /**
154 - * Schedule the event to pull image alt/title
155 - *
156 - * @uses action: optml_pull_image_data_init
157 - */
158 - public function pull_image_data_init() {
159 - if ( ! wp_next_scheduled( 'optml_pull_image_data' ) ) {
160 - wp_schedule_single_event( time() + 5, 'optml_pull_image_data' );
161 - }
162 - }
163 -
164 - /**
165 - * Delete the processed meta from an image when the alt text is changed
166 - *
167 - * @uses action: updated_post_meta, added_post_meta
168 - */
169 - public function detect_image_alt_change( $meta_id, $post_id, $meta_key, $meta_value ) {
170 -
171 - // Check if the updated metadata is for alt text and it's an attachment
172 - if ( $meta_key === '_wp_attachment_image_alt' && get_post_type( $post_id ) === 'attachment' ) {
173 - delete_post_meta( $post_id, self::IMAGE_DATA_COLLECTED );
174 - }
175 - }
176 - /**
177 - * Delete the processed meta from an image when the title is changed
178 - *
179 - * @uses filter: wp_insert_attachment_data
180 - */
181 - public function detect_image_title_changes( $data, $postarr, $unsanitized_postarr, $update ) {
182 -
183 - // Check if it's an attachment being updated
184 - if ( $data['post_type'] !== 'attachment' ) {
185 - return $data;
186 - }
187 - if ( ! isset( $postarr['ID'] ) ) {
188 - return $data;
189 - }
190 - if ( isset( $postarr['post_title'] ) && isset( $postarr['original_post_title'] ) && $postarr['post_title'] !== $postarr['original_post_title'] ) {
191 - delete_post_meta( $postarr['ID'], self::IMAGE_DATA_COLLECTED );
192 - }
193 -
194 - return $data;
195 - }
196 - /**
197 - * Delete the processed meta from an image when the title is changed
198 - *
199 - * @uses filter: wp_insert_attachment_data
200 - */
201 - public function legacy_detect_image_title_changes( $data, $postarr, $unsanitized_postarr ) {
202 - return $this->detect_image_title_changes( $data, $postarr, $unsanitized_postarr, true );
203 - }
204 - /**
205 - * Init no_script setup value based on whether the user is connected or not.
206 - */
207 - public function init_no_script() {
208 - if ( $this->settings->is_connected() ) {
209 - $raw_settings = $this->settings->get_raw_settings();
210 - if ( ! isset( $raw_settings['no_script'] ) ) {
211 - $this->settings->update( 'no_script', 'enabled' );
212 - }
213 - }
214 - }
215 - /**
216 - * Checks if domain has changed
217 - */
218 - public function check_domain_change() {
219 - $previous_domain = get_option( 'optml_current_domain', 0 );
220 - $site_url = $this->to_domain_hash( get_home_url() );
221 -
222 - if ( $site_url !== $previous_domain ) {
223 - update_option( 'optml_current_domain', $site_url );
224 - if ( $previous_domain !== 0 ) {
225 - $this->daily_sync();
226 - }
227 - }
228 - }
229 - /**
230 - * Update the limit dimensions setting to enabled if the user is new.
231 - */
232 - public function update_default_settings() {
233 - if ( get_option( self::NEW_USER_DEFAULTS_UPDATED ) === 'yes' ) {
234 - return;
235 - }
236 -
237 - if ( $this->settings->is_connected() ) {
238 - update_option( self::NEW_USER_DEFAULTS_UPDATED, 'yes' );
239 - return;
240 - }
241 -
242 - $this->settings->update( 'limit_dimensions', 'enabled' );
243 - $this->settings->update( 'lazyload', 'enabled' );
244 -
245 - update_option( self::NEW_USER_DEFAULTS_UPDATED, 'yes' );
246 - }
247 - /**
248 - * Enable limit dimensions for old users after removing the Resize option.
249 - *
250 - * @return void
251 - */
252 - public function update_limit_dimensions() {
253 - if ( get_option( self::OLD_USER_ENABLED_LD ) === 'yes' ) {
254 - return;
255 - }
256 -
257 - // New users already have this enabled as we changed defaults.
258 - if ( ! $this->settings->is_connected() ) {
259 - return;
260 - }
261 -
262 - $this->settings->update( 'limit_dimensions', 'enabled' );
263 -
264 - update_option( self::OLD_USER_ENABLED_LD, 'yes' );
265 - }
266 -
267 - /**
268 - * Enable cloud sites and add the current site to the whitelist.
269 - *
270 - * @return void
271 - */
272 - public function update_cloud_sites_default() {
273 - if ( get_option( self::OLD_USER_ENABLED_CL ) === 'yes' ) {
274 - return;
275 - }
276 -
277 - if ( ! $this->settings->is_connected() ) {
278 - return;
279 - }
280 -
281 - // This is already enabled. Don't alter it.
282 - if ( $this->settings->get( 'cloud_images' ) === 'enabled' ) {
283 - update_option( self::OLD_USER_ENABLED_CL, 'yes' );
284 -
285 - return;
286 - }
287 -
288 - $this->settings->update( 'cloud_images', 'enabled' );
289 - $this->settings->update( 'cloud_sites', $this->settings->get_cloud_sites_whitelist_default() );
290 -
291 - update_option( self::OLD_USER_ENABLED_CL, 'yes' );
292 - }
293 -
294 - /**
295 - * Adds Optimole tag to admin bar
296 - */
297 - public function add_report_menu() {
298 - global $wp_admin_bar;
299 -
300 - $wp_admin_bar->add_node(
301 - [
302 - 'id' => 'optml_report_script',
303 - 'href' => '#',
304 - 'title' => '<span class="ab-icon"></span>Optimole ' . __( 'debugger', 'optimole-wp' ),
305 - ]
306 - );
307 - $wp_admin_bar->add_menu(
308 - [
309 - 'id' => 'optml_status',
310 - 'title' => __( 'Troubleshoot this page', 'optimole-wp' ),
311 - 'parent' => 'optml_report_script',
312 - ]
313 - );
314 - }
315 -
316 - /**
317 - * Adds Optimole css to admin bar
318 - */
319 - public function print_report_css() {
320 - ?>
321 - <style type="text/css">
322 - li#wp-admin-bar-optml_report_script > div :hover {
323 - cursor: pointer;
324 - color: #00b9eb !important;
325 - text-decoration: underline;
326 - }
327 -
328 - #wpadminbar #wp-admin-bar-optml_report_script .ab-icon:before {
329 - content: "\f227";
330 - top: 3px;
331 - }
332 -
333 - /* The Modal (background) */
334 - .optml-modal {
335 - display: none; /* Hidden by default */
336 - position: fixed; /* Stay in place */
337 - z-index: 2147483641; /* Sit on top */
338 - padding-top: 100px; /* Location of the box */
339 - left: 0;
340 - top: 0;
341 - width: 100%; /* Full width */
342 - height: 100%; /* Full height */
343 - overflow: auto; /* Enable scroll if needed */
344 - background-color: rgb(0, 0, 0); /* Fallback color */
345 - background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
346 - }
347 -
348 - /* Modal Content */
349 - .optml-modal-content {
350 - background-color: #fefefe;
351 - margin: auto;
352 - padding: 20px;
353 - border: 1px solid #888;
354 - width: 80%;
355 - }
356 -
357 - /* The Close Button */
358 - .optml-close {
359 - color: #aaaaaa;
360 - float: right;
361 - font-size: 28px;
362 - font-weight: bold;
363 - }
364 -
365 - .optml-modal-content ul {
366 - list-style: none;
367 - font-size: 80%;
368 - margin-top: 50px;
369 - }
370 -
371 - .optml-close:hover,
372 - .optml-close:focus {
373 - color: #000;
374 - text-decoration: none;
375 - cursor: pointer;
376 - }
377 - </style>
378 - <?php
379 - }
380 -
381 - /**
382 - * Register public actions.
383 - */
384 - public function register_public_actions() {
385 - add_action( 'wp_head', [ $this, 'generator' ] );
386 - add_filter( 'wp_resource_hints', [ $this, 'add_dns_prefetch' ], 10, 2 );
387 -
388 - if ( Optml_Manager::should_ignore_image_tags() ) {
389 - return;
390 - }
391 - if ( ! is_admin() && $this->settings->get( 'report_script' ) === 'enabled' && current_user_can( 'manage_options' ) ) {
392 -
393 - add_action( 'wp_head', [ $this, 'print_report_css' ] );
394 - add_action( 'wp_before_admin_bar_render', [ $this, 'add_report_menu' ] );
395 - add_action( 'wp_enqueue_scripts', [ $this, 'add_diagnosis_script' ] );
396 - }
397 - if ( ! $this->settings->use_lazyload()
398 - || ( $this->settings->get( 'native_lazyload' ) === 'enabled'
399 - && $this->settings->get( 'video_lazyload' ) === 'disabled'
400 - && $this->settings->get( 'bg_replacer' ) === 'disabled' ) ) {
401 - return;
402 - }
403 - add_action( 'wp_enqueue_scripts', [ $this, 'frontend_scripts' ] );
404 - add_action( 'wp_head', [ $this, 'inline_bootstrap_script' ] );
405 -
406 - add_filter( 'optml_additional_html_classes', [ $this, 'add_no_js_class_to_html_tag' ], 10 );
407 - }
408 -
409 - /**
410 - * Use filter to add additional class to html tag.
411 - *
412 - * @param array $classes The classes to be added.
413 - *
414 - * @return array
415 - */
416 - public function add_no_js_class_to_html_tag( $classes ) {
417 - // we need the space padding since some plugins might not target correctly with js there own classes
418 - // this causes some issues if they concat directly, this way we can protect against that since no matter what
419 - // there will be an extra space padding so that classes can be easily identified
420 - return array_merge( $classes, [ ' optml_no_js ' ] );
421 - }
422 -
423 - /**
424 - * Adds script for lazyload/js replacement.
425 - */
426 - public function inline_bootstrap_script() {
427 - $domain = 'https://' . $this->settings->get_cdn_url() . '/js-lib';
428 -
429 - if ( defined( 'OPTML_JS_CDN' ) && constant( 'OPTML_JS_CDN' ) ) {
430 - $domain = 'https://' . constant( 'OPTML_JS_CDN' ) . '/js-lib';
431 - }
432 -
433 - $min = ! OPTML_DEBUG ? '.min' : '';
434 - $bgclasses = Optml_Lazyload_Replacer::get_lazyload_bg_classes();
435 - $watcher_classes = Optml_Lazyload_Replacer::get_watcher_lz_classes();
436 - $lazyload_bg_selectors = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
437 - foreach ( $bgclasses as $key ) {
438 - $lazyload_bg_selectors[] = '.' . $key;
439 - }
440 - $lazyload_bg_selectors = empty( $lazyload_bg_selectors ) ? '' : sprintf( '%s', implode( ', ', (array) $lazyload_bg_selectors ) );
441 - $bgclasses = empty( $bgclasses ) ? '' : sprintf( '"%s"', implode( '","', (array) $bgclasses ) );
442 - $watcher_classes = empty( $watcher_classes ) ? '' : sprintf( '"%s"', implode( '","', (array) $watcher_classes ) );
443 - $default_network = ( $this->settings->get( 'network_optimization' ) === 'enabled' );
444 - $limit_dimensions = $this->settings->get( 'limit_dimensions' ) === 'enabled';
445 - $limit_width = $limit_dimensions ? $this->settings->get( 'limit_width' ) : 0;
446 - $limit_height = $limit_dimensions ? $this->settings->get( 'limit_height' ) : 0;
447 - $retina_ready = $limit_dimensions ||
448 - ! ( $this->settings->get( 'retina_images' ) === 'enabled' );
449 - $scale_is_disabled = ( $this->settings->get( 'scale' ) === 'enabled' );
450 - $native_lazy_enabled = ( $this->settings->get( 'native_lazyload' ) === 'enabled' );
451 - $output = sprintf(
452 - '
453 - <style type="text/css">
454 - img[data-opt-src]:not([data-opt-lazy-loaded]) {
455 - transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
456 - -webkit-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
457 - -moz-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
458 - -o-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
459 - }
460 - img[data-opt-src]:not([data-opt-lazy-loaded]) {
461 - opacity: .75;
462 - -webkit-filter: blur(8px);
463 - -moz-filter: blur(8px);
464 - -o-filter: blur(8px);
465 - -ms-filter: blur(8px);
466 - filter: blur(8px);
467 - transform: scale(1.04);
468 - animation: 0.1s ease-in;
469 - -webkit-transform: translate3d(0, 0, 0);
470 - }
471 - %s
472 - </style>
473 - <script type="application/javascript">
474 - document.documentElement.className = document.documentElement.className.replace(/\boptml_no_js\b/g, "");
475 - (function(w, d){
476 - var b = d.getElementsByTagName("head")[0];
477 - var s = d.createElement("script");
478 - var v = ("IntersectionObserver" in w && "isIntersecting" in w.IntersectionObserverEntry.prototype) ? "_no_poly" : "";
479 - s.async = true;
480 - s.src = "%s/v2/latest/optimole_lib" + v + "%s.js";
481 - b.appendChild(s);
482 - w.optimoleData = {
483 - lazyloadOnly: "optimole-lazy-only",
484 - backgroundReplaceClasses: [%s],
485 - nativeLazyload : %s,
486 - scalingDisabled: %s,
487 - watchClasses: [%s],
488 - backgroundLazySelectors: "%s",
489 - network_optimizations: %s,
490 - ignoreDpr: %s,
491 - quality: %d,
492 - maxWidth: %d,
493 - maxHeight: %d,
494 - }
495 - }(window, document));
496 - </script>',
497 - Optml_Lazyload_Replacer::IFRAME_TEMP_COMMENT,
498 - esc_url( $domain ),
499 - $min,
500 - wp_strip_all_tags( $bgclasses ),
501 - $native_lazy_enabled ? 'true' : 'false',
502 - $scale_is_disabled ? 'true' : 'false',
503 - wp_strip_all_tags( $watcher_classes ),
504 - addcslashes( wp_strip_all_tags( $lazyload_bg_selectors ), '"' ),
505 - defined( 'OPTML_NETWORK_ON' ) && constant( 'OPTML_NETWORK_ON' ) ? ( OPTML_NETWORK_ON ? 'true' : 'false' ) : ( $default_network ? 'true' : 'false' ),
506 - $retina_ready ? 'true' : 'false',
507 - $this->settings->get_numeric_quality(),
508 - $limit_width,
509 - $limit_height
510 - );
511 - echo $output;
512 - }
513 -
514 - /**
515 - * Adds script for lazyload/js replacement.
516 - */
517 - public function add_diagnosis_script() {
518 -
519 - wp_enqueue_script( 'optml-report', OPTML_URL . 'assets/js/report_script.js' );
520 - $ignored_domains = [ 'gravatar.com', 'instagram.com', 'fbcdn' ];
521 - $report_script = [
522 - 'optmlCdn' => $this->settings->get_cdn_url(),
523 - 'restUrl' => untrailingslashit( rest_url( OPTML_NAMESPACE . '/v1' ) ) . '/check_redirects',
524 - 'nonce' => wp_create_nonce( 'wp_rest' ),
525 - 'ignoredDomains' => $ignored_domains,
526 - 'wait' => __( 'We are checking the current page for any issues with optimized images ...', 'optimole-wp' ),
527 - 'description' => __( 'Optimole page analyzer', 'optimole-wp' ),
528 - ];
529 - wp_localize_script( 'optml-report', 'reportScript', $report_script );
530 - }
531 -
532 - /**
533 - * Add settings links in the plugin listing page.
534 - *
535 - * @param array $links Old plugin links.
536 - *
537 - * @return array Altered links.
538 - */
539 - function add_action_links( $links ) {
540 - if ( ! is_array( $links ) ) {
541 - return $links;
542 - }
543 -
544 - return array_merge(
545 - $links,
546 - [
547 - '<a href="' . admin_url( 'admin.php?page=optimole' ) . '">' . __( 'Settings', 'optimole-wp' ) . '</a>',
548 - ]
549 - );
550 - }
551 -
552 - /**
553 - * Check if we should show the notice.
554 - *
555 - * @return bool Should show?
556 - */
557 - public function should_show_notice() {
558 - if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
559 - return false;
560 - }
561 -
562 - if ( is_network_admin() ) {
563 - return false;
564 - }
565 -
566 - if ( ! current_user_can( 'manage_options' ) ) {
567 - return false;
568 - }
569 -
570 - if ( $this->settings->is_connected() ) {
571 - return false;
572 - }
573 -
574 - $current_screen = get_current_screen();
575 -
576 - if ( empty( $current_screen ) ) {
577 - return false;
578 - }
579 -
580 - if ( ( get_option( 'optml_notice_optin', 'no' ) === 'yes' ) ) {
581 - return false;
582 - }
583 -
584 - return true;
585 - }
586 -
587 - /**
588 - * Show upgrade notice.
589 - */
590 - public function add_notice_upgrade() {
591 - if ( ! $this->should_show_upgrade() ) {
592 - return;
593 - }
594 - ?>
595 - <div class="notice optml-notice-optin" style="background-color: #577BF9; color:white; border: none !important; display: flex;">
596 - <div style="margin: 1% 2%;">
597 - <img src='<?php echo OPTML_URL . 'assets/img/upgrade_icon.png'; ?>'>
598 - </div>
599 - <div style="margin-top: 0.7%;">
600 - <p style="font-size: 16px !important;"> <?php printf( __( '%1$sIt seems your are close to the 5.0000 visits limit with %3$sOptiMole%4$s for this month.%2$s %5$s For a larger quota you may want to check the upgrade plans. If you exceed the quota we will need to deliver back your original, un-optimized images, which might decrease your site speed performance.', 'optimole-wp' ), '<strong>', '</strong>', '<strong>', '</strong>', '<br/><br/>', '<i>', '</i >', '<strong>', '</strong>' ); ?></p>
601 - <p style="margin: 1.5% 0;">
602 - <a href="https://optimole.com/pricing" target="_blank" style="border-radius: 4px;padding: 9px 10px;border: 2px solid #FFF;color: white;text-decoration: none;"><?php _e( 'Check upgrade plans', 'optimole-wp' ); ?>
603 - </a>
604 - <a style="padding: 2%; color: white;"
605 - href="<?php echo wp_nonce_url( add_query_arg( [ 'optml_hide_upg' => 'yes' ] ), 'hide_nonce', 'optml_nonce' ); ?>"><?php _e( 'I have already done this', 'optimole-wp' ); ?></a>
606 - </p>
607 - </div>
608 - </div>
609 - <?php
610 - }
611 -
612 - /**
613 - * Check if we should show the upgrade notice to users.
614 - *
615 - * @return bool Should we show it?
616 - */
617 - public function should_show_upgrade() {
618 - $current_screen = get_current_screen();
619 - if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
620 - is_network_admin() ||
621 - ! current_user_can( 'manage_options' ) ||
622 - ! $this->settings->is_connected() ||
623 - empty( $current_screen )
624 - ) {
625 - return false;
626 - }
627 - if ( get_option( 'optml_notice_hide_upg', 'no' ) === 'yes' ) {
628 - return false;
629 - }
630 - if ( $current_screen->base !== 'upload' ) {
631 - return false;
632 - }
633 - $service_data = $this->settings->get( 'service_data' );
634 - if ( ! isset( $service_data['plan'] ) ) {
635 - return false;
636 - }
637 - if ( $service_data['plan'] !== 'free' ) {
638 - return false;
639 - }
640 - $visitors_limit = isset( $service_data['visitors_limit'] ) ? (int) $service_data['visitors_limit'] : 0;
641 - $visitors_left = isset( $service_data['visitors_left'] ) ? (int) $service_data['visitors_left'] : 0;
642 - if ( $visitors_limit === 0 ) {
643 - return false;
644 - }
645 - if ( $visitors_left > 2000 ) {
646 - return false;
647 - }
648 -
649 - return true;
650 - }
651 -
652 - /**
653 - * CSS styles for Notice.
654 - */
655 - public static function notice_styles() {
656 - ?>
657 - <style>
658 - .optml-notice-optin:not(.has-dismiss) {
659 - background: url(" <?php echo esc_attr( OPTML_URL . '/assets/img/disconnected.svg' ); ?> ") #fff 100% 0 no-repeat;
660 - position: relative;
661 - padding: 0;
662 - }
663 -
664 - .optml-notice-optin.has-dismiss {
665 - position: relative;
666 - }
667 -
668 - .optml-notice-optin .content {
669 - background: rgba(255, 255, 255, 0.75);
670 - display: flex;
671 - align-items: center;
672 - padding: 20px;
673 - }
674 -
675 - .optml-notice-optin img {
676 - max-width: 100px;
677 - margin-right: 20px;
678 - display: none;
679 - }
680 -
681 - .optml-notice-optin .description {
682 - font-size: 14px;
683 - margin-bottom: 20px;
684 - color: #000;
685 - }
686 -
687 - .optml-notice-optin .actions {
688 - margin-top: auto;
689 - display: flex;
690 - gap: 20px;
691 - }
692 -
693 - @media screen and (min-width: 768px) {
694 - .optml-notice-optin img {
695 - display: block;
696 - }
697 - }
698 - </style>
699 - <?php
700 - }
701 -
702 - /**
703 - * JS for Notice.
704 - */
705 - public static function notice_js( $action ) {
706 - ?>
707 - <script>
708 - jQuery(document).ready(function($) {
709 - // AJAX request to update the option value
710 - $( '.optml-notice-optin button.notice-dismiss' ).click(function(e) {
711 - e.preventDefault();
712 -
713 - var notice = $(this).closest( '.optml-notice-optin' );
714 - var nonce = '<?php echo esc_attr( wp_create_nonce( $action ) ); ?>';
715 -
716 - $.ajax({
717 - url: window.ajaxurl,
718 - type: 'POST',
719 - data: {
720 - action: '<?php echo esc_attr( $action ); ?>',
721 - nonce
722 - },
723 - complete() {
724 - notice.remove();
725 - }
726 - });
727 - });
728 - });
729 - </script>
730 - <?php
731 - }
732 -
733 - /**
734 - * Adds opt in notice.
735 - */
736 - public function add_notice() {
737 - if ( ! $this->should_show_notice() ) {
738 - return;
739 - }
740 -
741 - self::notice_styles();
742 - ?>
743 - <div class="notice notice-info optml-notice-optin">
744 - <div class="content">
745 - <img src="<?php echo OPTML_URL . '/assets/img/logo.svg'; ?>" alt="<?php echo esc_attr__( 'Logo', 'optimole-wp' ); ?>"/>
746 -
747 - <div>
748 - <p class="notice-title"> <?php echo esc_html__( 'Finish setting up!', 'optimole-wp' ); ?></p>
749 - <p class="description"> <?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>
750 - <div class="actions">
751 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=optimole' ) ); ?>"
752 - class="button button-primary button-hero"><?php _e( 'Connect to OptiMole', 'optimole-wp' ); ?>
753 - </a>
754 - <a class="button button-secondary button-hero"
755 - 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' ); ?>
756 - </a>
757 - </div>
758 - </div>
759 - </div>
760 - </div>
761 - <?php
762 - }
763 -
764 - /**
765 - * Adds conflicts notice.
766 - */
767 - public function add_notice_conflicts() {
768 - if ( $this->settings->is_connected() || ! $this->conflicting_plugins->should_show_notice() ) {
769 - return;
770 - }
771 -
772 - $plugins = $this->conflicting_plugins->get_conflicting_plugins();
773 - $names = [];
774 -
775 - foreach ( $plugins as $plugin ) {
776 - $plugin_data = get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin );
777 - $names[] = $plugin_data['Name'];
778 - }
779 -
780 - $names = implode( ', ', $names );
781 -
782 - self::notice_styles();
783 - self::notice_js( 'optml_dismiss_conflict_notice' );
784 - ?>
785 - <div class="notice notice-info optml-notice-optin has-dismiss">
786 - <div class="content">
787 - <img src="<?php echo OPTML_URL . '/assets/img/logo.svg'; ?>" alt="<?php echo esc_attr__( 'Logo', 'optimole-wp' ); ?>"/>
788 -
789 - <div>
790 - <p class="notice-title"><strong><?php echo esc_html__( 'Oops... Multiple image optimization plugins active', 'optimole-wp' ); ?></strong></p>
791 - <p class="description"> <?php printf( __( 'We noticed multiple image optimization plugins active on your site, which may cause issues in Optimole. We recommend using only one image optimization plugin on your site for the best results. The following plugins may cause issues in Optimole: %2$s%1$s%3$s.', 'optimole-wp' ), $names, '<strong>', '</strong>' ); ?></p>
792 - <div class="actions">
793 - <a href="<?php echo esc_url( admin_url( 'plugins.php?optimole_conflicts' ) ); ?>"
794 - class="button button-primary button-hero"><?php _e( 'Manage Plugins', 'optimole-wp' ); ?>
795 - </a>
796 - </div>
797 - </div>
798 - </div>
799 -
800 - <button type="button" class="notice-dismiss">
801 - <span class="screen-reader-text"><?php _e( 'Dismiss this notice.', 'optimole-wp' ); ?></span>
802 - </button>
803 - </div>
804 - <?php
805 - }
806 -
807 - /**
808 - * Add style classes for lazy loading background images.
809 - */
810 - protected function get_background_lazy_css() {
811 -
812 - $watchers = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
813 -
814 - $css = [];
815 - foreach ( $watchers as $selector ) {
816 - $css[] = 'html ' . $selector . ':not(.optml-bg-lazyloaded)';
817 - }
818 - if ( empty( $css ) ) {
819 - return '';
820 - }
821 - $css = implode( ",\n", $css ) . ' { background-image: none !important; } ';
822 -
823 - return strip_tags( $css );
824 - }
825 -
826 - /**
827 - * Enqueue frontend scripts.
828 - */
829 - public function frontend_scripts() {
830 -
831 - $bg_css = $this->get_background_lazy_css();
832 -
833 - wp_register_style( 'optm_lazyload_noscript_style', false );
834 - wp_enqueue_style( 'optm_lazyload_noscript_style' );
835 - wp_add_inline_style( 'optm_lazyload_noscript_style', "html.optml_no_js img[data-opt-src] { display: none !important; } \n " . $bg_css );
836 -
837 - if ( $this->settings->use_lazyload() === true ) {
838 - wp_register_script( 'optml-print', false );
839 - wp_enqueue_script( 'optml-print' );
840 - $script = '
841 - (function(w, d){
842 - w.addEventListener("beforeprint", function(){
843 - let images = d.getElementsByTagName( "img" );
844 - for (let img of images) {
845 - if ( !img.dataset.optSrc) {
846 - continue;
847 - }
848 - img.src = img.dataset.optSrc;
849 - delete img.dataset.optSrc;
850 - }
851 - });
852 -
853 - }(window, document));
854 - ';
855 - wp_add_inline_script( 'optml-print', $script );
856 - }
857 -
858 - }
859 -
860 - /**
861 46 * Maybe redirect to dashboard page.
862 47 */
863 48 public function maybe_redirect() {
864 - if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_optin'] ) && $_GET['optml_hide_optin'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
865 - update_option( 'optml_notice_optin', 'yes' );
866 - }
867 -
868 - if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_upg'] ) && $_GET['optml_hide_upg'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
869 - update_option( 'optml_notice_hide_upg', 'yes' );
870 - }
871 -
872 49 if ( ! get_transient( 'optml_fresh_install' ) ) {
873 50 return;
874 51 }
875 52
@@ -885,10 +62,9 @@
885 62
886 63 if ( $this->settings->is_connected() ) {
887 64 return;
888 65 }
889 -
890 - wp_safe_redirect( admin_url( 'admin.php?page=optimole' ) );
66 + wp_safe_redirect( admin_url( 'upload.php?page=optimole' ) );
891 67 exit;
892 68 }
893 69
894 70 /**
@@ -909,39 +85,20 @@
909 85 */
910 86 function daily_sync() {
911 87
912 88 $api_key = $this->settings->get( 'api_key' );
913 - $service_data = $this->settings->get( 'service_data' );
914 - $application = '';
915 -
916 - if ( isset( $service_data['cdn_key'] ) ) {
917 - $application = $service_data['cdn_key'];
918 - }
919 -
920 89 if ( empty( $api_key ) ) {
921 90 return;
922 91 }
923 92
924 93 $request = new Optml_Api();
925 - $data = $request->get_user_data( $api_key, $application );
926 - if ( $data === false || is_wp_error( $data ) ) {
94 + $data = $request->get_user_data( $api_key );
95 + if ( $data === false ) {
927 96 return;
928 97 }
929 - if ( $data === 'disconnect' ) {
930 - $settings = new Optml_Settings();
931 - $settings->reset();
932 - return;
933 - }
934 98
935 - add_filter( 'optml_dont_trigger_settings_updated', '__return_true' );
936 99 $this->settings->update( 'service_data', $data );
937 100
938 - if ( isset( $data['extra_visits'] ) ) {
939 - $this->settings->update_frontend_banner_from_remote( $data['extra_visits'] );
940 - }
941 -
942 - remove_filter( 'optml_dont_trigger_settings_updated', '__return_true' );
943 -
944 101 }
945 102
946 103 /**
947 104 * Adds cdn url for prefetch.
@@ -951,11 +108,9 @@
951 108 *
952 109 * @return array Altered hints array.
953 110 */
954 111 public function add_dns_prefetch( $hints, $relation_type ) {
955 - if ( 'dns-prefetch' !== $relation_type &&
956 - 'preconnect' !== $relation_type
957 - ) {
112 + if ( 'dns-prefetch' !== $relation_type ) {
958 113 return $hints;
959 114 }
960 115 if ( ! $this->settings->is_connected() ) {
961 116 return $hints;
@@ -962,9 +117,9 @@
962 117 }
963 118 if ( ! $this->settings->is_enabled() ) {
964 119 return $hints;
965 120 }
966 - $hints[] = sprintf( 'https://%s', $this->settings->get_cdn_url() );
121 + $hints[] = sprintf( '//%s', $this->settings->get_cdn_url() );
967 122
968 123 return $hints;
969 124 }
970 125
@@ -971,639 +126,183 @@
971 126 /**
972 127 * Add the dashboard page.
973 128 */
974 129 public function add_dashboard_page() {
975 - if ( defined( 'OPTIOMLE_HIDE_ADMIN_AREA' ) && OPTIOMLE_HIDE_ADMIN_AREA ) {
976 - return;
977 - }
978 -
979 - add_menu_page(
980 - 'Optimole',
981 - 'Optimole',
982 - 'manage_options',
983 - 'optimole',
984 - [ $this, 'render_dashboard_page' ],
985 - OPTML_URL . 'assets/img/logo.svg',
986 - 11
987 - );
130 + add_media_page( 'Optimole', 'Optimole', 'manage_options', 'optimole', array( $this, 'render_dashboard_page' ) );
988 131 }
989 132
990 133 /**
991 - * Add menu icon style.
992 - *
993 - * @return void
994 - */
995 - public function menu_icon_style() {
996 - echo '<style>#toplevel_page_optimole img{ max-width:22px;padding-top:6px!important;opacity:.9!important;} #toplevel_page_optimole li.wp-first-item{ display:none }</style>';
997 - }
998 -
999 - /**
1000 - * Add the settings page.
1001 - *
1002 - * We do it with another priority as it goes above the cloud library otherwise.
1003 - */
1004 - public function add_settings_subpage() {
1005 - if ( defined( 'OPTIOMLE_HIDE_ADMIN_AREA' ) && OPTIOMLE_HIDE_ADMIN_AREA ) {
1006 - return;
1007 - }
1008 -
1009 - if ( ! $this->settings->is_connected() ) {
1010 - return;
1011 - }
1012 -
1013 - add_submenu_page(
1014 - 'optimole',
1015 - __( 'Settings', 'optimole-wp' ),
1016 - __( 'Settings', 'optimole-wp' ),
1017 - 'manage_options',
1018 - 'optimole#settings',
1019 - [ $this, 'render_dashboard_page' ]
1020 - );
1021 - }
1022 -
1023 -
1024 - /**
1025 - * Redirect old dashboard.
1026 - *
1027 - * @return void
1028 - */
1029 - public function redirect_old_dashboard() {
1030 - if ( ! is_admin() ) {
1031 - return;
1032 - }
1033 -
1034 - global $pagenow;
1035 -
1036 - if ( $pagenow !== 'upload.php' ) {
1037 - return;
1038 - }
1039 -
1040 - if ( ! isset( $_GET['page'] ) ) {
1041 - return;
1042 - }
1043 -
1044 - if ( $_GET['page'] !== 'optimole' ) {
1045 - return;
1046 - }
1047 -
1048 - wp_safe_redirect( admin_url( 'admin.php?page=optimole' ) );
1049 -
1050 - exit;
1051 - }
1052 -
1053 - /**
1054 134 * Render dashboard page.
1055 135 */
1056 136 public function render_dashboard_page() {
1057 - if ( get_option( 'optml_notice_optin', 'no' ) !== 'yes' ) {
1058 - update_option( 'optml_notice_optin', 'yes' );
1059 - }
1060 137 ?>
1061 - <style >
1062 - .notice:not(.optml-notice-optin){
1063 - display: none !important;
1064 - }
1065 - </style>
1066 - <div id="optimole-app"></div>
138 + <div id="optimole-app">
139 + <app></app>
140 + </div>
1067 141 <?php
1068 142 }
1069 143
1070 144 /**
1071 145 * Enqueue scripts needed for admin functionality.
1072 - *
1073 - * @codeCoverageIgnore
1074 146 */
1075 147 public function enqueue() {
1076 -
1077 148 $current_screen = get_current_screen();
1078 149 if ( ! isset( $current_screen->id ) ) {
1079 150 return;
1080 151 }
1081 -
1082 - if ( $current_screen->id !== 'toplevel_page_optimole' ) {
152 + if ( $current_screen->id != 'media_page_optimole' ) {
1083 153 return;
1084 154 }
1085 -
1086 - $asset_file = include OPTML_PATH . 'assets/build/dashboard/index.asset.php';
1087 -
1088 - wp_register_script(
1089 - OPTML_NAMESPACE . '-admin',
1090 - OPTML_URL . 'assets/build/dashboard/index.js',
1091 - $asset_file['dependencies'],
1092 - $asset_file['version'],
1093 - true
1094 - );
1095 -
155 + wp_register_script( OPTML_NAMESPACE . '-admin', OPTML_URL . 'assets/js/bundle' . ( ! OPTML_DEBUG ? '.min' : '' ) . '.js', array(), OPTML_VERSION );
1096 156 wp_localize_script( OPTML_NAMESPACE . '-admin', 'optimoleDashboardApp', $this->localize_dashboard_app() );
1097 157 wp_enqueue_script( OPTML_NAMESPACE . '-admin' );
1098 -
1099 - wp_enqueue_style(
1100 - OPTML_NAMESPACE . '-admin',
1101 - OPTML_URL . 'assets/build/dashboard/style-index.css',
1102 - [
1103 - 'wp-components',
1104 - ],
1105 - $asset_file['version']
1106 - );
1107 158 }
1108 159
1109 160 /**
1110 161 * Localize the dashboard app.
1111 162 *
1112 - * @codeCoverageIgnore
1113 163 * @return array
1114 164 */
1115 165 private function localize_dashboard_app() {
166 + $api_key = $this->settings->get( 'api_key' );
167 + $service_data = $this->settings->get( 'service_data' );
168 + $admin_bar_item = $this->settings->get( 'admin_bar_item' );
169 + $image_replacer = $this->settings->get( 'image_replacer' );
170 + $user = get_userdata( get_current_user_id() );
171 + $args = array(
172 + 'strings' => $this->get_dashboard_strings(),
173 + 'assets_url' => OPTML_URL . 'assets/',
174 + 'connection_status' => empty( $service_data ) ? 'no' : 'yes',
175 + 'api_key' => $api_key,
176 + 'root' => rest_url( OPTML_NAMESPACE . '/v1' ),
177 + 'nonce' => wp_create_nonce( 'wp_rest' ),
178 + 'user_data' => $service_data,
179 + 'quality' => $this->settings->get( 'quality' ),
180 + 'current_user' => array(
181 + 'email' => $user->user_email
182 + ),
183 + 'admin_bar_item' => $admin_bar_item,
184 + 'image_replacer' => $image_replacer,
185 + 'home_url' => home_url(),
186 + );
1116 187
1117 - global $wp_version;
1118 - $is_offload_media_available = 'no';
1119 - if ( version_compare( $wp_version, '5.3', '>=' ) ) {
1120 - $is_offload_media_available = 'yes';
1121 - }
1122 - $api_key = $this->settings->get( 'api_key' );
1123 - $service_data = $this->settings->get( 'service_data' );
1124 - $user = get_userdata( get_current_user_id() );
1125 - $user_status = 'inactive';
1126 - $auto_connect = get_option( Optml_Settings::OPTML_USER_EMAIL, 'no' );
1127 - $available_apps = isset( $service_data['available_apps'] ) ? $service_data['available_apps'] : null;
1128 - if ( isset( $service_data['cdn_key'] ) && $available_apps !== null ) {
1129 - foreach ( $service_data['available_apps'] as $app ) {
1130 - if ( isset( $app['key'] ) && $app['key'] === $service_data['cdn_key'] && isset( $app['status'] ) && $app['status'] === 'active' ) {
1131 - $user_status = 'active';
1132 - }
1133 - }
1134 - }
1135 - $routes = [];
1136 - foreach ( Optml_Rest::$rest_routes as $route_type ) {
1137 - foreach ( $route_type as $route => $details ) {
1138 - $routes[ $route ] = OPTML_NAMESPACE . '/v1/' . $route;
1139 - }
1140 - }
1141 -
1142 - return [
1143 - 'strings' => $this->get_dashboard_strings(),
1144 - 'assets_url' => OPTML_URL . 'assets/',
1145 - 'dam_url' => 'admin.php?page=optimole-dam',
1146 - 'connection_status' => empty( $service_data ) ? 'no' : 'yes',
1147 - 'has_application' => isset( $service_data['app_count'] ) && $service_data['app_count'] >= 1 ? 'yes' : 'no',
1148 - 'user_status' => $user_status,
1149 - 'available_apps' => $available_apps,
1150 - 'api_key' => $api_key,
1151 - 'routes' => $routes,
1152 - 'nonce' => wp_create_nonce( 'wp_rest' ),
1153 - 'user_data' => $service_data,
1154 - 'remove_latest_images' => defined( 'OPTML_REMOVE_LATEST_IMAGES' ) && constant( 'OPTML_REMOVE_LATEST_IMAGES' ) ? ( OPTML_REMOVE_LATEST_IMAGES ? 'yes' : 'no' ) : 'no',
1155 - 'current_user' => [
1156 - 'email' => $user->user_email,
1157 - ],
1158 - 'site_settings' => $this->settings->get_site_settings(),
1159 - 'offload_limit' => $this->settings->get( 'offload_limit' ),
1160 - 'home_url' => home_url(),
1161 - 'days_since_install' => round( ( time() - get_option( 'optimole_wp_install', 0 ) ) / DAY_IN_SECONDS ),
1162 - 'is_offload_media_available' => $is_offload_media_available,
1163 - 'auto_connect' => $auto_connect,
1164 - 'cron_disabled' => defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON && ! function_exists( 'as_schedule_single_action' ),
1165 - 'submenu_links' => [
1166 - [
1167 - 'href' => 'admin.php?page=optimole#settings',
1168 - 'text' => __( 'Settings', 'optimole-wp' ),
1169 - 'hash' => '#settings',
1170 - ],
1171 - ],
1172 - ];
188 + return $args;
1173 189 }
1174 190
1175 191 /**
1176 192 * Get all dashboard strings.
1177 193 *
1178 - * @codeCoverageIgnore
1179 194 * @return array
1180 195 */
1181 196 private function get_dashboard_strings() {
1182 - return [
1183 - 'optimole' => 'Optimole',
1184 - 'version' => OPTML_VERSION,
1185 - 'terms_menu' => __( 'Terms', 'optimole-wp' ),
1186 - 'privacy_menu' => __( 'Privacy', 'optimole-wp' ),
1187 - 'testdrive_menu' => __( 'Test Optimole', 'optimole-wp' ),
1188 - 'service_details' => __( 'Image optimization service', 'optimole-wp' ),
1189 - 'connect_btn' => __( 'Connect to Optimole', 'optimole-wp' ),
1190 - 'disconnect_btn' => __( 'Disconnect', 'optimole-wp' ),
1191 - 'select' => __( 'Select', 'optimole-wp' ),
1192 - 'your_domain' => __( 'your domain', 'optimole-wp' ),
1193 - 'add_api' => __( 'Add your API Key', 'optimole-wp' ),
1194 - 'your_api_key' => __( 'Your API Key', 'optimole-wp' ),
1195 - 'looking_for_api_key' => __( 'LOOKING FOR YOUR API KEY?', 'optimole-wp' ),
1196 - 'refresh_stats_cta' => __( 'Refresh Stats', 'optimole-wp' ),
1197 - 'updating_stats_cta' => __( 'UPDATING STATS', 'optimole-wp' ),
1198 - 'api_key_placeholder' => __( 'API Key', 'optimole-wp' ),
1199 - 'account_needed_heading' => __( 'Sign-up for API key', 'optimole-wp' ),
1200 - 'invalid_key' => __( 'Invalid API Key', 'optimole-wp' ),
1201 - 'keep_connected' => __( 'Ok, keep me connected', 'optimole-wp' ),
1202 - 'cloud_library' => __( 'Cloud Library', 'optimole-wp' ),
1203 - 'image_storage' => __( 'Image Storage', 'optimole-wp' ),
1204 - 'disconnect_title' => __( 'You are about to disconnect from the Optimole API', 'optimole-wp' ),
1205 - 'disconnect_desc' => __(
1206 - 'Please note that disconnecting your site from the Optimole API will impact your website performance.
1207 -If you still want to disconnect click the button below.',
1208 - 'optimole-wp'
1209 - ),
1210 - 'email_address_label' => __( 'Your email address', 'optimole-wp' ),
1211 - 'steps_connect_api_title' => __( 'Connect your account', 'optimole-wp' ),
1212 - 'register_btn' => __( 'Create & connect your account ', 'optimole-wp' ),
1213 - 'step_one_api_title' => __( 'Enter your API key.', 'optimole-wp' ),
1214 - 'optml_dashboard' => sprintf( __( 'Get it from the %1$s Optimole Dashboard%2$s.', 'optimole-wp' ), '<a style="white-space:nowrap; text-decoration: underline !important;" href="https://dashboard.optimole.com/" target="_blank"> ', '<span style="text-decoration:none; font-size:15px; margin-top:2px;" class="dashicons dashicons-external"></span></a>' ),
1215 - 'steps_connect_api_desc' => sprintf( __( 'Copy the API Key you have received via email or you can get it from %1$s Optimole dashboard%2$s. If your account has multiple domains select the one you want to use. <br/>', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/" target="_blank"> ', '</a>' ),
1216 - 'api_exists' => __( 'I already have an API key.', 'optimole-wp' ),
1217 - 'back_to_register' => __( 'Register account', 'optimole-wp' ),
1218 - 'back_to_connect' => __( 'Go to previous step', 'optimole-wp' ),
1219 - '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>' ),
1220 - 'invalid_email' => __( 'Please use a valid email address.', 'optimole-wp' ),
1221 - 'connected' => __( 'CONNECTED', 'optimole-wp' ),
1222 - 'connecting' => __( 'CONNECTING', 'optimole-wp' ),
1223 - 'not_connected' => __( 'NOT CONNECTED', 'optimole-wp' ),
1224 - 'usage' => __( 'Monthly Usage', 'optimole-wp' ),
1225 - 'quota' => __( 'Monthly visits quota', 'optimole-wp' ),
1226 - 'logged_in_as' => __( 'LOGGED IN AS', 'optimole-wp' ),
1227 - 'private_cdn_url' => __( 'IMAGES DOMAIN', 'optimole-wp' ),
1228 - 'existing_user' => __( 'Existing user?', 'optimole-wp' ),
1229 - 'notification_message_register' => __( 'We sent you the API Key in the email. Add it below to connect to Optimole.', 'optimole-wp' ),
1230 - 'premium_support' => __( 'Access our Premium Support', 'optimole-wp' ),
1231 - 'account_needed_title' => sprintf(
197 + return array(
198 + 'optimole' => 'Optimole',
199 + 'version' => OPTML_VERSION,
200 + 'terms_menu' => __( 'Terms', 'optimole-wp' ),
201 + 'privacy_menu' => __( 'Privacy', 'optimole-wp' ),
202 + 'testdrive_menu' => __( 'Test Optimole', 'optimole-wp' ),
203 + 'service_details' => __( 'Image optimization service', 'optimole-wp' ),
204 + 'connect_btn' => __( 'Connect to OptiMole Service', 'optimole-wp' ),
205 + 'disconnect_btn' => __( 'Disconnect', 'optimole-wp' ),
206 + 'api_key_placeholder' => __( 'API Key', 'optimole-wp' ),
207 + 'account_needed_heading' => __( 'Sign-up for API key', 'optimole-wp' ),
208 + 'invalid_key' => __( 'Invalid API Key', 'optimole-wp' ),
209 + 'status' => __( 'Status', 'optimole-wp' ),
210 + 'email_address_label' => __( 'Your email address', 'optimole-wp' ),
211 + 'register_btn' => __( 'Register & Email API key', 'optimole-wp' ),
212 + 'step_one_api_title' => __( 'Enter your API key.', 'optimole-wp' ),
213 + 'step_one_api_desc' => sprintf( __( 'Copy the API key you have received via email or you can get it from %s Optimole dashboard%s. <br/>', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/" target="_blank"> ', '</a>' ),
214 + 'step_two_api_title' => __( 'Connect to Optimole.', 'optimole-wp' ),
215 + 'step_two_api_desc' => __( ' Fill in the upper API key field and connect to Optimole service.', 'optimole-wp' ),
216 + 'api_exists' => __( 'I already have an API key.', 'optimole-wp' ),
217 + 'back_to_register' => __( 'Register account', 'optimole-wp' ),
218 + 'back_to_connect' => __( 'Connect account', 'optimole-wp' ),
219 + 'error_register' => sprintf( __( 'Error registering account. You can try again %shere%s ', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/register" target="_blank"> ', '</a>' ),
220 + 'connected' => __( 'Connected', 'optimole-wp' ),
221 + 'not_connected' => __( 'Not connected', 'optimole-wp' ),
222 + 'usage' => __( 'Monthly Usage', 'optimole-wp' ),
223 + 'quota' => __( 'Monthly Quota', 'optimole-wp' ),
224 + 'logged_in_as' => __( 'Logged in as', 'optimole-wp' ),
225 + 'private_cdn_url' => __( 'Private CDN url', 'optimole-wp' ),
226 + 'options' => __( 'Options', 'optimole-wp' ),
227 + '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' ),
228 + 'account_needed_title' => sprintf(
1232 229 __( 'In order to get access to free image optimization service you will need an API key from %s.', 'optimole-wp' ),
1233 230 ' <a href="https://dashboard.optimole.com/register" target="_blank">optimole.com</a>'
1234 231 ),
1235 - 'account_needed_subtitle_1' => sprintf(
1236 - __( 'You will get access to our %1$simage optimization service for FREE%2$s in the limit of %3$s5k%4$s %5$svisitors%6$s per month. ', 'optimole-wp' ),
1237 - '<strong>',
1238 - '</strong>',
1239 - '<strong>',
1240 - '</strong>',
1241 - '<a href="https://docs.optimole.com/article/1134-how-optimole-counts-the-number-of-visitors" target="_blank">',
1242 - '</a>'
232 + 'account_needed_subtitle_1' => sprintf(
233 + __( 'You will get access to our image optimization service for free in the limit of 1GB traffic per month. ', 'optimole-wp' )
1243 234 ),
1244 - 'account_needed_subtitle_3' => sprintf(
1245 - __( 'Need help? %1$sGetting Started with Optimole%2$s', 'optimole-wp' ),
1246 - '<a target="_blank" href="https://docs.optimole.com/article/1173-how-to-get-started-with-optimole-in-just-3-steps">',
1247 - '</a>'
235 + 'account_needed_subtitle_2' => sprintf(
236 + __( 'Bonus, if you dont use a CDN, we got you covered, we will serve the images using our default CDN.', 'optimole-wp' )
1248 237 ),
1249 - 'account_needed_subtitle_2' => sprintf(
1250 - __(
1251 - 'Bonus, if you dont use a CDN, we got you covered, %1$swe will serve the images using CloudFront CDN%2$s from 450+ locations.',
1252 - 'optimole-wp'
1253 - ),
1254 - '<strong>',
1255 - '</strong>'
238 + 'dashboard_menu_item' => __( 'Dashboard', 'optimole-wp' ),
239 + 'settings_menu_item' => __( 'Settings', 'optimole-wp' ),
240 + 'options_strings' => array(
241 + 'toggle_ab_item' => __( 'Admin bar status', 'optimole-wp' ),
242 + 'enable_image_replace' => __( 'Enable image replacement', 'optimole-wp' ),
243 + 'show' => __( 'Show', 'optimole-wp' ),
244 + 'hide' => __( 'Hide', 'optimole-wp' ),
245 + 'high_q_title' => __( 'High', 'optimole-wp' ),
246 + 'medium_q_title' => __( 'Medium', 'optimole-wp' ),
247 + 'low_q_title' => __( 'Low', 'optimole-wp' ),
248 + 'auto_q_title' => __( 'Auto', 'optimole-wp' ),
249 + 'quality_title' => __( 'Compression quality', 'optimole-wp' ),
250 + 'quality_desc' => __( 'Select how much would like to compress the images.', 'optimole-wp' ),
251 + 'enabled' => __( 'Enabled', 'optimole-wp' ),
252 + 'option_saved' => __( 'Option saved.', 'optimole-wp' ),
253 + 'disabled' => __( 'Disabled', 'optimole-wp' ),
254 + 'image_1_label' => __( 'Original', 'optimole-wp' ),
255 + 'image_2_label' => __( 'Optimized', 'optimole-wp' ),
256 + 'save_quality_btn' => __( 'Save', 'optimole-wp' ),
257 + 'sample_image_loading' => __( ' Loading a sample image. ', 'optimole-wp' ),
258 + 'no_images_found' => __( 'You dont have any images in your Media Library. Add one and check how the Optimole will perform.', 'optimole-wp' ),
259 + 'quality_slider_desc' => __( ' See one sample image which will help you choose the right quality of the compression.', 'optimole-wp' ),
260 + 'replacer_desc' => __( 'Replace all the image urls from your website with the ones optimized by Optimole.', 'optimole-wp' ),
261 + 'admin_bar_desc' => __( 'Show in the WordPress admin bar the available quota from Optimole service.', 'optimole-wp' ),
1256 262 ),
1257 - 'account_needed_footer' => sprintf( __( 'Trusted by more than %1$s happy users', 'optimole-wp' ), number_format_i18n( 200000, 0 ) ),
1258 - 'account_connecting_title' => __( 'Connecting to Optimole', 'optimole-wp' ),
1259 - 'account_connecting_subtitle' => __( 'Sit tight while we connect you to the Dashboard', 'optimole-wp' ),
1260 - 'notice_just_activated' => ! $this->settings->is_connected() ?
1261 - 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. You can relax, we\'ll take it from here.', 'optimole-wp' ), '<strong>', '</strong>' )
1262 - : '',
1263 - 'notice_api_not_working' => __(
1264 - '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/>
1265 -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.',
1266 - 'optimole-wp'
1267 - ),
1268 - 'notice_disabled_account' => sprintf( __( '%3$sYour account has been disabled due to exceeding quota.%4$s All images are being redirected to the original unoptimized URL. %5$sPlease %1$supgrade%2$s to re-activate the account.', 'optimole-wp' ), '<b><a href="https://optimole.com/pricing">', '</a></b>', '<b>', '</b>', '<br>' ),
1269 - 'signup_terms' => sprintf( __( 'By signing up, you agree to our %1$sTerms of Service %3$s and %2$sPrivacy Policy %3$s.', 'optimole-wp' ), '<a href="https://optimole.com/terms/" target="_blank" >', '<a href="https://optimole.com/privacy-policy/" target="_blank">', '</a>' ),
1270 - 'dashboard_menu_item' => __( 'Dashboard', 'optimole-wp' ),
1271 - 'settings_menu_item' => __( 'Settings', 'optimole-wp' ),
1272 - 'help_menu_item' => __( 'Help', 'optimole-wp' ),
1273 - 'settings_exclusions_menu_item' => __( 'Exclusions', 'optimole-wp' ),
1274 - 'settings_resize_menu_item' => __( 'Resize', 'optimole-wp' ),
1275 - 'settings_compression_menu_item' => __( 'Compression', 'optimole-wp' ),
1276 - 'advanced_settings_menu_item' => __( 'Advanced', 'optimole-wp' ),
1277 - 'general_settings_menu_item' => __( 'General', 'optimole-wp' ),
1278 - 'lazyload_settings_menu_item' => __( 'Lazyload', 'optimole-wp' ),
1279 - 'watermarks_menu_item' => __( 'Watermark', 'optimole-wp' ),
1280 - 'conflicts_menu_item' => __( 'Possible Issues', 'optimole-wp' ),
1281 - 'conflicts' => [
1282 - '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' ),
1283 - 'message' => __( 'Details', 'optimole-wp' ),
1284 - 'conflict_close' => __( 'I\'ve done this.', 'optimole-wp' ),
1285 - 'no_conflicts_found' => __( 'No conflicts found. We are all peachy now. 🍑', 'optimole-wp' ),
1286 - ],
1287 - 'upgrade' => [
1288 - 'title' => __( 'Upgrade', 'optimole-wp' ),
1289 - 'title_long' => __( 'Upgrade to Optimole Pro', 'optimole-wp' ),
1290 - 'reason_1' => __( 'Priority & Live Chat support', 'optimole-wp' ),
1291 - 'reason_2' => __( 'Extend visits limit', 'optimole-wp' ),
1292 - 'reason_3' => __( 'Custom domain', 'optimole-wp' ),
1293 - 'reason_4' => __( 'Site audit', 'optimole-wp' ),
1294 - 'cta' => __( 'View plans', 'optimole-wp' ),
1295 - ],
1296 - 'neve' => [
1297 - 'is_active' => defined( 'NEVE_VERSION' ) ? 'yes' : 'no',
1298 - 'byline' => __( 'Fast, perfomance built-in WordPress theme.', 'optimole-wp' ),
1299 - 'reason_1' => __( 'Lightweight, 25kB in page-weight.', 'optimole-wp' ),
1300 - 'reason_2' => __( '100+ Starter Sites available.', 'optimole-wp' ),
1301 - 'reason_3' => __( 'AMP/Mobile ready.', 'optimole-wp' ),
1302 - 'reason_4' => __( 'Lots of customizations options.', 'optimole-wp' ),
1303 - 'reason_5' => __( 'Fully compatible with Optimole.', 'optimole-wp' ),
1304 - ],
1305 - 'metrics' => [
1306 - 'metricsTitle1' => __( 'Images optimized', 'optimole-wp' ),
1307 - 'metricsSubtitle1' => __( 'Since plugin activation', 'optimole-wp' ),
1308 - 'metricsTitle2' => __( 'Saved file size', 'optimole-wp' ),
1309 - 'metricsSubtitle2' => __( 'For the latest 10 images', 'optimole-wp' ),
1310 - 'metricsTitle3' => __( 'Average compression', 'optimole-wp' ),
1311 - 'metricsSubtitle3' => __( 'During last month', 'optimole-wp' ),
1312 - 'metricsTitle4' => __( 'Traffic', 'optimole-wp' ),
1313 - 'metricsSubtitle4' => __( 'During last month', 'optimole-wp' ),
1314 - ],
1315 - 'options_strings' => [
1316 - 'best_format_title' => __( 'Automatic Best Image Format Selection', 'optimole-wp' ),
1317 - 'best_format_desc' => sprintf( __( 'When enabled, Optimole picks the ideal format for your images, balancing quality and speed. It tests different formats, like AVIF and WebP, ensuring images look good and load quickly. %1$sLearn more%2$s.', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1942-best-format">', '</a>' ),
1318 - 'add_filter' => __( 'Add filter', 'optimole-wp' ),
1319 - 'add_site' => __( 'Add site', 'optimole-wp' ),
1320 - 'admin_bar_desc' => __( 'Show in the WordPress admin bar the available quota from Optimole service.', 'optimole-wp' ),
1321 - 'auto_q_title' => __( 'Auto', 'optimole-wp' ),
1322 - 'cache_desc' => sprintf( __( 'Clears all Optimole’s cached resources (images, JS, CSS). Useful if you made changes to your images and don\'t see those applying on your site. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1941-clear-cached-resources">', '</a>' ),
1323 - 'cache_title' => __( 'Clear Cached Resources', 'optimole-wp' ),
1324 - 'clear_cache_notice' => __( 'Clearing cached resources will re-optimize the images and might affect the site performance for a few minutes.', 'optimole-wp' ),
1325 - 'image_size_notice' => sprintf( __( 'Use this option if you notice images are not cropped correctly after using Optimole. Add the affected image sizes here to automatically adjust and correct their cropping for optimal display. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1947-add-new-image-crop-size">', '</a>' ),
1326 - 'clear_cache_images' => __( 'Clear cached images', 'optimole-wp' ),
1327 - 'clear_cache_assets' => __( 'Clear cached CSS & JS', 'optimole-wp' ),
1328 - 'connect_step_0' => __( 'Connecting your site to the Optimole service.', 'optimole-wp' ),
1329 - 'connect_step_1' => __( 'Checking for possible conflicts.', 'optimole-wp' ),
1330 - 'connect_step_2' => __( 'Inspecting the images from your site.', 'optimole-wp' ),
1331 - 'connect_step_3' => __( 'All done, Optimole is currently optimizing your site.', 'optimole-wp' ),
1332 - 'disabled' => __( 'Disabled', 'optimole-wp' ),
1333 - 'enable_avif_title' => __( 'AVIF Image Support', 'optimole-wp' ),
1334 - 'enable_avif_desc' => sprintf( __( 'Enable this to automatically convert images to the AVIF format on browsers that support it. This format provides quality images with reduced file sizes, and faster webpage loading. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1943-avif-conversion">', '</a>' ),
1335 - 'enable_bg_lazyload_desc' => sprintf( __( 'Enable this to lazy-load images set as CSS backgrounds. If Optimole misses any, you can directly target specific CSS selectors to ensure all background images are optimized. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1169-how-to-enable-the-background-lazyload-feature-for-certain-background-images">', '</a>' ),
1336 - 'enable_bg_lazyload_title' => __( 'CSS Background Lazy Load', 'optimole-wp' ),
1337 - 'enable_video_lazyload_desc' => sprintf( __( 'By default, lazy loading does not work for embedded videos and iframes. Enable this option to activate the lazy-load on these elements. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1952-lazy-loading-for-embedded-videos-and-iframes">', '</a>' ),
1338 - 'enable_video_lazyload_title' => __( 'Lazy Loading for Embedded Videos and Iframes', 'optimole-wp' ),
1339 - 'enable_noscript_desc' => sprintf( __( 'Enables fallback images for browsers that can\'t handle JavaScript-based lazy loading or related features. Disabling it may resolve conflicts with other plugins or configurations and decrease HTML page size. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1959-noscript-tag">', '</a>' ),
1340 - 'enable_noscript_title' => __( 'Noscript Tag', 'optimole-wp' ),
1341 - 'enable_gif_replace_title' => __( 'GIF to Video Conversion', 'optimole-wp' ),
1342 - 'enable_report_title' => __( 'Enable Error Diagnosis Tool', 'optimole-wp' ),
1343 - 'enable_report_desc' => sprintf( __( 'Activates the Optimole debugging tool in the admin bar for reports on Optimole-related website issues using the built-in diagnostic feature. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1390-how-does-the-error-diagnosis-tool-work">', '</a>' ),
1344 - 'enable_offload_media_title' => __( 'Store Your Images in Optimole Cloud', 'optimole-wp' ),
1345 - 'enable_offload_media_desc' => sprintf( __( 'Free up space on your server by transferring your images to Optimole Cloud; you can transfer them back anytime. Once moved, the images will still be visible in the Media Library and can be used as before. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1967-store-your-images-in-optimole-cloud">', '</a>' ),
1346 - 'enable_cloud_images_title' => __( 'Unified Image Access', 'optimole-wp' ),
1347 - 'enable_cloud_images_desc' => sprintf( __( 'Enable this setting to access all your Optimole images, including those from other websites connected to your Optimole account, directly on this site. They will be available for browsing in the Cloud Library tab. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1323-cloud-library-browsing">', '</a>' ),
1348 - 'enable_image_replace' => __( 'Enable Optimole Image Handling', 'optimole-wp' ),
1349 - 'enable_lazyload_placeholder_desc' => sprintf( __( 'Enable this to use a generic transparent placeholder instead of the blurry images during lazy loading. Enhance the visual experience by selecting a custom color for the placeholder. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1192-lazy-load-generic-placeholder">', '</a>' ),
1350 - 'enable_lazyload_placeholder_title' => __( 'Lazy Load with Generic Placeholder', 'optimole-wp' ),
1351 - 'enable_network_opt_desc' => sprintf( __( 'When enabled, Optimole will automatically reduce the image quality when it detects a slower network, making your images load faster on low-speed internet connections. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1945-network-based-optimizations">', '</a>' ),
1352 - 'enable_network_opt_title' => __( 'Network-based Optimizations', 'optimole-wp' ),
1353 - 'enable_resize_smart_desc' => sprintf( __( 'When enabled, Optimole automatically detects the most interesting or important part of your images. When pictures are resized or cropped, this feature ensures the focus stays on the most interesting part of the picture. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1871-how-to-use-the-smart-cropping-in-optimole">', '</a>' ),
1354 - 'enable_resize_smart_title' => __( 'Smart Cropping', 'optimole-wp' ),
1355 - 'enable_retina_desc' => sprintf( __( 'Enable this feature to optimize your images for Retina displays. Retina-ready images are optimized to look sharp on screens with higher pixel density, offering viewers enhanced visual quality. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1391-what-is-a-retina-image">', '</a>' ),
1356 - 'enable_retina_title' => __( 'Retina Quality', 'optimole-wp' ),
1357 - 'enable_limit_dimensions_desc' => sprintf( __( 'Define the max width or height limits for images on your website. Larger images will be automatically adjusted to fit within these parameters while preserving their original aspect ratio. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1946-limit-image-sizes">', '</a>' ),
1358 - 'enable_limit_dimensions_title' => __( 'Limit Image Sizes', 'optimole-wp' ),
1359 - 'enable_limit_dimensions_notice' => __( 'When you enable this feature to define a max width or height for image resizing, please note that DPR (retina) images will be disabled. This is done to ensure consistency in image dimensions across your website. Although this may result in slightly lower image quality for high-resolution displays, it will help maintain uniform image sizes, improving your website\'s overall layout and potentially boosting performance. ', 'optimole-wp' ),
1360 - 'enable_badge_title' => __( 'Enable Optimole Badge', 'optimole-wp' ),
1361 - 'enable_badge_description' => sprintf( __( 'Get 20.000 more visits for free by enabling the Optimole badge on your websites. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1940-optimole-badge">', '</a>' ),
1362 - 'image_sizes_title' => __( 'Your cropped image sizes', 'optimole-wp' ),
1363 - 'enabled' => __( 'Enabled', 'optimole-wp' ),
1364 - 'exclude_class_desc' => sprintf( __( '%1$sImage tag%2$s contains class', 'optimole-wp' ), '<strong>', '</strong>' ),
1365 - 'exclude_ext_desc' => sprintf( __( '%1$sImage extension%2$s is', 'optimole-wp' ), '<strong>', '</strong>' ),
1366 - 'exclude_filename_desc' => sprintf( __( '%1$sImage filename%2$s contains', 'optimole-wp' ), '<strong>', '</strong>' ),
1367 - 'exclude_desc_optimize' => sprintf( __( 'Here you can define exceptions, in case you don\'t want some images to be optimised. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1191-exclude-from-optimizing-or-lazy-loading">', '</a>' ),
1368 - 'exclude_title_lazyload' => __( 'Don\'t lazy-load images if', 'optimole-wp' ),
1369 - 'exclude_desc_lazyload' => sprintf( __( 'Define exceptions, in case you don\'t want the lazy-load to be active on certain images. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1191-exclude-from-optimizing-or-lazy-loading">', '</a>' ),
1370 - 'exclude_title_optimize' => __( 'Don\'t optimize images if', 'optimole-wp' ),
1371 - 'exclude_url_desc' => sprintf( __( '%1$sPage url%2$s contains', 'optimole-wp' ), '<strong>', '</strong>' ),
1372 - 'name' => sprintf( __( '%1$sName: %2$s', 'optimole-wp' ), '<strong>', '</strong>' ),
1373 - 'cropped' => __( 'cropped', 'optimole-wp' ),
1374 - 'exclude_url_match_desc' => sprintf( __( '%1$sPage url%2$s matches', 'optimole-wp' ), '<strong>', '</strong>' ),
1375 - 'exclude_first' => __( 'Exclude first', 'optimole-wp' ),
1376 - 'images' => __( 'images', 'optimole-wp' ),
1377 - 'exclude_first_images_title' => __( 'Bypass Lazy Load for First Images', 'optimole-wp' ),
1378 - 'exclude_first_images_desc' => sprintf( __( 'Indicate how many images at the top of each page should bypass lazy loading, ensuring they’re instantly visible. Enter 0 to not exclude any images from the lazy loading process. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1948-bypass-lazy-load-for-first-images">', '</a>' ),
1379 - 'filter_class' => __( 'Image class', 'optimole-wp' ),
1380 - 'filter_ext' => __( 'Image extension', 'optimole-wp' ),
1381 - 'filter_filename' => __( 'Image filename', 'optimole-wp' ),
1382 - 'filter_operator_contains' => __( 'contains', 'optimole-wp' ),
1383 - 'filter_operator_matches' => __( 'matches', 'optimole-wp' ),
1384 - 'filter_operator_is' => __( 'is', 'optimole-wp' ),
1385 - 'filter_url' => __( 'Page URL', 'optimole-wp' ),
1386 - 'filter_helper' => __( 'For homepage use `home` keyword.', 'optimole-wp' ),
1387 - 'gif_replacer_desc' => sprintf( __( 'Enable this to automatically convert GIF images to Video files (MP4 and WebM). %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1171-gif-to-video-conversion">', '</a>' ),
1388 - 'height_field' => __( 'Height', 'optimole-wp' ),
1389 - 'add_image_size_button' => __( 'Add size', 'optimole-wp' ),
1390 - 'add_image_size_desc' => __( 'Add New Image Crop Size', 'optimole-wp' ),
1391 - 'here' => __( ' here.', 'optimole-wp' ),
1392 - 'hide' => __( 'Hide', 'optimole-wp' ),
1393 - 'high_q_title' => __( 'High', 'optimole-wp' ),
1394 - 'image_1_label' => __( 'Original', 'optimole-wp' ),
1395 - 'image_2_label' => __( 'Optimized', 'optimole-wp' ),
1396 - 'lazyload_desc' => sprintf( __( 'Scales large images to fit their display space, ensuring your website runs fast. With lazy loading, images appear when needed while scrolling, making navigation smoother. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1939-scale-images-lazy-load">', '</a>' ),
1397 - 'filter_length_error' => __( 'The filter should be at least 3 characters long.', 'optimole-wp' ),
1398 - 'scale_desc' => sprintf( __( 'Enable this to allow Optimole to resize lazy-loaded images for optimal display on your screen. Keep it disabled to retain the original image size, though it may result in slower page loads. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1950-image-scaling">', '</a>' ),
1399 - 'low_q_title' => __( 'Low', 'optimole-wp' ),
1400 - 'medium_q_title' => __( 'Medium', 'optimole-wp' ),
1401 - 'no_images_found' => __( 'You dont have any images in your Media Library. Add one and check how the Optimole will perform.', 'optimole-wp' ),
1402 - 'native_desc' => sprintf( __( 'Enable to use the browser\'s built-in lazy loading feature. Enabling this will disable the auto scale feature, meaning images will not be automatically resized to fit the screen dimensions. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1949-browser-native-lazy-load">', '</a>' ),
1403 - 'option_saved' => __( 'Option saved.', 'optimole-wp' ),
1404 - 'ml_quality_desc' => sprintf( __( 'Optimole ML algorithms will predict the optimal image quality to get the smallest possible size with minimum perceived quality losses. When disabled, you can control the quality manually. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1016-what-is-the-difference-between-the-auto-high-medium-low-compression-levels">', '</a>' ),
1405 - 'quality_desc' => __( 'Lower image quality might boost your loading speed by lowering the size. However, the low image quality may negatively impact the visual appearance of the images. Try experimenting with the setting, then click the View sample image link to see what option works best for you.', 'optimole-wp' ),
1406 - 'quality_selected_value' => __( 'Selected value', 'optimole-wp' ),
1407 - 'quality_slider_desc' => __( 'See one sample image which will help you choose the right quality of the compression.', 'optimole-wp' ),
1408 - 'quality_title' => __( 'Auto Quality Powered by ML(Machine Learning)', 'optimole-wp' ),
1409 - 'strip_meta_title' => __( 'Strip Image Metadata', 'optimole-wp' ),
1410 - 'strip_meta_desc' => sprintf( __( 'Removes extra information from images, including EXIF and IPTC data (like camera settings and copyright info). This makes the pictures lighter and helps your website load faster. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1944-strip-image-metadata">', '</a>' ),
1411 - 'replacer_desc' => sprintf( __( 'When enabled, Optimole will manage, optimize, and serve all the images on your website. If disabled, optimization, lazy loading, and other features will no longer be available. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1218-how-to-turn-off-image-replacement-in-optimoles-wordpress-plugin">', '</a>' ),
1412 - 'sample_image_loading' => __( 'Loading a sample image. ', 'optimole-wp' ),
1413 - 'save_changes' => __( 'Save changes', 'optimole-wp' ),
1414 - 'show' => __( 'Show', 'optimole-wp' ),
1415 - 'selected_sites_title' => __( 'CURRENTLY SHOWING IMAGES FROM', 'optimole-wp' ),
1416 - 'selected_sites_desc' => __( 'Site: ', 'optimole-wp' ),
1417 - 'selected_all_sites_desc' => __( 'Currently viewing images from all sites ', 'optimole-wp' ),
1418 - 'select_all_sites_desc' => __( 'View images from all sites ', 'optimole-wp' ),
1419 - 'select_site' => __( 'Select a website', 'optimole-wp' ),
1420 - 'cloud_site_title' => __( 'Show images only from these sites: ', 'optimole-wp' ),
1421 - 'cloud_site_desc' => __( 'Browse images only from the specified websites. Otherwise, images from all websites will appear in the library.', 'optimole-wp' ),
1422 - 'toggle_ab_item' => __( 'Admin bar status', 'optimole-wp' ),
1423 - 'toggle_lazyload' => __( 'Scale Images & Lazy loading', 'optimole-wp' ),
1424 - 'toggle_scale' => __( 'Image Scaling', 'optimole-wp' ),
1425 - 'toggle_native' => __( 'Browser Native Lazy Load', 'optimole-wp' ),
1426 - 'on_toggle' => __( 'On', 'optimole-wp' ),
1427 - 'off_toggle' => __( 'Off', 'optimole-wp' ),
1428 - 'view_sample_image' => __( 'View sample image', 'optimole-wp' ),
1429 - 'watch_placeholder_lazyload' => __( 'Add each CSS selector on a new line or separated by comma(,)', 'optimole-wp' ),
1430 - 'watch_desc_lazyload' => sprintf( __( 'Enter CSS selectors for any background images not covered by the default lazy loading. This ensures those images also benefit from the optimized loading process. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1169-how-to-enable-the-background-lazyload-feature-for-certain-background-images">', '</a>' ),
1431 - 'watch_title_lazyload' => __( 'Extend CSS Background Lazy Loading', 'optimole-wp' ),
1432 - 'width_field' => __( 'Width', 'optimole-wp' ),
1433 - 'crop' => __( 'crop', 'optimole-wp' ),
1434 - 'toggle_cdn' => __( 'Serve CSS & JS Through Optimole', 'optimole-wp' ),
1435 - 'cdn_desc' => sprintf( __( 'When enabled, Optimole will optimize your CSS and JS files and, if they contain images, the images as well, then deliver them via the CDN for faster webpage loading. %1$sLearn more%2$s', 'optimole-wp' ), '<a class="inline-block text-purple-gray underline" target=”_blank” href="https://docs.optimole.com/article/1966-serve-css-js-through-optimole">', '</a>' ),
1436 - 'enable_css_minify_title' => __( 'Minify CSS files', 'optimole-wp' ),
1437 - 'css_minify_desc' => __( 'Once Optimole will serve your CSS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
1438 - 'enable_js_minify_title' => __( 'Minify JS files', 'optimole-wp' ),
1439 - 'js_minify_desc' => __( 'Once Optimole will serve your JS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
1440 - 'sync_title' => __( 'Offload Existing Images', 'optimole-wp' ),
1441 - 'rollback_title' => __( 'Restore Offloaded Images', 'optimole-wp' ),
1442 - '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' ),
1443 - 'rollback_desc' => __( 'Pull all the offloaded images to Optimole Cloud back to your server.', 'optimole-wp' ),
1444 - 'sync_media' => __( 'Sync images', 'optimole-wp' ),
1445 - 'rollback_media' => __( 'Rollback images', 'optimole-wp' ),
1446 - 'sync_media_progress' => __( 'Moving your images to Optimole...', 'optimole-wp' ),
1447 - 'estimated_time' => __( 'Estimated time remaining', 'optimole-wp' ),
1448 - 'calculating_estimated_time' => __( 'We are currently calculating the estimated time for this job...', 'optimole-wp' ),
1449 - 'images_processing' => __( 'We are currently processing your images in the background. Leaving the page won\'t stop the process.', 'optimole-wp' ),
1450 - 'active_optimize_exclusions' => __( 'Active Optimizing Exclusions', 'optimole-wp' ),
1451 - 'active_lazyload_exclusions' => __( 'Active Lazy-loading Exclusions', 'optimole-wp' ),
1452 - 'minutes' => __( 'minutes', 'optimole-wp' ),
1453 - 'stop' => __( 'Stop', 'optimole-wp' ),
1454 - 'show_logs' => __( 'Show Logs', 'optimole-wp' ),
1455 - 'hide_logs' => __( 'Hide Logs', 'optimole-wp' ),
1456 - 'view_logs' => __( 'View Full Logs', 'optimole-wp' ),
1457 - 'rollback_media_progress' => __( 'Moving images into your media library...', 'optimole-wp' ),
1458 - 'rollback_media_error' => __( 'An unexpected error occured while pulling the offloaded back to your site', 'optimole-wp' ),
1459 - 'rollback_media_error_desc' => __( 'You can try again to pull back the rest of the images.', 'optimole-wp' ),
1460 - 'remove_notice' => __( 'Remove notice', 'optimole-wp' ),
1461 - 'sync_media_error' => __( 'An unexpected error occured while offloading all existing images from your site to Optimole ', 'optimole-wp' ),
1462 - 'sync_media_link' => __( 'The selected images have been offloaded to our servers, you can check them', 'optimole-wp' ),
1463 - 'rollback_media_link' => __( 'The selected images have been restored to your server, you can check them', 'optimole-wp' ),
1464 - 'sync_media_error_desc' => __( 'You can try again to offload the rest of the images to Optimole.', 'optimole-wp' ),
1465 - 'offload_disable_warning_title' => __( 'Important! Please read carefully', 'optimole-wp' ),
1466 - 'offload_disable_warning_desc' => __( 'If you turn off 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 turning off the option?', 'optimole-wp' ),
1467 - 'offload_enable_info_desc' => sprintf( __( 'You are not required to use the offload functionality for the plugin to work, use it if you want to save on hosting space. %1$s More details%2$s', 'optimole-wp' ), '<a style="white-space: nowrap;" target=”_blank” href="https://docs.optimole.com/article/1323-cloud-library-browsing">', '<span style="font-size:15px; margin-top:2px;" class="dashicons dashicons-external"></span></a>' ),
1468 - 'offload_conflicts_part_1' => __( 'We have detected the following plugins that conflict with the offload features: ', 'optimole-wp' ),
1469 - 'offload_conflicts_part_2' => __( 'Please disable those plugins temporarily in order for Optimole to rollback the images to your site.', 'optimole-wp' ),
1470 - 'offloading_success' => sprintf( __( '%s Your images are now stored in Optimole Cloud.', 'optimole-wp' ), '<strong>' . __( 'Transfer Complete.', 'optimole-wp' ) . '</strong>' ),
1471 - 'rollback_success' => sprintf( __( '%s Your images have been restored to your website.', 'optimole-wp' ), '<strong>' . __( 'Transfer Complete.', 'optimole-wp' ) . '</strong>' ),
1472 - 'offloading_radio_legend' => __( 'Where your images are stored', 'optimole-wp' ),
1473 - 'offload_radio_option_rollback_title' => __( 'Optimole Cloud and your website', 'optimole-wp' ),
1474 - 'offload_radio_option_rollback_desc' => __( 'Images are stored in both the local WordPress media library and Optimole Cloud.', 'optimole-wp' ),
1475 - 'offload_radio_option_offload_title' => __( 'Optimole Cloud only', 'optimole-wp' ),
1476 - 'offload_radio_option_offload_desc' => __( 'Images are stored only in Optimole Cloud, allowing you to save space on your server. When enabled, any new images you upload in the Media Library will be automatically transferred to Optimole Cloud.', 'optimole-wp' ),
1477 - 'offload_limit_reached' => sprintf( __( 'You have reached the maximum offloading limit of %s images. To increase the offload limit and for more information, contact our support.', 'optimole-wp' ), '<strong>#offload_limit#</strong>' ),
1478 - 'select' => __( 'Please select one ...', 'optimole-wp' ),
1479 - 'yes' => __( 'Restore images after disabling', 'optimole-wp' ),
1480 - 'no' => __( 'Do not restore images after disabling', 'optimole-wp' ),
1481 - 'lazyload_placeholder_color' => __( 'Placeholder Color', 'optimole-wp' ),
1482 - 'clear' => __( 'Clear', 'optimole-wp' ),
1483 - 'settings_saved' => __( 'Settings saved', 'optimole-wp' ),
1484 - 'settings_saved_error' => __( 'Error saving settings. Please reload the page and try again.', 'optimole-wp' ),
1485 - 'cache_cleared' => __( 'Cache cleared', 'optimole-wp' ),
1486 - 'cache_cleared_error' => __( 'Error clearing cache. Please reload the page and try again.', 'optimole-wp' ),
1487 - 'offloading_start_title' => __( 'Transfer your images to Optimole', 'optimole-wp' ),
1488 - 'offloading_start_description' => __( 'This process will transfer and store your images in Optimole Cloud and may take a while, depending on the number of images.', 'optimole-wp' ),
1489 - 'offloading_start_action' => __( 'Transfer to Optimole Cloud', 'optimole-wp' ),
1490 - 'offloading_stop_title' => __( 'Are you sure?', 'optimole-wp' ),
1491 - 'offloading_stop_description' => __( 'This will halt the ongoing process. To retrieve images transferred from the Optimole Cloud, use the Rollback option.', 'optimole-wp' ),
1492 - 'offloading_stop_action' => __( 'Cancel the transfer to Optimole', 'optimole-wp' ),
1493 - 'rollback_start_title' => __( 'Transfer back all images to your site', 'optimole-wp' ),
1494 - 'rollback_start_description' => __( 'This process will transfer back all images from Optimole to your website and may take a while, depending on the number of images.', 'optimole-wp' ),
1495 - 'rollback_start_action' => __( 'Transfer back from Optimole', 'optimole-wp' ),
1496 - 'rollback_stop_title' => __( 'Are you sure?', 'optimole-wp' ),
1497 - 'rollback_stop_description' => __( 'Canceling will halt the ongoing process, and any remaining images will stay in the Optimole Cloud. To transfer images to the Optimole Cloud, use the Offloading option.', 'optimole-wp' ),
1498 - 'rollback_stop_action' => __( 'Cancel the transfer from Optimole', 'optimole-wp' ),
1499 - ],
1500 - 'help' => [
1501 - 'section_one_title' => __( 'Help and Support', 'optimole-wp' ),
1502 - 'section_two_title' => __( 'Documentation', 'optimole-wp' ),
1503 - 'section_two_sub' => __( 'Docs Page', 'optimole-wp' ),
1504 - 'get_support_title' => __( 'Get Support', 'optimole-wp' ),
1505 - 'get_support_desc' => __( 'Need help or got a question? Submit a ticket and we\'ll get back to you.', 'optimole-wp' ),
1506 - 'get_support_cta' => __( 'Contact Support', 'optimole-wp' ),
1507 - 'feat_request_title' => __( 'Have a feature request?', 'optimole-wp' ),
1508 - 'feat_request_desc' => __( 'Help us improve Optimole by sharing feedback and ideas for new features.', 'optimole-wp' ),
1509 - 'feat_request_cta' => __( 'Submit a Feature Request', 'optimole-wp' ),
1510 - 'feedback_title' => __( 'Changelog', 'optimole-wp' ),
1511 - 'feedback_desc' => __( 'Check our changelog to see latest fixes and features implemented.', 'optimole-wp' ),
1512 - 'feedback_cta' => __( 'View Changelog', 'optimole-wp' ),
1513 - 'account_title' => __( 'Account', 'optimole-wp' ),
1514 - 'account_item_one' => __( 'How Optimole counts the visitors?', 'optimole-wp' ),
1515 - 'account_item_two' => __( 'What happens if I exceed plan limits?', 'optimole-wp' ),
1516 - 'account_item_three' => __( 'Visits based plan', 'optimole-wp' ),
1517 - 'image_processing_title' => __( 'Image Processing', 'optimole-wp' ),
1518 - 'image_processing_item_one' => __( 'Getting Started With Optimole', 'optimole-wp' ),
1519 - 'image_processing_item_two' => __( 'How Optimole can serve WebP images', 'optimole-wp' ),
1520 - 'image_processing_item_three' => __( 'Adding Watermarks to your images', 'optimole-wp' ),
1521 - 'api_title' => __( 'API', 'optimole-wp' ),
1522 - 'api_item_one' => __( 'Cloud Library Browsing', 'optimole-wp' ),
1523 - 'api_item_two' => __( 'Exclude from Optimizing or Lazy Loading', 'optimole-wp' ),
1524 - 'api_item_three' => __( 'Custom Integration', 'optimole-wp' ),
1525 - ],
1526 - 'watermarks' => [
1527 - 'image' => __( 'Image', 'optimole-wp' ),
1528 - 'loading_remove_watermark' => __( 'Removing watermark resource ...', 'optimole-wp' ),
1529 - 'max_allowed' => __( 'You are allowed to save maximum 5 images.', 'optimole-wp' ),
1530 - 'list_header' => __( 'Possible watermarks', 'optimole-wp' ),
1531 - 'settings_header' => __( 'Watermarks position settings', 'optimole-wp' ),
1532 - 'no_images_found' => __( 'No images available for watermark. Please upload one.', 'optimole-wp' ),
1533 - 'id' => __( 'ID', 'optimole-wp' ),
1534 - 'name' => __( 'Name', 'optimole-wp' ),
1535 - 'type' => __( 'Type', 'optimole-wp' ),
1536 - 'action' => __( 'Action', 'optimole-wp' ),
1537 - 'upload' => __( 'Upload', 'optimole-wp' ),
1538 - 'add_desc' => __( 'Add new watermark', 'optimole-wp' ),
1539 - 'wm_title' => __( 'Active watermark', 'optimole-wp' ),
1540 - 'wm_desc' => __( 'The active watermark to use from the list of uploaded watermarks.', 'optimole-wp' ),
1541 - 'opacity_field' => __( 'Opacity', 'optimole-wp' ),
1542 - 'opacity_title' => __( 'Watermark opacity', 'optimole-wp' ),
1543 - 'opacity_desc' => __( 'A value between 0 and 100 for the opacity level. If set to 0 it will disable the watermark.', 'optimole-wp' ),
1544 - 'position_title' => __( 'Watermark position', 'optimole-wp' ),
1545 - 'position_desc' => __( 'The place relative to the image where the watermark should be placed.', 'optimole-wp' ),
1546 - 'pos_nowe_title' => __( 'North-West', 'optimole-wp' ),
1547 - 'pos_no_title' => __( 'North', 'optimole-wp' ),
1548 - 'pos_noea_title' => __( 'North-East', 'optimole-wp' ),
1549 - 'pos_we_title' => __( 'West', 'optimole-wp' ),
1550 - 'pos_ce_title' => __( 'Center', 'optimole-wp' ),
1551 - 'pos_ea_title' => __( 'East', 'optimole-wp' ),
1552 - 'pos_sowe_title' => __( 'South-West', 'optimole-wp' ),
1553 - 'pos_so_title' => __( 'South', 'optimole-wp' ),
1554 - 'pos_soea_title' => __( 'South-East', 'optimole-wp' ),
1555 - 'offset_x_field' => __( 'Offset X', 'optimole-wp' ),
1556 - 'offset_y_field' => __( 'Offset Y', 'optimole-wp' ),
1557 - 'offset_title' => __( 'Watermark offset', 'optimole-wp' ),
1558 - 'offset_desc' => __( 'Offset the watermark from set position on X and Y axis. Values can be positive or negative.', 'optimole-wp' ),
1559 - 'scale_field' => __( 'Scale', 'optimole-wp' ),
1560 - 'scale_title' => __( 'Watermark scale', 'optimole-wp' ),
1561 - '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' ),
1562 - 'save_changes' => __( 'Save changes', 'optimole-wp' ),
1563 - ],
1564 - 'latest_images' => [
263 + 'latest_images' => array(
1565 264 'image' => __( 'Image', 'optimole-wp' ),
1566 - '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>' ),
265 + 'no_images_found' => sprintf( __( 'We might have a delay finding optimized images. Meanwhile you can visit your %shomepage%s and check how our plugin performs. ', 'optimole-wp' ), '<a href="' . esc_url( home_url() ) . '" target="_blank" >', '</a>' ),
1567 266 'compression' => __( 'Optimization', 'optimole-wp' ),
1568 267 'loading_latest_images' => __( 'Loading your optimized images...', 'optimole-wp' ),
1569 268 'last' => __( 'Last', 'optimole-wp' ),
1570 - 'saved' => __( 'Saved', 'optimole-wp' ),
1571 - 'smaller' => __( 'smaller', 'optimole-wp' ),
1572 269 'optimized_images' => __( 'optimized images', 'optimole-wp' ),
1573 270 'same_size' => __( '🙉 We couldn\'t do better, this image is already optimized at maximum. ', 'optimole-wp' ),
1574 271 'small_optimization' => __( '😬 Not that much, just <strong>{ratio}</strong> smaller.', 'optimole-wp' ),
1575 272 'medium_optimization' => __( '🤓 We are on the right track, <strong>{ratio}</strong> squeezed.', 'optimole-wp' ),
1576 273 'big_optimization' => __( '❤️❤️❤️ Our moles just nailed it, this one is <strong>{ratio}</strong> smaller. ', 'optimole-wp' ),
1577 - ],
1578 - 'csat' => [
1579 - 'title' => __( 'Your opinion matters', 'optimole-wp' ),
1580 - 'close' => __( 'Close', 'optimole-wp' ),
1581 - 'heading_one' => __( 'How easy did you find to get started using Optimole, on a scale of 1 to 5?', 'optimole-wp' ),
1582 - 'heading_two' => __( 'Any specific feedback you would like to add?', 'optimole-wp' ),
1583 - 'heading_three' => __( 'Thank you!', 'optimole-wp' ),
1584 - 'low' => __( 'Very Poor', 'optimole-wp' ),
1585 - 'high' => __( 'Excellent', 'optimole-wp' ),
1586 - 'feedback_placeholder' => __( 'Add your feedback here (optional)', 'optimole-wp' ),
1587 - 'skip' => __( 'Skip', 'optimole-wp' ),
1588 - 'submit' => __( 'Submit', 'optimole-wp' ),
1589 - 'thank_you' => __( 'Your input is highly appreciated and helps us shape a better experience in Optimole.', 'optimole-wp' ),
1590 - ],
1591 - 'cron_error' => sprintf( __( 'It seems that you have the %1$s constant defined as %2$s. The offloading process uses cron events to offload the images in the background. Please remove the constant from your wp-config.php file in order for the offloading process to work.', 'optimole-wp' ), '<code>DISABLE_WP_CRON</code>', '<code>true</code>' ),
1592 - 'cancel' => __( 'Cancel', 'optimole-wp' ),
1593 - ];
274 + )
275 + );
1594 276 }
1595 277
1596 278 /**
1597 - * Allow SVG uploads
279 + * Add top admin bar notice of traffic quota/usage.
1598 280 *
1599 - * @param array $mimes Supported mimes.
1600 - *
1601 - * @return array
1602 - * @access public
1603 - * @uses filter:upload_mimes
281 + * @param WP_Admin_Bar $wp_admin_bar Admin bar resource.
1604 282 */
1605 - public function allow_meme_types( $mimes ) {
1606 - $mimes['svg'] = 'image/svg+xml';
1607 - return $mimes;
283 + public function add_traffic_node( $wp_admin_bar ) {
284 + if ( ! is_user_logged_in() ) {
285 + return;
286 + }
287 + $settings = new Optml_Settings();
288 + if ( ! $settings->is_connected() ) {
289 + return;
290 + }
291 + $should_load = $settings->get( 'admin_bar_item' );
292 +
293 + $service_data = $this->settings->get( 'service_data' );
294 + if ( empty( $service_data ) ) {
295 + return;
296 + }
297 + $args = array(
298 + 'id' => 'optml_image_quota',
299 + 'title' => 'Optimole' . __( ' Image Traffic', 'optimole-wp' ) . ': ' . number_format( floatval( ( $service_data['usage'] / 1000 ) ), 3 ) . ' / ' . number_format( floatval( ( $service_data['quota'] / 1000 ) ), 0 ) . 'GB',
300 + 'href' => 'https://dashboard.optimole.com/',
301 + 'meta' => array(
302 + 'target' => '_blank',
303 + 'class' => $should_load !== 'enabled' ? 'hidden' : ''
304 + )
305 + );
306 + $wp_admin_bar->add_node( $args );
1608 307 }
1609 308 }