PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / trunk
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! vtrunk
3.8.0 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 All 112 releases
templately / modules / full-site-import / Runners / GutenbergContent.php

GutenbergContent.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! trunk, at modules/full-site-import/Runners/GutenbergContent.php

274 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Modules\FullSiteImport\Runners;
4
5 use Templately\Modules\ThemeBuilder\PageTemplates;
6 use Templately\Modules\FullSiteImport\Utils\Utils;
7 use Templately\Utils\Helper;
8 use WP_Error;
9
10 /**
11 * @property \Templately\Modules\GutenbergIntegration\Utils\GutenbergHelper $json
12 */
13 class GutenbergContent extends BaseRunner {
14
15 public function get_name(): string {
16 return 'content';
17 }
18
19 public function get_label(): string {
20 return __( 'Block Editor Content', 'templately' );
21 }
22
23 public function should_run( $data, $imported_data = [] ): bool {
24 return $this->platform == 'gutenberg' && ! empty( $this->manifest['content'] );
25 }
26
27 public function should_log(): bool {
28 return true;
29 }
30
31 public function get_action(): string {
32 return 'updateLog';
33 }
34
35 public function log_message(): string {
36 return __( 'Importing Gutenberg Page and Post Templates', 'templately' );
37 }
38
39 /**
40 * Lay the customizer's typography OVER the pack's, entry by entry.
41 *
42 * This used to be a wholesale replace guarded by `! empty()`. The wizard sends
43 * `{"custom":{}}` for a Gutenberg import whose typography nobody touched, and an
44 * array holding one empty key is not empty — so the pack's whole set (h1, body,
45 * button and every `ebcustomtypo_*` entry) was replaced by nothing. Essential
46 * Blocks then emitted no `--ebcustomtypo_*` variables, its headings fell back to
47 * the wrapper's `line-height: 0`, and every wrapped heading on the imported site
48 * drew its lines on top of each other.
49 *
50 * So: the pack is the base, and the customizer can only ADD or OVERRIDE. An entry
51 * it does not mention survives; a field it sends as null (the denormalizer emits
52 * null for every property the user left alone) does not erase the pack's value.
53 * The Elementor runner has always merged this way.
54 *
55 * @param array $pack The pack's `global_typography`.
56 * @param mixed $incoming The customizer's typography, as sent.
57 * @return array
58 */
59 public static function merge_typography( array $pack, $incoming ): array {
60 if ( ! is_array( $incoming ) ) {
61 return $pack;
62 }
63
64 $overlay = function ( $base, $entry ) {
65 if ( ! is_array( $entry ) ) {
66 return $base;
67 }
68 $entry = array_filter( $entry, function ( $value ) {
69 return null !== $value;
70 } );
71 if ( empty( $entry ) ) {
72 return $base;
73 }
74 return is_array( $base ) ? array_merge( $base, $entry ) : $entry;
75 };
76
77 foreach ( $incoming as $key => $entry ) {
78 if ( 'custom' === $key ) {
79 if ( ! is_array( $entry ) ) {
80 continue;
81 }
82 $custom = isset( $pack['custom'] ) && is_array( $pack['custom'] ) ? $pack['custom'] : [];
83 foreach ( $entry as $id => $custom_entry ) {
84 $merged = $overlay( $custom[ $id ] ?? null, $custom_entry );
85 if ( null !== $merged ) {
86 $custom[ $id ] = $merged;
87 }
88 }
89 if ( ! empty( $custom ) ) {
90 $pack['custom'] = $custom;
91 }
92 continue;
93 }
94
95 $merged = $overlay( $pack[ $key ] ?? null, $entry );
96 if ( null !== $merged ) {
97 $pack[ $key ] = $merged;
98 }
99 }
100
101 return $pack;
102 }
103
104 public function import( $data, $imported_data ): array {
105 $contents = $this->manifest['content'];
106
107 // Log start of import
108 if(!$this->is_key_processed('started', 'import')){
109 $this->log( 0 );
110 $this->mark_key_processed('started', 'import');
111 }
112
113 if(isset($this->manifest['has_settings']) && $this->manifest['has_settings'] && !$this->is_key_processed('global_colors', 'settings')){
114 $file = $this->dir_path . "settings.json";
115 $settings = Utils::read_json_file( $file );
116
117 if(!empty($data['color'])){
118 if (isset($settings['global_colors'])) {
119 foreach ($settings['global_colors'] as $key => $color) {
120 $settings['global_colors'][$key]['color'] = $data['color'][$color['var']] ?? $color['color'];
121 }
122 }
123
124 if (isset($settings['custom_colors'])) {
125 foreach ($settings['custom_colors'] as $key => $color) {
126 $settings['custom_colors'][$key]['color'] = $data['color'][$color['var']] ?? $color['color'];
127 }
128 }
129 }
130 // `logo` arrives either as a bare url string or as an { id, url } array,
131 // and upload_logo() takes a URL — handing it the array made
132 // wp_http_validate_url() reject it, so a remote logo never imported.
133 $logo_url = Utils::get_logo_url($data['logo'] ?? null);
134 $logo_id = is_array($data['logo'] ?? null) ? ($data['logo']['id'] ?? 0) : 0;
135
136 if(!empty($logo_id)){
137 $site_logo_id = $logo_id;
138 $settings['site_logo'] = $site_logo_id;
139 Utils::update_option( 'site_logo', $site_logo_id );
140 $this->origin->update_imported_list('attachment', $logo_id);
141 }
142 else if (!empty($logo_url) && strpos($logo_url, 'data:image/') === 0) {
143 // Upload base64 data URL
144 $site_logo = Utils::upload_logo_base64($logo_url, $this->session_id);
145
146 if(!empty($site_logo['id'])){
147 $settings['site_logo'] = $site_logo['id'];
148 Utils::update_option( 'site_logo', $site_logo['id'] );
149 $this->origin->update_imported_list('attachment', $site_logo['id']);
150 }
151 }
152 else if(!empty($logo_url)){
153 // Upload remote URL
154 $site_logo = Utils::upload_logo($logo_url, $this->session_id);
155 if(!empty($site_logo['id'])){
156 $settings['site_logo'] = $site_logo['id'];
157 Utils::update_option( 'site_logo', $site_logo['id'] );
158 $this->origin->update_imported_list('attachment', $site_logo['id']);
159 }
160 }
161
162
163 $typography = self::merge_typography(
164 isset( $settings['global_typography'] ) && is_array( $settings['global_typography'] ) ? $settings['global_typography'] : [],
165 $data['typography'] ?? null
166 );
167 // Never invent the key: a pack with no typography and a customizer that sent
168 // none must store what it always stored — nothing.
169 if ( ! empty( $typography ) ) {
170 $settings['global_typography'] = $typography;
171 }
172
173 $settings = array_map('json_encode', $settings);
174
175 // Save the settings to the 'eb_global_styles' option
176 Utils::update_option('eb_global_styles', $settings);
177
178 $this->mark_key_processed('global_colors', 'settings');
179 }
180
181 $processed = 0;
182 $total = array_reduce($contents, function($carry, $item) {
183 return $carry + count($item);
184 }, 0);
185
186 $results = $this->loop( $contents, function($type, $posts, $results ) use($total) {
187 // Inner loop accumulates results for this type
188 $inner_result = $this->loop( $posts, function($id, $settings, $result ) use($type, $results, $total) {
189 $path = $this->dir_path . 'content' . DIRECTORY_SEPARATOR;
190
191 $import = $this->import_page_content( $id, $type, $path, $settings );
192
193 if ( ! $import ) {
194 $result[ $type ]['failed'][ $id ] = $import;
195 } else {
196 Utils::import_page_settings( $import['id'], $settings );
197 $result[ $type ]['succeed'][ $id ] = $import['id'];
198 }
199
200 // Broadcast Log - merge with outer results for accurate counting
201 $merged = array_merge($results, $result);
202 $processed = 0;
203 foreach ($merged as $t => $data) {
204 if (is_array($data) && $t !== '__attachments') {
205 $processed += count($data['succeed'] ?? []) + count($data['failed'] ?? []);
206 }
207 }
208 $progress = $total > 0 ? floor( ( 100 * $processed ) / $total ) : 100;
209 $this->log( $progress );
210
211 $result['__attachments'][$type][ $id ] = isset($import['__attachments']) ? $import['__attachments'] : [];
212
213 return $result;
214 }, $type);
215
216 // Non-recursive merge of inner result with outer results
217 $results = array_merge($results, $inner_result);
218 return $results;
219 });
220
221 return [ 'content' => $results ];
222 }
223
224 /**
225 * @param $id
226 * @param $type
227 * @param $path
228 * @param $settings
229 *
230 * @return false|int|void|WP_Error
231 */
232 private function import_page_content( $id, $type, $path, $settings ) {
233 try {
234 $json_content = Utils::read_json_file( $path . '/' . $type . '/' . $id . '.json' );
235 if ( ! empty( $json_content ) ) {
236
237 /**
238 * TODO:
239 *
240 * We can check if there is any data for settings.
241 * if yes: ignore content from insert.
242 *
243 * Process the content while finalizing.
244 */
245
246 $post_data = [
247 'post_title' => $json_content['title'] ?? ucfirst( $type ) . ' - (by Templately)',
248 'post_status' => 'publish',
249 'post_type' => $type,
250 'post_content' => wp_slash( $json_content['content'] ),
251 'page_template' => PageTemplates::TEMPLATE_HEADER_FOOTER
252 ];
253 $inserted = wp_insert_post( $post_data );
254
255 if ( is_wp_error( $inserted ) ) {
256 return false;
257 }
258
259 $attachments = $this->json->parse_images($json_content['content']);
260
261 $result = [];
262 if (!empty($attachments)) {
263 $result['__attachments'] = $attachments;
264 }
265 $result['id'] = $inserted;
266
267 return $result;
268 }
269 } catch ( \Exception $e ) {
270 return false;
271 }
272 }
273
274 }