PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.0
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / app / Supports / Template.php
kirki / app / Supports Last commit date
Facades 4 days ago Canvas.php 3 weeks ago CollectionItem.php 3 weeks ago ContentManager.php 3 weeks ago DateTime.php 3 weeks ago EditorPreview.php 4 days ago FileHandler.php 4 days ago FilterHooks.php 4 days ago PageUrl.php 4 days ago Role.php 3 weeks ago Template.php 4 days ago
Template.php
413 lines
1 <?php
2
3 namespace Kirki\App\Supports;
4
5 defined('ABSPATH') || exit;
6
7 use Kirki\App\Constants\PageContentTypes;
8 use Kirki\App\Constants\UtilityPageType;
9 use Kirki\App\DTO\Page\EditorPagePayloadDTO;
10 use Kirki\App\DTO\Symbol\SymbolDTO;
11 use Kirki\App\Models\Page as PageModel;
12 use Kirki\App\Models\Post as PostModel;
13 use Kirki\App\Services\PageService;
14 use Kirki\App\Supports\Facades\Symbol;
15 use Kirki\Framework\Sanitizer;
16 use Kirki\Framework\Supports\Facades\File;
17
18 use function Kirki\App\is_truthy;
19
20 class Template
21 {
22 /**
23 * @param string|string[] $name
24 * @param string|null $prefix
25 *
26 * @return string|string[]
27 */
28 public static function add_prefix_to_class_name($name, $prefix = null)
29 {
30
31 if (is_array($name)) {
32 foreach ($name as $key => $class_name) {
33 $name[$key] = static::add_prefix_to_class_name($class_name, $prefix);
34 }
35
36 return $name;
37 }
38
39 $name = strtolower($name);
40
41 if (!in_array($name, KIRKI_PRESERVED_CLASS_LIST)) {
42 $name = $prefix ? strtolower($prefix) . '-' . $name : $name;
43 }
44
45 return $name;
46 }
47
48 /**
49 * Assign utility page template
50 *
51 * @param int $page_id
52 * @param string $utility_page_type
53 *
54 * @return bool
55 */
56 public static function assign_utility_page_template(int $page_id, string $utility_page_type) {
57 if (in_array($utility_page_type, UtilityPageType::get_constant_values(), true)) {
58 $remote_url = KIRKI_PUBLIC_ASSETS_URL . '/pre-built-pages/basic/' . $utility_page_type . '.zip';
59 return static::process_template($page_id, $remote_url);
60 }
61
62 return false;
63 }
64
65 /**
66 * Assign custom page template
67 *
68 * @param int $page_id
69 * @param string $template_url
70 *
71 * @return bool
72 */
73 public static function assign_custom_page_template(int $page_id, string $template_url) {
74 return static::process_template($page_id, $template_url);
75 }
76
77 /**
78 * Process kirki template zip
79 *
80 * @param int $page_id
81 * @param string $remote_url
82 *
83 * @return bool
84 */
85 protected static function process_template(int $page_id, string $remote_url)
86 {
87 $file_name_new = uniqid('', true) . '.zip'; // 'random.ext'
88 $zip_file_path = FileHandler::download_zip_from_remote($remote_url, $file_name_new);
89
90 if ($zip_file_path) {
91 $json_data = static::save_kirki_template_from_zip($page_id, $zip_file_path);
92
93 if (!empty($json_data)) {
94 // delete zip file
95 File::delete($zip_file_path);
96 return true;
97 }
98 }
99
100 return false;
101 }
102
103 /**
104 * Process kirki template zip
105 *
106 * @param int $page_id
107 * @param string $zip_path
108 * @return bool|array
109 */
110 protected static function save_kirki_template_from_zip(int $page_id, string $zip_path)
111 {
112 if ($page_id === 0) {
113 return false;
114 }
115
116 $kirki_json_data = static::get_kirki_template_from_zip($zip_path);
117
118 $is_include_media = true;
119 $should_process_symbols = true;
120 $kirki_json_data = static::process_template_from_json(
121 $kirki_json_data,
122 !$is_include_media,
123 !$should_process_symbols
124 );
125
126 if (!is_truthy($kirki_json_data)) {
127 return false;
128 }
129
130 $kirki_json_data['blocks']['root'] = [
131 'accept' => '*',
132 'children' => ['body'],
133 'id' => 'root',
134 'name' => 'root',
135 'styleIds' => [],
136 'title' => 'Root',
137 ];
138
139 foreach ($kirki_json_data['styles'] as $key => $style) {
140 $style['name'] = static::add_prefix_to_class_name($style['name'], 'post-' . $page_id);
141 unset($style['isGlobal']);
142 unset($style['isDefault']);
143 unset($style['isGlobalStyle']);
144 $kirki_json_data['styles'][$key] = $style;
145 }
146
147 $payload = EditorPagePayloadDTO::from_array([
148 'page' => PageModel::find($page_id),
149 'data' => $kirki_json_data
150 ]);
151
152 foreach (PageContentTypes::get_constant_values() as $page_content_type) {
153 (new PageService())->save_page_data($payload, $page_content_type);
154 }
155
156 return $kirki_json_data;
157 }
158
159 /**
160 * Process kirki template zip
161 *
162 * @param string $zip_path
163 * @return false|string
164 */
165 protected static function get_kirki_template_from_zip(string $zip_path)
166 {
167 $temp_folder_path = FileHandler::get_temp_folder_path();
168
169 $result = FileHandler::extract_zip_file($zip_path, $temp_folder_path);
170
171 if ($result === false) {
172 File::delete($temp_folder_path);
173 return false;
174 }
175
176 $kirki_json_file = $temp_folder_path . '/kirki-data.json';
177
178 if (File::missing($kirki_json_file)) {
179 File::delete($temp_folder_path);
180
181 return false;
182 }
183
184 $kirki_json_data = File::get($kirki_json_file);
185
186 // delete temp folder
187 File::delete($temp_folder_path);
188
189 if (empty($kirki_json_data)) {
190 return false;
191 }
192
193 return $kirki_json_data;
194 }
195
196 /**
197 * Process kirki template zip
198 *
199 * @param string $kirki_json_data
200 * @param boolean $is_include_media
201 * @param boolean $should_process_symbols
202 *
203 * @return array
204 */
205 protected static function process_template_from_json(string $kirki_json_data, bool $is_include_media = false, bool $should_process_symbols = true)
206 {
207 $kirki_json_data = json_decode($kirki_json_data, true);
208
209 $asset_urls = $kirki_json_data['asset_urls'] ?? [];
210 $blocks = $kirki_json_data['blocks'] ?? [];
211 $symbols = $kirki_json_data['symbols'] ?? [];
212
213 if ($is_include_media) {
214 $uploaded_attachment_ids = static::attach_assets_from_zip($asset_urls);
215 $assets_urls_map = [];
216
217 if (!empty($uploaded_attachment_ids)) {
218 $uploaded_attachment_urls = PostModel::query()
219 ->where_in('ID', array_filter(array_values($uploaded_attachment_ids)))
220 ->get(['ID', 'guid'])
221 ->pluck('guid', 'ID')
222 ->to_array();
223
224 foreach ($asset_urls as $key => $asset_item) {
225 $url = $asset_item['url'];
226 $assets_urls_map[$asset_item['id']] = $asset_item;
227
228 if (!isset($uploaded_attachment_ids[$url])) {
229 $asset_urls[$key] = array_merge($asset_item, [
230 'url' => null,
231 'attachment_id' => 0,
232 'index' => isset($asset_item['index']) ? $asset_item['index'] : null,
233 'thumbnail' => isset($asset_item['thumbnail']) ? $asset_item['thumbnail'] : false,
234 ]);
235
236 continue;
237 }
238
239 $attachment_id = $uploaded_attachment_ids[$url] ?? 0;
240 $attachment_url = $uploaded_attachment_urls[$attachment_id] ?? null;
241
242 $asset_urls[$key] = array_merge($asset_item, [
243 'url' => $attachment_url,
244 'attachment_id' => $attachment_id,
245 'index' => isset($asset_item['index']) ? $asset_item['index'] : null,
246 'thumbnail' => isset($asset_item['thumbnail']) ? $asset_item['thumbnail'] : false,
247 ]);
248 }
249 }
250
251 // update blocks with new asset urls
252 foreach ($asset_urls as $key => $asset_item) {
253 if (
254 !isset($blocks[$asset_item['id']]['name'], $asset_item['name'])
255 || $blocks[$asset_item['id']]['name'] !== $asset_item['name']
256 ) {
257 continue;
258 }
259
260 switch($asset_item['name']) {
261 case 'image':
262 $blocks[$asset_item['id']]['properties']['attributes']['src'] = $asset_item['url'];
263 $blocks[$asset_item['id']]['properties']['wp_attachment_id'] = $asset_item['attachment_id'];
264
265 break;
266 case 'video':
267 if ($asset_item['thumbnail']) {
268 $blocks[$asset_item['id']]['properties']['thumbnail']['url'] = $asset_item['url'];
269 break;
270 }
271
272 $blocks[$asset_item['id']]['properties']['attributes']['src'] = $asset_item['url'];
273 break;
274 case 'lottie':
275 $blocks[$asset_item['id']]['properties']['lottie']['src'] = $asset_item['url'];
276 break;
277 case 'lightbox':
278 if ($asset_item['thumbnail']) {
279 $blocks[ $asset_item['id'] ]['properties']['lightbox']['thumbnail']['src'] = $asset_item['url'];
280 break;
281 }
282
283 $blocks[$asset_item['id']]['properties']['lightbox']['media'][$asset_item['index']]['sources']['original'] = $asset_item['url'];
284 break;
285 }
286 }
287
288 if ($should_process_symbols) {
289 // update symbols with new asset urls
290 foreach ($symbols as $sym_key => $symbol) {
291 foreach ($symbol['symbolData']['data'] as $key => $block) {
292 $block_id = $block['id'];
293
294 if (isset($assets_urls_map[$block_id])) {
295 switch($assets_urls_map[$block_id]['name']) {
296 case 'image':
297 $symbol['symbolData']['data'][$key]['attributes']['src'] = $assets_urls_map[$block_id]['url'];
298 $symbol['symbolData']['data'][$key]['wp_attachment_id'] = $assets_urls_map[$block_id]['attachment_id'];
299 break;
300 case 'video':
301 if ($assets_urls_map[$block_id]['thumbnail']) {
302 $symbol['symbolData']['data'][$key]['thumbnail']['url'] = $assets_urls_map[$block_id]['url'];
303 break;
304 }
305
306 $symbol['symbolData']['data'][$key]['attributes']['src'] = $assets_urls_map[$block_id]['url'];
307 break;
308 case 'lottie':
309 $symbol['symbolData']['data'][$key]['lottie']['src'] = $assets_urls_map[$block_id]['url'];
310 break;
311 case 'lightbox':
312 if ( $assets_urls_map[$block_id]['thumbnail'] ) {
313 $symbol['symbolData']['data'][$key]['lightbox']['thumbnail']['src'] = $assets_urls_map[$block_id]['url'];
314 break;
315 }
316
317 $symbol['symbolData']['data'][$key]['lightbox']['media'][$assets_urls_map[$block_id]['index']]['sources']['original'] = $assets_urls_map[$block_id]['url'];
318 break;
319
320 }
321 }
322 }
323
324 $symbols[$sym_key]['symbolData']['data'] = $symbol['symbolData']['data'];
325 }
326 }
327 }
328
329 $saved_symbols_tracker = [];
330
331 if ($should_process_symbols && is_truthy($symbols)) {
332 foreach ($symbols as $symbol) {
333 $symbol_id = $symbol['id'];
334 $symbol_element_id = $symbol['elementId'];
335
336 // Check if the symbol is already saved
337 if (!isset($saved_symbols_tracker[$symbol_id])) {
338 // Save the symbol to the database
339 $saved_symbol = Symbol::save(SymbolDTO::from_array($symbol));
340
341 // Add the saved symbol to the tracker
342 if ($saved_symbol) {
343 $saved_symbols_tracker[$symbol_id] = $saved_symbol->id ?? null;
344 }
345 }
346
347 // Update all relevant elements with the symbol's ID
348 if (
349 isset($blocks[$symbol_element_id], $saved_symbols_tracker[$symbol_id])
350 && $blocks[$symbol_element_id]['name'] === 'symbol'
351 ) {
352 $blocks[$symbol_element_id]['properties']['symbolId'] = $saved_symbols_tracker[$symbol_id];
353 }
354 }
355 }
356
357 // remove asset_urls
358 unset($kirki_json_data['asset_urls']);
359
360 $kirki_json_data['blocks'] = $blocks;
361 $kirki_json_data['symbols'] = $symbols;
362
363 return $kirki_json_data;
364 }
365
366 protected static function attach_assets_from_zip(array $asset_urls)
367 {
368 $uploaded_attachment_ids = [];
369
370 foreach ($asset_urls as $asset_item) {
371 $url = $asset_item['url'];
372
373 if (isset($uploaded_attachment_ids[$url]) && !empty($uploaded_attachment_ids[$url])) {
374 continue;
375 }
376
377 $attachment_id = null;
378 $asset_name = basename($asset_item['url']);
379 $temp_folder_path = FileHandler::get_temp_folder_path();
380 $source_file_path = $temp_folder_path . '/' . Sanitizer::apply_rule($asset_name, Sanitizer::FILE_NAME);
381
382 if (File::exists($source_file_path)) {
383 $file_name = basename($source_file_path);
384
385 // Upload the file
386 $_FILES['file'] = [
387 'name' => Sanitizer::apply_rule($file_name, Sanitizer::FILE_NAME),
388 'tmp_name' => $source_file_path,
389 ];
390
391 if (!function_exists('media_handle_upload')) {
392 require_once ABSPATH . 'wp-admin/includes/image.php';
393 require_once ABSPATH . 'wp-admin/includes/media.php';
394 }
395
396 $attachment_id = media_handle_upload('file', 0, [], [
397 'test_form' => false,
398 'action' => 'upload-attachment',
399 ]
400 );
401
402 // Check if the upload was successful
403 if (is_wp_error($attachment_id)) {
404 $attachment_id = null;
405 }
406 }
407
408 $uploaded_attachment_ids[$url] = $attachment_id ? (int) $attachment_id : null;
409 }
410
411 return $uploaded_attachment_ids;
412 }
413 }