Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,79 @@
<?php
namespace Elementor\Core\Base;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

abstract class Module {

/**
* @var \ReflectionClass
*/
private $reflection;

private $components = [];

/**
* @var Module
*/
protected static $_instances = [];

/**
* Throw error on object clone
*
* The whole idea of the singleton design pattern is that there is a single
* object therefore, we don't want the object to be cloned.
*
* @since 1.0.0
* @return void
*/
public function __clone() {
// Cloning instances of the class is forbidden
_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'elementor' ), '1.0.0' );
}

/**
* Disable unserializing of the class
*
* @since 1.0.0
* @return void
*/
public function __wakeup() {
// Unserializing instances of the class is forbidden
_doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin&#8217; huh?', 'elementor' ), '1.0.0' );
}

public static function class_name() {
return get_called_class();
}

/**
* @return static
*/
public static function instance() {
if ( empty( static::$_instances[ static::class_name() ] ) ) {
static::$_instances[ static::class_name() ] = new static();
}

return static::$_instances[ static::class_name() ];
}

abstract public function get_name();

public function __construct() {
$this->reflection = new \ReflectionClass( $this );
}

public function add_component( $id, $instance ) {
$this->components[ $id ] = $instance;
}

public function get_component( $id ) {
if ( isset( $this->components[ $id ] ) ) {
return $this->components[ $id ];
}

return false;
}
}
@@ -0,0 +1,25 @@
<?php
namespace Elementor\Core;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

final class Modules_Manager {

private $modules = null;

public function __construct() {
$modules = [
'history'
];

foreach ( $modules as $module_id ) {
$class_name = str_replace( '-', ' ', $module_id );
$class_name = str_replace( ' ', '', ucwords( $class_name ) );
$class_name = 'Elementor\\Modules\\' . $class_name . '\Module';

$this->modules[ $module_id ] = $class_name::instance();
}
}
}
@@ -0,0 +1,192 @@
<?php
namespace Elementor\Core\Settings\Base;

use Elementor\CSS_File;
use Elementor\Plugin;
use Elementor\Utils;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

abstract class Manager {

/**
* @var Model[]
*/
private $models_cache = [];

public function __construct() {
if ( Utils::is_ajax() ) {
add_action( 'wp_ajax_elementor_save_' . $this->get_name() . '_settings', [ $this, 'ajax_save_settings' ] );
}

add_action( 'elementor/init', [ $this, 'on_elementor_init' ] );

add_action( 'elementor/' . $this->get_css_file_name() . '-css-file/parse', [ $this, 'add_settings_css_rules' ] );
}

/**
* @return Model
*/
abstract public function get_model_for_config();

/**
* @return string
*/
abstract public function get_name();

/**
* @param int $id
*
* @return Model
*/
final public function get_model( $id = 0 ) {
if ( ! isset( $this->models_cache[ $id ] ) ) {
$this->create_model( $id );
}

return $this->models_cache[ $id ];
}

final public function ajax_save_settings() {
Plugin::$instance->editor->verify_ajax_nonce();

$data = json_decode( stripslashes( $_POST['data'] ), true );

$id = 0;

if ( ! empty( $_POST['id'] ) ) {
$id = $_POST['id'];
}

$this->ajax_before_save_settings( $data, $id );

$this->save_settings( $data, $id );

$success_response_data = apply_filters( 'elementor/' . $this->get_name() . '/settings/success_response_data', [], $id, $data );

wp_send_json_success( $success_response_data );
}

final public function save_settings( array $settings, $id = 0 ) {
$special_settings = $this->get_special_settings_names();

$settings_to_save = $settings;

foreach ( $special_settings as $special_setting ) {
if ( isset( $settings_to_save[ $special_setting ] ) ) {
unset( $settings_to_save[ $special_setting ] );
}
}

$this->save_settings_to_db( $settings_to_save, $id );

// Clear cache after save.
if ( isset( $this->models_cache[ $id ] ) ) {
unset( $this->models_cache[ $id ] );
}

$css_file = $this->get_css_file_for_update( $id );

$css_file->update();
}

public function add_settings_css_rules( CSS_File $css_file ) {
$model = $this->get_model_for_css_file( $css_file );

$css_file->add_controls_stack_style_rules(
$model,
$model->get_style_controls(),
$model->get_settings(),
[ '{{WRAPPER}}' ],
[ $model->get_css_wrapper_selector() ]
);
}

public function on_elementor_init() {
Plugin::$instance->editor->add_editor_template( $this->get_editor_template(), 'text' );
}

/**
* @param int $id
*
* @return array
*/
abstract protected function get_saved_settings( $id );

/**
* @return string
*/
abstract protected function get_css_file_name();

/**
* @param array $settings
* @param int $id
*
* @return void
*/
abstract protected function save_settings_to_db( array $settings, $id );

/**
* @param CSS_File $css_file
*
* @return Model
*/
abstract protected function get_model_for_css_file( CSS_File $css_file );

/**
* @param int $id
*
* @return CSS_File
*/
abstract protected function get_css_file_for_update( $id );

protected function get_special_settings_names() {
return [];
}

protected function ajax_before_save_settings( array $data, $id ) {}

protected function print_editor_template_content( $name ) {
?>
<div class="elementor-panel-navigation">
<# _.each( elementor.config.settings.<?php echo $name; ?>.tabs, function( tabTitle, tabSlug ) { #>
<div class="elementor-panel-navigation-tab elementor-tab-control-{{ tabSlug }}" data-tab="{{ tabSlug }}">
<a href="#">{{{ tabTitle }}}</a>
</div>
<# } ); #>
</div>
<div id="elementor-panel-<?php echo $name; ?>-settings-controls"></div>
<?php
}

/**
* @param int $id
*/
private function create_model( $id ) {
$class_parts = explode( '\\', get_called_class() );

array_splice( $class_parts, count( $class_parts ) - 1, 1, 'Model' );

$class_name = implode( '\\', $class_parts );

$this->models_cache[ $id ] = new $class_name( [
'id' => $id,
'settings' => $this->get_saved_settings( $id ),
] );
}

private function get_editor_template() {
$name = $this->get_name();

ob_start();
?>
<script type="text/template" id="tmpl-elementor-panel-<?php echo $name; ?>-settings">
<?php $this->print_editor_template_content( $name ); ?>
</script>
<?php

return ob_get_clean();
}
}
@@ -0,0 +1,15 @@
<?php
namespace Elementor\Core\Settings\Base;

use Elementor\Controls_Stack;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

abstract class Model extends Controls_Stack {

abstract public function get_css_wrapper_selector();

abstract public function get_panel_page_settings();
}
@@ -0,0 +1,132 @@
<?php
namespace Elementor\Core\Settings\General;

use Elementor\Controls_Manager;
use Elementor\CSS_File;
use Elementor\Core\Settings\Base\Manager as BaseManager;
use Elementor\Core\Settings\Base\Model as BaseModel;
use Elementor\Global_CSS_File;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Manager extends BaseManager {

const PANEL_TAB_LIGHTBOX = 'lightbox';

const META_KEY = '_elementor_general_settings';

public function __construct() {
parent::__construct();

$this->add_panel_tabs();
}

/**
* @return string
*/
public function get_name() {
return 'general';
}

/**
* @return BaseModel
*/
public function get_model_for_config() {
return $this->get_model();
}

/**
* @param int $id
*
* @return array
*/
protected function get_saved_settings( $id ) {
$model_controls = Model::get_controls_list();

$settings = [];

foreach ( $model_controls as $tab_name => $sections ) {

foreach ( $sections as $section_name => $section_data ) {

foreach ( $section_data['controls'] as $control_name => $control_data ) {
$saved_setting = get_option( $control_name, null );

if ( null !== $saved_setting ) {
$settings[ $control_name ] = get_option( $control_name );
}
}
}
}

return $settings;
}

/**
* @return string
*/
protected function get_css_file_name() {
return 'global';
}

/**
* @param array $settings
* @param int $id
*
* @return void
*/
protected function save_settings_to_db( array $settings, $id ) {
$model_controls = Model::get_controls_list();

$one_list_settings = [];

foreach ( $model_controls as $tab_name => $sections ) {

foreach ( $sections as $section_name => $section_data ) {

foreach ( $section_data['controls'] as $control_name => $control_data ) {
if ( isset( $settings[ $control_name ] ) ) {
$one_list_control_name = str_replace( 'elementor_', '', $control_name );

$one_list_settings[ $one_list_control_name ] = $settings[ $control_name ];

update_option( $control_name, $settings[ $control_name ] );
} else {
delete_option( $control_name );
}
}
}
}

// Save all settings in one list for future usage
if ( ! empty( $one_list_settings ) ) {
update_option( self::META_KEY, $one_list_settings );
} else {
delete_option( self::META_KEY );
}
}

/**
* @param CSS_File $css_file
*
* @return BaseModel
*/
protected function get_model_for_css_file( CSS_File $css_file ) {
return $this->get_model();
}

/**
* @param int $id
*
* @return CSS_File
*/
protected function get_css_file_for_update( $id ) {
return new Global_CSS_File();
}

private function add_panel_tabs() {
Controls_Manager::add_tab( self::PANEL_TAB_LIGHTBOX, __( 'Lightbox', 'elementor' ) );
}
}
@@ -0,0 +1,149 @@
<?php
namespace Elementor\Core\Settings\General;

use Elementor\Controls_Manager;
use Elementor\Core\Settings\Base\Model as BaseModel;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Model extends BaseModel {

public function get_name() {
return 'global-settings';
}

public function get_css_wrapper_selector() {
return '';
}

public function get_panel_page_settings() {
return [
'title' => __( 'Global Settings', 'elementor' ),
'menu' => [
'icon' => 'fa fa-cogs',
'beforeItem' => 'clear-page',
],
];
}

public static function get_controls_list() {

return [
Controls_Manager::TAB_STYLE => [
'style' => [
'label' => __( 'Style', 'elementor' ),
'controls' => [
'elementor_default_generic_fonts' => [
'label' => __( 'Default Generic Fonts', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => 'Sans-serif',
'description' => __( 'The list of fonts used if the chosen font is not available.', 'elementor' ),
'label_block' => true,
],
'elementor_container_width' => [
'label' => __( 'Content Width', 'elementor' ) . ' (px)',
'type' => Controls_Manager::NUMBER,
'min' => 0,
'description' => __( 'Sets the default width of the content area (Default: 1140)', 'elementor' ),
'selectors' => [
'.elementor-section.elementor-section-boxed > .elementor-container' => 'max-width: {{VALUE}}px',
],
],
'elementor_space_between_widgets' => [
'label' => __( 'Widgets Space', 'elementor' ) . ' (px)',
'type' => Controls_Manager::NUMBER,
'min' => 0,
'placeholder' => '20',
'description' => __( 'Sets the default space between widgets (Default: 20)', 'elementor' ),
'selectors' => [
'.elementor-widget:not(:last-child)' => 'margin-bottom: {{VALUE}}px',
],
],
'elementor_stretched_section_container' => [
'label' => __( 'Stretched Section Fit To', 'elementor' ),
'type' => Controls_Manager::TEXT,
'placeholder' => 'body',
'description' => __( 'Enter parent element selector to which stretched sections will fit to (e.g. #primary / .wrapper / main etc). Leave blank to fit to page width.', 'elementor' ),
'label_block' => true,
'frontend_available' => true,
],
'elementor_page_title_selector' => [
'label' => __( 'Page Title Selector', 'elementor' ),
'type' => Controls_Manager::TEXT,
'placeholder' => 'h1.entry-title',
'description' => __( 'Elementor lets you hide the page title. This works for themes that have "h1.entry-title" selector. If your theme\'s selector is different, please enter it above.', 'elementor' ),
'label_block' => true,
],
],
],
],
Manager::PANEL_TAB_LIGHTBOX => [
'lightbox' => [
'label' => __( 'Lightbox', 'elementor' ),
'controls' => [
'elementor_global_image_lightbox' => [
'label' => __( 'Image Lightbox', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'yes',
'description' => __( 'Open all image links in a lightbox popup window. The lightbox will automatically work on any link that leads to an image file.', 'elementor' ),
'frontend_available' => true,
],
'elementor_enable_lightbox_in_editor' => [
'label' => __( 'Enable In Editor', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'yes',
'description' => __( '', 'elementor' ),
'frontend_available' => true,
],
'elementor_lightbox_color' => [
'label' => __( 'Background Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'.elementor-lightbox' => 'background-color: {{VALUE}}',
],
],
'elementor_lightbox_ui_color' => [
'label' => __( 'UI Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'.elementor-lightbox .dialog-lightbox-close-button, .elementor-lightbox .elementor-swiper-button' => 'color: {{VALUE}}',
],
],
'elementor_lightbox_ui_color_hover' => [
'label' => __( 'UI Hover Color', 'elementor' ),
'type' => Controls_Manager::COLOR,
'selectors' => [
'.elementor-lightbox .dialog-lightbox-close-button:hover, .elementor-lightbox .elementor-swiper-button:hover' => 'color: {{VALUE}}',
],
],
],
],
],
];
}

protected function _register_controls() {
$controls_list = self::get_controls_list();

foreach ( $controls_list as $tab_name => $sections ) {

foreach ( $sections as $section_name => $section_data ) {

$this->start_controls_section(
$section_name, [
'label' => $section_data['label'],
'tab' => $tab_name,
]
);

foreach ( $section_data['controls'] as $control_name => $control_data ) {
$this->add_control( $control_name, $control_data );
}

$this->end_controls_section();
}
}
}
}
@@ -0,0 +1,77 @@
<?php
namespace Elementor\Core\Settings;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Manager {
/**
* @var Base\Manager[]
*/
private static $settings_managers = [];

private static $builtin_settings_managers_names = [ 'page', 'general' ];

public static function add_settings_manager( Base\Manager $manager ) {
self::$settings_managers[ $manager->get_name() ] = $manager;
}

/**
* @return Base\Manager|Base\Manager[]
*/
public static function get_settings_managers( $manager_name = null ) {
if ( $manager_name ) {
if ( isset( self::$settings_managers[ $manager_name ] ) ) {
return self::$settings_managers[ $manager_name ];
}

return null;
}

return self::$settings_managers;
}

private static function register_default_settings_managers() {
foreach ( self::$builtin_settings_managers_names as $manager_name ) {
$manager_class = __NAMESPACE__ . '\\' . ucfirst( $manager_name ) . '\Manager';

self::add_settings_manager( new $manager_class() );
}
}

public static function get_settings_managers_config() {
$config = [];

foreach ( self::$settings_managers as $name => $manager ) {
$settings_model = $manager->get_model_for_config();

$config[ $name ] = [
'name' => $manager->get_name(),
'panelPage' => $settings_model->get_panel_page_settings(),
'cssWrapperSelector' => $settings_model->get_css_wrapper_selector(),
'controls' => $settings_model->get_controls(),
'tabs' => $settings_model->get_tabs_controls(),
'settings' => $settings_model->get_settings(),
];
}

return $config;
}

public static function get_settings_frontend_config() {
$config = [];

foreach ( self::$settings_managers as $name => $manager ) {
$settings_model = $manager->get_model_for_config();

$config[ $name ] = $settings_model->get_frontend_settings();
}

return $config;
}

public static function run() {
self::register_default_settings_managers();
}
}
@@ -0,0 +1,174 @@
<?php
namespace Elementor\Core\Settings\Page;

use Elementor\CSS_File;
use Elementor\Core\Settings\Base\Manager as BaseManager;
use Elementor\Core\Settings\Manager as SettingsManager;
use Elementor\Core\Settings\Base\Model as BaseModel;
use Elementor\Post_CSS_File;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Manager extends BaseManager {

const TEMPLATE_CANVAS = 'elementor_canvas';

const META_KEY = '_elementor_page_settings';

public function __construct() {
parent::__construct();

add_action( 'init', [ $this, 'init' ] );

add_filter( 'template_include', [ $this, 'template_include' ] );
}

/**
* @deprecated since 1.6.0
*
* @param int $id
*
* @return BaseModel
*/
public static function get_page( $id ) {
return SettingsManager::get_settings_managers( 'page' )->get_model( $id );
}

public static function add_page_templates( $post_templates ) {
$post_templates = [
self::TEMPLATE_CANVAS => __( 'Elementor', 'elementor' ) . ' ' . __( 'Canvas', 'elementor' ),
] + $post_templates;

return $post_templates;
}

public static function is_cpt_custom_templates_supported() {
require_once ABSPATH . '/wp-admin/includes/theme.php';

return method_exists( wp_get_theme(), 'get_post_templates' );
}

public function template_include( $template ) {
if ( is_singular() ) {
$page_template = get_post_meta( get_the_ID(), '_wp_page_template', true );

if ( self::TEMPLATE_CANVAS === $page_template ) {
$template = ELEMENTOR_PATH . '/includes/page-templates/canvas.php';
}
}

return $template;
}

public function init() {
$post_types = get_post_types_by_support( 'elementor' );

foreach ( $post_types as $post_type ) {
add_filter( "theme_{$post_type}_templates", [ __CLASS__, 'add_page_templates' ], 10, 4 );
}
}

public function get_name() {
return 'page';
}

/**
* @return BaseModel
*/
public function get_model_for_config() {
return $this->get_model( get_the_ID() );
}

protected function ajax_before_save_settings( array $data, $id ) {
$post = get_post( $id );

if ( empty( $post ) ) {
wp_send_json_error( 'Invalid Post' );
}

if ( ! current_user_can( 'edit_post', $id ) ) {
wp_send_json_error( __( 'Access Denied.', 'elementor' ) );
}

$post->post_title = $data['post_title'];

$allowed_post_statuses = get_post_statuses();

if ( isset( $data['post_status'] ) && isset( $allowed_post_statuses[ $data['post_status'] ] ) ) {
$post_type_object = get_post_type_object( $post->post_type );
if ( 'publish' !== $data['post_status'] || current_user_can( $post_type_object->cap->publish_posts ) ) {
$post->post_status = $data['post_status'];
}
}

wp_update_post( $post );

if ( self::is_cpt_custom_templates_supported() ) {
$template = 'default';

if ( isset( $data['template'] ) ) {
$template = $data['template'];
}

update_post_meta( $post->ID, '_wp_page_template', $template );
}
}

protected function save_settings_to_db( array $settings, $id ) {
if ( ! empty( $settings ) ) {
update_post_meta( $id, self::META_KEY, $settings );
} else {
delete_post_meta( $id, self::META_KEY );
}
}

protected function get_css_file_for_update( $id ) {
return new Post_CSS_File( $id );
}

protected function get_saved_settings( $id ) {
$settings = get_post_meta( $id, self::META_KEY, true );

if ( ! $settings ) {
$settings = [];
}

if ( self::is_cpt_custom_templates_supported() ) {
$saved_template = get_post_meta( $id, '_wp_page_template', true );

if ( $saved_template ) {
$settings['template'] = $saved_template;
}
}

return $settings;
}

protected function get_css_file_name() {
return 'post';
}

/**
* @param CSS_File $css_file
*
* @return BaseModel
*/
protected function get_model_for_css_file( CSS_File $css_file ) {
if ( ! $css_file instanceof Post_CSS_File ) {
return null;
}

return $this->get_model( $css_file->get_post_id() );
}

protected function get_special_settings_names() {
return [
'id',
'post_title',
'post_status',
'template',
];
}
}
@@ -0,0 +1,180 @@
<?php
namespace Elementor\Core\Settings\Page;

use Elementor\Controls_Manager;
use Elementor\Core\Settings\Base\Model as BaseModel;
use Elementor\Group_Control_Background;
use Elementor\Settings;
use Elementor\Core\Settings\Manager as SettingsManager;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Model extends BaseModel {

/**
* @var \WP_Post
*/
private $post;

public function __construct( array $data = [] ) {
$this->post = get_post( $data['id'] );

if ( ! $this->post ) {
$this->post = new \WP_Post( (object) [] );
}

parent::__construct( $data );
}

public function get_name() {
return 'page-settings';
}

public function get_unique_name() {
return $this->get_name() . '-' . $this->post->ID;
}

public function get_css_wrapper_selector() {
return 'body.elementor-page-' . $this->get_id();
}

public function get_panel_page_settings() {
return [
'title' => __( 'Page Settings', 'elementor' ),
'menu' => [
'icon' => 'fa fa-cog',
'beforeItem' => 'clear-page',
],
];
}

public function on_export( $element_data ) {
if ( ! empty( $element_data['settings']['template'] ) && Manager::TEMPLATE_CANVAS !== $element_data['settings']['template'] ) {
unset( $element_data['settings']['template'] );
}

return $element_data;
}

protected function _register_controls() {
$this->start_controls_section(
'section_page_settings',
[
'label' => __( 'Page Settings', 'elementor' ),
'tab' => Controls_Manager::TAB_SETTINGS,
]
);

$this->add_control(
'post_title',
[
'label' => __( 'Title', 'elementor' ),
'type' => Controls_Manager::TEXT,
'default' => $this->post->post_title,
'label_block' => true,
'separator' => 'none',
]
);

$page_title_selector = SettingsManager::get_settings_managers( 'general' )->get_model()->get_settings( 'elementor_page_title_selector' );

if ( ! $page_title_selector ) {
$page_title_selector = 'h1.entry-title';
}

$this->add_control(
'hide_title',
[
'label' => __( 'Hide Title', 'elementor' ),
'type' => Controls_Manager::SWITCHER,
'label_off' => __( 'No', 'elementor' ),
'label_on' => __( 'Yes', 'elementor' ),
// translators: %s: Setting Page link
'description' => sprintf( __( 'Not working? You can set a different selector for the title in the <a href="%s" target="_blank">Settings page</a>.', 'elementor' ), Settings::get_url() ),
'selectors' => [
'{{WRAPPER}} ' . $page_title_selector => 'display: none',
],
'export' => '__return_true',
]
);

if ( Manager::is_cpt_custom_templates_supported() ) {
require_once ABSPATH . '/wp-admin/includes/template.php';

$options = [
'default' => __( 'Default', 'elementor' ),
];

$options += array_flip( get_page_templates( null, $this->post->post_type ) );

$this->add_control(
'template',
[
'label' => __( 'Template', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => 'default',
'options' => $options,
'export' => function( $value ) {
return Manager::TEMPLATE_CANVAS === $value;
},
]
);
}

$post_type_object = get_post_type_object( $this->post->post_type );

$can_publish = current_user_can( $post_type_object->cap->publish_posts );

if ( 'publish' === $this->post->post_status || 'private' === $this->post->post_status || $can_publish ) {
$this->add_control(
'post_status',
[
'label' => __( 'Status', 'elementor' ),
'type' => Controls_Manager::SELECT,
'default' => $this->post->post_status,
'options' => get_post_statuses(),
]
);
}

$this->end_controls_section();

$this->start_controls_section(
'section_page_style',
[
'label' => __( 'Page Style', 'elementor' ),
'tab' => Controls_Manager::TAB_STYLE,
]
);

$this->add_group_control(
Group_Control_Background::get_type(),
[
'name' => 'background',
'label' => __( 'Background', 'elementor' ),
'fields_options' => [
'__all' => [
'export' => '__return_true',
],
],
]
);

$this->add_responsive_control(
'padding',
[
'label' => __( 'Padding', 'elementor' ),
'type' => Controls_Manager::DIMENSIONS,
'size_units' => [ 'px', 'em', '%' ],
'selectors' => [
'{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}',
],
'export' => '__return_true',
]
);

$this->end_controls_section();
}
}
@@ -0,0 +1,109 @@
<?php
/**
* Plugin Name: Elementor
* Description: The most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.
* Plugin URI: https://elementor.com/?utm_source=wp-plugins&utm_campaign=plugin-uri&utm_medium=wp-dash
* Author: Elementor.com
* Version: 1.8.11
* Author URI: https://elementor.com/?utm_source=wp-plugins&utm_campaign=author-uri&utm_medium=wp-dash
*
* Text Domain: elementor
*
* @package Elementor
* @category Core
*
* Elementor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Elementor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

define( 'ELEMENTOR_VERSION', '1.8.11' );
define( 'ELEMENTOR_PREVIOUS_STABLE_VERSION', '1.7.12' );

define( 'ELEMENTOR__FILE__', __FILE__ );
define( 'ELEMENTOR_PLUGIN_BASE', plugin_basename( ELEMENTOR__FILE__ ) );
define( 'ELEMENTOR_PATH', plugin_dir_path( ELEMENTOR__FILE__ ) );

if ( defined( 'ELEMENTOR_TESTS' ) && ELEMENTOR_TESTS ) {
define( 'ELEMENTOR_URL', 'file://' . ELEMENTOR_PATH );
} else {
define( 'ELEMENTOR_URL', plugins_url( '/', ELEMENTOR__FILE__ ) );
}

define( 'ELEMENTOR_MODULES_PATH', plugin_dir_path( ELEMENTOR__FILE__ ) . '/modules' );
define( 'ELEMENTOR_ASSETS_URL', ELEMENTOR_URL . 'assets/' );

add_action( 'plugins_loaded', 'elementor_load_plugin_textdomain' );

if ( ! version_compare( PHP_VERSION, '5.4', '>=' ) ) {
add_action( 'admin_notices', 'elementor_fail_php_version' );
} elseif ( ! version_compare( get_bloginfo( 'version' ), '4.5', '>=' ) ) {
add_action( 'admin_notices', 'elementor_fail_wp_version' );
} else {
// Fix language if the `get_user_locale` is difference from the `get_locale
if ( isset( $_REQUEST['action'] ) && 0 === strpos( $_REQUEST['action'], 'elementor' ) ) {
add_action( 'set_current_user', function() {
global $current_user;
$current_user->locale = get_locale();
} );

// Fix for Polylang
define( 'PLL_AJAX_ON_FRONT', true );

add_action( 'pll_pre_init', function( $polylang ) {
$post_language = $polylang->model->post->get_language( $_REQUEST['post'], 'locale' );
$_REQUEST['lang'] = $post_language->locale;
} );
}

require( ELEMENTOR_PATH . 'includes/plugin.php' );
}

/**
* Load gettext translate for our text domain.
*
* @since 1.0.0
*
* @return void
*/
function elementor_load_plugin_textdomain() {
load_plugin_textdomain( 'elementor' );
}

/**
* Show in WP Dashboard notice about the plugin is not activated (PHP version).
*
* @since 1.0.0
*
* @return void
*/
function elementor_fail_php_version() {
/* translators: %s: PHP version */
$message = sprintf( esc_html__( 'Elementor requires PHP version %s+, plugin is currently NOT ACTIVE.', 'elementor' ), '5.4' );
$html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
echo wp_kses_post( $html_message );
}

/**
* Show in WP Dashboard notice about the plugin is not activated (WP version).
*
* @since 1.5.0
*
* @return void
*/
function elementor_fail_wp_version() {
/* translators: %s: WP version */
$message = sprintf( esc_html__( 'Elementor requires WordPress version %s+. Because you are using an earlier version, the plugin is currently NOT ACTIVE.', 'elementor' ), '4.5' );
$html_message = sprintf( '<div class="error">%s</div>', wpautop( $message ) );
echo wp_kses_post( $html_message );
}

Large diffs are not rendered by default.

@@ -0,0 +1,175 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Api {

public static $api_info_url = 'http://my.elementor.com/api/v1/info/';
private static $api_feedback_url = 'http://my.elementor.com/api/v1/feedback/';
private static $api_get_template_content_url = 'http://my.elementor.com/api/v1/templates/%d';

/**
* This function notifies the user of upgrade notices, new templates and contributors
*
* @static
* @since 1.0.0
* @access private
* @param bool $force
*
* @return array|bool
*/
private static function _get_info_data( $force = false ) {
$cache_key = 'elementor_remote_info_api_data_' . ELEMENTOR_VERSION;
$info_data = get_transient( $cache_key );

if ( $force || false === $info_data ) {
$response = wp_remote_post( self::$api_info_url, [
'timeout' => 25,
'body' => [
// Which API version is used
'api_version' => ELEMENTOR_VERSION,
// Which language to return
'site_lang' => get_bloginfo( 'language' ),
],
] );

if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
set_transient( $cache_key, [], 2 * HOUR_IN_SECONDS );

return false;
}

$info_data = json_decode( wp_remote_retrieve_body( $response ), true );
if ( empty( $info_data ) || ! is_array( $info_data ) ) {
set_transient( $cache_key, [], 2 * HOUR_IN_SECONDS );

return false;
}

if ( isset( $info_data['templates'] ) ) {
update_option( 'elementor_remote_info_templates_data', $info_data['templates'], 'no' );
unset( $info_data['templates'] );
}
set_transient( $cache_key, $info_data, 12 * HOUR_IN_SECONDS );
}

return $info_data;
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function get_upgrade_notice() {
$data = self::_get_info_data();
if ( empty( $data['upgrade_notice'] ) ) {
return false;
}

return $data['upgrade_notice'];
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function get_templates_data() {
self::_get_info_data();

$templates = get_option( 'elementor_remote_info_templates_data' );
if ( empty( $templates ) ) {
return [];
}

return $templates;
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function get_template_content( $template_id ) {
$url = sprintf( self::$api_get_template_content_url, $template_id );

$body_args = [
// Which API version is used.
'api_version' => ELEMENTOR_VERSION,
// Which language to return.
'site_lang' => get_bloginfo( 'language' ),
];

$body_args = apply_filters( 'elementor/api/get_templates/body_args', $body_args );

$response = wp_remote_get( $url, [
'timeout' => 40,
'body' => $body_args,
] );

if ( is_wp_error( $response ) ) {
return $response;
}

$response_code = (int) wp_remote_retrieve_response_code( $response );

if ( 200 !== $response_code ) {
return new \WP_Error( 'response_code_error', 'The request returned with a status code of ' . $response_code );
}

$template_content = json_decode( wp_remote_retrieve_body( $response ), true );

if ( isset( $template_content['error'] ) ) {
return new \WP_Error( 'response_error', $template_content['error'] );
}

if ( empty( $template_content['data'] ) && empty( $template_content['content'] ) ) {
return new \WP_Error( 'template_data_error', 'An invalid data was returned' );
}

return $template_content;
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function send_feedback( $feedback_key, $feedback_text ) {
return wp_remote_post( self::$api_feedback_url, [
'timeout' => 30,
'body' => [
'api_version' => ELEMENTOR_VERSION,
'site_lang' => get_bloginfo( 'language' ),
'feedback_key' => $feedback_key,
'feedback' => $feedback_text,
],
] );
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function ajax_reset_api_data() {
check_ajax_referer( 'elementor_reset_library', '_nonce' );

self::_get_info_data( true );

wp_send_json_success();
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function init() {
add_action( 'wp_ajax_elementor_reset_library', [ __CLASS__, 'ajax_reset_api_data' ] );
}
}
@@ -0,0 +1,157 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Autoloader {

private static $classes_map = [
'Admin' => 'includes/admin.php',
'Api' => 'includes/api.php',
'Base_Control' => 'includes/controls/base.php',
'Base_Data_Control' => 'includes/controls/base-data.php',
'Base_UI_Control' => 'includes/controls/base-ui.php',
'Beta_Testers' => 'includes/beta-testers.php',
'Compatibility' => 'includes/compatibility.php',
'Conditions' => 'includes/conditions.php',
'Control_Base_Multiple' => 'includes/controls/base-multiple.php',
'Control_Base_Units' => 'includes/controls/base-units.php',
'Controls_Manager' => 'includes/managers/controls.php',
'Controls_Stack' => 'includes/base/controls-stack.php',
'CSS_File' => 'includes/css-file/css-file.php',
'DB' => 'includes/db.php',
'Debug\Debug' => 'includes/debug/debug.php',
'Editor' => 'includes/editor.php',
'Elements_Manager' => 'includes/managers/elements.php',
'Embed' => 'includes/embed.php',
'Fonts' => 'includes/fonts.php',
'Frontend' => 'includes/frontend.php',
'Global_CSS_File' => 'includes/css-file/global-css-file.php',
'Group_Control_Background' => 'includes/controls/groups/background.php',
'Group_Control_Base' => 'includes/controls/groups/base.php',
'Group_Control_Border' => 'includes/controls/groups/border.php',
'Group_Control_Box_Shadow' => 'includes/controls/groups/box-shadow.php',
'Group_Control_Image_Size' => 'includes/controls/groups/image-size.php',
'Group_Control_Interface' => 'includes/interfaces/group-control.php',
'Group_Control_Text_Shadow' => 'includes/controls/groups/text-shadow.php',
'Group_Control_Typography' => 'includes/controls/groups/typography.php',
'Heartbeat' => 'includes/heartbeat.php',
'Images_Manager' => 'includes/managers/image.php',
'Maintenance' => 'includes/maintenance.php',
'Maintenance_Mode' => 'includes/maintenance-mode.php',
'Post_CSS_File' => 'includes/css-file/post-css-file.php',
'Posts_CSS_Manager' => 'includes/managers/css-files.php',
'Preview' => 'includes/preview.php',
'Responsive' => 'includes/responsive.php',
'Rollback' => 'includes/rollback.php',
'Scheme_Base' => 'includes/schemes/base.php',
'Scheme_Color' => 'includes/schemes/color.php',
'Scheme_Color_Picker' => 'includes/schemes/color-picker.php',
'Scheme_Typography' => 'includes/schemes/typography.php',
'Scheme_Interface' => 'includes/interfaces/scheme.php',
'Schemes_Manager' => 'includes/managers/schemes.php',
'Settings' => 'includes/settings/settings.php',
'Settings_Controls' => 'includes/settings/controls.php',
'Settings_Validations' => 'includes/settings/validations.php',
'Settings_Page' => 'includes/settings/settings-page.php',
'Shapes' => 'includes/shapes.php',
'Skins_Manager' => 'includes/managers/skins.php',
'Stylesheet' => 'includes/stylesheet.php',
'System_Info\Main' => 'includes/settings/system-info/main.php',
'TemplateLibrary\Classes\Import_Images' => 'includes/template-library/classes/class-import-images.php',
'TemplateLibrary\Manager' => 'includes/template-library/manager.php',
'TemplateLibrary\Source_Base' => 'includes/template-library/sources/base.php',
'TemplateLibrary\Source_Local' => 'includes/template-library/sources/local.php',
'TemplateLibrary\Source_Remote' => 'includes/template-library/sources/remote.php',
'Tools' => 'includes/settings/tools.php',
'Tracker' => 'includes/tracker.php',
'Upgrades' => 'includes/upgrades.php',
'User' => 'includes/user.php',
'Utils' => 'includes/utils.php',
'Widget_WordPress' => 'includes/widgets/wordpress.php',
'Widgets_Manager' => 'includes/managers/widgets.php',
'WordPress_Widgets_Manager' => 'includes/managers/wordpress-widgets.php',
];

private static $classes_aliases = [
'Control_Base' => 'Base_Data_Control',
'PageSettings\Manager' => 'Core\Settings\Page\Manager',
'Revisions_Manager' => 'Modules\History\Revisions_Manager',
];

/**
* @static
* @since 1.6.0
* @access public
*/
public static function run() {
spl_autoload_register( [ __CLASS__, 'autoload' ] );
}

/**
* @static
* @since 1.6.0
* @access public
* @return array
*/
public static function get_classes_aliases() {
return self::$classes_aliases;
}

/**
* @static
* @since 1.6.0
* @access private
*/
private static function load_class( $relative_class_name ) {
if ( isset( self::$classes_map[ $relative_class_name ] ) ) {
$filename = ELEMENTOR_PATH . '/' . self::$classes_map[ $relative_class_name ];
} else {
$filename = strtolower(
preg_replace(
[ '/([a-z])([A-Z])/', '/_/', '/\\\/' ],
[ '$1-$2', '-', DIRECTORY_SEPARATOR ],
$relative_class_name
)
);

$filename = ELEMENTOR_PATH . $filename . '.php';
}

if ( is_readable( $filename ) ) {
require $filename;
}
}

/**
* @static
* @since 1.6.0
* @access private
*/
private static function autoload( $class ) {
if ( 0 !== strpos( $class, __NAMESPACE__ . '\\' ) ) {
return;
}

$relative_class_name = preg_replace( '/^' . __NAMESPACE__ . '\\\/', '', $class );

$has_class_alias = isset( self::$classes_aliases[ $relative_class_name ] );

// Backward Compatibility: Save old class name for set an alias after the new class is loaded
if ( $has_class_alias ) {
$relative_class_name = self::$classes_aliases[ $relative_class_name ];
}

$final_class_name = __NAMESPACE__ . '\\' . $relative_class_name;

if ( ! class_exists( $final_class_name ) ) {
self::load_class( $relative_class_name );
}

if ( $has_class_alias ) {
class_alias( $final_class_name, $class );
}
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,352 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Skin Base
*
* Abstract class to register new skins to Elementor widgets. Skins allow you to
* add new templates, set custom controls and more.
*
* To add skins to widgets use the `_register_skins()` method and register new
* skins using `add_skin()` method.
*
* @abstract
*/
abstract class Skin_Base {

/**
* Parent widget.
*
* Holds the parent widget of the skin. Default value is null, no parent widget.
*
* @access protected
*
* @var Widget_Base|null
*/
protected $parent = null;

/**
* Skin base constructor.
*
* Initializing the skin base class by setting parent widget and registering
* controls actions.
*
* @since 1.0.0
* @access public
* @param Widget_Base $parent
*/
public function __construct( Widget_Base $parent ) {
$this->parent = $parent;

$this->_register_controls_actions();
}

/**
* Retrieve skin ID.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function get_id();

/**
* Retrieve skin title.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function get_title();

/**
* Render skin.
*
* Generates the final HTML on the frontend.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function render();

/**
* Render skin output in the editor.
*
* Written as a Backbone JavaScript template and used to generate the live preview.
*
* @since 1.0.0
* @access public
*
* @deprecated
*/
public function _content_template() {}

/**
* Register skin controls actions.
*
* Run on init and used to register new skins to be injected to the widget.
* This method is used to register new actions that specify the locaion of
* the skin in the widget.
*
* Example usage:
* `add_action( 'elementor/element/{widget_id}/{section_id}/before_section_end', [ $this, 'register_controls' ] );`
*
* @since 1.0.0
* @access protected
*/
protected function _register_controls_actions() {}

/**
* Retrieve skin control ID.
*
* Used to get the skin control ID. Note that skin controls have special
* prefix to destiguish them from regular controls, and from controls in
* other skins.
*
* @since 1.0.0
* @access protected
*
* @param string $control_base_id Control base ID.
*
* @return string Control ID.
*/
protected function get_control_id( $control_base_id ) {
$skin_id = str_replace( '-', '_', $this->get_id() );
return $skin_id . '_' . $control_base_id;
}

/**
* Retrieve skin settings.
*
* Get all the skin settings or, when requested, a specific setting.
*
* @since 1.0.0
* @TODO: rename to get_setting() and create backward compitability.
*
* @access public
*
* @param string $control_base_id Control base ID.
*
* @return Widget_Base Widget instance.
*/
public function get_instance_value( $control_base_id ) {
$control_id = $this->get_control_id( $control_base_id );
return $this->parent->get_settings( $control_id );
}

/**
* Start skin controls section.
*
* Used to add a new section of controls to the skin.
*
* @since 1.3.0
* @access public
*
* @param string $id Section ID.
* @param array $args Section arguments.
*/
public function start_controls_section( $id, $args ) {
$args['condition']['_skin'] = $this->get_id();
$this->parent->start_controls_section( $this->get_control_id( $id ), $args );
}

/**
* End skin controls section.
*
* Used to close an existing open skin controls section.
*
* @since 1.3.0
* @access public
*/
public function end_controls_section() {
$this->parent->end_controls_section();
}

/**
* Add new skin control.
*
* Register a single control to the allow the user to set/update skin data.
*
* @since 1.0.0
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments.
*
* @return bool True if skin added, False otherwise.
*/
public function add_control( $id, $args ) {
$args['condition']['_skin'] = $this->get_id();
return $this->parent->add_control( $this->get_control_id( $id ), $args );
}

/**
* Update skin control.
*
* Change the value of an existing skin control.
*
* @since 1.3.0
* @since 1.8.1 New `$options` parameter added.
*
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments. Only the new fields you want to update.
* @param array $options Optional. Some additional options.
*/
public function update_control( $id, $args, array $options = [] ) {
$args['condition']['_skin'] = $this->get_id();
$this->parent->update_control( $this->get_control_id( $id ), $args, $options );
}

/**
* Remove skin control.
*
* Unregister an existing skin control.
*
* @since 1.3.0
* @access public
*
* @param string $id Control ID.
*/
public function remove_control( $id ) {
$this->parent->remove_control( $this->get_control_id( $id ) );
}

/**
* Add new responsive skin control.
*
* Register a set of controls to allow editing based on user screen size.
*
* @since 1.0.5
* @access public
*
* @param string $id Responsive control ID.
* @param array $args Responsive control arguments.
*/
public function add_responsive_control( $id, $args ) {
$args['condition']['_skin'] = $this->get_id();
$this->parent->add_responsive_control( $this->get_control_id( $id ), $args );
}

/**
* Update responsive skin control.
*
* Change the value of an existing responsive skin control.
*
* @since 1.3.5
* @access public
*
* @param string $id Responsive control ID.
* @param array $args Responsive control arguments.
*/
public function update_responsive_control( $id, $args ) {
$this->parent->update_responsive_control( $this->get_control_id( $id ), $args );
}

/**
* Remove responsive skin control.
*
* Unregister an existing skin responsive control.
*
* @since 1.3.5
* @access public
*
* @param string $id Responsive control ID.
*/
public function remove_responsive_control( $id ) {
$this->parent->remove_responsive_control( $this->get_control_id( $id ) );
}

/**
* Start skin controls tab.
*
* Used to add a new tab inside a group of tabs.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments.
*/
public function start_controls_tab( $id, $args ) {
$args['condition']['_skin'] = $this->get_id();
$this->parent->start_controls_tab( $this->get_control_id( $id ), $args );
}

/**
* End skin controls tab.
*
* Used to close an existing open controls tab.
*
* @since 1.5.0
* @access public
*/
public function end_controls_tab() {
$this->parent->end_controls_tab();
}

/**
* Start skin controls tabs.
*
* Used to add a new set of tabs inside a section.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
*/
public function start_controls_tabs( $id ) {
$args['condition']['_skin'] = $this->get_id();
$this->parent->start_controls_tabs( $this->get_control_id( $id ) );
}

/**
* End skin controls tabs.
*
* Used to close an existing open controls tabs.
*
* @since 1.5.0
* @access public
*/
public function end_controls_tabs() {
$this->parent->end_controls_tabs();
}

/**
* Add new group control.
*
* Register a set of related controls grouped together as a single unified
* control.
*
* @since 1.0.0
* @access public
*
* @param string $group_name Group control name.
* @param array $args Group control arguments. Default is an empty array.
*/
final public function add_group_control( $group_name, $args = [] ) {
$args['name'] = $this->get_control_id( $args['name'] );
$args['condition']['_skin'] = $this->get_id();
$this->parent->add_group_control( $group_name, $args );
}

/**
* Set parent widget.
*
* Used to define the parent widget of the skin.
*
* @since 1.0.0
* @access public
*
* @param Widget_Base $parent Parent widget.
*/
public function set_parent( $parent ) {
$this->parent = $parent;
}
}

Large diffs are not rendered by default.

@@ -0,0 +1,78 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Beta_Testers {

private $transient_key;

/**
* @since 1.5.0
* @access private
*/
private function get_beta_version() {
$beta_version = get_site_transient( $this->transient_key );

if ( false === $beta_version ) {
$beta_version = 'false';

$response = wp_remote_get( 'https://plugins.svn.wordpress.org/elementor/trunk/readme.txt' );

if ( ! is_wp_error( $response ) && ! empty( $response['body'] ) ) {
preg_match( '/Beta tag: (.*)/i', $response['body'], $matches );
if ( isset( $matches[1] ) ) {
$beta_version = $matches[1];
}
}

set_site_transient( $this->transient_key, $beta_version, 6 * HOUR_IN_SECONDS );
}

return $beta_version;
}

/**
* @since 1.5.0
* @access public
*/
public function check_version( $transient ) {
if ( empty( $transient->checked ) ) {
return $transient;
}

delete_site_transient( $this->transient_key );

$plugin_slug = basename( ELEMENTOR__FILE__, '.php' );

$beta_version = $this->get_beta_version();
if ( 'false' !== $beta_version && version_compare( $beta_version, ELEMENTOR_VERSION, '>' ) ) {
$response = new \stdClass();
$response->plugin = $plugin_slug;
$response->slug = $plugin_slug;
$response->new_version = $beta_version;
$response->url = 'https://elementor.com/';
$response->package = sprintf( 'https://downloads.wordpress.org/plugin/elementor.%s.zip', $beta_version );

$transient->response[ ELEMENTOR_PLUGIN_BASE ] = $response;
}

return $transient;
}

/**
* @since 1.5.0
* @access public
*/
public function __construct() {
if ( 'yes' !== get_option( 'elementor_beta', 'no' ) ) {
return;
}

$this->transient_key = md5( 'elementor_beta_testers_response_key' );

add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_version' ] );
}
}
@@ -0,0 +1,189 @@
<?php
namespace Elementor;

use Elementor\TemplateLibrary\Source_Local;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Compatibility {

/**
* @static
* @since 1.0.0
* @access public
*/
public static function register_actions() {
add_action( 'init', [ __CLASS__, 'init' ] );

if ( is_admin() ) {
add_filter( 'wp_import_post_meta', [ __CLASS__, 'on_wp_import_post_meta' ] );
add_filter( 'wxr_importer.pre_process.post_meta', [ __CLASS__, 'on_wxr_importer_pre_process_post_meta' ] );
}
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function init() {
// Hotfix for NextGEN Gallery plugin.
if ( defined( 'NGG_PLUGIN_VERSION' ) ) {
add_filter( 'elementor/utils/get_edit_link', function( $edit_link ) {
return add_query_arg( 'display_gallery_iframe', '', $edit_link );
} );
}

// Hack for Ninja Forms.
if ( class_exists( '\Ninja_Forms' ) && class_exists( '\NF_Display_Render' ) ) {
add_action( 'elementor/preview/enqueue_styles', function() {
ob_start();
\NF_Display_Render::localize( 0 );

ob_clean();

wp_add_inline_script( 'nf-front-end', 'var nfForms = nfForms || [];' );
} );
}

// Exclude our Library from sitemap.xml in Yoast SEO plugin.
add_filter( 'wpseo_sitemaps_supported_post_types', function( $post_types ) {
unset( $post_types[ Source_Local::CPT ] );

return $post_types;
} );

add_filter( 'wpseo_sitemap_exclude_post_type', function( $retval, $post_type ) {
if ( Source_Local::CPT === $post_type ) {
$retval = true;
}

return $retval;
}, 10, 2 );

// Disable optimize files in Editor from Autoptimize plugin.
add_filter( 'autoptimize_filter_noptimize', function( $retval ) {
if ( Plugin::$instance->editor->is_edit_mode() ) {
$retval = true;
}

return $retval;
} );

// Add the description (content) tab for a new product, so it can be edited with Elementor.
add_filter( 'woocommerce_product_tabs', function( $tabs ) {
if ( ! isset( $tabs['description'] ) && Plugin::$instance->preview->is_preview_mode() ) {
$post = get_post();
if ( empty( $post->post_content ) ) {
$tabs['description'] = [
'title' => __( 'Description', 'elementor' ),
'priority' => 10,
'callback' => 'woocommerce_product_description_tab',
];
}
}

return $tabs;
} );

// Fix Jetpack Contact Form in Editor Mode.
if ( class_exists( 'Grunion_Editor_View' ) ) {
add_action( 'elementor/editor/before_enqueue_scripts', function() {
remove_action( 'media_buttons', 'grunion_media_button', 999 );
remove_action( 'admin_enqueue_scripts', 'grunion_enable_spam_recheck' );

remove_action( 'admin_notices', [ 'Grunion_Editor_View', 'handle_editor_view_js' ] );
remove_action( 'admin_head', [ 'Grunion_Editor_View', 'admin_head' ] );
} );
}

// Fix Popup Maker in Editor Mode.
if ( class_exists( 'PUM_Admin_Shortcode_UI' ) ) {
add_action( 'elementor/editor/before_enqueue_scripts', function() {
$pum_admin_instance = \PUM_Admin_Shortcode_UI::instance();

remove_action( 'print_media_templates', [ $pum_admin_instance, 'print_media_templates' ] );
remove_action( 'admin_print_footer_scripts', [ $pum_admin_instance, 'admin_print_footer_scripts' ], 100 );
remove_action( 'wp_ajax_pum_do_shortcode', [ $pum_admin_instance, 'wp_ajax_pum_do_shortcode' ] );

remove_action( 'admin_enqueue_scripts', [ $pum_admin_instance, 'admin_enqueue_scripts' ] );

remove_filter( 'pum_admin_var', [ $pum_admin_instance, 'pum_admin_var' ] );
} );
}

// Fix Preview URL for https://premium.wpmudev.org/project/domain-mapping/ plugin
if ( class_exists( 'domain_map' ) ) {
add_filter( 'elementor/utils/preview_url', function( $preview_url ) {
if ( wp_parse_url( $preview_url, PHP_URL_HOST ) !== $_SERVER['HTTP_HOST'] ) {
$preview_url = \domain_map::utils()->unswap_url( $preview_url );
$preview_url = add_query_arg( [
'dm' => \Domainmap_Module_Mapping::BYPASS,
], $preview_url );
}

return $preview_url;
} );
}

// Copy elementor data while polylang creates a translation copy
add_filter( 'pll_copy_post_metas', [ __CLASS__, 'save_polylang_meta' ], 10 , 4 );
}

/**
* @static
* @since 1.6.0
* @access public
*/
public static function save_polylang_meta( $keys, $sync, $from, $to ) {
// Copy only for a new post.
if ( ! $sync ) {
Plugin::$instance->db->copy_elementor_meta( $from, $to );
}

return $keys;
}

/**
* Normalize Elementor post meta on import,
* We need the `wp_slash` in order to avoid the unslashing during the `add_post_meta`
*
* @static
* @since 1.0.0
* @access public
* @param array $post_meta
*
* @return array
*/
public static function on_wp_import_post_meta( $post_meta ) {
foreach ( $post_meta as &$meta ) {
if ( '_elementor_data' === $meta['key'] ) {
$meta['value'] = wp_slash( $meta['value'] );
break;
}
}

return $post_meta;
}

/**
* Normalize Elementor post meta on import with the new WP_importer,
* We need the `wp_slash` in order to avoid the unslashing during the `add_post_meta`
*
* @static
* @since 1.0.0
* @access public
* @param array $post_meta
*
* @return array
*/
public static function on_wxr_importer_pre_process_post_meta( $post_meta ) {
if ( '_elementor_data' === $post_meta['key'] ) {
$post_meta['value'] = wp_slash( $post_meta['value'] );
}

return $post_meta;
}
}
@@ -0,0 +1,76 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Conditions {

/**
* @static
* @since 1.0.0
* @access public
*/
public static function compare( $left_value, $right_value, $operator ) {
switch ( $operator ) {
case '==':
return $left_value == $right_value;
case '!=':
return $left_value != $right_value;
case '!==':
return $left_value !== $right_value;
case 'in':
return -1 !== array_search( $left_value, $right_value );
case '!in':
return -1 === array_search( $left_value, $right_value );
case '<':
return $left_value < $right_value;
case '<=':
return $left_value <= $right_value;
case '>':
return $left_value > $right_value;
case '>=':
return $left_value >= $right_value;
default:
return $left_value === $right_value;
}
}

/**
* @static
* @since 1.0.0
* @access public
*/
public static function check( array $conditions, array $comparison ) {
$is_or_condition = isset( $conditions['relation'] ) && 'or' === $conditions['relation'];

$condition_succeed = ! $is_or_condition;

foreach ( $conditions['terms'] as $term ) {
if ( ! empty( $term['terms'] ) ) {
$comparison_result = self::check( $term, $comparison );
} else {
preg_match( '/(\w+)(?:\[(\w+)])?/', $term['name'], $parsed_name );

$value = $comparison[ $parsed_name[1] ];

if ( ! empty( $parsed_name[2] ) ) {
$value = $value[ $parsed_name[2] ];
}

$comparison_result = self::compare( $value, $term['value'], $term['operator'] );
}

if ( $is_or_condition ) {
if ( $comparison_result ) {
return true;
}
} elseif ( ! $comparison_result ) {
return false;
}
}

return $condition_succeed;
}
}
@@ -0,0 +1,187 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Animation control.
*
* A base control for creating entrance animation control. Displays a select box
* with the available entrance animation effects @see Control_Animation::get_animations()
*
* Creating new control in the editor (inside `Widget_Base::_register_controls()`
* method):
*
* $this->add_control(
* 'animation',
* [
* 'label' => __( 'Entrance Animation', 'plugin-domain' ),
* 'type' => Controls_Manager::ANIMATION,
* 'prefix_class' => 'animated ',
* ]
* );
*
* PHP usage (inside `Widget_Base::render()` method):
*
* echo '<div class="' . $this->get_settings( 'animation' ) . '"> ... </div>';
*
* JS usage (inside `Widget_Base::_content_template()` method):
*
* <div class="{{ settings.animation }}"> ... </div>
*
* @since 1.0.0
*
* @param string $label Optional. The label that appears above of the
* field. Default is empty.
* @param string $description Optional. The description that appears below the
* field. Default is empty.
* @param string $default Optional. The selected animation key. Default is
* empty.
* @param string $separator Optional. Set the position of the control separator.
* Available values are 'default', 'before', 'after'
* and 'none'. 'default' will position the separator
* depending on the control type. 'before' / 'after'
* will position the separator before/after the
* control. 'none' will hide the separator. Default
* is 'default'.
* @param bool $show_label Optional. Whether to display the label. Default is
* true.
* @param bool $label_block Optional. Whether to display the label in a
* separate line. Default is false.
*/
class Control_Animation extends Base_Data_Control {

/**
* List of animations.
*
* Holds the list of all the available animations.
*
* @access private
* @static
*
* @var array
*/
private static $_animations;

/**
* Retrieve control type.
*
* Get the animation control type.
*
* @since 1.0.0
* @access public
*
* @return string Control type.
*/
public function get_type() {
return 'animation';
}

/**
* Retrieve animations list.
*
* Get the list of all the available animations.
*
* @static
* @since 1.0.0
* @access public
*
* @return string Control type.
*/
public static function get_animations() {
if ( is_null( self::$_animations ) ) {
self::$_animations = [
'Fading' => [
'fadeIn' => 'Fade In',
'fadeInDown' => 'Fade In Down',
'fadeInLeft' => 'Fade In Left',
'fadeInRight' => 'Fade In Right',
'fadeInUp' => 'Fade In Up',
],
'Zooming' => [
'zoomIn' => 'Zoom In',
'zoomInDown' => 'Zoom In Down',
'zoomInLeft' => 'Zoom In Left',
'zoomInRight' => 'Zoom In Right',
'zoomInUp' => 'Zoom In Up',
],
'Bouncing' => [
'bounceIn' => 'Bounce In',
'bounceInDown' => 'Bounce In Down',
'bounceInLeft' => 'Bounce In Left',
'bounceInRight' => 'Bounce In Right',
'bounceInUp' => 'Bounce In Up',
],
'Sliding' => [
'slideInDown' => 'Slide In Down',
'slideInLeft' => 'Slide In Left',
'slideInRight' => 'Slide In Right',
'slideInUp' => 'Slide In Up',
],
'Rotating' => [
'rotateIn' => 'Rotate In',
'rotateInDownLeft' => 'Rotate In Down Left',
'rotateInDownRight' => 'Rotate In Down Right',
'rotateInUpLeft' => 'Rotate In Up Left',
'rotateInUpRight' => 'Rotate In Up Right',
],
'Attention Seekers' => [
'bounce' => 'Bounce',
'flash' => 'Flash',
'pulse' => 'Pulse',
'rubberBand' => 'Rubber Band',
'shake' => 'Shake',
'headShake' => 'Head Shake',
'swing' => 'Swing',
'tada' => 'Tada',
'wobble' => 'Wobble',
'jello' => 'Jello',
],
'Light Speed' => [
'lightSpeedIn' => 'Light Speed In',
],
'Specials' => [
'rollIn' => 'Roll In',
],
];
}

return self::$_animations;
}

/**
* Render animations control template.
*
* Used to generate the control HTML in the editor using Underscore JS
* template. The variables for the class are available using `data` JS
* object.
*
* @since 1.0.0
* @access public
*/
public function content_template() {
$control_uid = $this->get_control_uid();
?>
<div class="elementor-control-field">
<label for="<?php echo $control_uid; ?>" class="elementor-control-title">{{{ data.label }}}</label>
<div class="elementor-control-input-wrapper">
<select id="<?php echo $control_uid; ?>" data-setting="{{ data.name }}">
<option value=""><?php _e( 'None', 'elementor' ); ?></option>
<?php foreach ( self::get_animations() as $animations_group_name => $animations_group ) : ?>
<optgroup label="<?php echo $animations_group_name; ?>">
<?php foreach ( $animations_group as $animation_name => $animation_title ) : ?>
<option value="<?php echo $animation_name; ?>"><?php echo $animation_title; ?></option>
<?php endforeach; ?>
</optgroup>
<?php endforeach; ?>
</select>
</div>
</div>
<# if ( data.description ) { #>
<div class="elementor-control-field-description">{{{ data.description }}}</div>
<# } #>
<?php
}
}
@@ -0,0 +1,92 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Base data control.
*
* A base control for creating data controls.
*
* @since 1.5.0
* @abstract
*/
abstract class Base_Data_Control extends Base_Control {

/**
* Retrieve data control default value.
*
* Get the default value of the data control. Used to return the default
* values while initializing the data control.
*
* @since 1.5.0
* @access public
*
* @return string Control default value.
*/
public function get_default_value() {
return '';
}

/**
* Retrieve data control value.
*
* Get the value of the data control from a specific widget settings.
*
* @since 1.5.0
* @access public
*
* @param array $control Control
* @param array $widget Widget
*
* @return mixed Control values.
*/
public function get_value( $control, $widget ) {
if ( ! isset( $control['default'] ) ) {
$control['default'] = $this->get_default_value();
}

if ( ! isset( $widget[ $control['name'] ] ) ) {
return $control['default'];
}

return $widget[ $control['name'] ];
}

/**
* Retrieve data control style value.
*
* Get the style of the control. Used when adding CSS rules to the control
* while extracting CSS from the `selectors` data argument.
*
* @since 1.5.0
* @access public
*
* @param string $css_property CSS property.
* @param string $control_value Control value.
*
* @return string Control style value.
*/
public function get_style_value( $css_property, $control_value ) {
return $control_value;
}

/**
* Retrieve data control unique ID.
*
* Get the unique ID of the control. Used to set a uniq CSS ID for the
* element.
*
* @since 1.5.0
* @access protected
*
* @param string $input_type Input type. Default is 'default'.
*
* @return string Unique ID.
*/
protected function get_control_uid( $input_type = 'default' ) {
return 'elementor-control-' . $input_type . '-{{{ data._cid }}}';
}
}
@@ -0,0 +1,87 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Base multiple control.
*
* A base control for creating controls that return more than a single value.
* Each value of the multi-value control will be returned as an item in a
* key => value array.
*
* @since 1.0.0
* @abstract
*/
abstract class Control_Base_Multiple extends Base_Data_Control {

/**
* Retrieve multiple control default value.
*
* Get the default value of the multiple control. Used to return the default
* values while initializing the multiple control.
*
* @since 1.0.0
* @access public
*
* @return array Control default value.
*/
public function get_default_value() {
return [];
}

/**
* Retrieve multiple control value.
*
* Get the value of the multiple control from a specific widget settings.
*
* @since 1.0.0
* @access public
*
* @param array $control Control
* @param array $widget Widget
*
* @return mixed Control values.
*/
public function get_value( $control, $widget ) {
$value = parent::get_value( $control, $widget );

if ( empty( $control['default'] ) ) {
$control['default'] = [];
}

if ( ! is_array( $value ) ) {
$value = [];
}

$control['default'] = array_merge(
$this->get_default_value(),
$control['default']
);

return array_merge(
$control['default'],
$value
);
}

/**
* Retrieve multiple control style value.
*
* Get the style of the control. Used when adding CSS rules to the control
* while extracting CSS from the `selectors` data argument.
*
* @since 1.0.5
* @access public
*
* @param string $css_property CSS property.
* @param string $control_value Control value.
*
* @return array Control style value.
*/
public function get_style_value( $css_property, $control_value ) {
return $control_value[ $css_property ];
}
}
@@ -0,0 +1,31 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Base UI control.
*
* A base control for creating UI controls.
*
* @abstract
*/
abstract class Base_UI_Control extends Base_Control {

/**
* Retrieve features.
*
* Get the list of all the available features.
*
* @since 1.5.0
* @access public
* @static
*
* @return array Features array.
*/
public static function get_features() {
return [ 'ui' ];
}
}
@@ -0,0 +1,138 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Base units control.
*
* A base control for creating unit control.
*
* @since 1.0.0
* @abstract
*
* @param array $default {
* Optional. Defautl unit values.
*
* @type int $top Optional. Top unit. Default is empty.
* @type int $right Optional. Right unit. Default is empty.
* @type int $bottom Optional. Bottom unit. Default is empty.
* @type int $left Optional. Left unit. Default is empty.
* @type string $unit Optional. The CSS unit type. Available units are
* '%', 'px', 'em', 'rem' or 'deg'. Default is 'px'.
* @type bool $isLinked Optional. Whether to link all the values together
* or not. Used to prevent setting different values
* foreach unit location (top, right, bottom,
* left). Default is True, all the unit are linked.
* }
* @param array $size_units Optional. An array of available CSS
* units like 'px', '%' and 'em'.
* Default is [ 'px' ].
* @param array|string $allowed_dimensions Optional. Which fields to show.
* Available values are 'all',
* 'horizontal', 'vertical',
* [ 'top', 'left' ... ]. Default is 'all'.
* @param array $range {
* The range parameter is populated by default with ranges for each register
* size (e.g. px|em|rem|%|deg). @see Control_Base_Units::get_default_settings()
*
* {
* @type integer $min Optional. The minimum value of range.
* @type integer $max Optional. The maximum value of range.
* @type integer $step Optional. The intervals value that will be incremented
* or decremented when using the controls' spinners.
* },
* ...
* }
*/
abstract class Control_Base_Units extends Control_Base_Multiple {

/**
* Retrieve units control default value.
*
* Get the default value of the units control. Used to return the default
* values while initializing the units control.
*
* @since 1.0.0
* @access public
*
* @return array Control default value.
*/
public function get_default_value() {
return [
'unit' => 'px',
];
}

/**
* Retrieve units control default settings.
*
* Get the default settings of the units control. Used to return the default
* settings while initializing the units control.
*
* @since 1.0.0
* @access protected
*
* @return array Control default settings.
*/
protected function get_default_settings() {
return [
'size_units' => [ 'px' ],
'range' => [
'px' => [
'min' => 0,
'max' => 100,
'step' => 1,
],
'em' => [
'min' => 0.1,
'max' => 10,
'step' => 0.1,
],
'rem' => [
'min' => 0.1,
'max' => 10,
'step' => 0.1,
],
'%' => [
'min' => 0,
'max' => 100,
'step' => 1,
],
'deg' => [
'min' => 0,
'max' => 360,
'step' => 1,
],
'vh' => [
'min' => 0,
'max' => 100,
'step' => 1,
],
],
];
}

/**
* Print units control settings.
*
* Used to generate the units control template in the editor.
*
* @since 1.0.0
* @access protected
*/
protected function print_units_template() {
?>
<# if ( data.size_units.length > 1 ) { #>
<div class="elementor-units-choices">
<# _.each( data.size_units, function( unit ) { #>
<input id="elementor-choose-{{ data._cid + data.name + unit }}" type="radio" name="elementor-choose-{{ data.name }}" data-setting="unit" value="{{ unit }}">
<label class="elementor-units-choices-label" for="elementor-choose-{{ data._cid + data.name + unit }}">{{{ unit }}}</label>
<# } ); #>
</div>
<# } #>
<?php
}
}
@@ -0,0 +1,211 @@
<?php
namespace Elementor;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* Base control.
*
* A base control for creating controls in the panel. Each control accepts all
* the params listed below.
*
* @since 1.0.0
* @abstract
*
* @param string $label Optional. The label that appears above of the
* field. Default is empty.
* @param string $title Optional. The field title that appears on mouse
* hover. Default is empty.
* @param string $placeholder Optional. The field placeholder that appears when
* the field has no values. Default is empty.
* @param string $description Optional. The description that appears below the
* field. Default is empty.
* @param mixed $default Optional. The field default value.
* @param string $separator Optional. Set the position of the control separator.
* Available values are 'default', 'before', 'after'
* and 'none'. 'default' will position the separator
* depending on the control type. 'before' / 'after'
* will position the separator before/after the
* control. 'none' will hide the separator. Default
* is 'default'.
* @param bool $show_label Optional. Whether to display the label. Default is
* true.
* @param bool $label_block Optional. Whether to display the label in a
* separate line. Default is false.
*/
abstract class Base_Control {

/**
* Base settings.
*
* Holds all the base settings of the control.
*
* @access private
*
* @var array
*/
private $_base_settings = [
'label' => '',
'title' => '',
'placeholder' => '',
'description' => '',
'separator' => 'default',
'show_label' => true,
'label_block' => false,
];

/**
* Settings.
*
* Holds all the settings of the control.
*
* @access private
*
* @var array
*/
private $_settings = [];

/**
* Retrieve features.
*
* Get the list of all the available features. Currently Elementor uses only
* the `UI` feature.
*
* @since 1.5.0
* @access public
* @static
*
* @return array Features array.
*/
public static function get_features() {
return [];
}

/**
* Retrieve control type.
*
* @since 1.5.0
* @access public
* @abstract
*/
abstract public function get_type();

/**
* Control base constructor.
*
* Initializing the control base class.
*
* @since 1.5.0
* @access public
*/
public function __construct() {
$this->_settings = array_merge( $this->_base_settings, $this->get_default_settings() );

$this->_settings['features'] = static::get_features();
}

/**
* Enqueue control scripts and styles.
*
* Used to register and enqueue custom scripts and styles used by the control.
*
* @since 1.5.0
* @access public
*/
public function enqueue() {}

/**
* Retrieve control settings.
*
* Get the control settings or a specific setting value.
*
* @since 1.0.0
* @access public
*
* @param string $setting_key Optional. Specific key to return from the
* settings. If key set it will return the
* specific value of the key, otherwise the
* entire key array will be returned. Dafault is
* null.
*
* @return mixed The control settings, or specific setting value.
*/
final public function get_settings( $setting_key = null ) {
if ( $setting_key ) {
if ( isset( $this->_settings[ $setting_key ] ) ) {
return $this->_settings[ $setting_key ];
}

return null;
}

return $this->_settings;
}

/**
* Set control settings.
*
* Used to set or to update the settings of an existing control.
*
* @since 1.5.0
* @access public
*
* @param string $key Control settings key.
* @param mixed $value Control settings value.
*/
final public function set_settings( $key, $value ) {
$this->_settings[ $key ] = $value;
}

/**
* Control content template.
*
* Used to generate the control HTML in the editor using Underscore JS
* template. The variables for the class are available using `data` JS
* object.
*
* Note that the content template is wrapped by Base_Control::print_template().
*
* @since 1.5.0
* @access public
* @abstract
*/
abstract public function content_template();

/**
* Print control template.
*
* Used to generate the control HTML in the editor using Underscore JS
* template. The variables for the class are available using `data` JS
* object.
*
* @since 1.0.0
* @access public
*/
final public function print_template() {
?>
<script type="text/html" id="tmpl-elementor-control-<?php echo esc_attr( $this->get_type() ); ?>-content">
<div class="elementor-control-content">
<?php $this->content_template(); ?>
</div>
</script>
<?php
}

/**
* Retrieve default control settings.
*
* Get the default settings of the control. Used to return the default
* settings while initializing the control.
*
* @since 1.5.0
* @access protected
*
* @return array Control default settings.
*/
protected function get_default_settings() {
return [];
}
}