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

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