PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.3.1
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.3.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.3.1, at includes/Utils/Helper.php

474 lines 12.4 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 * 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 }
35
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 }
46
47 /**
48 * Collect IP from request.
49 *
50 * @return string
51 */
52 public static function get_ip() {
53 $ip = '127.0.0.1'; // Local IP
54 if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
55 $ip = $_SERVER['HTTP_CLIENT_IP'];
56 } elseif (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
57 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
58 } else {
59 $ip = ! empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
60 }
61
62 return sanitize_text_field($ip);
63 }
64
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';
76
77 if (is_readable($file)) {
78 include_once $file;
79 }
80 }
81
82 /**
83 * Sanitize Helper
84 *
85 * @param mixed $value
86 * @param string $type
87 *
88 * @return bool|string
89 */
90 public static function sanitize($value, $type = 'text') {
91 switch ($type) {
92 case 'boolean':
93 $sanitized_value = rest_sanitize_boolean($value);
94 break;
95 default:
96 $sanitized_value = sanitize_text_field($value);
97 break;
98 }
99
100 return $sanitized_value;
101 }
102
103 /**
104 * API Error Formatter
105 *
106 * @param int $error_code
107 * @param mixed $error_message
108 * @param string $endpoint
109 * @param integer $status
110 * @param array $additional_data
111 * @return WP_Error
112 */
113 public static function error($error_code, $error_message, $endpoint = '', $status = 500, $additional_data = []) {
114 $additional_data['status'] = $status;
115 if (! empty($endpoint)) {
116 $additional_data['endpoint'] = $endpoint;
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);
121
122 return new WP_Error($error_code, $error_message, $additional_data);
123 }
124
125 /**
126 * API Response Formatter
127 *
128 * @param mixed $data
129 * @return WP_REST_Response
130 */
131 public static function success($data) {
132 return new WP_REST_Response($data, 200);
133 }
134
135 /**
136 * Normalize Favourites Data
137 *
138 * @param array $favourites
139 * @param array $_favourites
140 * @param boolean $undo
141 *
142 * @return array
143 */
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) {
147 return $item != $favourites['id'];
148 }));
149 return $_favourites;
150 }
151
152 array_map(function ($item) use (&$_favourites) {
153 if (! is_null($item)) {
154 $item = (array) $item;
155 if (isset($_favourites[$item['type']])) {
156 $_favourites[$item['type']][] = $item['id'];
157 } else {
158 $_favourites[$item['type']] = [$item['id']];
159 }
160 }
161 return $_favourites;
162 }, $favourites);
163
164 return $_favourites;
165 }
166
167 public function normalizeReviews($favourites, $_favourites = [], $undo = false) {
168 array_map(function ($item) use (&$_favourites) {
169 if (! is_null($item)) {
170 $item = (array) $item;
171 if (!isset($_favourites[$item['type']])) {
172 $_favourites[$item['type']] = [];
173 }
174 $_favourites[$item['type']][$item['type_id']] = $item['rating'];
175 }
176 return $_favourites;
177 }, $favourites);
178
179 return $_favourites;
180 }
181
182 /**
183 * Trigger Error
184 *
185 * @param object $triggered_by
186 * @return void
187 */
188 public static function trigger_error($triggered_by, $method = 'get_instance') {
189 $class = get_class($triggered_by);
190 $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
191 $file = $trace[0]['file'];
192 $line = $trace[0]['line'];
193 trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
194 }
195
196 /**
197 * Printing Error Logs in debug.log file.
198 *
199 * @param mixed $log
200 * @return void
201 */
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));
206 } else {
207 error_log($log ?: '');
208 }
209 }
210 }
211
212 public static function should_flush() {
213 if (isset($_REQUEST['is_lightspeed']) && $_REQUEST['is_lightspeed'] === 'true') {
214 return false;
215 }
216 return (!defined('TEMPLATELY_IGNORE_FLUSH_ALL') || !TEMPLATELY_IGNORE_FLUSH_ALL) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') === false;
217 }
218
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 }
474