PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 2.2.13
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v2.2.13
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
← All changes | includes/Utils/Helper.php +75 -599 3.6.22.2.13 View file →
@@ -1,15 +1,11 @@
1 1 <?php
2 -
3 2 namespace Templately\Utils;
4 3
5 -use Elementor\Plugin;
6 -use Templately\Core\Importer\Utils\Utils;
7 4 use WP_Error;
8 5 use WP_REST_Response;
9 6 use function get_plugins;
10 7 use function is_plugin_active;
11 -
12 8 /**
13 9 * Utility Helper for Templately
14 10 *
15 11 * This class contains some helper functions for easy access.
@@ -16,46 +12,31 @@
16 12 *
17 13 * @since 1.0.0
18 14 */
19 15 class Helper extends Base {
20 - /**
21 - * Check if development API should be used
22 - *
23 - * @return bool True if development API should be used
24 - */
25 - public static function is_dev_api(){
26 - // Only check TEMPLATELY_DEV_API constant - no fallback mechanisms
27 - return defined( 'TEMPLATELY_DEV_API' ) && constant( 'TEMPLATELY_DEV_API' );
28 - }
16 + /**
17 + * Get installed WordPress Plugin List
18 + * @return array
19 + */
20 + public static function get_plugins(){
21 + if( ! function_exists( 'get_plugins' ) ) {
22 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
23 + }
24 + return get_plugins();
25 + }
29 26
30 - /**
31 - * Get installed WordPress Plugin List
32 - * @return array
33 - */
34 - public static function get_plugins() {
35 - if (! function_exists('get_plugins')) {
36 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
37 - }
38 - return get_plugins();
39 - }
40 - public static function is_plugins_installed($plugin_file) {
41 - $_plugins = self::get_plugins();
42 - $is_installed = isset($_plugins[$plugin_file]);
43 - return $is_installed;
44 - }
27 + /**
28 + * Get installed WordPress Plugin List
29 + * @return boolean
30 + */
31 + public static function is_plugin_active( $plugin ){
32 + if( ! function_exists( 'is_plugin_active' ) ) {
33 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
34 + }
35 + return is_plugin_active( $plugin );
36 + }
45 37
46 - /**
47 - * Get installed WordPress Plugin List
48 - * @return boolean
49 - */
50 - public static function is_plugin_active($plugin) {
51 - if (! function_exists('is_plugin_active')) {
52 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
53 - }
54 - return is_plugin_active($plugin);
55 - }
56 -
57 - /**
38 + /**
58 39 * Collect IP from request.
59 40 *
60 41 * @return string
61 42 */
@@ -60,156 +41,37 @@
60 41 * @return string
61 42 */
62 43 public static function get_ip() {
63 44 $ip = '127.0.0.1'; // Local IP
64 - if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
45 + if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
65 46 $ip = $_SERVER['HTTP_CLIENT_IP'];
66 - } elseif (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
47 + } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
67 48 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
68 49 } else {
69 - $ip = ! empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
50 + $ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : $ip;
70 51 }
71 52
72 - return sanitize_text_field($ip);
53 + return sanitize_text_field( $ip );
73 54 }
74 55
75 - /**
76 - * Get views for front-end display
77 - *
78 - * @param string $name it will be file name only from the view's folder.
79 - * @param array $data
80 - * @return void
81 - */
82 - public static function views($name, $data = []) {
83 - extract($data);
84 - $helper = self::class;
85 - $file = TEMPLATELY_PATH . 'views/' . $name . '.php';
56 + /**
57 + * Get views for front-end display
58 + *
59 + * @param string $name it will be file name only from the view's folder.
60 + * @param array $data
61 + * @return void
62 + */
63 + public static function views( $name, $data = [] ){
64 + extract( $data );
65 + $helper = self::class;
66 + $file = TEMPLATELY_PATH . 'views/' . $name . '.php';
86 67
87 - if (is_readable($file)) {
88 - include_once $file;
89 - }
90 - }
68 + if( is_readable( $file ) ) {
69 + include_once $file;
70 + }
71 + }
91 72
92 73 /**
93 - * Get API URL for Templately endpoints
94 - *
95 - * @param string $endpoint API endpoint path (e.g., 'v2/import/pack/123')
96 - * @return string Complete API URL
97 - */
98 - public static function get_api_url($endpoint): string {
99 - $base_url = self::is_dev_api() ? 'https://app.templately.dev' : 'https://app.templately.com';
100 -
101 - /**
102 - * Filter the base URL for development API
103 - *
104 - * @since 3.5.0
105 - * @param string $base_url The default base URL
106 - */
107 - $base_url = apply_filters('templately_dev_api_base_url', $base_url);
108 -
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 - // Resolve requested platform: $_REQUEST wins (frontend-supplied), then caller's extra_headers, then default.
138 - if ( isset( $_REQUEST['requested_platform'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
139 - $extra_headers['x-templately-requested-platform'] = sanitize_text_field( wp_unslash( $_REQUEST['requested_platform'] ) );
140 - } elseif ( ! isset( $extra_headers['x-templately-requested-platform'] ) ) {
141 - $extra_headers['x-templately-requested-platform'] = 'templately';
142 - }
143 -
144 - // Merge additional headers
145 - $headers = array_merge($headers, $extra_headers);
146 -
147 - $args = [
148 - 'timeout' => $timeout,
149 - 'headers' => $headers,
150 - ];
151 -
152 - // Apply filter to allow network admin or other functionality to modify request args
153 - $args = apply_filters( 'templately_api_request_params', $args, $method, $api_url );
154 -
155 - // Add body for POST requests
156 - if (strtoupper($method) === 'POST') {
157 - $args['body'] = is_array($body) ? json_encode($body) : $body;
158 - }
159 -
160 - // Make the appropriate request
161 - if (strtoupper($method) === 'POST') {
162 - $response = wp_remote_post($api_url, $args);
163 - } else {
164 - $response = wp_remote_get($api_url, $args);
165 - }
166 -
167 - // Check for verification header in the response
168 - self::check_verification_header($response);
169 -
170 -
171 - // Check for site disconnection in response body
172 - self::check_site_disconnection($response);
173 -
174 - return $response;
175 - }
176 -
177 - /**
178 - * Make a GET request to Templately API
179 - *
180 - * @param string $endpoint API endpoint path (e.g., 'v2/import/pack/123')
181 - * @param array $query_params Query parameters as key-value pairs
182 - * @param array $extra_headers Additional headers beyond the standard ones
183 - * @param int $timeout Request timeout in seconds (default: 30)
184 - * @return array|WP_Error Response array or WP_Error on failure
185 - */
186 - public static function make_api_get_request($endpoint, $query_params = [], $extra_headers = [], $timeout = 30) {
187 - $api_url = self::get_api_url($endpoint);
188 -
189 - // Add query parameters if provided
190 - if (!empty($query_params)) {
191 - $api_url = add_query_arg($query_params, $api_url);
192 - }
193 -
194 - return self::make_api_request('GET', $api_url, [], $extra_headers, $timeout);
195 - }
196 -
197 - /**
198 - * Make a POST request to Templately API
199 - *
200 - * @param string $endpoint API endpoint path (e.g., 'v2/feedback/store')
201 - * @param array $body Request body data
202 - * @param array $extra_headers Additional headers beyond the standard ones
203 - * @param int $timeout Request timeout in seconds (default: 30)
204 - * @return array|WP_Error Response array or WP_Error on failure
205 - */
206 - public static function make_api_post_request($endpoint, $body = [], $extra_headers = [], $timeout = 30) {
207 - $api_url = self::get_api_url($endpoint);
208 - return self::make_api_request('POST', $api_url, $body, $extra_headers, $timeout);
209 - }
210 -
211 - /**
212 74 * Sanitize Helper
213 75 *
214 76 * @param mixed $value
215 77 * @param string $type
@@ -215,15 +77,15 @@
215 77 * @param string $type
216 78 *
217 79 * @return bool|string
218 80 */
219 - public static function sanitize($value, $type = 'text') {
220 - switch ($type) {
81 + public static function sanitize( $value, $type = 'text' ){
82 + switch ( $type ) {
221 83 case 'boolean':
222 - $sanitized_value = rest_sanitize_boolean($value);
84 + $sanitized_value = rest_sanitize_boolean( $value );
223 85 break;
224 86 default:
225 - $sanitized_value = sanitize_text_field($value);
87 + $sanitized_value = sanitize_text_field( $value );
226 88 break;
227 89 }
228 90
229 91 return $sanitized_value;
@@ -229,194 +91,8 @@
229 91 return $sanitized_value;
230 92 }
231 93
232 94 /**
233 - * Escape a string for safe embedding inside a GraphQL or JSON string literal.
234 - *
235 - * GraphQL string escaping rules are identical to JSON string escaping (per the
236 - * GraphQL spec), so wp_json_encode() is the authoritative escaper. We strip the
237 - * outer quotes it adds and return only the escaped inner content, ready to be
238 - * wrapped in your own quote pair.
239 - *
240 - * Handles pre-encoded JSON: when the caller has already run json_encode() +
241 - * wp_slash() on a value (e.g. categories, dependencies in Items.php), the
242 - * quotes are already escaped as \" and the string is ready to embed. Calling
243 - * wp_json_encode() again would double-escape those backslashes. We detect this
244 - * case by checking whether wp_unslash() produces valid JSON, and if so, return
245 - * the value directly without further encoding.
246 - *
247 - * @param string $value Raw string or wp_slash(json_encode()) output.
248 - * @return string Escaped string, safe to place between double quotes in GraphQL/JSON.
249 - */
250 - public static function esc_json_string( $value ) {
251 - $value = (string) $value;
252 -
253 - // If wp_slash() was applied to a JSON string upstream, the quotes are
254 - // already escaped (e.g. {\"key\":\"val\"}). Detect this by unslashing and
255 - // checking for valid JSON — if it matches, the value is already suitable
256 - // for embedding in a string literal; return it as-is to avoid doubling backslashes.
257 - $unslashed = wp_unslash( $value );
258 - if ( $unslashed !== $value ) {
259 - $decoded = json_decode( $unslashed, true );
260 - if ( json_last_error() === JSON_ERROR_NONE && null !== $decoded ) {
261 - return $value;
262 - }
263 - }
264 -
265 - $encoded = wp_json_encode( $value );
266 - // wp_json_encode wraps the value in "...", strip those outer quotes.
267 - return substr( $encoded, 1, -1 );
268 - }
269 -
270 - /**
271 - * Check for X-Templately-Verified header and update user verification status
272 - *
273 - * @param array|WP_Error $response The HTTP response array from wp_remote_get/wp_remote_post
274 - * @return void
275 - */
276 - public static function check_verification_header($response) {
277 - // Only process if response is not a WP_Error and contains headers
278 - if (is_wp_error($response)) {
279 - return;
280 - }
281 -
282 - // Retrieve the X-Templately-Verified header
283 - $verification_header = wp_remote_retrieve_header($response, 'X-Templately-Verified');
284 -
285 - // Check if header exists and has a truthy value
286 - if (!empty($verification_header) && filter_var($verification_header, FILTER_VALIDATE_BOOLEAN)) {
287 - try {
288 - // Get current user data
289 - $options = Options::get_instance();
290 - $user = $options->get('user');
291 -
292 - // Only update if user data exists and is not already verified
293 - if (!empty($user) && is_array($user) && empty($user['is_verified'])) {
294 - // Set verification flag
295 - $user['is_verified'] = true;
296 -
297 - // Save updated user data
298 - $options->set('user', $user);
299 -
300 - }
301 -
302 - if (!empty($user['is_verified'])){
303 - if(!headers_sent()){
304 - header( 'X-Templately-Verified: true' );
305 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
306 - self::log('User verification status already updated via X-Templately-Verified header');
307 - }
308 - }
309 -
310 - return true;
311 - }
312 - } catch (\Exception $e) {
313 - // Log error if debug logging is enabled
314 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
315 - self::log('Error updating user verification status: ' . $e->getMessage());
316 - }
317 - }
318 - }
319 -
320 - return false;
321 - }
322 -
323 - /**
324 - * Check for site disconnection status in API response body
325 - *
326 - * Detects SiteNotConnected errors and updates user disconnection status.
327 - * Sends X-Templately-Disconnected header for frontend detection.
328 - *
329 - *
330 - * @param array|WP_Error|mixed $response The response object or body array
331 - * @return bool True if site is disconnected, false otherwise
332 - */
333 - public static function check_site_disconnection($response) {
334 - if (is_wp_error($response)) {
335 - return false;
336 - }
337 -
338 - $response_body = $response;
339 -
340 - // If it's a raw WP response array with body, decode it
341 - if (is_array($response) && isset($response['body']) && is_string($response['body'])) {
342 - $response_body = json_decode(wp_remote_retrieve_body($response), true);
343 - }
344 -
345 - // Check if response body indicates site disconnection
346 - if (!is_array($response_body)) {
347 - return false;
348 - }
349 -
350 - $status = $response_body['status'] ?? null;
351 - $status_text = $response_body['statusText'] ?? null;
352 -
353 - // Check for SiteNotConnected error
354 - if ($status === 'error' && $status_text === 'SiteNotConnected') {
355 - try {
356 - // Get current user data
357 - $options = Options::get_instance();
358 - $user = $options->get('user');
359 -
360 - // Only update if user data exists
361 - if (!empty($user) && is_array($user)) {
362 - // Set disconnection flag
363 - $user['is_disconnected'] = true;
364 -
365 - // Save updated user data
366 - $options->set('user', $user);
367 -
368 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
369 - self::log('Site disconnection detected: SiteNotConnected status');
370 - }
371 - }
372 -
373 - // Send header for frontend detection
374 - if (!headers_sent()) {
375 - header('X-Templately-Disconnected: true');
376 - }
377 -
378 - return true;
379 - } catch (\Exception $e) {
380 - // Log error if debug logging is enabled
381 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
382 - self::log('Error updating site disconnection status: ' . $e->getMessage());
383 - }
384 - }
385 - }
386 -
387 - return false;
388 - }
389 -
390 - /**
391 - * Clear site disconnection status
392 - *
393 - * Called after successful site migration to reset the disconnection flag.
394 - *
395 - * @return void
396 - */
397 - public static function clear_site_disconnection() {
398 - try {
399 - $options = Options::get_instance();
400 - $user = $options->get('user');
401 -
402 - if (!empty($user) && is_array($user)) {
403 - $user['site_url'] = base64_encode( home_url('/') );
404 - $user['is_disconnected'] = false;
405 - $options->set('user', $user);
406 -
407 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
408 - self::log('Site disconnection status cleared and URL updated.');
409 - }
410 - }
411 - } catch (\Exception $e) {
412 - if (defined('TEMPLATELY_DEBUG_LOG') && constant('TEMPLATELY_DEBUG_LOG')) {
413 - self::log('Error clearing site disconnection status: ' . $e->getMessage());
414 - }
415 - }
416 - }
417 -
418 - /**
419 95 * API Error Formatter
420 96 *
421 97 * @param int $error_code
422 98 * @param mixed $error_message
@@ -424,18 +100,15 @@
424 100 * @param integer $status
425 101 * @param array $additional_data
426 102 * @return WP_Error
427 103 */
428 - public static function error($error_code, $error_message, $endpoint = '', $status = 500, $additional_data = []) {
104 + public static function error( $error_code, $error_message, $endpoint = '', $status = 500, $additional_data = [] ) {
429 105 $additional_data['status'] = $status;
430 - if (! empty($endpoint)) {
106 + if ( ! empty( $endpoint ) ) {
431 107 $additional_data['endpoint'] = $endpoint;
432 108 }
433 - // Add browser padding to avoid browsers not serving small JSON responses
434 - $padding_length = 512;
435 - $additional_data['browser_padding'] = str_repeat(' ', $padding_length);
436 109
437 - return new WP_Error($error_code, $error_message, $additional_data);
110 + return new WP_Error( $error_code, $error_message, $additional_data );
438 111 }
439 112
440 113 /**
441 114 * API Response Formatter
@@ -442,10 +115,10 @@
442 115 *
443 116 * @param mixed $data
444 117 * @return WP_REST_Response
445 118 */
446 - public static function success($data) {
447 - return new WP_REST_Response($data, 200);
119 + public static function success( $data ) {
120 + return new WP_REST_Response( $data, 200 );
448 121 }
449 122
450 123 /**
451 124 * Normalize Favourites Data
@@ -455,42 +128,42 @@
455 128 * @param boolean $undo
456 129 *
457 130 * @return array
458 131 */
459 - public function normalizeFavourites($favourites, $_favourites = [], $undo = false) {
460 - if ($undo) {
461 - $_favourites[$favourites['type']] = array_values(array_filter($_favourites[$favourites['type']], function ($item) use ($favourites) {
132 + public function normalizeFavourites( $favourites, $_favourites = [], $undo = false ){
133 + if( $undo ) {
134 + $_favourites[ $favourites['type'] ] = array_values(array_filter( $_favourites[ $favourites['type'] ], function( $item ) use( $favourites ) {
462 135 return $item != $favourites['id'];
463 - }));
136 + } ));
464 137 return $_favourites;
465 138 }
466 139
467 - array_map(function ($item) use (&$_favourites) {
468 - if (! is_null($item)) {
140 + array_map( function( $item ) use ( &$_favourites) {
141 + if( ! is_null( $item ) ) {
469 142 $item = (array) $item;
470 - if (isset($_favourites[$item['type']])) {
471 - $_favourites[$item['type']][] = $item['id'];
143 + if ( isset( $_favourites[ $item['type'] ] ) ){
144 + $_favourites[ $item['type'] ][] = $item['id'];
472 145 } else {
473 - $_favourites[$item['type']] = [$item['id']];
146 + $_favourites[ $item['type'] ] = [ $item['id'] ];
474 147 }
475 148 }
476 149 return $_favourites;
477 - }, $favourites);
150 + }, $favourites );
478 151
479 152 return $_favourites;
480 153 }
481 154
482 - public function normalizeReviews($favourites, $_favourites = [], $undo = false) {
483 - array_map(function ($item) use (&$_favourites) {
484 - if (! is_null($item)) {
155 + public function normalizeReviews( $favourites, $_favourites = [], $undo = false ){
156 + array_map( function( $item ) use ( &$_favourites) {
157 + if( ! is_null( $item ) ) {
485 158 $item = (array) $item;
486 - if (!isset($_favourites[$item['type']])) {
487 - $_favourites[$item['type']] = [];
159 + if ( !isset( $_favourites[ $item['type'] ] ) ){
160 + $_favourites[ $item['type'] ] = [];
488 161 }
489 - $_favourites[$item['type']][$item['type_id']] = $item['rating'];
162 + $_favourites[ $item['type'] ][$item['type_id']] = $item['rating'];
490 163 }
491 164 return $_favourites;
492 - }, $favourites);
165 + }, $favourites );
493 166
494 167 return $_favourites;
495 168 }
496 169
@@ -499,10 +172,10 @@
499 172 *
500 173 * @param object $triggered_by
501 174 * @return void
502 175 */
503 - public static function trigger_error($triggered_by, $method = 'get_instance') {
504 - $class = get_class($triggered_by);
176 + public static function trigger_error( $triggered_by, $method = 'get_instance' ){
177 + $class = get_class( $triggered_by );
505 178 $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
506 179 $file = $trace[0]['file'];
507 180 $line = $trace[0]['line'];
508 181 trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
@@ -510,214 +183,17 @@
510 183
511 184 /**
512 185 * Printing Error Logs in debug.log file.
513 186 *
514 - * @param mixed $log The data to log
515 - * @param string $context Optional context for categorizing log entries
516 - * @param string $level Optional log level (debug, info, warning, error)
187 + * @param mixed $log
517 188 * @return void
518 189 */
519 - public static function log($log, $context = '', $level = 'info') {
520 - // Allow complete override of logging behavior
521 - $override_result = apply_filters('templately_log_override', null, $log, $context, $level);
522 - if ($override_result !== null) {
523 - return;
524 - }
525 -
526 - // Only log if WP_DEBUG_LOG is enabled
527 - if (!defined('WP_DEBUG_LOG') || !WP_DEBUG_LOG) {
528 - return;
529 - }
530 -
531 - // Format the log message
532 - $formatted_message = self::format_log_message($log, $context, $level);
533 -
534 - // Write to error log
535 - error_log($formatted_message);
536 - }
537 -
538 - /**
539 - * Format log message with context and level
540 - *
541 - * @param mixed $log The data to log
542 - * @param string $context Context for categorizing log entries
543 - * @param string $level Log level
544 - * @return string Formatted log message
545 - */
546 - private static function format_log_message($log, $context = '', $level = 'info') {
547 - // Convert arrays and objects to readable format
548 - if (is_array($log) || is_object($log)) {
549 - $log_content = print_r($log, true);
550 - } else {
551 - $log_content = (string) ($log ?: '');
552 - }
553 -
554 - // Build the formatted message
555 - $timestamp = current_time('Y-m-d H:i:s');
556 - $level_upper = strtoupper($level);
557 -
558 - if (!empty($context)) {
559 - return "[{$timestamp}] [{$level_upper}] [{$context}] {$log_content}";
560 - } else {
561 - return "[{$timestamp}] [{$level_upper}] {$log_content}";
562 - }
563 - }
564 -
565 - public static function should_flush() {
566 - if (isset($_REQUEST['is_lightspeed']) && $_REQUEST['is_lightspeed'] === 'true') {
567 - return false;
568 - }
569 - return (!defined('TEMPLATELY_IGNORE_FLUSH_ALL') || !TEMPLATELY_IGNORE_FLUSH_ALL) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') === false;
570 - }
571 -
572 - public static function get_block_by_name($blocks, $search) {
573 - $queue = $blocks;
574 -
575 - while (!empty($queue)) {
576 - $current_block = array_shift($queue);
577 -
578 - if ($search === $current_block['blockName']) {
579 - return $current_block;
580 - }
581 -
582 - if (isset($current_block['innerBlocks'])) {
583 - // Add nested blocks to the end of the queue for processing
584 - $queue = array_merge($queue, $current_block['innerBlocks']);
585 - }
586 - }
587 -
588 - return false;
589 - }
590 -
591 - /**
592 - * Only checks if user can install/activate plugins
593 - *
594 - * @param [type] $cap
595 - * @param [type] ...$args
596 - * @return void
597 - */
598 - public static function current_user_can($cap, ...$args) {
599 - $user = wp_get_current_user();
600 -
601 - // Multisite super admin has all caps by definition, Unless specifically denied.
602 - if (is_multisite() && is_super_admin($user->ID)) {
603 - return true;
604 - }
605 -
606 - $caps = map_meta_cap($cap, $user->ID, ...$args);
607 -
608 - switch ($cap) {
609 - case 'install_plugins':
610 - case 'upload_plugins':
611 - $caps = ['install_plugins'];
612 - break;
613 - case 'install_themes':
614 - case 'upload_themes':
615 - $caps = ['install_themes'];
616 - break;
617 - case 'activate_plugins':
618 - case 'deactivate_plugins':
619 - case 'activate_plugin':
620 - case 'deactivate_plugin':
621 - $caps = ['activate_plugins'];
622 - break;
623 - default:
624 - break;
625 - }
626 -
627 - // Maintain BC for the argument passed to the "user_has_cap" filter.
628 - $args = array_merge(array($cap, $user->ID), $args);
629 -
630 - /**
631 - * See WP_User::has_cap() for description.
632 - */
633 - $capabilities = apply_filters('user_has_cap', $user->allcaps, $caps, $args, $user);
634 -
635 - // Everyone is allowed to exist.
636 - $capabilities['exist'] = true;
637 -
638 - // Nobody is allowed to do things they are not allowed to do.
639 - unset($capabilities['do_not_allow']);
640 -
641 - // Must have ALL requested caps.
642 - foreach ((array) $caps as $cap) {
643 - if (empty($capabilities[$cap])) {
644 - return false;
645 - }
646 - }
647 -
648 - return true;
649 - }
650 -
651 - /**
652 - * Calculates the elapsed time and checks if it is close to the maximum execution time.
653 - * Returns true if the script should exit to avoid exceeding the limit.
654 - *
655 - * @return bool True if the script should exit, false otherwise.
656 - */
657 - public static function fsi_should_exit() {
658 - if (defined('TEMPLATELY_START_TIME') && ini_get('max_execution_time')) {
659 - $max_time = ini_get('max_execution_time');
660 - $elapsed = microtime(true) - TEMPLATELY_START_TIME;
661 - $delay = max(5, $max_time * 20 / 100);
662 -
663 - // Check if elapsed time is close to max execution time
664 - if ($max_time - $elapsed <= $delay) {
665 - return ['max_time' => $max_time, 'elapsed' => $elapsed, 'delay' => $delay];
666 - }
667 - }
668 - return false;
669 - }
670 -
671 - /**
672 - * Enable Elementor Container
673 - * This function will enable the Elementor Container feature.
674 - * Without this feature, some of the templates may not work properly.
675 - *
676 - * @return boolean
677 - */
678 - public static function enable_elementor_container() {
679 - if (class_exists('Elementor\Plugin')) {
680 - $control_name = Plugin::instance()->experiments->get_feature_option_key('container');
681 - if (get_option($control_name) !== 'active') {
682 - update_option($control_name, 'active');
683 - return true;
684 - }
685 - }
686 - return false;
687 - }
688 -
689 - /**
690 - * Undocumented function
691 - *
692 - * @param [type] $args
693 - * @param [type] $defaults
694 - * @return array
695 - */
696 - public static function recursive_wp_parse_args($args, $defaults) {
697 - $args = (array) $args;
698 - $defaults = (array) $defaults;
699 - $r = $defaults;
700 - foreach ($args as $key => $value) {
701 - if (is_array($value) && isset($r[$key])) {
702 - // also handle numeric array. if both $value and $r[ $key ] are numeric array. wp_is_numeric_array()
703 - if (wp_is_numeric_array($value) && wp_is_numeric_array($r[$key])) {
704 - foreach ($value as $k => $v) {
705 - if (!in_array($v, $r[$key])) {
706 - if (!isset($r[$key][$k])) {
707 - $r[$key][$k] = $v;
708 - } else {
709 - $r[$key][] = $v;
710 - }
711 - }
712 - }
713 - } else {
714 - $r[$key] = self::recursive_wp_parse_args($value, $r[$key]);
715 - }
190 + public static function log( $log ){
191 + if ( WP_DEBUG_LOG === true ) {
192 + if ( is_array( $log ) || is_object( $log ) ) {
193 + error_log( print_r( $log, true ) );
716 194 } else {
717 - $r[$key] = $value;
195 + error_log( $log );
718 196 }
719 197 }
720 - return $r;
721 198 }
722 -
723 -}
199 +}