PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.6.0
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.6.0
3.6.0 3.5.3 3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / vendor / themegrill / themegrill-sdk / src / Product.php
everest-forms / vendor / themegrill / themegrill-sdk / src Last commit date
Common 1 month ago Modules 1 month ago Loader.php 1 month ago Product.php 1 month ago
Product.php
496 lines
1 <?php
2 /**
3 * The product model class for ThemeGrill SDK
4 *
5 * @package ThemeGrillSDK
6 * @subpackage Product
7 * @copyright Copyright (c) 2025, ThemeGrill
8 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9 * @since 1.0.0
10 */
11
12 namespace ThemeGrillSDK;
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Product model for ThemeGrill SDK.
21 */
22 class Product {
23 /**
24 * Define plugin type string.
25 */
26 const PLUGIN_TYPE = 'plugin';
27 /**
28 * Define theme type string.
29 */
30 const THEME_TYPE = 'theme';
31 /**
32 * If the product has a pro version, contains the pro slug.
33 *
34 * @var string $pro_slug Pro slug, if available.
35 */
36 public $pro_slug;
37 /**
38 * Current product slug.
39 *
40 * @var string $slug THe product slug.
41 */
42 private $slug;
43 /**
44 * Product basefile, with the proper metadata.
45 *
46 * @var string $basefile The file with headers.
47 */
48 private $basefile;
49 /**
50 * Type of the product.
51 *
52 * @var string $type The product type ( plugin | theme ).
53 */
54 private $type;
55 /**
56 * The file name.
57 *
58 * @var string $file The file name.
59 */
60 private $file;
61 /**
62 * Product name, fetched from the file headers.
63 *
64 * @var string $name The product name.
65 */
66 private $name;
67 /**
68 * Product normalized key.
69 *
70 * @var string $key The product ready key.
71 */
72 private $key;
73 /**
74 * Author URL
75 *
76 * @var string $author_url The author url.
77 */
78 private $author_url;
79 /**
80 * Product store url.
81 *
82 * @var string $store_url The store url.
83 */
84 private $store_url;
85 /**
86 * Product install timestamp.
87 *
88 * @var int $install The date of install.
89 */
90 private $install;
91 /**
92 * Product store/author name.
93 *
94 * @var string $store_name The store name.
95 */
96 private $store_name;
97 /**
98 * Does the product requires license.
99 *
100 * @var bool $requires_license Either user needs to activate it with license.
101 */
102 private $requires_license;
103 /**
104 * Is the product available on wordpress.org
105 *
106 * @var bool $wordpress_available Either is available on WordPress or not.
107 */
108 private $wordpress_available;
109 /**
110 * Current version of the product.
111 *
112 * @var string $version The product version.
113 */
114 private $version;
115 /**
116 * TG download ID used for licensing and updates.
117 * Set via file header: TG Item ID: 123
118 *
119 * @var int $item_id The TG item ID.
120 */
121 private $item_id = 0;
122 /**
123 * Holds a map of loaded products objects.
124 *
125 * @var array Array of loaded products.
126 */
127 private static $cached_products = [];
128 /**
129 * Root api endpoint.
130 */
131 const API_URL = 'https://api.themegrill.com/';
132
133 /**
134 * Themegrill_sdk_Product constructor.
135 *
136 * @param string $basefile Product basefile.
137 */
138 public function __construct( $basefile ) {
139 if ( ! empty( $basefile ) ) {
140 if ( is_file( $basefile ) ) {
141 $this->basefile = $basefile;
142 $this->setup_from_path();
143 $this->setup_from_fileheaders();
144 }
145 }
146 $install = get_option( $this->get_key() . '_install', 0 );
147 if ( 0 === $install ) {
148 $install = time();
149 /**
150 * Action to be triggered when the product is first activated.
151 *
152 * @param string $basefile The basefile of the product.
153 */
154 do_action( 'themegrill_sdk_first_activation', $basefile );
155
156 update_option( $this->get_key() . '_install', time() );
157 }
158 $this->install = $install;
159 self::$cached_products[ crc32( $basefile ) ] = $this;
160 $current_version = get_option( $this->slug . '_version', '' );
161
162 if ( $current_version !== $this->version && wp_cache_get( "{$this->slug}_version_upgrade" ) === false ) {
163 // Set the cache lock to avoid multiple calls.
164 wp_cache_set( "{$this->slug}_version_upgrade", true, HOUR_IN_SECONDS );
165 /**
166 * Action to be triggered when the product is updated.
167 *
168 * @param string $current_version The current version of the product.
169 * @param string $new_version The new version of the product.
170 * @param string $basefile The basefile of the product.
171 */
172 do_action( "themegrill_sdk_update_{$this->slug}", $current_version, $this->version, $basefile );
173
174 // Update the version of the product.
175 update_option( "{$this->slug}_version", $this->version );
176 // Delete the cache lock.
177 wp_cache_delete( "{$this->slug}_version_upgrade" );
178 }
179 }
180
181 /**
182 * Return a product.
183 *
184 * @param string $basefile Product basefile.
185 *
186 * @return Product Product Object.
187 */
188 public static function get( $basefile ) {
189 $key = crc32( $basefile );
190 if ( isset( self::$cached_products[ $key ] ) ) {
191 return self::$cached_products[ $key ];
192 }
193 self::$cached_products[ $key ] = new Product( $basefile );
194
195 return self::$cached_products[ $key ];
196 }
197
198 /**
199 * Setup props from path.
200 */
201 public function setup_from_path() {
202 $this->file = basename( $this->basefile );
203 $dir = dirname( $this->basefile );
204 $this->slug = basename( $dir );
205 $exts = explode( '.', $this->basefile );
206 $ext = $exts[ count( $exts ) - 1 ];
207 if ( 'css' === $ext ) {
208 $this->type = 'theme';
209 }
210 if ( 'php' === $ext ) {
211 $this->type = 'plugin';
212 }
213 $this->key = self::key_ready_name( $this->slug );
214 }
215
216 /**
217 * Normalize string.
218 *
219 * @param string $string the String to be normalized for cron handler.
220 *
221 * @return string $name The normalized string.
222 */
223 public static function key_ready_name( $string ) {
224 return str_replace( '-', '_', strtolower( trim( $string ) ) );
225 }
226
227 /**
228 * Setup props from fileheaders.
229 */
230 public function setup_from_fileheaders() {
231 $file_headers = array(
232 'RequiresLicense' => 'Requires License',
233 'WordPressAvailable' => 'WordPress Available',
234 'ProSlug' => 'Pro Slug',
235 'Version' => 'Version',
236 'TGItemID' => 'TG Item ID',
237 );
238 if ( 'plugin' === $this->type ) {
239 $file_headers['Name'] = 'Plugin Name';
240 $file_headers['AuthorName'] = 'Author';
241 $file_headers['AuthorURI'] = 'Author URI';
242 }
243 if ( 'theme' === $this->type ) {
244 $file_headers['Name'] = 'Theme Name';
245 $file_headers['AuthorName'] = 'Author';
246 $file_headers['AuthorURI'] = 'Author URI';
247 }
248 $file_headers = get_file_data( $this->basefile, $file_headers );
249
250 $this->name = $file_headers['Name'];
251 $this->store_name = $file_headers['AuthorName'];
252 $this->author_url = $file_headers['AuthorURI'];
253 $this->store_url = $file_headers['AuthorURI'];
254
255 $this->requires_license = ( 'yes' === $file_headers['RequiresLicense'] ) ? true : false;
256 $this->wordpress_available = ( 'yes' === $file_headers['WordPressAvailable'] ) ? true : false;
257 $this->pro_slug = ! empty( $file_headers['ProSlug'] ) ? $file_headers['Pro Slug'] : '';
258 $this->version = $file_headers['Version'];
259 $this->item_id = ! empty( $file_headers['TGItemID'] ) ? (int) $file_headers['TGItemID'] : 0;
260 }
261
262 /**
263 * Return the product key.
264 *
265 * @return string The product key.
266 */
267 public function get_key() {
268 return $this->key;
269 }
270
271 /**
272 * Check if the product is either theme or plugin.
273 *
274 * @return string Product type.
275 */
276 public function get_type() {
277 return $this->type;
278 }
279
280 /**
281 * Return if the product is used as a plugin.
282 *
283 * @return bool Is plugin?
284 */
285 public function is_plugin() {
286 return self::PLUGIN_TYPE === $this->type;
287 }
288
289 /**
290 * Return if the product is used as a theme.
291 *
292 * @return bool Is theme ?
293 */
294 public function is_theme() {
295 return self::THEME_TYPE === $this->type;
296 }
297
298 /**
299 * Returns the product slug.
300 *
301 * @return string The product slug.
302 */
303 public function get_slug() {
304 return $this->slug;
305 }
306
307 /**
308 * The magic var_dump info method.
309 *
310 * @return array Debug info.
311 */
312 public function __debugInfo() {
313 return array(
314 'name' => $this->name,
315 'slug' => $this->slug,
316 'version' => $this->version,
317 'basefile' => $this->basefile,
318 'key' => $this->key,
319 'type' => $this->type,
320 'store_name' => $this->store_name,
321 'store_url' => $this->store_url,
322 'wordpress_available' => $this->wordpress_available,
323 'requires_license' => $this->requires_license,
324 );
325 }
326
327 /**
328 * Getter for product version.
329 *
330 * @return string The product version.
331 */
332 public function get_version() {
333 return $this->version;
334 }
335
336 /**
337 * Returns the TG item ID for licensing and update checks.
338 *
339 * @return int The TG item ID, or 0 if not set.
340 */
341 public function get_item_id() {
342 return $this->item_id;
343 }
344
345 /**
346 * Returns current product license, if available.
347 *
348 * @return string Return license key, if available.
349 */
350 public function get_license() {
351
352 if ( ! $this->requires_license() ) {
353 return 'free';
354 }
355 $license_data = get_option( $this->get_key() . '_license_data', '' );
356
357 if ( empty( $license_data ) ) {
358 return get_option( $this->get_key() . '_license', '' );
359 }
360 if ( ! isset( $license_data->key ) ) {
361 return get_option( $this->get_key() . '_license', '' );
362 }
363
364 return $license_data->key;
365 }
366
367 /**
368 * Either the product requires license or not.
369 *
370 * @return bool Either requires license or not.
371 */
372 public function requires_license() {
373 return $this->requires_license;
374 }
375
376 /**
377 * If product is available on wordpress.org or not.
378 *
379 * @return bool Either is wp available or not.
380 */
381 public function is_wordpress_available() {
382 return $this->wordpress_available;
383 }
384
385 /**
386 * Return friendly name.
387 *
388 * @return string Friendly name.
389 */
390 public function get_friendly_name() {
391 $name = apply_filters( $this->get_key() . '_friendly_name', $this->get_name() );
392 return $name;
393 }
394
395 /**
396 * Return the product version cache key.
397 *
398 * @return string The product version cache key.
399 */
400 public function get_cache_key() {
401 return $this->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->get_version() ) . 'versions';
402 }
403
404 /**
405 * Getter for product name.
406 *
407 * @return string The product name.
408 */
409 public function get_name() {
410 return $this->name;
411 }
412
413 /**
414 * Returns the Store name.
415 *
416 * @return string Store name.
417 */
418 public function get_store_name() {
419 return $this->store_name;
420 }
421
422 /**
423 * Returns the store url.
424 *
425 * @return string The store url.
426 */
427 public function get_store_url() {
428 return $this->store_url;
429 }
430
431 /**
432 * Returns product basefile, which holds the metaheaders.
433 *
434 * @return string The product basefile.
435 */
436 public function get_basefile() {
437 return $this->basefile;
438 }
439
440 /**
441 * Get changelog url.
442 *
443 * @return string Changelog url.
444 */
445 public function get_changelog() {
446 return add_query_arg(
447 [
448 'name' => rawurlencode( $this->get_name() ),
449 'edd_action' => 'view_changelog',
450 'locale' => get_user_locale(),
451 ],
452 $this->get_store_url()
453 );
454 }
455
456 /**
457 * Returns product filename.
458 *
459 * @return string The product filename.
460 */
461 public function get_file() {
462 return $this->file;
463 }
464
465 /**
466 * Returns the pro slug, if available.
467 *
468 * @return string The pro slug.
469 */
470 public function get_pro_slug() {
471 return $this->pro_slug;
472 }
473
474 /**
475 * Return the install timestamp.
476 *
477 * @return int The install timestamp.
478 */
479 public function get_install_time() {
480 return $this->install;
481 }
482
483 /**
484 * Returns the URL of the product base file.
485 *
486 * @param string $path The path to the file.
487 *
488 * @return string The URL of the product base file.
489 */
490 public function get_base_url( $path = '/' ) {
491 if ( $this->type ) {
492 return plugins_url( $path, $this->basefile );
493 }
494 }
495 }
496