PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 3.4.0
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v3.4.0
4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / admin / controllers / wizard / class-wizard-template-preview-controller.php
superb-blocks / src / admin / controllers / wizard Last commit date
class-wizard-controller.php 1 year ago class-wizard-restorationpoint-controller.php 1 year ago class-wizard-template-preview-controller.php 1 year ago
class-wizard-template-preview-controller.php
338 lines
1 <?php
2
3 namespace SuperbAddons\Admin\Controllers\Wizard;
4
5 use SuperbAddons\Config\Capabilities;
6 use SuperbAddons\Data\Controllers\CacheController;
7 use SuperbAddons\Data\Utils\CacheTypes;
8 use SuperbAddons\Data\Utils\GutenbergCache;
9 use SuperbAddons\Data\Utils\Wizard\AddonsPageTemplateUtil;
10 use SuperbAddons\Data\Utils\Wizard\WizardItemIdAffix;
11 use SuperbAddons\Data\Utils\Wizard\WizardItemTypes;
12 use WP_Query;
13
14 defined('ABSPATH') || exit();
15
16 class WizardTemplatePreviewController
17 {
18 const TEMPLATE_PREVIEW_KEY = 'superbaddons-template-preview';
19 const TEMPLATE_TYPE_KEY = 'superbaddons-template-type';
20 const USE_PAGE_TEMPLATE_KEY = 'superbaddons-template-custom';
21 const TEMPLATE_PART_PREVIEW_TRANSIENT = 'superbaddons_template_part_preview';
22
23 public static function InitializeTemplatePreview()
24 {
25 if (is_admin()) {
26 return;
27 }
28
29 add_action('wp_loaded', function () {
30 if (isset($_GET[self::TEMPLATE_PREVIEW_KEY]) && isset($_GET[self::TEMPLATE_TYPE_KEY]) && isset($_GET[self::USE_PAGE_TEMPLATE_KEY])) {
31 if (!current_user_can(Capabilities::ADMIN)) return;
32 $template_id = $_GET[self::TEMPLATE_PREVIEW_KEY];
33 $template_type = $_GET[self::TEMPLATE_TYPE_KEY];
34 $template_custom = $_GET[self::USE_PAGE_TEMPLATE_KEY] == 1;
35 show_admin_bar(false);
36 switch ($template_type) {
37 case WizardItemTypes::WP_TEMPLATE:
38 case WizardItemTypes::WP_TEMPLATE_PART:
39 self::SetPlaceholderFilters($template_id, $template_type);
40 self::PreviewBlockTemplate($template_id, $template_type, $template_custom);
41 exit();
42 break;
43 case WizardItemTypes::PATTERN:
44 case WizardItemTypes::PAGE:
45 self::SetPlaceholderFilters($template_id, $template_type);
46 self::PreviewSuperbTemplate($template_id, $template_type, $template_custom);
47 exit();
48 break;
49 default:
50 // Static preview
51 break;
52 }
53 }
54 });
55 }
56
57 private static function SetPlaceholderFilters($template_id, $template_type)
58 {
59 if ($template_type == WizardItemTypes::WP_TEMPLATE_PART || $template_type == WizardItemTypes::PATTERN) {
60 // Enqueue part preview specific styles
61 wp_enqueue_style('superbaddons-wizard-part-preview-styles', SUPERBADDONS_ASSETS_PATH . '/css/page-wizard-preview.min.css', array(), SUPERBADDONS_VERSION);
62 }
63 // Filter the header and footer parts to show a placeholder image instead of the actual content if a preview is requested instead of default theme header/footer.
64 self::FilterHeaderFooterPreviewParts();
65
66 // Set the post ID to 0 to prevent the preview from showing the actual content of the page and to prevent Undefined index: postId in /wp-includes/blocks/comments.php on line 31
67 add_filter("render_block_context", function ($context) {
68 if (isset($context['postId'])) {
69 return $context;
70 }
71 $context['postId'] = 0;
72 return $context;
73 });
74
75 add_filter('the_title', function ($title) use ($template_type, $template_id) {
76 if (!empty($title)) {
77 return $title;
78 }
79 if ($template_type === WizardItemTypes::WP_TEMPLATE) {
80 $template = get_block_template($template_id, WizardItemTypes::WP_TEMPLATE);
81 if ($template) {
82 return $template->title;
83 }
84 }
85
86 return esc_html__("Placeholder Title", "superb-blocks");
87 });
88
89 // Replace the post content with a placeholder content for preview
90 add_filter("the_content", function ($content) {
91 return sprintf('<!-- wp:heading {"level":1,"style":{"spacing":{"padding":{"top":"50px","bottom":"50px","left":"50px","right":"50px"}}}} --> <h1 class="wp-block-heading" style="padding-top:50px;padding-right:50px;padding-bottom:50px;padding-left:50px">%s</h1> <!-- /wp:heading -->', esc_html__("This is a preview of the template. Any page content that you create will appear here.", "superb-blocks"));
92 }, 10);
93
94 // Replace the posts with a placeholder title and placeholder content for preview
95 add_filter('the_posts', function ($posts, $query) {
96 if (!isset($query->query)) {
97 return $posts;
98 }
99
100 if (isset($query->query['post_type']) && $query->query['post_type'] !== 'post') {
101 return $posts;
102 }
103
104 $amount = isset($query->query['posts_per_page']) ? $query->query['posts_per_page'] : 3;
105 $amount = ($amount === -1) ? 3 : min($amount, 10);
106
107 $placeholder_posts = array();
108 for ($i = 0; $i < $amount; $i++) {
109 // Create a placeholder post
110 $placeholder_posts[] = (object)array(
111 'post_title' => esc_html__("Placeholder Post", "superb-blocks") . " " . ($i + 1),
112 'post_content' => '',
113 'post_status' => 'publish',
114 'post_type' => 'post',
115 'post_author' => 1,
116 'post_date' => date('Y-m-d H:i:s'),
117 );
118 }
119 return $placeholder_posts;
120 }, 10, 2);
121
122 // Replace the post thumbnail with a placeholder for preview
123 add_filter("post_thumbnail_html", function () {
124 return self::GetPlaceholderPreviewImage();
125 }, 0, 0);
126
127 // Replace featured image in "Featured Image" blocks with a placeholder for preview
128 add_filter("render_block", function ($block_content, $block) {
129 if (isset($block['blockName']) && $block['blockName'] === 'core/post-featured-image' && empty($block_content)) {
130 return '<figure class="alignwide wp-block-post-featured-image">' . self::GetPlaceholderPreviewImage() . '</figure>';
131 }
132 return $block_content;
133 }, 10, 2);
134
135 // Start global wp_query query to make sure placeholder posts are shown.
136 global $wp_query;
137 if (!$wp_query || !$wp_query instanceof WP_Query) {
138 return;
139 }
140 $wp_query = new WP_Query([
141 'post_type' => 'post',
142 ]);
143 }
144
145 private static function GetPlaceholderPreviewImage()
146 {
147 return '<img width="1900" height="1267" src="' . esc_url(SUPERBADDONS_ASSETS_PATH . "/img/placeholder-image.svg") . '" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" style="height:100%;object-fit:cover;">';
148 }
149
150 private static function PreviewBlockTemplate($template_id, $template_type = WizardItemTypes::WP_TEMPLATE)
151 {
152 if (strpos($template_id, WizardItemIdAffix::FILE_TEMPLATE) !== false) {
153 // If the template is a file template, get the file template preview.
154 $template_id = str_replace(WizardItemIdAffix::FILE_TEMPLATE, '', $template_id);
155 self::PreviewBlockFileTemplate($template_id, $template_type);
156 return;
157 }
158
159 if (strpos($template_id, WizardItemIdAffix::RESTORATION_POINT) !== false) {
160 // If the template is a restoration point, get the restoration point preview.
161 $template_id = str_replace(WizardItemIdAffix::RESTORATION_POINT, '', $template_id);
162 self::PreviewRestorationPoint($template_id);
163 return;
164 }
165
166 $template = get_block_template($template_id, $template_type);
167 if (!$template || $template->type !== $template_type || $template->status !== 'publish' || $template->theme !== get_stylesheet() || empty($template->content)) {
168 return;
169 }
170
171 $template_html = self::GetTheTemplateHTML($template->content);
172
173 self::RenderTemplateCanvas($template_html);
174 }
175
176 private static function PreviewBlockFileTemplate($template_id, $template_type)
177 {
178 $template = get_block_file_template($template_id, $template_type);
179 if ($template->theme !== get_stylesheet() || empty($template->content)) {
180 return;
181 }
182
183 $template_html = self::GetTheTemplateHTML($template->content);
184
185 self::RenderTemplateCanvas($template_html);
186 }
187
188 private static function PreviewRestorationPoint($template_id)
189 {
190 $restoration_point = WizardRestorationPointController::GetTemplateRestorationPoint($template_id);
191 if (!$restoration_point) return;
192
193 $template_html = self::GetTheTemplateHTML($restoration_point['content']);
194
195 self::RenderTemplateCanvas($template_html);
196 }
197
198 private static function PreviewSuperbTemplate($template_id, $template_type = WizardItemTypes::PAGE, $template_custom = false)
199 {
200 //// Get the preview URL from the cache by page id.
201 switch ($template_type) {
202 case WizardItemTypes::PAGE:
203 $cache_type = GutenbergCache::PAGES;
204 break;
205 case WizardItemTypes::PATTERN:
206 $cache_type = GutenbergCache::PATTERNS;
207 break;
208 default:
209 return;
210 }
211 // The cache has already been set, otherwise the preview will not work and we shouldn't be here.
212 $cache = CacheController::GetCache($cache_type, CacheTypes::GUTENBERG);
213 if (!$cache || !isset($cache->items)) return;
214 $preview_url = false;
215 foreach ($cache->items as $template) {
216 if ($template->id === $template_id) {
217 $preview_url = $template->preview;
218 break;
219 }
220 }
221
222 if (!$preview_url) return;
223
224 $preview_content = '<img src="' . esc_url($preview_url) . '" class="superbaddons-preview-image" width="100%" height="auto" style="user-select:none;">';
225
226 if ($template_type === WizardItemTypes::PAGE) {
227 // Override the content with a placeholder content for preview
228 if ($template_custom) {
229 add_filter("the_content", function () use ($preview_content) {
230 return $preview_content;
231 }, PHP_INT_MAX);
232 $template = get_block_template(get_stylesheet() . '//' . AddonsPageTemplateUtil::TEMPLATE_ID, WizardItemTypes::WP_TEMPLATE);
233 $content = $template->content;
234 } else {
235 $content = AddonsPageTemplateUtil::GetAddonsPageTemplateContent($preview_content);
236 }
237 } else {
238 // Preview pattern only
239 $content = $preview_content;
240 }
241
242 $template_html = self::GetTheTemplateHTML($content);
243
244 self::RenderTemplateCanvas($template_html);
245 }
246
247 private static function FilterHeaderFooterPreviewParts()
248 {
249 add_filter('render_block', function ($block_content, $block) {
250 if (isset($block['blockName']) && $block['blockName'] === 'core/template-part') {
251 if (isset($block['attrs']['slug']) && $block['attrs']['slug'] === 'header') {
252 $header_content = self::GetTemplatePartPreview('header');
253 if ($header_content) {
254 return $header_content;
255 }
256 }
257 if (isset($block['attrs']['slug']) && $block['attrs']['slug'] === 'footer') {
258 $footer_content = self::GetTemplatePartPreview('footer');
259 if ($footer_content) {
260 return $footer_content;
261 }
262 }
263 }
264 return $block_content;
265 }, 10, 2);
266 }
267
268 private static function GetTemplatePartPreview($slug)
269 {
270 $template_part_preview = WizardController::GetPartPreviewTransient();
271 if (!$template_part_preview || !isset($template_part_preview[$slug])) {
272 return false;
273 }
274
275 if (strpos($template_part_preview[$slug], WizardItemIdAffix::FILE_TEMPLATE) !== false) {
276 $template_id = get_stylesheet() . '//' . str_replace(WizardItemIdAffix::FILE_TEMPLATE, '', $template_part_preview[$slug]);
277 $template = get_block_file_template($template_id, WizardItemTypes::WP_TEMPLATE_PART);
278 return self::GetTheTemplateHTML($template->content);
279 }
280
281 if (strpos($template_part_preview[$slug], WizardItemIdAffix::RESTORATION_POINT) !== false) {
282 $restoration_id = str_replace(WizardItemIdAffix::RESTORATION_POINT, '', $template_part_preview[$slug]);
283 $restoration_point = WizardRestorationPointController::GetTemplateRestorationPoint($restoration_id);
284 if (!$restoration_point) return false;
285
286 return self::GetTheTemplateHTML($restoration_point['content']);
287 }
288
289
290 if ($template_part_preview[$slug] === $slug || strpos($slug, get_stylesheet()) !== false) return false;
291
292 $cache = CacheController::GetCache(GutenbergCache::PATTERNS, CacheTypes::GUTENBERG);
293 if (!$cache || !isset($cache->items)) return false;
294
295 $preview_url = false;
296 foreach ($cache->items as $template) {
297 if ($template->id === $template_part_preview[$slug]) {
298 $preview_url = $template->preview;
299 break;
300 }
301 }
302
303 if (!$preview_url) return false;
304
305 return '<img src="' . esc_url($preview_url) . '" class="superbaddons-preview-image" width="100%" height="auto" style="user-select:none;">';
306 }
307
308 private static function GetTheTemplateHTML($content)
309 {
310 global $_wp_current_template_content;
311 $_wp_current_template_content = $content;
312 return get_the_block_template_html();
313 }
314
315 private static function RenderTemplateCanvas($content)
316 {
317 ?>
318 <!DOCTYPE html>
319 <html <?php language_attributes(); ?>>
320
321 <head>
322 <meta charset="<?php bloginfo('charset'); ?>" />
323 <?php wp_head(); ?>
324 </head>
325
326 <body <?php body_class(); ?>>
327 <?php wp_body_open(); ?>
328
329 <?php echo $content; ?>
330
331 <?php wp_footer(); ?>
332 </body>
333
334 </html>
335 <?php
336 }
337 }
338