PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.4.1
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.4.1
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
templately / includes / Utils / Helper.php

Helper.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! 3.4.1, at includes/Utils/Helper.php

484 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Utils;
4
5 use Elementor\Plugin;
6 use Templately\Core\Importer\Utils\Utils;
7 use WP_Error;
8 use WP_REST_Response;
9 use function get_plugins;
10 use function is_plugin_active;
11
12 /**
13 * Utility Helper for Templately
14 *
15 * This class contains some helper functions for easy access.
16 *
17 * @since 1.0.0
18 */
19 class Helper extends Base {
20 /**
21 * Check if development API should be used
22 *
23 * This method maintains backward compatibility by checking both TEMPLATELY_DEV_API
24 * and falling back to TEMPLATELY_DEV if needed. This fallback logic should NOT be
25 * removed as it ensures existing setups continue to work.
26 *
27 * @return bool True if development API should be used
28 */
29 public static function is_dev_api(){
30 // Primary check: TEMPLATELY_DEV_API constant
31 if ( defined( 'TEMPLATELY_DEV_API' ) ) {
32 return constant( 'TEMPLATELY_DEV_API' );
33 }
34
35 // Fallback: Legacy TEMPLATELY_DEV constant for backward compatibility
36 return defined( 'TEMPLATELY_DEV' ) && constant( 'TEMPLATELY_DEV' );
37 }
38
39 /**
40 * Get installed WordPress Plugin List
41 * @return array
42 */
43 public static function get_plugins() {
44 if (! function_exists('get_plugins')) {
45 require_once ABSPATH . 'wp-admin/includes/plugin.php';
46 }
47 return get_plugins();
48 }
49 public static function is_plugins_installed($plugin_file) {
50 $_plugins = self::get_plugins();
51 $is_installed = isset($_plugins[$plugin_file]);
52 return $is_installed;
53 }
54
55 /**
56 * Get installed WordPress Plugin List
57 * @return boolean
58 */
59 public static function is_plugin_active($plugin) {
60 if (! function_exists('is_plugin_active')) {
61 require_once ABSPATH . 'wp-admin/includes/plugin.php';
62 }
63 return is_plugin_active($plugin);
64 }
65
66 /**
67 * Collect IP from request.
68 *
69 * @return string
70 */
71 public static function get_ip() {
72 $ip = '127.0.0.1'; // Local IP
73 if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
74 $ip = $_SERVER['HTTP_CLIENT_IP'];
75 } elseif (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
76 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
77 } else {
78 $ip = ! empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
79 }
80
81 return sanitize_text_field($ip);
82 }
83
84 /**
85 * Get views for front-end display
86 *
87 * @param string $name it will be file name only from the view's folder.
88 * @param array $data
89 * @return void
90 */
91 public static function views($name, $data = []) {
92 extract($data);
93 $helper = self::class;
94 $file = TEMPLATELY_PATH . 'views/' . $name . '.php';
95
96 if (is_readable($file)) {
97 include_once $file;
98 }
99 }
100
101 /**
102 * Get API URL for Templately endpoints
103 *
104 * @param string $endpoint API endpoint path (e.g., 'v2/import/pack/123')
105 * @return string Complete API URL
106 */
107 public static function get_api_url($endpoint): string {
108 $base_url = self::is_dev_api() ? 'https://app.templately.dev' : 'https://app.templately.com';
109 return "{$base_url}/api/{$endpoint}";
110 }
111
112 /**
113 * Make a unified API request to Templately API
114 *
115 * @param string $method HTTP method (GET or POST)
116 * @param string $api_url Complete API URL
117 * @param array $body Request body data (for POST requests)
118 * @param array $extra_headers Additional headers beyond the standard ones
119 * @param int $timeout Request timeout in seconds (default: 30)
120 * @return array|WP_Error Response array or WP_Error on failure
121 */
122 private static function make_api_request($method, $api_url, $body = [], $extra_headers = [], $timeout = 30) {
123 $api_key = Options::get_instance()->get('api_key');
124
125 $headers = [
126 'Authorization' => 'Bearer ' . $api_key,
127 'x-templately-ip' => self::get_ip(),
128 'x-templately-url' => home_url('/'),
129 'x-templately-version' => defined( 'TEMPLATELY_VERSION' ) ? constant( 'TEMPLATELY_VERSION' ) : '1.0.0',
130 ];
131
132 // Add Content-Type for POST requests
133 if (strtoupper($method) === 'POST') {
134 $headers['Content-Type'] = 'application/json';
135 }
136
137 // Merge additional headers
138 $headers = array_merge($headers, $extra_headers);
139
140 $args = [
141 'timeout' => $timeout,
142 'headers' => $headers,
143 ];
144
145 // Apply filter to allow network admin or other functionality to modify request args
146 $args = apply_filters( 'templately_api_request_params', $args, $method, $api_url );
147
148 // Add body for POST requests
149 if (strtoupper($method) === 'POST') {
150 $args['body'] = is_array($body) ? json_encode($body) : $body;
151 }
152
153 // Make the appropriate request
154 if (strtoupper($method) === 'POST') {
155 return wp_remote_post($api_url, $args);
156 } else {
157 return wp_remote_get($api_url, $args);
158 }
159 }
160
161 /**
162 * Make a GET request to Templately API
163 *
164 * @param string $endpoint API endpoint path (e.g., 'v2/import/pack/123')
165 * @param array $query_params Query parameters as key-value pairs
166 * @param array $extra_headers Additional headers beyond the standard ones
167 * @param int $timeout Request timeout in seconds (default: 30)
168 * @return array|WP_Error Response array or WP_Error on failure
169 */
170 public static function make_api_get_request($endpoint, $query_params = [], $extra_headers = [], $timeout = 30) {
171 $api_url = self::get_api_url($endpoint);
172
173 // Add query parameters if provided
174 if (!empty($query_params)) {
175 $api_url = add_query_arg($query_params, $api_url);
176 }
177
178 return self::make_api_request('GET', $api_url, [], $extra_headers, $timeout);
179 }
180
181 /**
182 * Make a POST request to Templately API
183 *
184 * @param string $endpoint API endpoint path (e.g., 'v2/feedback/store')
185 * @param array $body Request body data
186 * @param array $extra_headers Additional headers beyond the standard ones
187 * @param int $timeout Request timeout in seconds (default: 30)
188 * @return array|WP_Error Response array or WP_Error on failure
189 */
190 public static function make_api_post_request($endpoint, $body = [], $extra_headers = [], $timeout = 30) {
191 $api_url = self::get_api_url($endpoint);
192 return self::make_api_request('POST', $api_url, $body, $extra_headers, $timeout);
193 }
194
195 /**
196 * Sanitize Helper
197 *
198 * @param mixed $value
199 * @param string $type
200 *
201 * @return bool|string
202 */
203 public static function sanitize($value, $type = 'text') {
204 switch ($type) {
205 case 'boolean':
206 $sanitized_value = rest_sanitize_boolean($value);
207 break;
208 default:
209 $sanitized_value = sanitize_text_field($value);
210 break;
211 }
212
213 return $sanitized_value;
214 }
215
216 /**
217 * API Error Formatter
218 *
219 * @param int $error_code
220 * @param mixed $error_message
221 * @param string $endpoint
222 * @param integer $status
223 * @param array $additional_data
224 * @return WP_Error
225 */
226 public static function error($error_code, $error_message, $endpoint = '', $status = 500, $additional_data = []) {
227 $additional_data['status'] = $status;
228 if (! empty($endpoint)) {
229 $additional_data['endpoint'] = $endpoint;
230 }
231 // Add browser padding to avoid browsers not serving small JSON responses
232 $padding_length = 512;
233 $additional_data['browser_padding'] = str_repeat(' ', $padding_length);
234
235 return new WP_Error($error_code, $error_message, $additional_data);
236 }
237
238 /**
239 * API Response Formatter
240 *
241 * @param mixed $data
242 * @return WP_REST_Response
243 */
244 public static function success($data) {
245 return new WP_REST_Response($data, 200);
246 }
247
248 /**
249 * Normalize Favourites Data
250 *
251 * @param array $favourites
252 * @param array $_favourites
253 * @param boolean $undo
254 *
255 * @return array
256 */
257 public function normalizeFavourites($favourites, $_favourites = [], $undo = false) {
258 if ($undo) {
259 $_favourites[$favourites['type']] = array_values(array_filter($_favourites[$favourites['type']], function ($item) use ($favourites) {
260 return $item != $favourites['id'];
261 }));
262 return $_favourites;
263 }
264
265 array_map(function ($item) use (&$_favourites) {
266 if (! is_null($item)) {
267 $item = (array) $item;
268 if (isset($_favourites[$item['type']])) {
269 $_favourites[$item['type']][] = $item['id'];
270 } else {
271 $_favourites[$item['type']] = [$item['id']];
272 }
273 }
274 return $_favourites;
275 }, $favourites);
276
277 return $_favourites;
278 }
279
280 public function normalizeReviews($favourites, $_favourites = [], $undo = false) {
281 array_map(function ($item) use (&$_favourites) {
282 if (! is_null($item)) {
283 $item = (array) $item;
284 if (!isset($_favourites[$item['type']])) {
285 $_favourites[$item['type']] = [];
286 }
287 $_favourites[$item['type']][$item['type_id']] = $item['rating'];
288 }
289 return $_favourites;
290 }, $favourites);
291
292 return $_favourites;
293 }
294
295 /**
296 * Trigger Error
297 *
298 * @param object $triggered_by
299 * @return void
300 */
301 public static function trigger_error($triggered_by, $method = 'get_instance') {
302 $class = get_class($triggered_by);
303 $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
304 $file = $trace[0]['file'];
305 $line = $trace[0]['line'];
306 trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
307 }
308
309 /**
310 * Printing Error Logs in debug.log file.
311 *
312 * @param mixed $log
313 * @return void
314 */
315 public static function log($log) {
316 if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
317 if (is_array($log) || is_object($log)) {
318 error_log(print_r($log, true));
319 } else {
320 error_log($log ?: '');
321 }
322 }
323 }
324
325 public static function should_flush() {
326 if (isset($_REQUEST['is_lightspeed']) && $_REQUEST['is_lightspeed'] === 'true') {
327 return false;
328 }
329 return (!defined('TEMPLATELY_IGNORE_FLUSH_ALL') || !TEMPLATELY_IGNORE_FLUSH_ALL) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') === false;
330 }
331
332 public static function get_block_by_name($blocks, $search) {
333 $queue = $blocks;
334
335 while (!empty($queue)) {
336 $current_block = array_shift($queue);
337
338 if ($search === $current_block['blockName']) {
339 return $current_block;
340 }
341
342 if (isset($current_block['innerBlocks'])) {
343 // Add nested blocks to the end of the queue for processing
344 $queue = array_merge($queue, $current_block['innerBlocks']);
345 }
346 }
347
348 return false;
349 }
350
351 /**
352 * Only checks if user can install/activate plugins
353 *
354 * @param [type] $cap
355 * @param [type] ...$args
356 * @return void
357 */
358 public static function current_user_can($cap, ...$args) {
359 $user = wp_get_current_user();
360
361 // Multisite super admin has all caps by definition, Unless specifically denied.
362 if (is_multisite() && is_super_admin($user->ID)) {
363 return true;
364 }
365
366 $caps = map_meta_cap($cap, $user->ID, ...$args);
367
368 switch ($cap) {
369 case 'install_plugins':
370 case 'upload_plugins':
371 $caps = ['install_plugins'];
372 break;
373 case 'install_themes':
374 case 'upload_themes':
375 $caps = ['install_themes'];
376 break;
377 case 'activate_plugins':
378 case 'deactivate_plugins':
379 case 'activate_plugin':
380 case 'deactivate_plugin':
381 $caps = ['activate_plugins'];
382 break;
383 default:
384 break;
385 }
386
387 // Maintain BC for the argument passed to the "user_has_cap" filter.
388 $args = array_merge(array($cap, $user->ID), $args);
389
390 /**
391 * See WP_User::has_cap() for description.
392 */
393 $capabilities = apply_filters('user_has_cap', $user->allcaps, $caps, $args, $user);
394
395 // Everyone is allowed to exist.
396 $capabilities['exist'] = true;
397
398 // Nobody is allowed to do things they are not allowed to do.
399 unset($capabilities['do_not_allow']);
400
401 // Must have ALL requested caps.
402 foreach ((array) $caps as $cap) {
403 if (empty($capabilities[$cap])) {
404 return false;
405 }
406 }
407
408 return true;
409 }
410
411 /**
412 * Calculates the elapsed time and checks if it is close to the maximum execution time.
413 * Returns true if the script should exit to avoid exceeding the limit.
414 *
415 * @return bool True if the script should exit, false otherwise.
416 */
417 public static function fsi_should_exit() {
418 if (defined('TEMPLATELY_START_TIME') && ini_get('max_execution_time')) {
419 $max_time = ini_get('max_execution_time');
420 $elapsed = microtime(true) - TEMPLATELY_START_TIME;
421 $delay = max(5, $max_time * 20 / 100);
422
423 // Check if elapsed time is close to max execution time
424 if ($max_time - $elapsed <= $delay) {
425 return ['max_time' => $max_time, 'elapsed' => $elapsed, 'delay' => $delay];
426 }
427 }
428 return false;
429 }
430
431 /**
432 * Enable Elementor Container
433 * This function will enable the Elementor Container feature.
434 * Without this feature, some of the templates may not work properly.
435 *
436 * @return boolean
437 */
438 public static function enable_elementor_container() {
439 if (class_exists('Elementor\Plugin')) {
440 $control_name = Plugin::instance()->experiments->get_feature_option_key('container');
441 if (get_option($control_name) === 'inactive') {
442 update_option($control_name, 'active');
443 return true;
444 }
445 }
446 return false;
447 }
448
449 /**
450 * Undocumented function
451 *
452 * @param [type] $args
453 * @param [type] $defaults
454 * @return array
455 */
456 public static function recursive_wp_parse_args($args, $defaults) {
457 $args = (array) $args;
458 $defaults = (array) $defaults;
459 $r = $defaults;
460 foreach ($args as $key => $value) {
461 if (is_array($value) && isset($r[$key])) {
462 // also handle numeric array. if both $value and $r[ $key ] are numeric array. wp_is_numeric_array()
463 if (wp_is_numeric_array($value) && wp_is_numeric_array($r[$key])) {
464 foreach ($value as $k => $v) {
465 if (!in_array($v, $r[$key])) {
466 if (!isset($r[$key][$k])) {
467 $r[$key][$k] = $v;
468 } else {
469 $r[$key][] = $v;
470 }
471 }
472 }
473 } else {
474 $r[$key] = self::recursive_wp_parse_args($value, $r[$key]);
475 }
476 } else {
477 $r[$key] = $value;
478 }
479 }
480 return $r;
481 }
482
483 }
484