PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.3.3
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.3.3
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 +344 -75 3.0.73.3.3 View file →
@@ -1,11 +1,15 @@
1 1 <?php
2 +
2 3 namespace Templately\Utils;
3 4
5 +use Elementor\Plugin;
6 +use Templately\Core\Importer\Utils\Utils;
4 7 use WP_Error;
5 8 use WP_REST_Response;
6 9 use function get_plugins;
7 10 use function is_plugin_active;
11 +
8 12 /**
9 13 * Utility Helper for Templately
10 14 *
11 15 * This class contains some helper functions for easy access.
@@ -12,31 +16,36 @@
12 16 *
13 17 * @since 1.0.0
14 18 */
15 19 class Helper extends Base {
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 - }
20 + /**
21 + * Get installed WordPress Plugin List
22 + * @return array
23 + */
24 + public static function get_plugins() {
25 + if (! function_exists('get_plugins')) {
26 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
27 + }
28 + return get_plugins();
29 + }
30 + public static function is_plugins_installed($plugin_file) {
31 + $_plugins = self::get_plugins();
32 + $is_installed = isset($_plugins[$plugin_file]);
33 + return $is_installed;
34 + }
26 35
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 - }
36 + /**
37 + * Get installed WordPress Plugin List
38 + * @return boolean
39 + */
40 + public static function is_plugin_active($plugin) {
41 + if (! function_exists('is_plugin_active')) {
42 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
43 + }
44 + return is_plugin_active($plugin);
45 + }
37 46
38 - /**
47 + /**
39 48 * Collect IP from request.
40 49 *
41 50 * @return string
42 51 */
@@ -41,35 +50,35 @@
41 50 * @return string
42 51 */
43 52 public static function get_ip() {
44 53 $ip = '127.0.0.1'; // Local IP
45 - if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
54 + if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
46 55 $ip = $_SERVER['HTTP_CLIENT_IP'];
47 - } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
56 + } elseif (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
48 57 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
49 58 } else {
50 - $ip = ! empty( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : $ip;
59 + $ip = ! empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
51 60 }
52 61
53 - return sanitize_text_field( $ip );
62 + return sanitize_text_field($ip);
54 63 }
55 64
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';
65 + /**
66 + * Get views for front-end display
67 + *
68 + * @param string $name it will be file name only from the view's folder.
69 + * @param array $data
70 + * @return void
71 + */
72 + public static function views($name, $data = []) {
73 + extract($data);
74 + $helper = self::class;
75 + $file = TEMPLATELY_PATH . 'views/' . $name . '.php';
67 76
68 - if( is_readable( $file ) ) {
69 - include_once $file;
70 - }
71 - }
77 + if (is_readable($file)) {
78 + include_once $file;
79 + }
80 + }
72 81
73 82 /**
74 83 * Sanitize Helper
75 84 *
@@ -77,15 +86,15 @@
77 86 * @param string $type
78 87 *
79 88 * @return bool|string
80 89 */
81 - public static function sanitize( $value, $type = 'text' ){
82 - switch ( $type ) {
90 + public static function sanitize($value, $type = 'text') {
91 + switch ($type) {
83 92 case 'boolean':
84 - $sanitized_value = rest_sanitize_boolean( $value );
93 + $sanitized_value = rest_sanitize_boolean($value);
85 94 break;
86 95 default:
87 - $sanitized_value = sanitize_text_field( $value );
96 + $sanitized_value = sanitize_text_field($value);
88 97 break;
89 98 }
90 99
91 100 return $sanitized_value;
@@ -100,15 +109,18 @@
100 109 * @param integer $status
101 110 * @param array $additional_data
102 111 * @return WP_Error
103 112 */
104 - public static function error( $error_code, $error_message, $endpoint = '', $status = 500, $additional_data = [] ) {
113 + public static function error($error_code, $error_message, $endpoint = '', $status = 500, $additional_data = []) {
105 114 $additional_data['status'] = $status;
106 - if ( ! empty( $endpoint ) ) {
115 + if (! empty($endpoint)) {
107 116 $additional_data['endpoint'] = $endpoint;
108 117 }
118 + // Add browser padding to avoid browsers not serving small JSON responses
119 + $padding_length = 512;
120 + $additional_data['browser_padding'] = str_repeat(' ', $padding_length);
109 121
110 - return new WP_Error( $error_code, $error_message, $additional_data );
122 + return new WP_Error($error_code, $error_message, $additional_data);
111 123 }
112 124
113 125 /**
114 126 * API Response Formatter
@@ -115,10 +127,10 @@
115 127 *
116 128 * @param mixed $data
117 129 * @return WP_REST_Response
118 130 */
119 - public static function success( $data ) {
120 - return new WP_REST_Response( $data, 200 );
131 + public static function success($data) {
132 + return new WP_REST_Response($data, 200);
121 133 }
122 134
123 135 /**
124 136 * Normalize Favourites Data
@@ -128,42 +140,42 @@
128 140 * @param boolean $undo
129 141 *
130 142 * @return array
131 143 */
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 ) {
144 + public function normalizeFavourites($favourites, $_favourites = [], $undo = false) {
145 + if ($undo) {
146 + $_favourites[$favourites['type']] = array_values(array_filter($_favourites[$favourites['type']], function ($item) use ($favourites) {
135 147 return $item != $favourites['id'];
136 - } ));
148 + }));
137 149 return $_favourites;
138 150 }
139 151
140 - array_map( function( $item ) use ( &$_favourites) {
141 - if( ! is_null( $item ) ) {
152 + array_map(function ($item) use (&$_favourites) {
153 + if (! is_null($item)) {
142 154 $item = (array) $item;
143 - if ( isset( $_favourites[ $item['type'] ] ) ){
144 - $_favourites[ $item['type'] ][] = $item['id'];
155 + if (isset($_favourites[$item['type']])) {
156 + $_favourites[$item['type']][] = $item['id'];
145 157 } else {
146 - $_favourites[ $item['type'] ] = [ $item['id'] ];
158 + $_favourites[$item['type']] = [$item['id']];
147 159 }
148 160 }
149 161 return $_favourites;
150 - }, $favourites );
162 + }, $favourites);
151 163
152 164 return $_favourites;
153 165 }
154 166
155 - public function normalizeReviews( $favourites, $_favourites = [], $undo = false ){
156 - array_map( function( $item ) use ( &$_favourites) {
157 - if( ! is_null( $item ) ) {
167 + public function normalizeReviews($favourites, $_favourites = [], $undo = false) {
168 + array_map(function ($item) use (&$_favourites) {
169 + if (! is_null($item)) {
158 170 $item = (array) $item;
159 - if ( !isset( $_favourites[ $item['type'] ] ) ){
160 - $_favourites[ $item['type'] ] = [];
171 + if (!isset($_favourites[$item['type']])) {
172 + $_favourites[$item['type']] = [];
161 173 }
162 - $_favourites[ $item['type'] ][$item['type_id']] = $item['rating'];
174 + $_favourites[$item['type']][$item['type_id']] = $item['rating'];
163 175 }
164 176 return $_favourites;
165 - }, $favourites );
177 + }, $favourites);
166 178
167 179 return $_favourites;
168 180 }
169 181
@@ -172,10 +184,10 @@
172 184 *
173 185 * @param object $triggered_by
174 186 * @return void
175 187 */
176 - public static function trigger_error( $triggered_by, $method = 'get_instance' ){
177 - $class = get_class( $triggered_by );
188 + public static function trigger_error($triggered_by, $method = 'get_instance') {
189 + $class = get_class($triggered_by);
178 190 $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
179 191 $file = $trace[0]['file'];
180 192 $line = $trace[0]['line'];
181 193 trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
@@ -186,19 +198,276 @@
186 198 *
187 199 * @param mixed $log
188 200 * @return void
189 201 */
190 - public static function log( $log ){
191 - if ( defined('WP_DEBUG_LOG') && WP_DEBUG_LOG === true ) {
192 - if ( is_array( $log ) || is_object( $log ) ) {
193 - error_log( print_r( $log, true ) );
202 + public static function log($log) {
203 + if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
204 + if (is_array($log) || is_object($log)) {
205 + error_log(print_r($log, true));
194 206 } else {
195 - error_log( $log ?: '' );
207 + error_log($log ?: '');
196 208 }
197 209 }
198 210 }
199 211
200 - public static function should_flush(){
212 + public static function should_flush() {
213 + if (isset($_REQUEST['is_lightspeed']) && $_REQUEST['is_lightspeed'] === 'true') {
214 + return false;
215 + }
201 216 return (!defined('TEMPLATELY_IGNORE_FLUSH_ALL') || !TEMPLATELY_IGNORE_FLUSH_ALL) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') === false;
202 217 }
203 218
204 -}
219 + public static function get_block_by_name($blocks, $search) {
220 + $queue = $blocks;
221 +
222 + while (!empty($queue)) {
223 + $current_block = array_shift($queue);
224 +
225 + if ($search === $current_block['blockName']) {
226 + return $current_block;
227 + }
228 +
229 + if (isset($current_block['innerBlocks'])) {
230 + // Add nested blocks to the end of the queue for processing
231 + $queue = array_merge($queue, $current_block['innerBlocks']);
232 + }
233 + }
234 +
235 + return false;
236 + }
237 +
238 + /**
239 + * Only checks if user can install/activate plugins
240 + *
241 + * @param [type] $cap
242 + * @param [type] ...$args
243 + * @return void
244 + */
245 + public static function current_user_can($cap, ...$args) {
246 + $user = wp_get_current_user();
247 +
248 + // Multisite super admin has all caps by definition, Unless specifically denied.
249 + if (is_multisite() && is_super_admin($user->ID)) {
250 + return true;
251 + }
252 +
253 + $caps = map_meta_cap($cap, $user->ID, ...$args);
254 +
255 + switch ($cap) {
256 + case 'install_plugins':
257 + case 'upload_plugins':
258 + $caps = ['install_plugins'];
259 + break;
260 + case 'install_themes':
261 + case 'upload_themes':
262 + $caps = ['install_themes'];
263 + break;
264 + case 'activate_plugins':
265 + case 'deactivate_plugins':
266 + case 'activate_plugin':
267 + case 'deactivate_plugin':
268 + $caps = ['activate_plugins'];
269 + break;
270 + default:
271 + break;
272 + }
273 +
274 + // Maintain BC for the argument passed to the "user_has_cap" filter.
275 + $args = array_merge(array($cap, $user->ID), $args);
276 +
277 + /**
278 + * See WP_User::has_cap() for description.
279 + */
280 + $capabilities = apply_filters('user_has_cap', $user->allcaps, $caps, $args, $user);
281 +
282 + // Everyone is allowed to exist.
283 + $capabilities['exist'] = true;
284 +
285 + // Nobody is allowed to do things they are not allowed to do.
286 + unset($capabilities['do_not_allow']);
287 +
288 + // Must have ALL requested caps.
289 + foreach ((array) $caps as $cap) {
290 + if (empty($capabilities[$cap])) {
291 + return false;
292 + }
293 + }
294 +
295 + return true;
296 + }
297 +
298 + /**
299 + * Calculates the elapsed time and checks if it is close to the maximum execution time.
300 + * Returns true if the script should exit to avoid exceeding the limit.
301 + *
302 + * @return bool True if the script should exit, false otherwise.
303 + */
304 + public static function fsi_should_exit() {
305 + if (defined('TEMPLATELY_START_TIME') && ini_get('max_execution_time')) {
306 + $max_time = ini_get('max_execution_time');
307 + $elapsed = microtime(true) - TEMPLATELY_START_TIME;
308 + $delay = max(5, $max_time * 20 / 100);
309 +
310 + // Check if elapsed time is close to max execution time
311 + if ($max_time - $elapsed <= $delay) {
312 + return ['max_time' => $max_time, 'elapsed' => $elapsed, 'delay' => $delay];
313 + }
314 + }
315 + return false;
316 + }
317 +
318 + /**
319 + * Enable Elementor Container
320 + * This function will enable the Elementor Container feature.
321 + * Without this feature, some of the templates may not work properly.
322 + *
323 + * @return boolean
324 + */
325 + public static function enable_elementor_container() {
326 + if (class_exists('Elementor\Plugin')) {
327 + $control_name = Plugin::instance()->experiments->get_feature_option_key('container');
328 + if (get_option($control_name) === 'inactive') {
329 + update_option($control_name, 'active');
330 + return true;
331 + }
332 + }
333 + return false;
334 + }
335 +
336 + /**
337 + * Undocumented function
338 + *
339 + * @param [type] $args
340 + * @param [type] $defaults
341 + * @return array
342 + */
343 + public static function recursive_wp_parse_args($args, $defaults) {
344 + $args = (array) $args;
345 + $defaults = (array) $defaults;
346 + $r = $defaults;
347 + foreach ($args as $key => $value) {
348 + if (is_array($value) && isset($r[$key])) {
349 + // also handle numeric array. if both $value and $r[ $key ] are numeric array. wp_is_numeric_array()
350 + if (wp_is_numeric_array($value) && wp_is_numeric_array($r[$key])) {
351 + foreach ($value as $k => $v) {
352 + if (!in_array($v, $r[$key])) {
353 + if (!isset($r[$key][$k])) {
354 + $r[$key][$k] = $v;
355 + } else {
356 + $r[$key][] = $v;
357 + }
358 + }
359 + }
360 + } else {
361 + $r[$key] = self::recursive_wp_parse_args($value, $r[$key]);
362 + }
363 + } else {
364 + $r[$key] = $value;
365 + }
366 + }
367 + return $r;
368 + }
369 +
370 + /**
371 + * Save template data to file
372 + *
373 + * Common function for saving templates to files, used by AI content operations
374 + *
375 + * @param string $process_id The process ID
376 + * @param string $content_id The content ID
377 + * @param string $template The template data (base64 encoded or raw)
378 + * @param array $ai_page_ids Array of AI page IDs
379 + * @param bool $is_preview Whether this is a preview operation
380 + * @param bool $is_skipped Whether the template was skipped
381 + * @return array|WP_Error Result array with status and data
382 + */
383 + public static function save_template_to_file($process_id, $content_id, $template, $ai_page_ids, $is_preview = false, $is_skipped = false) {
384 + $upload_dir = wp_upload_dir();
385 +
386 + // Always save to preview directory for AI content workflow
387 + $tmp_dir = trailingslashit($upload_dir['basedir']) . 'templately' . DIRECTORY_SEPARATOR . 'preview' . DIRECTORY_SEPARATOR . $process_id . DIRECTORY_SEPARATOR;
388 +
389 + // Decode template if it's base64 encoded
390 + if (! empty($template) && base64_decode($template, true) !== false) {
391 + $template = base64_decode($template);
392 + }
393 +
394 + // Handle empty template (skipped)
395 + if (empty($template)) {
396 + $template = json_encode([
397 + "isSkipped" => true,
398 + ]);
399 + }
400 +
401 + // Find the correct directory for the content ID
402 + $found_key = null;
403 + foreach ($ai_page_ids as $key => $ids) {
404 + if (in_array($content_id, $ids)) {
405 + $found_key = $key;
406 + break;
407 + }
408 + }
409 +
410 + if ($found_key === null) {
411 + return self::error('invalid_content_id', __('Content ID not found in AI page IDs.', 'templately'), 'save_template_to_file', 400);
412 + }
413 +
414 + // Create directory and file path
415 + $page_dir = $tmp_dir . $found_key . DIRECTORY_SEPARATOR;
416 + $file_path = $page_dir . $content_id . '.ai.json';
417 + wp_mkdir_p($page_dir);
418 +
419 + // Save the file
420 + $is_success = file_put_contents($file_path, $template);
421 +
422 + if ($is_success) {
423 + // Update processed pages option
424 + $processed_pages = get_option("templately_ai_processed_pages", []);
425 + $processed_pages[$process_id] = $processed_pages[$process_id] ?? [];
426 + $processed_pages[$process_id]['pages'][$content_id] = $is_skipped;
427 + update_option("templately_ai_processed_pages", $processed_pages, false);
428 +
429 + return [
430 + 'status' => 'success',
431 + 'data' => [
432 + 'process_id' => $process_id,
433 + // 'file_path' => $file_path,
434 + 'content_id' => $content_id,
435 + ],
436 + ];
437 + }
438 +
439 + return self::error('file_save_failed', __('Failed to save template file.', 'templately'), 'save_template_to_file', 500);
440 + }
441 +
442 + /**
443 + * Get matched session data by process ID
444 + *
445 + * Helper function to retrieve session data for a given process ID
446 + *
447 + * @param string $process_id The process ID to match
448 + * @return array|false Returns matched data array or false if not found
449 + */
450 + public static function get_matched_session_data($process_id) {
451 + if (empty($process_id)) {
452 + return false;
453 + }
454 +
455 + $all_data = Utils::get_all_session_data();
456 +
457 + if (empty($all_data) || ! is_array($all_data)) {
458 + return false;
459 + }
460 +
461 + // INSERT_YOUR_CODE
462 + if (is_array($all_data)) {
463 + $all_data = array_reverse($all_data);
464 + }
465 + foreach ($all_data as $data) {
466 + if (isset($data['process_id']) && ($data['process_id'] === $process_id)) {
467 + return $data;
468 + }
469 + }
470 +
471 + return false;
472 + }
473 +}