PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.0-dev1
Elementor Website Builder – more than just a page builder v3.6.0-dev1
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.6.0-dev1, at modules/page-templates/module.php

437 lines 11.1 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 => _x( 'Elementor Canvas', 'Page Template', 'elementor' ),
158 self::TEMPLATE_HEADER_FOOTER => _x( 'Elementor Full Width', 'Page Template', 'elementor' ),
159 self::TEMPLATE_THEME => _x( 'Theme', 'Page Template', '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 ( $document instanceof PageBase || $document instanceof LibraryPageDocument ) {
250 $this->register_template_control( $document );
251 }
252 }
253
254 /**
255 * Register template control.
256 *
257 * Adds custom controls to any given document.
258 *
259 * @since 2.0.0
260 * @access public
261 *
262 * @param Document $document The document instance.
263 * @param string $control_id Optional. The control ID. Default is `template`.
264 */
265 public function register_template_control( $document, $control_id = 'template' ) {
266 if ( ! Utils::is_cpt_custom_templates_supported() ) {
267 return;
268 }
269
270 require_once ABSPATH . '/wp-admin/includes/template.php';
271
272 $document->start_injection( [
273 'of' => 'post_status',
274 'fallback' => [
275 'of' => 'post_title',
276 ],
277 ] );
278
279 $control_options = [
280 'options' => array_flip( get_page_templates( null, $document->get_main_post()->post_type ) ),
281 ];
282
283 $this->add_template_controls( $document, $control_id, $control_options );
284
285 $document->end_injection();
286 }
287
288 // The $options variable is an array of $control_options to overwrite the default
289 public function add_template_controls( Document $document, $control_id, $control_options ) {
290 // Default Control Options
291 $default_control_options = [
292 'label' => esc_html__( 'Page Layout', 'elementor' ),
293 'type' => Controls_Manager::SELECT,
294 'default' => 'default',
295 'options' => [
296 'default' => esc_html__( 'Default', 'elementor' ),
297 ],
298 ];
299
300 $control_options = array_replace_recursive( $default_control_options, $control_options );
301
302 $document->add_control(
303 $control_id,
304 $control_options
305 );
306
307 $document->add_control(
308 $control_id . '_default_description',
309 [
310 'type' => Controls_Manager::RAW_HTML,
311 'raw' => '<b>' . esc_html__( 'The default page template as defined in Elementor Panel → Hamburger Menu → Site Settings.', 'elementor' ) . '</b>',
312 'content_classes' => 'elementor-descriptor',
313 'condition' => [
314 $control_id => 'default',
315 ],
316 ]
317 );
318
319 $document->add_control(
320 $control_id . '_theme_description',
321 [
322 'type' => Controls_Manager::RAW_HTML,
323 'raw' => '<b>' . esc_html__( 'Default Page Template from your theme.', 'elementor' ) . '</b>',
324 'content_classes' => 'elementor-descriptor',
325 'condition' => [
326 $control_id => self::TEMPLATE_THEME,
327 ],
328 ]
329 );
330
331 $document->add_control(
332 $control_id . '_canvas_description',
333 [
334 'type' => Controls_Manager::RAW_HTML,
335 'raw' => '<b>' . esc_html__( 'No header, no footer, just Elementor', 'elementor' ) . '</b>',
336 'content_classes' => 'elementor-descriptor',
337 'condition' => [
338 $control_id => self::TEMPLATE_CANVAS,
339 ],
340 ]
341 );
342
343 $document->add_control(
344 $control_id . '_header_footer_description',
345 [
346 'type' => Controls_Manager::RAW_HTML,
347 'raw' => '<b>' . esc_html__( 'This template includes the header, full-width content and footer', 'elementor' ) . '</b>',
348 'content_classes' => 'elementor-descriptor',
349 'condition' => [
350 $control_id => self::TEMPLATE_HEADER_FOOTER,
351 ],
352 ]
353 );
354
355 if ( $document instanceof Kit ) {
356 $document->add_control(
357 'reload_preview_description',
358 [
359 'type' => Controls_Manager::RAW_HTML,
360 'raw' => esc_html__( 'Changes will be reflected in the preview only after the page reloads.', 'elementor' ),
361 'content_classes' => 'elementor-descriptor',
362 ]
363 );
364 }
365 }
366
367 /**
368 * Filter metadata update.
369 *
370 * Filters whether to update metadata of a specific type.
371 *
372 * Elementor don't allow WordPress to update the parent page template
373 * during `wp_update_post`.
374 *
375 * Fired by `update_{$meta_type}_metadata` filter.
376 *
377 * @since 2.0.0
378 * @access public
379 *
380 * @param bool $check Whether to allow updating metadata for the given type.
381 * @param int $object_id Object ID.
382 * @param string $meta_key Meta key.
383 *
384 * @return bool Whether to allow updating metadata of a specific type.
385 */
386 public function filter_update_meta( $check, $object_id, $meta_key ) {
387 if ( '_wp_page_template' === $meta_key && Plugin::$instance->common ) {
388 /** @var \Elementor\Core\Common\Modules\Ajax\Module $ajax */
389 $ajax = Plugin::$instance->common->get_component( 'ajax' );
390
391 $ajax_data = $ajax->get_current_action_data();
392
393 $is_autosave_action = $ajax_data && 'save_builder' === $ajax_data['action'] && Document::STATUS_AUTOSAVE === $ajax_data['data']['status'];
394
395 // Don't allow WP to update the parent page template.
396 // (during `wp_update_post` from page-settings or save_plain_text).
397 if ( $is_autosave_action && ! wp_is_post_autosave( $object_id ) && Document::STATUS_DRAFT !== get_post_status( $object_id ) ) {
398 $check = false;
399 }
400 }
401
402 return $check;
403 }
404
405 /**
406 * Support `wp_body_open` action, available since WordPress 5.2.
407 *
408 * @since 2.7.0
409 * @access public
410 */
411 public static function body_open() {
412 if ( function_exists( 'wp_body_open' ) ) {
413 wp_body_open();
414 } else {
415 do_action( 'wp_body_open' );
416 }
417 }
418
419 /**
420 * Page templates module constructor.
421 *
422 * Initializing Elementor page templates module.
423 *
424 * @since 2.0.0
425 * @access public
426 */
427 public function __construct() {
428 add_action( 'init', [ $this, 'add_wp_templates_support' ] );
429
430 add_filter( 'template_include', [ $this, 'template_include' ], 11 /* After Plugins/WooCommerce */ );
431
432 add_action( 'elementor/documents/register_controls', [ $this, 'action_register_template_control' ] );
433
434 add_filter( 'update_post_metadata', [ $this, 'filter_update_meta' ], 10, 3 );
435 }
436 }
437