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

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