PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.5.1
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.5.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 / Core / Importer / Utils / Utils.php

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

513 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Core\Importer\Utils;
4
5 use Exception;
6 use Templately\Core\Importer\FullSiteImport;
7 use Templately\Core\Importer\WPImport;
8 use Templately\Utils\Base;
9 use Templately\Utils\Helper;
10
11 class Utils extends Base {
12
13
14 /**
15 * @throws Exception
16 */
17 public static function read_json_file( $path ) {
18 if ( ! file_exists( $path ) ) {
19 throw new Exception( __( 'JSON file not exists. ' . basename( $path ), 'templately' ) );
20 }
21
22 $file_content = self::file_get_contents( $path );
23
24 return $file_content ? json_decode( $file_content, true ) : [];
25 }
26
27 /**
28 * @param $file
29 * @param mixed ...$args
30 *
31 * @return false|string
32 */
33 public static function file_get_contents( $file, ...$args ) {
34 if ( ! is_file( $file ) || ! is_readable( $file ) ) {
35 return false;
36 }
37
38 return file_get_contents( $file, ...$args );
39 }
40
41 public static function get_builtin_wp_post_types(): array {
42 $post_type_args = [
43 'show_in_nav_menus' => true,
44 'public' => true
45 ];
46 $_post_types = get_post_types( $post_type_args, 'objects' );
47
48 return array_merge( array_keys( $_post_types ), [ 'nav_menu_item', 'wp_navigation' ] );
49 }
50
51 public static function map_old_new_post_ids( array $imported_data ) {
52 $result = [];
53
54 $result += $imported_data['templates']['succeed'] ?? [];
55
56 if ( isset( $imported_data['content'] ) ) {
57 foreach ( $imported_data['content'] as $post_type ) {
58 $result += $post_type['succeed'] ?? [];
59 }
60 }
61
62 if ( isset( $imported_data['wp-content'] ) ) {
63 foreach ( $imported_data['wp-content'] as $post_type ) {
64 $result += $post_type['succeed'] ?? [];
65 }
66 }
67
68 // add attachments data
69 if ( !empty( $imported_data['attachments']['succeed'] ) ) {
70 $result += $imported_data['attachments']['succeed'] ?? [];
71 }
72
73
74 return $result;
75 }
76
77 public static function map_old_new_term_ids( array $imported_data ) {
78 $result = [];
79
80 if ( isset( $imported_data['terms'] ) ) {
81 foreach ( $imported_data['terms'] as $post_type ) {
82 $result += $post_type['succeed'] ?? [];
83 }
84 }
85
86 return $result;
87 }
88
89 public static function map_old_new_term_ids_el( array $imported_data ): array {
90 $result = [];
91
92 if ( ! isset( $imported_data['taxonomies'] ) ) {
93 return $result;
94 }
95
96 foreach ( $imported_data['taxonomies'] as $post_type_taxonomies ) {
97 foreach ( $post_type_taxonomies as $taxonomy ) {
98 foreach ( $taxonomy as $term ) {
99 $result[ $term['old_id'] ] = $term['new_id'];
100 }
101 }
102 }
103
104 return $result;
105 }
106
107 /**
108 * @param string $platform
109 *
110 * @return ImportHelper
111 */
112 public static function get_json_helper( string $platform ) {
113 return $platform === 'elementor' ? new ElementorHelper() : new GutenbergHelper();
114 }
115
116 public static function get_backup_options() {
117 global $wpdb;
118
119 $prefix = '__templately_';
120 $table_name = $wpdb->options; // Assuming default options table name
121
122 $sql = "SELECT option_name, option_value FROM {$table_name} WHERE option_name LIKE %s";
123 $prepared_sql = $wpdb->prepare($sql, array("$prefix%")); // Escape wildcard for security
124
125 $results = $wpdb->get_results($prepared_sql);
126
127 $templately_options = array();
128 foreach ($results as $row) {
129 $name = str_replace($prefix, '', $row->option_name);
130 $templately_options[$name] = maybe_unserialize($row->option_value);
131 }
132
133 return $templately_options;
134 }
135
136 public static function backup_option_value($key, $autoload = 'no') {
137 $old_value = get_option($key);
138 if ($old_value) {
139 update_option("__templately_$key", $old_value, $autoload);
140 }
141 else {
142 add_option("__templately_$key", $old_value, '', $autoload);
143 }
144 }
145
146 public static function update_option($key, $value, $autoload = 'no') {
147 self::backup_option_value($key, $autoload);
148 return update_option($key, $value, $autoload);
149 }
150
151 public static function import_page_settings( $id, $settings ) {
152 $extra_settings = [
153 'page_on_front' => [
154 'show_on_front' => 'page'
155 ]
156 ];
157 if ( isset( $settings['page_for_posts'] ) && $settings['page_for_posts'] ) {
158 self::update_option( 'page_for_posts', $id );
159 }
160 if ( isset( $settings['show_on_front'] ) && $settings['show_on_front'] ) {
161 self::update_option( 'page_on_front', $id );
162 self::update_option( 'show_on_front', 'page' );
163 }
164 if ( ! empty( $settings['page_settings'] ) ) {
165 foreach ( $settings['page_settings'] as $option_name => $val ) {
166 $__val = $id;
167 if($option_name === 'fluent_cart_store_settings'){
168 $__val = $val;
169 }
170 self::update_option( $option_name, $__val );
171 if ( array_key_exists( $option_name, $extra_settings ) ) {
172 foreach ( $extra_settings[ $option_name ] as $name => $value ) {
173 self::update_option( $name, $value );
174 }
175 }
176 }
177 }
178 }
179
180 public static function upload_logo($url, $session_id) {
181 if(empty($url)) {
182 return ['error' => __('URL is empty', 'templately')];
183 }
184
185 // Validate URL and ensure scheme is present
186 if ( ! wp_http_validate_url( $url ) || !parse_url( $url, PHP_URL_SCHEME ) ) {
187 return ['error' => __('Invalid URL', 'templately')];
188 }
189
190 $post_data = self::prepare_post_data($url);
191 $wp_importer = new WPImport( null, ['fetch_attachments' => true, 'session_id' => $session_id] );
192 $attachment_id = $wp_importer->process_attachment($post_data, $url);
193
194 if(is_wp_error($attachment_id)){
195 return ['error' => $attachment_id->get_error_message()];
196 }
197
198 return [
199 'id' => (int) $attachment_id,
200 'url' => esc_url_raw(wp_get_attachment_url($attachment_id)),
201 ];
202 }
203
204 /**
205 * Upload base64 encoded image to media library
206 *
207 * @param string $base64 Base64 encoded image data (with or without data URI scheme)
208 * @param string $session_id Session ID for tracking (reserved for future use)
209 * @return array Array with 'id' and 'url' on success, or ['error' => message] on failure
210 */
211 public static function upload_logo_base64($base64, $session_id = null) {
212 if(empty($base64)) {
213 return ['error' => __('Base64 is empty', 'templately')];
214 }
215
216 // Upload the base64 image
217 $attachment_id = self::upload_base64_image($base64);
218
219 if(is_wp_error($attachment_id)){
220 return ['error' => $attachment_id->get_error_message()];
221 }
222
223 return [
224 'id' => (int) $attachment_id,
225 'url' => esc_url_raw(wp_get_attachment_url($attachment_id)),
226 ];
227 }
228
229 /**
230 * Upload base64 encoded image without dependency on prepare_post_data
231 * Handles MIME type detection and proper file extension assignment
232 *
233 * @param string $base64 Base64 encoded image data (with or without data URI scheme)
234 * @return int|\WP_Error Attachment ID on success, WP_Error on failure
235 */
236 public static function upload_base64_image($base64) {
237 // Strip data URL prefix if present (e.g., "data:image/png;base64,")
238 if (strpos($base64, 'data:image/') === 0) {
239 $base64_parts = explode(',', $base64, 2);
240 if (isset($base64_parts[1])) {
241 $base64 = $base64_parts[1];
242 }
243 }
244
245 // Decode base64 string
246 $decoded_image = base64_decode($base64, true);
247 if ($decoded_image === false) {
248 return new \WP_Error('invalid_base64', __('Invalid base64 data.', 'templately'));
249 }
250
251 // Detect MIME type from decoded image data
252 $mime_type = self::detect_mime_type_from_data($decoded_image);
253 if (empty($mime_type)) {
254 return new \WP_Error('unknown_mime_type', __('Unable to determine image MIME type.', 'templately'));
255 }
256
257 // Get file extension from MIME type
258 $extension = self::get_file_extension_by_mime_type($mime_type);
259 if (empty($extension)) {
260 return new \WP_Error('unsupported_mime_type', __('Unsupported image MIME type.', 'templately'));
261 }
262
263 // Generate unique filename
264 $filename = 'templately-logo-' . \wp_generate_uuid4() . '.' . $extension;
265
266 // Get upload directory
267 $upload_dir = \wp_upload_dir();
268 if (!$upload_dir['error']) {
269 $upload_path = $upload_dir['path'] . '/' . $filename;
270 } else {
271 return new \WP_Error('upload_dir_error', __('Unable to access upload directory.', 'templately'));
272 }
273
274 // Write decoded image to file
275 if (file_put_contents($upload_path, $decoded_image) === false) {
276 return new \WP_Error('upload_error', __('Error uploading image.', 'templately'));
277 }
278
279 // Create attachment post
280 $attachment_data = [
281 'post_mime_type' => $mime_type,
282 'post_title' => \sanitize_file_name(pathinfo($filename, PATHINFO_FILENAME)),
283 'post_content' => '',
284 'post_status' => 'inherit',
285 ];
286
287 $attachment_id = \wp_insert_attachment($attachment_data, $upload_path);
288 if (is_wp_error($attachment_id)) {
289 return $attachment_id;
290 }
291
292 // Ensure WordPress image functions are available
293 // These functions are defined in wp-admin/includes/image.php which is not always loaded
294 if (!function_exists('wp_generate_attachment_metadata')) {
295 require_once(ABSPATH . 'wp-admin/includes/image.php');
296 }
297
298 // Generate and update attachment metadata
299 $metadata = \wp_generate_attachment_metadata($attachment_id, $upload_path);
300 \wp_update_attachment_metadata($attachment_id, $metadata);
301
302 return $attachment_id;
303 }
304
305 /**
306 * Detect MIME type from image data
307 * Uses finfo_buffer if available, otherwise falls back to getimagesizefromstring
308 *
309 * @param string $image_data Raw image data
310 * @return string|null MIME type or null if unable to detect
311 */
312 private static function detect_mime_type_from_data($image_data) {
313 // Try using finfo_buffer first (most reliable)
314 if (function_exists('finfo_buffer')) {
315 $finfo = finfo_open(FILEINFO_MIME_TYPE);
316 if ($finfo) {
317 $mime_type = finfo_buffer($finfo, $image_data);
318 finfo_close($finfo);
319 if ($mime_type && strpos($mime_type, 'image/') === 0) {
320 return $mime_type;
321 }
322 }
323 }
324
325 // Fallback: use getimagesizefromstring
326 if (function_exists('getimagesizefromstring')) {
327 $image_info = @getimagesizefromstring($image_data);
328 if ($image_info && isset($image_info['mime'])) {
329 return $image_info['mime'];
330 }
331 }
332
333 return null;
334 }
335
336 /**
337 * Get file extension by MIME type
338 * Uses WordPress built-in functions for MIME type to extension conversion
339 *
340 * @since 3.4.5
341 * @param string $mime_type MIME type (e.g., 'image/png')
342 * @return string|null File extension without dot, or null if not found
343 */
344 private static function get_file_extension_by_mime_type($mime_type) {
345 // Use WordPress core function if available (WordPress 5.8.1+)
346 // wp_get_default_extension_for_mime_type() returns the default file extension for a given MIME type
347 if (function_exists('wp_get_default_extension_for_mime_type')) {
348 return \wp_get_default_extension_for_mime_type($mime_type);
349 }
350
351 // Fallback for WordPress < 5.8.1
352 // Use wp_get_mime_types() which returns array with extensions as keys and MIME types as values
353 // Example: ['jpg|jpeg|jpe' => 'image/jpeg', 'png' => 'image/png', ...]
354 $wp_mime_types = \wp_get_mime_types();
355
356 // Flip the array to get MIME type as key and extensions as value
357 $mime_map = array_flip($wp_mime_types);
358
359 if (isset($mime_map[$mime_type])) {
360 $extensions = $mime_map[$mime_type];
361 // Get first extension if multiple are available (e.g., 'jpg|jpeg|jpe' -> 'jpg')
362 return strtok($extensions, '|');
363 }
364
365 return null;
366 }
367
368 /**
369 * Inserts a template into the Gutenberg editor.
370 *
371 * @param mixed $data
372 * @param int $postId
373 * @return array
374 */
375 public static function import_and_replace_attachments($content, $postId = 0) {
376 // Instantiate GutenbergHelper
377 $helper = new GutenbergHelper();
378
379 $data = [
380 'content' => $content,
381 ];
382
383 // Organize URLs from the content
384 $organizedUrls = $helper->parse_images($data['content']);
385 if(empty($organizedUrls)){
386 return $content;
387 }
388
389 // Define template settings
390 $template_settings = [
391 'post_id' => $postId,
392 '__attachments' => $organizedUrls,
393 ];
394
395 // Map post IDs and disable logging
396 $helper->map_post_ids[$postId] = $postId;
397 $helper->shouldLog = false;
398
399 // Prepare the helper with the data and settings
400 $helper->prepare($data, $template_settings);
401
402 // Update the content in the data array
403 $content = wp_unslash($helper->get_content());
404
405 return $content;
406 }
407
408 public static function prepare_post_data($image_url, $post_parent = null, $logger = null) {
409 $filetype = wp_check_filetype(basename($image_url));
410 if (!$filetype['type']) {
411 if(is_callable($logger)){
412 // call the logger function
413 call_user_func($logger, 'prepare', 'Error: Unable to determine the file type.', -1, 'eventLog');
414 }
415 return null;
416 }
417
418 $post_data = array(
419 'post_title' => basename($image_url),
420 'post_content' => '',
421 'post_status' => 'inherit',
422 'post_mime_type' => $filetype['type'],
423 'guid' => $image_url,
424 );
425
426 if($post_parent){
427 $post_data['post_parent'] = $post_parent; // Set the parent post
428 }
429
430 if (preg_match('%wp-content/uploads/([0-9]{4}/[0-9]{2})%', $image_url, $matches)) {
431 $post_data['upload_date'] = $matches[1];
432 }
433 else{
434 $post_data['upload_date'] = date('Y/m');
435 }
436
437 return $post_data;
438 }
439
440 // ============================================================================
441 // Session Data Functions - DEPRECATED: Use SessionData class instead
442 // ============================================================================
443
444 /**
445 * @deprecated 3.4.7 Use SessionData::get_session_id() instead
446 */
447 public static function get_session_id(){
448 _deprecated_function(__METHOD__, '3.4.7', 'SessionData::get_session_id()');
449 return SessionData::get_session_id();
450 }
451
452 /**
453 * @deprecated 3.4.7 Use SessionData::save() or SessionData::set() instead
454 */
455 public static function update_session_data_by_id($data): bool {
456 _deprecated_function(__METHOD__, '3.4.7', 'SessionData::save() or SessionData::set()');
457 if($session_id = SessionData::get_session_id()){
458 $existing = SessionData::get_data($session_id);
459 return SessionData::save($session_id, array_merge($existing, $data));
460 }
461 return false;
462 }
463
464 /**
465 * @deprecated 3.4.7 Use SessionData::clean_by_pack_id() instead
466 */
467 public static function clean_session_data_by_pack_id($pack_id, $current_session_id) {
468 _deprecated_function(__METHOD__, '3.4.7', 'SessionData::clean_by_pack_id()');
469 return SessionData::clean_by_pack_id($pack_id, $current_session_id);
470 }
471
472 /**
473 * @deprecated 3.4.7 Use SessionData::cleanup_expired() instead
474 */
475 public static function cleanup_expired_sessions($max_age_days = 7) {
476 _deprecated_function(__METHOD__, '3.4.7', 'SessionData::cleanup_expired()');
477 return SessionData::cleanup_expired($max_age_days);
478 }
479
480
481
482 /**
483 * Clean up directory using RecursiveIteratorIterator approach
484 * This method handles directory cleanup with proper validation
485 *
486 * @param string $dir_path The directory path to clean up
487 * @return bool True on success, false on failure
488 */
489 public static function cleanup_directory($dir_path) {
490 if (empty($dir_path) || !file_exists($dir_path) || !is_dir($dir_path)) {
491 return false;
492 }
493
494 try {
495 $files = new \RecursiveIteratorIterator(
496 new \RecursiveDirectoryIterator($dir_path, \RecursiveDirectoryIterator::SKIP_DOTS),
497 \RecursiveIteratorIterator::CHILD_FIRST
498 );
499
500 foreach ($files as $fileinfo) {
501 $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
502 $todo($fileinfo->getRealPath());
503 }
504
505 rmdir($dir_path);
506 return true;
507 } catch (Exception $e) {
508 return false;
509 }
510 }
511
512 }
513