PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / trunk
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization vtrunk
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
optimole-wp / vendor / codeinwp / themeisle-sdk / src / Modules / About_us.php

About_us.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization trunk, at vendor/codeinwp/themeisle-sdk/src/Modules/About_us.php

546 lines 18.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The about page model class for ThemeIsle SDK
4 *
5 * Here's how to hook it in your plugin:
6 *
7 * add_filter( <product_slug>_about_us_metadata', 'add_about_meta' );
8 *
9 * function add_about_meta($data) {
10 * return [
11 * 'location' => <top level page - e.g. themes.php>,
12 * 'logo' => <logo url>,
13 * 'page_menu' => [['text' => '', 'url' => '']], // optional
14 * 'has_upgrade_menu' => <condition>,
15 * 'upgrade_link' => <url>,
16 * 'upgrade_text' => 'Get Pro Version',
17 * 'review_link' => false, // Leave it empty for default WPorg link or false to hide it.
18 * ]
19 * }
20 *
21 * @package ThemeIsleSDK
22 * @subpackage Modules
23 * @copyright Copyright (c) 2023, Andrei Baicus
24 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
25 * @since 3.2.42
26 */
27
28 namespace ThemeisleSDK\Modules;
29
30 use ThemeisleSDK\Common\Abstract_Module;
31 use ThemeisleSDK\Loader;
32 use ThemeisleSDK\Product;
33
34 // Exit if accessed directly.
35 if ( ! defined( 'ABSPATH' ) ) {
36 exit;
37 }
38
39 /**
40 * Promotions module for ThemeIsle SDK.
41 */
42 class About_Us extends Abstract_Module {
43 /**
44 * Sort weight for products that are not explicitly ranked.
45 *
46 * @var int
47 */
48 const SORT_WEIGHT_UNRANKED = 99;
49
50 /**
51 * Hand-picked display order for featured products, keyed by WP.org slug.
52 *
53 * @var array
54 */
55 const COMMON_PRODUCTS_PRIORITY = [
56 'neve' => 0,
57 'otter-blocks' => 1,
58 'wp-cloudflare-page-cache' => 2,
59 'optimole-wp' => 3,
60 'hyve-lite' => 4,
61 'wp-full-stripe-free' => 5,
62 'insert-php' => 6, // Woody plugin slug on WP.org.
63 'anti-spam' => 7, // Titan Anti-spam & Security plugin slug on WP.org.
64 ];
65
66 /**
67 * Sort weight per install status, lowest shows first.
68 *
69 * @var array
70 */
71 const STATUS_PRIORITY = [
72 'not-installed' => 0,
73 'installed' => 1,
74 'active' => 2,
75 ];
76
77 /**
78 * About data.
79 *
80 * @var array $about_data About page data, received from the filter.
81 *
82 * Shape of the $about_data property array:
83 * [
84 * 'location' => 'top level page',
85 * 'logo' => 'logo path',
86 * 'page_menu' => [['text' => '', 'url' => '']], // Optional
87 * 'has_upgrade_menu' => !defined('NEVE_PRO_VERSION'),
88 * 'upgrade_link' => 'upgrade url',
89 * 'upgrade_text' => 'Get Pro Version',
90 * ]
91 */
92 private $about_data = array();
93
94 /**
95 * Should we load this module.
96 *
97 * @param Product $product Product object.
98 *
99 * @return bool
100 */
101 public function can_load( $product ) {
102 if ( $this->is_from_partner( $product ) ) {
103 return false;
104 }
105
106 $this->about_data = apply_filters( $product->get_key() . '_about_us_metadata', array() );
107
108 return ! empty( $this->about_data );
109 }
110
111 /**
112 * Registers the hooks.
113 *
114 * @param Product $product Product to load.
115 */
116 public function load( $product ) {
117 $this->product = $product;
118
119 add_action( 'admin_menu', [ $this, 'add_submenu_pages' ] );
120 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_about_page_script' ] );
121 }
122
123 /**
124 * Adds submenu pages.
125 *
126 * @return void
127 */
128 public function add_submenu_pages() {
129 if ( ! isset( $this->about_data['location'] ) ) {
130 return;
131 }
132
133 // Refresh the about data to get the latest changes.
134 $this->about_data = apply_filters( $this->product->get_key() . '_about_us_metadata', array() );
135
136 add_submenu_page(
137 $this->about_data['location'],
138 Loader::$labels['about_us']['title'],
139 Loader::$labels['about_us']['title'],
140 'manage_options',
141 $this->get_about_page_slug(),
142 array( $this, 'render_about_us_page' ),
143 100
144 );
145
146 if ( ! isset( $this->about_data['has_upgrade_menu'] ) ) {
147 return;
148 }
149
150 if ( $this->about_data['has_upgrade_menu'] !== true ) {
151 return;
152 }
153
154 if ( ! isset( $this->about_data['upgrade_link'] ) ) {
155 return;
156 }
157
158 if ( ! isset( $this->about_data['upgrade_text'] ) ) {
159 return;
160 }
161
162 add_submenu_page(
163 $this->about_data['location'],
164 $this->about_data['upgrade_text'],
165 '<span class="tsdk-upg-menu-item">' . $this->about_data['upgrade_text'] . '</span>',
166 'manage_options',
167 $this->about_data['upgrade_link'],
168 '',
169 101
170 );
171 add_action(
172 'admin_footer',
173 function () {
174 ?>
175 <style>
176 .tsdk-upg-menu-item {
177 color: #009528;
178 }
179
180 .tsdk-upg-menu-item:hover {
181 color: #008a20;
182 }
183 </style>
184 <script type="text/javascript">
185 jQuery(document).ready(function ($) {
186 $('.tsdk-upg-menu-item').parent().attr('target', '_blank');
187 });
188 </script>
189 <?php
190 }
191 );
192 }
193
194 /**
195 * Render page content.
196 *
197 * @return void
198 */
199 public function render_about_us_page() {
200 echo '<div id="ti-sdk-about"></div>';
201 }
202
203 /**
204 * Enqueue scripts & styles.
205 *
206 * @return void
207 */
208 public function enqueue_about_page_script() {
209 $current_screen = get_current_screen();
210
211 if ( ! isset( $current_screen->id ) ) {
212 return;
213 }
214
215 if ( strpos( $current_screen->id, $this->get_about_page_slug() ) === false ) {
216 return;
217 }
218 global $themeisle_sdk_max_path;
219 $handle = 'ti-sdk-about-' . $this->product->get_key();
220 $asset_file = require $themeisle_sdk_max_path . '/assets/js/build/about/about.asset.php';
221 $deps = array_merge( $asset_file['dependencies'], [ 'updates' ] );
222
223 do_action( 'themeisle_internal_page', $this->product->get_slug(), 'about_us' );
224
225 wp_register_script( $handle, $this->get_sdk_uri() . 'assets/js/build/about/about.js', $deps, $asset_file['version'], true );
226 wp_localize_script( $handle, 'tiSDKAboutData', $this->get_about_localization_data() );
227
228 wp_enqueue_script( $handle );
229 wp_enqueue_style( $handle, $this->get_sdk_uri() . 'assets/js/build/about/about.css', [ 'wp-components' ], $asset_file['version'] );
230 }
231
232 /**
233 * Get localized data.
234 *
235 * @return array
236 */
237 private function get_about_localization_data() {
238 $links = isset( $this->about_data['page_menu'] ) ? $this->about_data['page_menu'] : [];
239 $product_pages = isset( $this->about_data['product_pages'] ) ? $this->about_data['product_pages'] : [];
240 $page_slug = $this->get_about_page_slug();
241
242 return [
243 'links' => $links,
244 'logoUrl' => $this->about_data['logo'],
245 'productPages' => $this->get_product_pages_data( $product_pages ),
246 'products' => $this->get_other_products_data(),
247 'services' => [
248 'websiteDesignUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-website-design/', 'services-website-design', $page_slug ),
249 'supportUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-support/', 'services-support', $page_slug ),
250 'speedUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-speed-optimization/', 'services-speed-optimization', $page_slug ),
251 'seoFoundationUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-seo-foundation/', 'services-seo-foundation', $page_slug ),
252 'maintenanceUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-maintenance/', 'services-maintenance', $page_slug ),
253 'hackedRepairUrl' => tsdk_utmify( 'https://themeisle.com/wordpress-hacked-site-repair/', 'services-hacked-site-repair', $page_slug ),
254 'exploreAllUrl' => tsdk_utmify( 'https://themeisle.com/services/', 'services-explore-all', $page_slug ),
255 ],
256 'homeUrl' => esc_url( home_url() ),
257 'pageSlug' => $page_slug,
258 'currentProduct' => [
259 'slug' => $this->product->get_key(),
260 'name' => $this->product->get_name(),
261 ],
262 'teamImage' => $this->get_sdk_uri() . 'assets/images/team.jpg',
263 'strings' => [
264 'aboutUs' => Loader::$labels['about_us']['title'],
265 'heroHeader' => Loader::$labels['about_us']['heroHeader'],
266 'heroTextFirst' => Loader::$labels['about_us']['heroTextFirst'],
267 'heroTextSecond' => Loader::$labels['about_us']['heroTextSecond'],
268 'teamImageCaption' => Loader::$labels['about_us']['teamImageCaption'],
269 'newsHeading' => Loader::$labels['about_us']['newsHeading'],
270 'emailPlaceholder' => Loader::$labels['about_us']['emailPlaceholder'],
271 'signMeUp' => Loader::$labels['about_us']['signMeUp'],
272 'services' => Loader::$labels['about_us']['services'],
273 'installNow' => Loader::$labels['about_us']['installNow'],
274 'activate' => Loader::$labels['about_us']['activate'],
275 'learnMore' => Loader::$labels['about_us']['learnMore'],
276 'installed' => Loader::$labels['about_us']['installed'],
277 'notInstalled' => Loader::$labels['about_us']['notInstalled'],
278 'active' => Loader::$labels['about_us']['active'],
279 ],
280 'canInstallPlugins' => current_user_can( 'install_plugins' ),
281 'canActivatePlugins' => current_user_can( 'activate_plugins' ),
282 'showReviewLink' => ! ( isset( $this->about_data['review_link'] ) && false === $this->about_data['review_link'] ),
283 ];
284 }
285
286 /**
287 * Get product pages data.
288 *
289 * @param array $product_pages Product pages.
290 *
291 * @return array
292 */
293 private function get_product_pages_data( $product_pages ) {
294
295 $otter_slug = 'otter-blocks';
296 $otter_plugin = [
297 'status' => 'not-installed',
298 ];
299 $otter_plugin['status'] = $this->is_plugin_installed( $otter_slug ) ? 'installed' : 'not-installed';
300 $otter_plugin['status'] = $this->is_plugin_active( $otter_slug ) ? 'active' : $otter_plugin['status'];
301 $otter_plugin['activationLink'] = $this->get_plugin_activation_link( $otter_slug );
302
303 $pages = [
304 'otter-page' => [
305 'name' => 'Otter Blocks',
306 'hash' => '#otter-page',
307 'product' => $otter_slug,
308 'plugin' => $otter_plugin,
309 'strings' => [
310 'heading' => Loader::$labels['about_us']['otter-page']['heading'],
311 'text' => Loader::$labels['about_us']['otter-page']['text'],
312 'buttons' => [
313 'install_otter_free' => Loader::$labels['about_us']['otter-page']['buttons']['install_otter_free'],
314 'install_now' => Loader::$labels['about_us']['otter-page']['buttons']['install_now'],
315 'learn_more' => Loader::$labels['about_us']['otter-page']['buttons']['learn_more'],
316 'learn_more_link' => tsdk_utmify( 'https://themeisle.com/plugins/otter-blocks/', 'otter-page', 'about-us' ),
317 ],
318 'features' => [
319 'advancedTitle' => Loader::$labels['about_us']['otter-page']['features']['advancedTitle'],
320 'advancedDesc' => Loader::$labels['about_us']['otter-page']['features']['advancedDesc'],
321 'fastTitle' => Loader::$labels['about_us']['otter-page']['features']['fastTitle'],
322 'fastDesc' => Loader::$labels['about_us']['otter-page']['features']['fastDesc'],
323 'mobileTitle' => Loader::$labels['about_us']['otter-page']['features']['mobileTitle'],
324 'mobileDesc' => Loader::$labels['about_us']['otter-page']['features']['mobileDesc'],
325 ],
326 'details' => [
327 's1Title' => Loader::$labels['about_us']['otter-page']['details']['s1Title'],
328 's1Text' => Loader::$labels['about_us']['otter-page']['details']['s1Text'],
329 's2Title' => Loader::$labels['about_us']['otter-page']['details']['s2Title'],
330 's2Text' => Loader::$labels['about_us']['otter-page']['details']['s2Text'],
331 's3Title' => Loader::$labels['about_us']['otter-page']['details']['s3Title'],
332 's3Text' => Loader::$labels['about_us']['otter-page']['details']['s3Text'],
333 's1Image' => $this->get_sdk_uri() . 'assets/images/otter/otter-builder.png',
334 's2Image' => $this->get_sdk_uri() . 'assets/images/otter/otter-patterns.png',
335 's3Image' => $this->get_sdk_uri() . 'assets/images/otter/otter-library.png',
336 ],
337 'testimonials' => [
338 'heading' => Loader::$labels['about_us']['otter-page']['testimonials']['heading'],
339 'users' => [
340 [
341 'avatar' => 'https://mllj2j8xvfl0.i.optimole.com/cb:3970~373ad/w:80/h:80/q:mauto/https://themeisle.com/wp-content/uploads/2021/05/avatar-03.png',
342 'name' => 'Michael Burry',
343 'text' => Loader::$labels['about_us']['otter-page']['testimonials']['users']['user_1'],
344 ],
345 [
346 'avatar' => 'https://mllj2j8xvfl0.i.optimole.com/cb:3970~373ad/w:80/h:80/q:mauto/https://themeisle.com/wp-content/uploads/2022/04/avatar-04.png',
347 'name' => 'Maria Gonzales',
348 'text' => Loader::$labels['about_us']['otter-page']['testimonials']['users']['user_2'],
349 ],
350 [
351 'avatar' => 'https://mllj2j8xvfl0.i.optimole.com/cb:3970~373ad/w:80/h:80/q:mauto/https://themeisle.com/wp-content/uploads/2022/04/avatar-05.png',
352 'name' => 'Florian Henckel',
353 'text' => Loader::$labels['about_us']['otter-page']['testimonials']['users']['user_3'],
354 ],
355 ],
356 ],
357 ],
358 ],
359 ];
360
361 return array_filter(
362 $pages,
363 function ( $page_data, $page_key ) use ( $product_pages ) {
364 return in_array( $page_key, $product_pages, true ) &&
365 isset( $page_data['plugin']['status'] ) &&
366 $page_data['plugin']['status'] === 'not-installed';
367 },
368 ARRAY_FILTER_USE_BOTH
369 );
370 }
371
372 /**
373 * Get products data.
374 *
375 * @return array
376 */
377 private function get_other_products_data() {
378 $products = [
379 'optimole-wp' => [
380 'name' => 'Optimole',
381 'description' => Loader::$labels['about_us']['others']['optimole_desc'],
382 ],
383 'neve' => [
384 'skip_api' => true,
385 'name' => 'Neve',
386 'description' => Loader::$labels['about_us']['others']['neve_desc'],
387 'icon' => $this->get_sdk_uri() . 'assets/images/neve.png',
388 ],
389 'learning-management-system' => [
390 'name' => 'Masteriyo LMS',
391 ],
392 'otter-blocks' => [
393 'name' => 'Otter',
394 ],
395 'tweet-old-post' => [
396 'name' => 'Revive Social',
397 ],
398 'feedzy-rss-feeds' => [
399 'name' => 'Feedzy',
400 ],
401 'insert-php' => [
402 'name' => 'Woody Code Snippets',
403 ],
404 'wpcf7-redirect' => [
405 'name' => 'Redirection for Contact Form 7',
406 ],
407 'anti-spam' => [
408 'name' => 'Titan Anti-spam & Security',
409 ],
410 'woocommerce-product-addon' => [
411 'name' => 'PPOM',
412 'condition' => class_exists( 'WooCommerce', false ),
413 ],
414 'visualizer' => [
415 'name' => 'Visualizer',
416 ],
417 'wp-landing-kit' => [
418 'skip_api' => true,
419 'premiumUrl' => tsdk_utmify( 'https://themeisle.com/plugins/wp-landing-kit', $this->get_about_page_slug() ),
420 'name' => 'WP Landing Kit',
421 'description' => Loader::$labels['about_us']['others']['landingkit_desc'],
422 'icon' => $this->get_sdk_uri() . 'assets/images/wplk.png',
423 ],
424 'multiple-pages-generator-by-porthas' => [
425 'name' => 'MPG',
426 ],
427 'sparks-for-woocommerce' => [
428 'skip_api' => true,
429 'premiumUrl' => tsdk_utmify( 'https://themeisle.com/plugins/sparks-for-woocommerce', $this->get_about_page_slug() ),
430 'name' => 'Sparks',
431 'description' => Loader::$labels['about_us']['others']['sparks_desc'],
432 'icon' => $this->get_sdk_uri() . 'assets/images/sparks.png',
433 'condition' => class_exists( 'WooCommerce', false ),
434 ],
435 'templates-patterns-collection' => [
436 'name' => 'Templates Cloud',
437 'description' => Loader::$labels['about_us']['others']['tpc_desc'],
438 ],
439 'wp-cloudflare-page-cache' => [
440 'name' => 'Super Page Cache',
441 ],
442 'hyve-lite' => [
443 'name' => 'Hyve Lite',
444 ],
445 'wp-full-stripe-free' => [
446 'name' => 'WP Full Pay',
447 ],
448 'easy-mcp-ai' => [
449 'name' => 'Easy MCP AI',
450 ],
451 ];
452
453 foreach ( $products as $slug => $product ) {
454 if ( isset( $product['condition'] ) && ! $product['condition'] ) {
455 unset( $products[ $slug ] );
456 continue;
457 }
458
459 if ( $slug === 'neve' ) {
460 $theme = get_template();
461 $themes = wp_get_themes();
462
463 $products[ $slug ]['status'] = isset( $themes['neve'] ) ? 'installed' : 'not-installed';
464 $products[ $slug ]['status'] = $theme === 'neve' ? 'active' : $products[ $slug ]['status'];
465
466 $products[ $slug ]['activationLink'] = add_query_arg(
467 [
468 'stylesheet' => 'neve',
469 'action' => 'activate',
470 '_wpnonce' => wp_create_nonce( 'switch-theme_neve' ),
471 ],
472 admin_url( 'themes.php' )
473 );
474
475 continue;
476 }
477
478 $products[ $slug ]['status'] = $this->is_plugin_installed( $slug ) ? 'installed' : 'not-installed';
479 $products[ $slug ]['status'] = $this->is_plugin_active( $slug ) ? 'active' : $products[ $slug ]['status'];
480 $products[ $slug ]['activationLink'] = $this->get_plugin_activation_link( $slug );
481
482 if ( 'easy-mcp-ai' === $slug ) {
483 // The shared builder stamps optimole_reference_key on every non-Otter slug; carry Easy MCP attribution instead.
484 $products[ $slug ]['activationLink'] = add_query_arg( 'easy_mcp_reference_key', 'a-' . $this->product->get_key(), remove_query_arg( 'optimole_reference_key', $products[ $slug ]['activationLink'] ) );
485 }
486
487
488 if ( isset( $product['skip_api'] ) ) {
489 continue;
490 }
491
492 $api_data = $this->call_plugin_api( $slug );
493 if ( ! isset( $product['icon'] ) && ( isset( $api_data->icons['2x'] ) || $api_data->icons['1x'] ) ) {
494 $products[ $slug ]['icon'] = isset( $api_data->icons['2x'] ) ? $api_data->icons['2x'] : $api_data->icons['1x'];
495 }
496 if ( ! isset( $product['description'] ) && isset( $api_data->short_description ) ) {
497 $products[ $slug ]['description'] = $api_data->short_description;
498 }
499 if ( ! isset( $product['name'] ) && isset( $api_data->name ) ) {
500 $products[ $slug ]['name'] = $api_data->name;
501 }
502 }
503
504 uksort(
505 $products,
506 function ( $left_slug, $right_slug ) use ( $products ) {
507 return $this->get_product_sort_key( $left_slug, $products )
508 <=> $this->get_product_sort_key( $right_slug, $products );
509 }
510 );
511
512 return $products;
513 }
514
515 /**
516 * Build a comparable sort key tuple for a product slug.
517 *
518 * @param string $slug Product slug.
519 * @param array $products All products keyed by slug.
520 *
521 * @return array
522 */
523 private function get_product_sort_key( $slug, $products ) {
524 $status = isset( $products[ $slug ]['status'] ) ? $products[ $slug ]['status'] : 'not-installed';
525 $is_active = 'active' === $status ? 1 : 0;
526 $common_weight = isset( self::COMMON_PRODUCTS_PRIORITY[ $slug ] ) ? self::COMMON_PRODUCTS_PRIORITY[ $slug ] : self::SORT_WEIGHT_UNRANKED;
527
528 // Install status only breaks ties between unranked products.
529 $status_weight = self::SORT_WEIGHT_UNRANKED === $common_weight
530 ? ( isset( self::STATUS_PRIORITY[ $status ] ) ? self::STATUS_PRIORITY[ $status ] : self::SORT_WEIGHT_UNRANKED )
531 : 0;
532
533 // Tuple order = sort precedence: active last, featured rank, status, then slug.
534 return array( $is_active, $common_weight, $status_weight, $slug );
535 }
536
537 /**
538 * Get the page slug.
539 *
540 * @return string
541 */
542 private function get_about_page_slug() {
543 return 'ti-about-' . $this->product->get_key();
544 }
545 }
546