436 lines
11 KiB
PHP
436 lines
11 KiB
PHP
<?php
|
|
namespace Elementor\Modules\PageTemplates;
|
|
|
|
use Elementor\Controls_Manager;
|
|
use Elementor\Core\Base\Document;
|
|
use Elementor\Core\Base\Module as BaseModule;
|
|
use Elementor\Core\Kits\Documents\Kit;
|
|
use Elementor\Plugin;
|
|
use Elementor\Utils;
|
|
use Elementor\Core\DocumentTypes\PageBase as PageBase;
|
|
use Elementor\Modules\Library\Documents\Page as LibraryPageDocument;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly
|
|
}
|
|
|
|
/**
|
|
* Elementor page templates module.
|
|
*
|
|
* Elementor page templates module handler class is responsible for registering
|
|
* and managing Elementor page templates modules.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
class Module extends BaseModule {
|
|
|
|
/**
|
|
* The of the theme.
|
|
*/
|
|
const TEMPLATE_THEME = 'elementor_theme';
|
|
|
|
/**
|
|
* Elementor Canvas template name.
|
|
*/
|
|
const TEMPLATE_CANVAS = 'elementor_canvas';
|
|
|
|
/**
|
|
* Elementor Header & Footer template name.
|
|
*/
|
|
const TEMPLATE_HEADER_FOOTER = 'elementor_header_footer';
|
|
|
|
/**
|
|
* Print callback.
|
|
*
|
|
* Holds the page template callback content.
|
|
*
|
|
* @since 2.0.0
|
|
* @access protected
|
|
*
|
|
* @var callable
|
|
*/
|
|
protected $print_callback;
|
|
|
|
/**
|
|
* Get module name.
|
|
*
|
|
* Retrieve the page templates module name.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @return string Module name.
|
|
*/
|
|
public function get_name() {
|
|
return 'page-templates';
|
|
}
|
|
|
|
/**
|
|
* Template include.
|
|
*
|
|
* Update the path for the Elementor Canvas template.
|
|
*
|
|
* Fired by `template_include` filter.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param string $template The path of the template to include.
|
|
*
|
|
* @return string The path of the template to include.
|
|
*/
|
|
public function template_include( $template ) {
|
|
if ( is_singular() ) {
|
|
$document = Plugin::$instance->documents->get_doc_for_frontend( get_the_ID() );
|
|
|
|
if ( $document && $document::get_property( 'support_wp_page_templates' ) ) {
|
|
$page_template = $document->get_meta( '_wp_page_template' );
|
|
|
|
$template_path = $this->get_template_path( $page_template );
|
|
|
|
if ( self::TEMPLATE_THEME !== $page_template && ! $template_path && $document->is_built_with_elementor() ) {
|
|
$kit_default_template = Plugin::$instance->kits_manager->get_current_settings( 'default_page_template' );
|
|
$template_path = $this->get_template_path( $kit_default_template );
|
|
}
|
|
|
|
if ( $template_path ) {
|
|
$template = $template_path;
|
|
|
|
Plugin::$instance->inspector->add_log( 'Page Template', Plugin::$instance->inspector->parse_template_path( $template ), $document->get_edit_url() );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $template;
|
|
}
|
|
|
|
/**
|
|
* Add WordPress templates.
|
|
*
|
|
* Adds Elementor templates to all the post types that support
|
|
* Elementor.
|
|
*
|
|
* Fired by `init` action.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*/
|
|
public function add_wp_templates_support() {
|
|
$post_types = get_post_types_by_support( 'elementor' );
|
|
|
|
foreach ( $post_types as $post_type ) {
|
|
add_filter( "theme_{$post_type}_templates", [ $this, 'add_page_templates' ], 10, 4 );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add page templates.
|
|
*
|
|
* Add the Elementor page templates to the theme templates.
|
|
*
|
|
* Fired by `theme_{$post_type}_templates` filter.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
* @static
|
|
*
|
|
* @param array $page_templates Array of page templates. Keys are filenames,
|
|
* checks are translated names.
|
|
*
|
|
* @param \WP_Theme $wp_theme
|
|
* @param \WP_Post $post
|
|
*
|
|
* @return array Page templates.
|
|
*/
|
|
public function add_page_templates( $page_templates, $wp_theme, $post ) {
|
|
if ( $post ) {
|
|
// FIX ME: Gutenberg not send $post as WP_Post object, just the post ID.
|
|
$post_id = ! empty( $post->ID ) ? $post->ID : $post;
|
|
|
|
$document = Plugin::$instance->documents->get( $post_id );
|
|
if ( $document && ! $document::get_property( 'support_wp_page_templates' ) ) {
|
|
return $page_templates;
|
|
}
|
|
}
|
|
|
|
$page_templates = [
|
|
self::TEMPLATE_CANVAS => esc_html__( 'Elementor Canvas', 'elementor' ),
|
|
self::TEMPLATE_HEADER_FOOTER => esc_html__( 'Elementor Full Width', 'elementor' ),
|
|
self::TEMPLATE_THEME => esc_html__( 'Theme', 'elementor' ),
|
|
] + $page_templates;
|
|
|
|
return $page_templates;
|
|
}
|
|
|
|
/**
|
|
* Set print callback.
|
|
*
|
|
* Set the page template callback.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param callable $callback
|
|
*/
|
|
public function set_print_callback( $callback ) {
|
|
$this->print_callback = $callback;
|
|
}
|
|
|
|
/**
|
|
* Print callback.
|
|
*
|
|
* Prints the page template content using WordPress loop.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*/
|
|
public function print_callback() {
|
|
while ( have_posts() ) :
|
|
the_post();
|
|
the_content();
|
|
endwhile;
|
|
}
|
|
|
|
/**
|
|
* Print content.
|
|
*
|
|
* Prints the page template content.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*/
|
|
public function print_content() {
|
|
if ( ! $this->print_callback ) {
|
|
$this->print_callback = [ $this, 'print_callback' ];
|
|
}
|
|
|
|
call_user_func( $this->print_callback );
|
|
}
|
|
|
|
/**
|
|
* Get page template path.
|
|
*
|
|
* Retrieve the path for any given page template.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param string $page_template The page template name.
|
|
*
|
|
* @return string Page template path.
|
|
*/
|
|
public function get_template_path( $page_template ) {
|
|
$template_path = '';
|
|
switch ( $page_template ) {
|
|
case self::TEMPLATE_CANVAS:
|
|
$template_path = __DIR__ . '/templates/canvas.php';
|
|
break;
|
|
case self::TEMPLATE_HEADER_FOOTER:
|
|
$template_path = __DIR__ . '/templates/header-footer.php';
|
|
break;
|
|
}
|
|
|
|
return $template_path;
|
|
}
|
|
|
|
/**
|
|
* Register template control.
|
|
*
|
|
* Adds custom controls to any given document.
|
|
*
|
|
* Fired by `update_post_metadata` action.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param Document $document The document instance.
|
|
*/
|
|
public function action_register_template_control( $document ) {
|
|
if (
|
|
( $document instanceof PageBase || $document instanceof LibraryPageDocument ) &&
|
|
$document::get_property( 'support_page_layout' )
|
|
) {
|
|
$this->register_template_control( $document );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register template control.
|
|
*
|
|
* Adds custom controls to any given document.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param Document $document The document instance.
|
|
* @param string $control_id Optional. The control ID. Default is `template`.
|
|
*/
|
|
public function register_template_control( $document, $control_id = 'template' ) {
|
|
if ( ! Utils::is_cpt_custom_templates_supported() ) {
|
|
return;
|
|
}
|
|
|
|
require_once ABSPATH . '/wp-admin/includes/template.php';
|
|
|
|
$document->start_injection( [
|
|
'of' => 'post_status',
|
|
'fallback' => [
|
|
'of' => 'post_title',
|
|
],
|
|
] );
|
|
|
|
$control_options = [
|
|
'options' => array_flip( get_page_templates( null, $document->get_main_post()->post_type ) ),
|
|
];
|
|
|
|
$this->add_template_controls( $document, $control_id, $control_options );
|
|
|
|
$document->end_injection();
|
|
}
|
|
|
|
// The $options variable is an array of $control_options to overwrite the default
|
|
public function add_template_controls( Document $document, $control_id, $control_options ) {
|
|
// Default Control Options
|
|
$default_control_options = [
|
|
'label' => esc_html__( 'Page Layout', 'elementor' ),
|
|
'type' => Controls_Manager::SELECT,
|
|
'default' => 'default',
|
|
'options' => [
|
|
'default' => esc_html__( 'Default', 'elementor' ),
|
|
],
|
|
];
|
|
|
|
$control_options = array_replace_recursive( $default_control_options, $control_options );
|
|
|
|
$document->add_control(
|
|
$control_id,
|
|
$control_options
|
|
);
|
|
|
|
$document->add_control(
|
|
$control_id . '_default_description',
|
|
[
|
|
'type' => Controls_Manager::RAW_HTML,
|
|
'raw' => '<b>' . esc_html__( 'The default page template as defined in Elementor Panel → Hamburger Menu → Site Settings.', 'elementor' ) . '</b>',
|
|
'content_classes' => 'elementor-descriptor',
|
|
'condition' => [
|
|
$control_id => 'default',
|
|
],
|
|
]
|
|
);
|
|
|
|
$document->add_control(
|
|
$control_id . '_theme_description',
|
|
[
|
|
'type' => Controls_Manager::RAW_HTML,
|
|
'raw' => '<b>' . esc_html__( 'Default Page Template from your theme.', 'elementor' ) . '</b>',
|
|
'content_classes' => 'elementor-descriptor',
|
|
'condition' => [
|
|
$control_id => self::TEMPLATE_THEME,
|
|
],
|
|
]
|
|
);
|
|
|
|
$document->add_control(
|
|
$control_id . '_canvas_description',
|
|
[
|
|
'type' => Controls_Manager::RAW_HTML,
|
|
'raw' => '<b>' . esc_html__( 'No header, no footer, just Elementor', 'elementor' ) . '</b>',
|
|
'content_classes' => 'elementor-descriptor',
|
|
'condition' => [
|
|
$control_id => self::TEMPLATE_CANVAS,
|
|
],
|
|
]
|
|
);
|
|
|
|
$document->add_control(
|
|
$control_id . '_header_footer_description',
|
|
[
|
|
'type' => Controls_Manager::RAW_HTML,
|
|
'raw' => '<b>' . esc_html__( 'This template includes the header, full-width content and footer', 'elementor' ) . '</b>',
|
|
'content_classes' => 'elementor-descriptor',
|
|
'condition' => [
|
|
$control_id => self::TEMPLATE_HEADER_FOOTER,
|
|
],
|
|
]
|
|
);
|
|
|
|
if ( $document instanceof Kit ) {
|
|
$document->add_control(
|
|
'reload_preview_description',
|
|
[
|
|
'type' => Controls_Manager::RAW_HTML,
|
|
'raw' => esc_html__( 'Changes will be reflected in the preview only after the page reloads.', 'elementor' ),
|
|
'content_classes' => 'elementor-descriptor',
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filter metadata update.
|
|
*
|
|
* Filters whether to update metadata of a specific type.
|
|
*
|
|
* Elementor don't allow WordPress to update the parent page template
|
|
* during `wp_update_post`.
|
|
*
|
|
* Fired by `update_{$meta_type}_metadata` filter.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*
|
|
* @param bool $check Whether to allow updating metadata for the given type.
|
|
* @param int $object_id Object ID.
|
|
* @param string $meta_key Meta key.
|
|
*
|
|
* @return bool Whether to allow updating metadata of a specific type.
|
|
*/
|
|
public function filter_update_meta( $check, $object_id, $meta_key ) {
|
|
if ( '_wp_page_template' === $meta_key && Plugin::$instance->common ) {
|
|
/** @var \Elementor\Core\Common\Modules\Ajax\Module $ajax */
|
|
$ajax = Plugin::$instance->common->get_component( 'ajax' );
|
|
|
|
$ajax_data = $ajax->get_current_action_data();
|
|
|
|
$is_autosave_action = $ajax_data && 'save_builder' === $ajax_data['action'] && Document::STATUS_AUTOSAVE === $ajax_data['data']['status'];
|
|
|
|
// Don't allow WP to update the parent page template.
|
|
// (during `wp_update_post` from page-settings or save_plain_text).
|
|
if ( $is_autosave_action && ! wp_is_post_autosave( $object_id ) && Document::STATUS_DRAFT !== get_post_status( $object_id ) ) {
|
|
$check = false;
|
|
}
|
|
}
|
|
|
|
return $check;
|
|
}
|
|
|
|
/**
|
|
* Support `wp_body_open` action, available since WordPress 5.2.
|
|
*
|
|
* @since 2.7.0
|
|
* @access public
|
|
*/
|
|
public static function body_open() {
|
|
wp_body_open();
|
|
}
|
|
|
|
/**
|
|
* Page templates module constructor.
|
|
*
|
|
* Initializing Elementor page templates module.
|
|
*
|
|
* @since 2.0.0
|
|
* @access public
|
|
*/
|
|
public function __construct() {
|
|
add_action( 'init', [ $this, 'add_wp_templates_support' ] );
|
|
|
|
add_filter( 'template_include', [ $this, 'template_include' ], 11 /* After Plugins/WooCommerce */ );
|
|
|
|
add_action( 'elementor/documents/register_controls', [ $this, 'action_register_template_control' ] );
|
|
|
|
add_filter( 'update_post_metadata', [ $this, 'filter_update_meta' ], 10, 3 );
|
|
}
|
|
}
|