PluginProbe
Elementor Website Builder – more than just a page builder / 3.22.3
Elementor Website Builder – more than just a page builder v3.22.3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / modules / page-templates / module.php

module.php in Elementor Website Builder – more than just a page builder 3.22.3, at modules/page-templates/module.php

436 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Modules\PageTemplates;
3
4 use Elementor\Controls_Manager;
5 use Elementor\Core\Base\Document;
6 use Elementor\Core\Base\Module as BaseModule;
7 use Elementor\Core\Kits\Documents\Kit;
8 use Elementor\Plugin;
9 use Elementor\Utils;
10 use Elementor\Core\DocumentTypes\PageBase as PageBase;
11 use Elementor\Modules\Library\Documents\Page as LibraryPageDocument;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly
15 }
16
17 /**
18 * Elementor page templates module.
19 *
20 * Elementor page templates module handler class is responsible for registering
21 * and managing Elementor page templates modules.
22 *
23 * @since 2.0.0
24 */
25 class Module extends BaseModule {
26
27 /**
28 * The of the theme.
29 */
30 const TEMPLATE_THEME = 'elementor_theme';
31
32 /**
33 * Elementor Canvas template name.
34 */
35 const TEMPLATE_CANVAS = 'elementor_canvas';
36
37 /**
38 * Elementor Header & Footer template name.
39 */
40 const TEMPLATE_HEADER_FOOTER = 'elementor_header_footer';
41
42 /**
43 * Print callback.
44 *
45 * Holds the page template callback content.
46 *
47 * @since 2.0.0
48 * @access protected
49 *
50 * @var callable
51 */
52 protected $print_callback;
53
54 /**
55 * Get module name.
56 *
57 * Retrieve the page templates module name.
58 *
59 * @since 2.0.0
60 * @access public
61 *
62 * @return string Module name.
63 */
64 public function get_name() {
65 return 'page-templates';
66 }
67
68 /**
69 * Template include.
70 *
71 * Update the path for the Elementor Canvas template.
72 *
73 * Fired by `template_include` filter.
74 *
75 * @since 2.0.0
76 * @access public
77 *
78 * @param string $template The path of the template to include.
79 *
80 * @return string The path of the template to include.
81 */
82 public function template_include( $template ) {
83 if ( is_singular() ) {
84 $document = Plugin::$instance->documents->get_doc_for_frontend( get_the_ID() );
85
86 if ( $document && $document::get_property( 'support_wp_page_templates' ) ) {
87 $page_template = $document->get_meta( '_wp_page_template' );
88
89 $template_path = $this->get_template_path( $page_template );
90
91 if ( self::TEMPLATE_THEME !== $page_template && ! $template_path && $document->is_built_with_elementor() ) {
92 $kit_default_template = Plugin::$instance->kits_manager->get_current_settings( 'default_page_template' );
93 $template_path = $this->get_template_path( $kit_default_template );
94 }
95
96 if ( $template_path ) {
97 $template = $template_path;
98
99 Plugin::$instance->inspector->add_log( 'Page Template', Plugin::$instance->inspector->parse_template_path( $template ), $document->get_edit_url() );
100 }
101 }
102 }
103
104 return $template;
105 }
106
107 /**
108 * Add WordPress templates.
109 *
110 * Adds Elementor templates to all the post types that support
111 * Elementor.
112 *
113 * Fired by `init` action.
114 *
115 * @since 2.0.0
116 * @access public
117 */
118 public function add_wp_templates_support() {
119 $post_types = get_post_types_by_support( 'elementor' );
120
121 foreach ( $post_types as $post_type ) {
122 add_filter( "theme_{$post_type}_templates", [ $this, 'add_page_templates' ], 10, 4 );
123 }
124 }
125
126 /**
127 * Add page templates.
128 *
129 * Add the Elementor page templates to the theme templates.
130 *
131 * Fired by `theme_{$post_type}_templates` filter.
132 *
133 * @since 2.0.0
134 * @access public
135 * @static
136 *
137 * @param array $page_templates Array of page templates. Keys are filenames,
138 * checks are translated names.
139 *
140 * @param \WP_Theme $wp_theme
141 * @param \WP_Post $post
142 *
143 * @return array Page templates.
144 */
145 public function add_page_templates( $page_templates, $wp_theme, $post ) {
146 if ( $post ) {
147 // FIX ME: Gutenberg not send $post as WP_Post object, just the post ID.
148 $post_id = ! empty( $post->ID ) ? $post->ID : $post;
149
150 $document = Plugin::$instance->documents->get( $post_id );
151 if ( $document && ! $document::get_property( 'support_wp_page_templates' ) ) {
152 return $page_templates;
153 }
154 }
155
156 $page_templates = [
157 self::TEMPLATE_CANVAS => esc_html__( 'Elementor Canvas', 'elementor' ),
158 self::TEMPLATE_HEADER_FOOTER => esc_html__( 'Elementor Full Width', 'elementor' ),
159 self::TEMPLATE_THEME => esc_html__( 'Theme', 'elementor' ),
160 ] + $page_templates;
161
162 return $page_templates;
163 }
164
165 /**
166 * Set print callback.
167 *
168 * Set the page template callback.
169 *
170 * @since 2.0.0
171 * @access public
172 *
173 * @param callable $callback
174 */
175 public function set_print_callback( $callback ) {
176 $this->print_callback = $callback;
177 }
178
179 /**
180 * Print callback.
181 *
182 * Prints the page template content using WordPress loop.
183 *
184 * @since 2.0.0
185 * @access public
186 */
187 public function print_callback() {
188 while ( have_posts() ) :
189 the_post();
190 the_content();
191 endwhile;
192 }
193
194 /**
195 * Print content.
196 *
197 * Prints the page template content.
198 *
199 * @since 2.0.0
200 * @access public
201 */
202 public function print_content() {
203 if ( ! $this->print_callback ) {
204 $this->print_callback = [ $this, 'print_callback' ];
205 }
206
207 call_user_func( $this->print_callback );
208 }
209
210 /**
211 * Get page template path.
212 *
213 * Retrieve the path for any given page template.
214 *
215 * @since 2.0.0
216 * @access public
217 *
218 * @param string $page_template The page template name.
219 *
220 * @return string Page template path.
221 */
222 public function get_template_path( $page_template ) {
223 $template_path = '';
224 switch ( $page_template ) {
225 case self::TEMPLATE_CANVAS:
226 $template_path = __DIR__ . '/templates/canvas.php';
227 break;
228 case self::TEMPLATE_HEADER_FOOTER:
229 $template_path = __DIR__ . '/templates/header-footer.php';
230 break;
231 }
232
233 return $template_path;
234 }
235
236 /**
237 * Register template control.
238 *
239 * Adds custom controls to any given document.
240 *
241 * Fired by `update_post_metadata` action.
242 *
243 * @since 2.0.0
244 * @access public
245 *
246 * @param Document $document The document instance.
247 */
248 public function action_register_template_control( $document ) {
249 if (
250 ( $document instanceof PageBase || $document instanceof LibraryPageDocument ) &&
251 $document::get_property( 'support_page_layout' )
252 ) {
253 $this->register_template_control( $document );
254 }
255 }
256
257 /**
258 * Register template control.
259 *
260 * Adds custom controls to any given document.
261 *
262 * @since 2.0.0
263 * @access public
264 *
265 * @param Document $document The document instance.
266 * @param string $control_id Optional. The control ID. Default is `template`.
267 */
268 public function register_template_control( $document, $control_id = 'template' ) {
269 if ( ! Utils::is_cpt_custom_templates_supported() ) {
270 return;
271 }
272
273 require_once ABSPATH . '/wp-admin/includes/template.php';
274
275 $document->start_injection( [
276 'of' => 'post_status',
277 'fallback' => [
278 'of' => 'post_title',
279 ],
280 ] );
281
282 $control_options = [
283 'options' => array_flip( get_page_templates( null, $document->get_main_post()->post_type ) ),
284 ];
285
286 $this->add_template_controls( $document, $control_id, $control_options );
287
288 $document->end_injection();
289 }
290
291 // The $options variable is an array of $control_options to overwrite the default
292 public function add_template_controls( Document $document, $control_id, $control_options ) {
293 // Default Control Options
294 $default_control_options = [
295 'label' => esc_html__( 'Page Layout', 'elementor' ),
296 'type' => Controls_Manager::SELECT,
297 'default' => 'default',
298 'options' => [
299 'default' => esc_html__( 'Default', 'elementor' ),
300 ],
301 ];
302
303 $control_options = array_replace_recursive( $default_control_options, $control_options );
304
305 $document->add_control(
306 $control_id,
307 $control_options
308 );
309
310 $document->add_control(
311 $control_id . '_default_description',
312 [
313 'type' => Controls_Manager::RAW_HTML,
314 'raw' => '<b>' . esc_html__( 'The default page template as defined in Elementor Panel → Hamburger Menu → Site Settings.', 'elementor' ) . '</b>',
315 'content_classes' => 'elementor-descriptor',
316 'condition' => [
317 $control_id => 'default',
318 ],
319 ]
320 );
321
322 $document->add_control(
323 $control_id . '_theme_description',
324 [
325 'type' => Controls_Manager::RAW_HTML,
326 'raw' => '<b>' . esc_html__( 'Default Page Template from your theme.', 'elementor' ) . '</b>',
327 'content_classes' => 'elementor-descriptor',
328 'condition' => [
329 $control_id => self::TEMPLATE_THEME,
330 ],
331 ]
332 );
333
334 $document->add_control(
335 $control_id . '_canvas_description',
336 [
337 'type' => Controls_Manager::RAW_HTML,
338 'raw' => '<b>' . esc_html__( 'No header, no footer, just Elementor', 'elementor' ) . '</b>',
339 'content_classes' => 'elementor-descriptor',
340 'condition' => [
341 $control_id => self::TEMPLATE_CANVAS,
342 ],
343 ]
344 );
345
346 $document->add_control(
347 $control_id . '_header_footer_description',
348 [
349 'type' => Controls_Manager::RAW_HTML,
350 'raw' => '<b>' . esc_html__( 'This template includes the header, full-width content and footer', 'elementor' ) . '</b>',
351 'content_classes' => 'elementor-descriptor',
352 'condition' => [
353 $control_id => self::TEMPLATE_HEADER_FOOTER,
354 ],
355 ]
356 );
357
358 if ( $document instanceof Kit ) {
359 $document->add_control(
360 'reload_preview_description',
361 [
362 'type' => Controls_Manager::RAW_HTML,
363 'raw' => esc_html__( 'Changes will be reflected in the preview only after the page reloads.', 'elementor' ),
364 'content_classes' => 'elementor-descriptor',
365 ]
366 );
367 }
368 }
369
370 /**
371 * Filter metadata update.
372 *
373 * Filters whether to update metadata of a specific type.
374 *
375 * Elementor don't allow WordPress to update the parent page template
376 * during `wp_update_post`.
377 *
378 * Fired by `update_{$meta_type}_metadata` filter.
379 *
380 * @since 2.0.0
381 * @access public
382 *
383 * @param bool $check Whether to allow updating metadata for the given type.
384 * @param int $object_id Object ID.
385 * @param string $meta_key Meta key.
386 *
387 * @return bool Whether to allow updating metadata of a specific type.
388 */
389 public function filter_update_meta( $check, $object_id, $meta_key ) {
390 if ( '_wp_page_template' === $meta_key && Plugin::$instance->common ) {
391 /** @var \Elementor\Core\Common\Modules\Ajax\Module $ajax */
392 $ajax = Plugin::$instance->common->get_component( 'ajax' );
393
394 $ajax_data = $ajax->get_current_action_data();
395
396 $is_autosave_action = $ajax_data && 'save_builder' === $ajax_data['action'] && Document::STATUS_AUTOSAVE === $ajax_data['data']['status'];
397
398 // Don't allow WP to update the parent page template.
399 // (during `wp_update_post` from page-settings or save_plain_text).
400 if ( $is_autosave_action && ! wp_is_post_autosave( $object_id ) && Document::STATUS_DRAFT !== get_post_status( $object_id ) ) {
401 $check = false;
402 }
403 }
404
405 return $check;
406 }
407
408 /**
409 * Support `wp_body_open` action, available since WordPress 5.2.
410 *
411 * @since 2.7.0
412 * @access public
413 */
414 public static function body_open() {
415 wp_body_open();
416 }
417
418 /**
419 * Page templates module constructor.
420 *
421 * Initializing Elementor page templates module.
422 *
423 * @since 2.0.0
424 * @access public
425 */
426 public function __construct() {
427 add_action( 'init', [ $this, 'add_wp_templates_support' ] );
428
429 add_filter( 'template_include', [ $this, 'template_include' ], 11 /* After Plugins/WooCommerce */ );
430
431 add_action( 'elementor/documents/register_controls', [ $this, 'action_register_template_control' ] );
432
433 add_filter( 'update_post_metadata', [ $this, 'filter_update_meta' ], 10, 3 );
434 }
435 }
436