first commit
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\AdminBar;
|
||||
|
||||
use Elementor\Core\Base\Document;
|
||||
use Elementor\Core\Base\App as BaseApp;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Module extends BaseApp {
|
||||
/**
|
||||
* @var Document[]
|
||||
*/
|
||||
private $documents = [];
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_active() {
|
||||
return is_admin_bar_showing();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'admin-bar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the documents that was rendered in the current page.
|
||||
*
|
||||
* @param Document $document
|
||||
* @param $is_excerpt
|
||||
*/
|
||||
public function add_document_to_admin_bar( Document $document, $is_excerpt ) {
|
||||
if (
|
||||
$is_excerpt ||
|
||||
! $document::get_property( 'show_on_admin_bar' ) ||
|
||||
! $document->is_editable_by_current_user()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->documents[ $document->get_main_id() ] = $document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scripts for module.
|
||||
*/
|
||||
public function enqueue_scripts() {
|
||||
if ( empty( $this->documents ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'elementor-admin-bar',
|
||||
$this->get_js_assets_url( 'admin-bar' ),
|
||||
[ 'elementor-common' ],
|
||||
ELEMENTOR_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
$this->print_config( 'elementor-admin-bar' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates admin bar menu items config.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_init_settings() {
|
||||
$settings = [];
|
||||
|
||||
if ( ! empty( $this->documents ) ) {
|
||||
$settings['elementor_edit_page'] = $this->get_edit_button_config();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register admin_bar config to parse later in the frontend and add to the admin bar with JS
|
||||
*
|
||||
* @param array $settings the admin_bar config
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
return apply_filters( 'elementor/frontend/admin_bar/settings', $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the config for 'Edit with elementor' menu item.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_edit_button_config() {
|
||||
$queried_object_id = get_queried_object_id();
|
||||
$href = null;
|
||||
|
||||
if ( is_singular() && isset( $this->documents[ $queried_object_id ] ) ) {
|
||||
$href = $this->documents[ $queried_object_id ]->get_edit_url();
|
||||
|
||||
unset( $this->documents[ $queried_object_id ] );
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => 'elementor_edit_page',
|
||||
'title' => __( 'Edit with Elementor', 'elementor' ),
|
||||
'href' => $href,
|
||||
'children' => array_map( function ( $document ) {
|
||||
return [
|
||||
'id' => "elementor_edit_doc_{$document->get_main_id()}",
|
||||
'title' => $document->get_post()->post_title,
|
||||
'sub_title' => $document::get_title(),
|
||||
'href' => $document->get_edit_url(),
|
||||
];
|
||||
}, $this->documents ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Module constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'elementor/frontend/get_builder_content', [ $this, 'add_document_to_admin_bar' ], 10, 2 );
|
||||
add_action( 'wp_footer', [ $this, 'enqueue_scripts' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\DynamicTags;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\DynamicTags\Manager;
|
||||
use Elementor\Core\DynamicTags\Tag;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor dynamic tags module.
|
||||
*
|
||||
* Elementor dynamic tags module handler class is responsible for registering
|
||||
* and managing Elementor dynamic tags modules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* Base dynamic tag group.
|
||||
*/
|
||||
const BASE_GROUP = 'base';
|
||||
|
||||
/**
|
||||
* Dynamic tags text category.
|
||||
*/
|
||||
const TEXT_CATEGORY = 'text';
|
||||
|
||||
/**
|
||||
* Dynamic tags URL category.
|
||||
*/
|
||||
const URL_CATEGORY = 'url';
|
||||
|
||||
/**
|
||||
* Dynamic tags image category.
|
||||
*/
|
||||
const IMAGE_CATEGORY = 'image';
|
||||
|
||||
/**
|
||||
* Dynamic tags media category.
|
||||
*/
|
||||
const MEDIA_CATEGORY = 'media';
|
||||
|
||||
/**
|
||||
* Dynamic tags post meta category.
|
||||
*/
|
||||
const POST_META_CATEGORY = 'post_meta';
|
||||
|
||||
/**
|
||||
* Dynamic tags gallery category.
|
||||
*/
|
||||
const GALLERY_CATEGORY = 'gallery';
|
||||
|
||||
/**
|
||||
* Dynamic tags number category.
|
||||
*/
|
||||
const NUMBER_CATEGORY = 'number';
|
||||
|
||||
/**
|
||||
* Dynamic tags number category.
|
||||
*/
|
||||
const COLOR_CATEGORY = 'color';
|
||||
|
||||
/**
|
||||
* Dynamic tags module constructor.
|
||||
*
|
||||
* Initializing Elementor dynamic tags module.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->register_groups();
|
||||
|
||||
add_action( 'elementor/dynamic_tags/register_tags', [ $this, 'register_tags' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the dynamic tags module name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'dynamic_tags';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get classes names.
|
||||
*
|
||||
* Retrieve the dynamic tag classes names.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Tag dynamic tag classes names.
|
||||
*/
|
||||
public function get_tag_classes_names() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get groups.
|
||||
*
|
||||
* Retrieve the dynamic tag groups.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Tag dynamic tag groups.
|
||||
*/
|
||||
public function get_groups() {
|
||||
return [
|
||||
self::BASE_GROUP => [
|
||||
'title' => 'Base Tags',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register groups.
|
||||
*
|
||||
* Add all the available tag groups.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function register_groups() {
|
||||
foreach ( $this->get_groups() as $group_name => $group_settings ) {
|
||||
Plugin::$instance->dynamic_tags->register_group( $group_name, $group_settings );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register tags.
|
||||
*
|
||||
* Add all the available dynamic tags.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param Manager $dynamic_tags
|
||||
*/
|
||||
public function register_tags( $dynamic_tags ) {
|
||||
foreach ( $this->get_tag_classes_names() as $tag_class ) {
|
||||
/** @var Tag $class_name */
|
||||
$class_name = $this->get_reflection()->getNamespaceName() . '\Tags\\' . $tag_class;
|
||||
|
||||
$dynamic_tags->register_tag( $class_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Gutenberg;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\User;
|
||||
use Elementor\Utils;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Module extends BaseModule {
|
||||
|
||||
protected $is_gutenberg_editor_active = false;
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'gutenberg';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function is_active() {
|
||||
return function_exists( 'register_block_type' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_elementor_rest_field() {
|
||||
register_rest_field( get_post_types( '', 'names' ),
|
||||
'gutenberg_elementor_mode', [
|
||||
'update_callback' => function( $request_value, $object ) {
|
||||
if ( ! User::is_current_user_can_edit( $object->ID ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Plugin::$instance->db->set_is_elementor_page( $object->ID, false );
|
||||
|
||||
return true;
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
$document = Plugin::$instance->documents->get( get_the_ID() );
|
||||
|
||||
if ( ! $document || ! $document->is_editable_by_current_user() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->is_gutenberg_editor_active = true;
|
||||
|
||||
$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
|
||||
|
||||
wp_enqueue_script( 'elementor-gutenberg', ELEMENTOR_ASSETS_URL . 'js/gutenberg' . $suffix . '.js', [ 'jquery' ], ELEMENTOR_VERSION, true );
|
||||
|
||||
$elementor_settings = [
|
||||
'isElementorMode' => $document->is_built_with_elementor(),
|
||||
'editLink' => $document->get_edit_url(),
|
||||
];
|
||||
Utils::print_js_config( 'elementor-gutenberg', 'ElementorGutenbergSettings', $elementor_settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function print_admin_js_template() {
|
||||
if ( ! $this->is_gutenberg_editor_active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<script id="elementor-gutenberg-button-switch-mode" type="text/html">
|
||||
<div id="elementor-switch-mode">
|
||||
<button id="elementor-switch-mode-button" type="button" class="button button-primary button-large">
|
||||
<span class="elementor-switch-mode-on"><?php echo __( '← Back to WordPress Editor', 'elementor' ); ?></span>
|
||||
<span class="elementor-switch-mode-off">
|
||||
<i class="eicon-elementor-square" aria-hidden="true"></i>
|
||||
<?php echo __( 'Edit with Elementor', 'elementor' ); ?>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="elementor-gutenberg-panel" type="text/html">
|
||||
<div id="elementor-editor"><a id="elementor-go-to-edit-page-link" href="#">
|
||||
<div id="elementor-editor-button" class="button button-primary button-hero">
|
||||
<i class="eicon-elementor-square" aria-hidden="true"></i>
|
||||
<?php echo __( 'Edit with Elementor', 'elementor' ); ?>
|
||||
</div>
|
||||
<div class="elementor-loader-wrapper">
|
||||
<div class="elementor-loader">
|
||||
<div class="elementor-loader-boxes">
|
||||
<div class="elementor-loader-box"></div>
|
||||
<div class="elementor-loader-box"></div>
|
||||
<div class="elementor-loader-box"></div>
|
||||
<div class="elementor-loader-box"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="elementor-loading-title"><?php echo __( 'Loading', 'elementor' ); ?></div>
|
||||
</div>
|
||||
</a></div>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'rest_api_init', [ $this, 'register_elementor_rest_field' ] );
|
||||
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_assets' ] );
|
||||
add_action( 'admin_footer', [ $this, 'print_admin_js_template' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\History;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor history module.
|
||||
*
|
||||
* Elementor history module handler class is responsible for registering and
|
||||
* managing Elementor history modules.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the history module name.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'history';
|
||||
}
|
||||
|
||||
/**
|
||||
* Localize settings.
|
||||
*
|
||||
* Add new localized settings for the history module.
|
||||
*
|
||||
* Fired by `elementor/editor/localize_settings` filter.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $settings Localized settings.
|
||||
*
|
||||
* @return array Localized settings.
|
||||
*/
|
||||
public function localize_settings( $settings ) {
|
||||
$settings = array_replace_recursive( $settings, [
|
||||
'i18n' => [
|
||||
'history' => __( 'History', 'elementor' ),
|
||||
'template' => __( 'Template', 'elementor' ),
|
||||
'added' => __( 'Added', 'elementor' ),
|
||||
'removed' => __( 'Removed', 'elementor' ),
|
||||
'edited' => __( 'Edited', 'elementor' ),
|
||||
'moved' => __( 'Moved', 'elementor' ),
|
||||
'pasted' => __( 'Pasted', 'elementor' ),
|
||||
'editing_started' => __( 'Editing Started', 'elementor' ),
|
||||
'style_pasted' => __( 'Style Pasted', 'elementor' ),
|
||||
'style_reset' => __( 'Style Reset', 'elementor' ),
|
||||
'settings_reset' => __( 'Settings Reset', 'elementor' ),
|
||||
'enabled' => __( 'Enabled', 'elementor' ),
|
||||
'disabled' => __( 'Disabled', 'elementor' ),
|
||||
'all_content' => __( 'All Content', 'elementor' ),
|
||||
'elements' => __( 'Elements', 'elementor' ),
|
||||
],
|
||||
] );
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function add_templates() {
|
||||
Plugin::$instance->common->add_template( __DIR__ . '/views/history-panel-template.php' );
|
||||
Plugin::$instance->common->add_template( __DIR__ . '/views/revisions-panel-template.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* History module constructor.
|
||||
*
|
||||
* Initializing Elementor history module.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter( 'elementor/editor/localize_settings', [ $this, 'localize_settings' ] );
|
||||
|
||||
add_action( 'elementor/editor/init', [ $this, 'add_templates' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\History;
|
||||
|
||||
use Elementor\Core\Base\Document;
|
||||
use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
|
||||
use Elementor\Core\Files\CSS\Post as Post_CSS;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\Utils;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor history revisions manager.
|
||||
*
|
||||
* Elementor history revisions manager handler class is responsible for
|
||||
* registering and managing Elementor revisions manager.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class Revisions_Manager {
|
||||
|
||||
/**
|
||||
* Maximum number of revisions to display.
|
||||
*/
|
||||
const MAX_REVISIONS_TO_DISPLAY = 100;
|
||||
|
||||
/**
|
||||
* Authors list.
|
||||
*
|
||||
* Holds all the authors.
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $authors = [];
|
||||
|
||||
/**
|
||||
* History revisions manager constructor.
|
||||
*
|
||||
* Initializing Elementor history revisions manager.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
self::register_actions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function handle_revision() {
|
||||
add_filter( 'wp_save_post_revision_check_for_changes', '__return_false' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param $post_content
|
||||
* @param $post_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function avoid_delete_auto_save( $post_content, $post_id ) {
|
||||
// Add a temporary string in order the $post will not be equal to the $autosave
|
||||
// in edit-form-advanced.php:210
|
||||
if ( $post_id && Plugin::$instance->db->is_built_with_elementor( $post_id ) ) {
|
||||
$post_content .= '<!-- Created with Elementor -->';
|
||||
}
|
||||
|
||||
return $post_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function remove_temp_post_content() {
|
||||
global $post;
|
||||
|
||||
if ( Plugin::$instance->db->is_built_with_elementor( $post->ID ) ) {
|
||||
$post->post_content = str_replace( '<!-- Created with Elementor -->', '', $post->post_content );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param array $query_args
|
||||
* @param bool $parse_result
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_revisions( $post_id = 0, $query_args = [], $parse_result = true ) {
|
||||
$post = get_post( $post_id );
|
||||
|
||||
if ( ! $post || empty( $post->ID ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$revisions = [];
|
||||
|
||||
$default_query_args = [
|
||||
'posts_per_page' => self::MAX_REVISIONS_TO_DISPLAY,
|
||||
'meta_key' => '_elementor_data',
|
||||
];
|
||||
|
||||
$query_args = array_merge( $default_query_args, $query_args );
|
||||
|
||||
$posts = wp_get_post_revisions( $post->ID, $query_args );
|
||||
|
||||
if ( ! wp_revisions_enabled( $post ) ) {
|
||||
$autosave = Utils::get_post_autosave( $post->ID );
|
||||
if ( $autosave ) {
|
||||
if ( $parse_result ) {
|
||||
array_unshift( $posts, $autosave );
|
||||
} else {
|
||||
array_unshift( $posts, $autosave->ID );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $parse_result ) {
|
||||
array_unshift( $posts, $post );
|
||||
} else {
|
||||
array_unshift( $posts, $post->ID );
|
||||
return $posts;
|
||||
}
|
||||
|
||||
$current_time = current_time( 'timestamp' );
|
||||
|
||||
/** @var \WP_Post $revision */
|
||||
foreach ( $posts as $revision ) {
|
||||
$date = date_i18n( _x( 'M j @ H:i', 'revision date format', 'elementor' ), strtotime( $revision->post_modified ) );
|
||||
|
||||
$human_time = human_time_diff( strtotime( $revision->post_modified ), $current_time );
|
||||
|
||||
if ( $revision->ID === $post->ID ) {
|
||||
$type = 'current';
|
||||
} elseif ( false !== strpos( $revision->post_name, 'autosave' ) ) {
|
||||
$type = 'autosave';
|
||||
} else {
|
||||
$type = 'revision';
|
||||
}
|
||||
|
||||
if ( ! isset( self::$authors[ $revision->post_author ] ) ) {
|
||||
self::$authors[ $revision->post_author ] = [
|
||||
'avatar' => get_avatar( $revision->post_author, 22 ),
|
||||
'display_name' => get_the_author_meta( 'display_name', $revision->post_author ),
|
||||
];
|
||||
}
|
||||
|
||||
$revisions[] = [
|
||||
'id' => $revision->ID,
|
||||
'author' => self::$authors[ $revision->post_author ]['display_name'],
|
||||
'timestamp' => strtotime( $revision->post_modified ),
|
||||
'date' => sprintf(
|
||||
/* translators: 1: Human readable time difference, 2: Date */
|
||||
__( '%1$s ago (%2$s)', 'elementor' ),
|
||||
$human_time,
|
||||
$date
|
||||
),
|
||||
'type' => $type,
|
||||
'gravatar' => self::$authors[ $revision->post_author ]['avatar'],
|
||||
];
|
||||
}
|
||||
|
||||
return $revisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.9.2
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function update_autosave( $autosave_data ) {
|
||||
self::save_revision( $autosave_data['ID'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function save_revision( $revision_id ) {
|
||||
$parent_id = wp_is_post_revision( $revision_id );
|
||||
|
||||
if ( $parent_id ) {
|
||||
Plugin::$instance->db->safe_copy_elementor_meta( $parent_id, $revision_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function restore_revision( $parent_id, $revision_id ) {
|
||||
$is_built_with_elementor = Plugin::$instance->db->is_built_with_elementor( $revision_id );
|
||||
|
||||
Plugin::$instance->db->set_is_elementor_page( $parent_id, $is_built_with_elementor );
|
||||
|
||||
if ( ! $is_built_with_elementor ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin::$instance->db->copy_elementor_meta( $revision_id, $parent_id );
|
||||
|
||||
$post_css = Post_CSS::create( $parent_id );
|
||||
|
||||
$post_css->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function ajax_get_revision_data( array $data ) {
|
||||
if ( ! isset( $data['id'] ) ) {
|
||||
throw new \Exception( 'You must set the revision ID.' );
|
||||
}
|
||||
|
||||
$revision = Plugin::$instance->documents->get( $data['id'] );
|
||||
|
||||
if ( ! $revision ) {
|
||||
throw new \Exception( 'Invalid revision.' );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_post', $revision->get_id() ) ) {
|
||||
throw new \Exception( __( 'Access denied.', 'elementor' ) );
|
||||
}
|
||||
|
||||
$revision_data = [
|
||||
'settings' => $revision->get_settings(),
|
||||
'elements' => $revision->get_elements_data(),
|
||||
];
|
||||
|
||||
return $revision_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function add_revision_support_for_all_post_types() {
|
||||
$post_types = get_post_types_by_support( 'elementor' );
|
||||
foreach ( $post_types as $post_type ) {
|
||||
add_post_type_support( $post_type, 'revisions' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
* @param array $return_data
|
||||
* @param Document $document
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function on_ajax_save_builder_data( $return_data, $document ) {
|
||||
$post_id = $document->get_main_id();
|
||||
|
||||
$latest_revisions = self::get_revisions(
|
||||
$post_id, [
|
||||
'posts_per_page' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
$all_revision_ids = self::get_revisions(
|
||||
$post_id, [
|
||||
'fields' => 'ids',
|
||||
], false
|
||||
);
|
||||
|
||||
// Send revisions data only if has revisions.
|
||||
if ( ! empty( $latest_revisions ) ) {
|
||||
$current_revision_id = self::current_revision_id( $post_id );
|
||||
|
||||
$return_data = array_replace_recursive( $return_data, [
|
||||
'config' => [
|
||||
'document' => [
|
||||
'revisions' => [
|
||||
'current_id' => $current_revision_id,
|
||||
],
|
||||
],
|
||||
],
|
||||
'latest_revisions' => $latest_revisions,
|
||||
'revisions_ids' => $all_revision_ids,
|
||||
] );
|
||||
}
|
||||
|
||||
return $return_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function db_before_save( $status, $has_changes ) {
|
||||
if ( $has_changes ) {
|
||||
self::handle_revision();
|
||||
}
|
||||
}
|
||||
|
||||
public static function document_config( $settings, $post_id ) {
|
||||
$settings['revisions'] = [
|
||||
'enabled' => ( $post_id && wp_revisions_enabled( get_post( $post_id ) ) ),
|
||||
'current_id' => self::current_revision_id( $post_id ),
|
||||
];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Localize settings.
|
||||
*
|
||||
* Add new localized settings for the revisions manager.
|
||||
*
|
||||
* Fired by `elementor/editor/editor_settings` filter.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function editor_settings( $settings ) {
|
||||
$settings = array_replace_recursive( $settings, [
|
||||
'i18n' => [
|
||||
'edit_draft' => __( 'Edit Draft', 'elementor' ),
|
||||
'edit_published' => __( 'Edit Published', 'elementor' ),
|
||||
'no_revisions_1' => __( 'Revision history lets you save your previous versions of your work, and restore them any time.', 'elementor' ),
|
||||
'no_revisions_2' => __( 'Start designing your page and you\'ll be able to see the entire revision history here.', 'elementor' ),
|
||||
'current' => __( 'Current Version', 'elementor' ),
|
||||
'restore' => __( 'Restore', 'elementor' ),
|
||||
'restore_auto_saved_data' => __( 'Restore Auto Saved Data', 'elementor' ),
|
||||
'restore_auto_saved_data_message' => __( 'There is an autosave of this post that is more recent than the version below. You can restore the saved data fron the Revisions panel', 'elementor' ),
|
||||
'revision' => __( 'Revision', 'elementor' ),
|
||||
'revision_history' => __( 'Revision History', 'elementor' ),
|
||||
'revisions_disabled_1' => __( 'It looks like the post revision feature is unavailable in your website.', 'elementor' ),
|
||||
'revisions_disabled_2' => sprintf(
|
||||
/* translators: %s: Codex URL */
|
||||
__( 'Learn more about <a target="_blank" href="%s">WordPress revisions</a>', 'elementor' ),
|
||||
'https://go.elementor.com/wordpress-revisions/'
|
||||
),
|
||||
],
|
||||
] );
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public static function ajax_get_revisions() {
|
||||
return self::get_revisions();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function register_ajax_actions( Ajax $ajax ) {
|
||||
$ajax->register_ajax_action( 'get_revisions', [ __CLASS__, 'ajax_get_revisions' ] );
|
||||
$ajax->register_ajax_action( 'get_revision_data', [ __CLASS__, 'ajax_get_revision_data' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.7.0
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
private static function register_actions() {
|
||||
add_action( 'wp_restore_post_revision', [ __CLASS__, 'restore_revision' ], 10, 2 );
|
||||
add_action( 'init', [ __CLASS__, 'add_revision_support_for_all_post_types' ], 9999 );
|
||||
add_filter( 'elementor/editor/localize_settings', [ __CLASS__, 'editor_settings' ] );
|
||||
add_filter( 'elementor/document/config', [ __CLASS__, 'document_config' ], 10, 2 );
|
||||
add_action( 'elementor/db/before_save', [ __CLASS__, 'db_before_save' ], 10, 2 );
|
||||
add_action( '_wp_put_post_revision', [ __CLASS__, 'save_revision' ] );
|
||||
add_action( 'wp_creating_autosave', [ __CLASS__, 'update_autosave' ] );
|
||||
add_action( 'elementor/ajax/register_actions', [ __CLASS__, 'register_ajax_actions' ] );
|
||||
|
||||
// Hack to avoid delete the auto-save revision in WP editor.
|
||||
add_filter( 'edit_post_content', [ __CLASS__, 'avoid_delete_auto_save' ], 10, 2 );
|
||||
add_action( 'edit_form_after_title', [ __CLASS__, 'remove_temp_post_content' ] );
|
||||
|
||||
if ( wp_doing_ajax() ) {
|
||||
add_filter( 'elementor/documents/ajax_save/return_data', [ __CLASS__, 'on_ajax_save_builder_data' ], 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.9.0
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
private static function current_revision_id( $post_id ) {
|
||||
$current_revision_id = $post_id;
|
||||
$autosave = Utils::get_post_autosave( $post_id );
|
||||
|
||||
if ( is_object( $autosave ) ) {
|
||||
$current_revision_id = $autosave->ID;
|
||||
}
|
||||
|
||||
return $current_revision_id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/template" id="tmpl-elementor-panel-history-page">
|
||||
<div id="elementor-panel-elements-navigation" class="elementor-panel-navigation">
|
||||
<div class="elementor-component-tab elementor-panel-navigation-tab" data-tab="actions"><?php echo __( 'Actions', 'elementor' ); ?></div>
|
||||
<div class="elementor-component-tab elementor-panel-navigation-tab" data-tab="revisions"><?php echo __( 'Revisions', 'elementor' ); ?></div>
|
||||
</div>
|
||||
<div id="elementor-panel-history-content"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-history-tab">
|
||||
<div id="elementor-history-list"></div>
|
||||
<div class="elementor-history-revisions-message"><?php echo __( 'Switch to Revisions tab for older versions', 'elementor' ); ?></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-history-no-items">
|
||||
<img class="elementor-nerd-box-icon" src="<?php echo ELEMENTOR_ASSETS_URL . 'images/information.svg'; ?>" />
|
||||
<div class="elementor-nerd-box-title"><?php echo __( 'No History Yet', 'elementor' ); ?></div>
|
||||
<div class="elementor-nerd-box-message"><?php echo __( 'Once you start working, you\'ll be able to redo / undo any action you make in the editor.', 'elementor' ); ?></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-history-item">
|
||||
<div class="elementor-history-item__details">
|
||||
<span class="elementor-history-item__title">{{{ title }}}</span>
|
||||
<span class="elementor-history-item__subtitle">{{{ subTitle }}}</span>
|
||||
<span class="elementor-history-item__action">{{{ action }}}</span>
|
||||
</div>
|
||||
<div class="elementor-history-item__icon">
|
||||
<span class="eicon" aria-hidden="true"></span>
|
||||
</div>
|
||||
</script>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/template" id="tmpl-elementor-panel-revisions">
|
||||
<div class="elementor-panel-box">
|
||||
<div class="elementor-panel-scheme-buttons">
|
||||
<div class="elementor-panel-scheme-button-wrapper elementor-panel-scheme-discard">
|
||||
<button class="elementor-button" disabled>
|
||||
<i class="eicon-close" aria-hidden="true"></i>
|
||||
<?php echo __( 'Discard', 'elementor' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
<div class="elementor-panel-scheme-button-wrapper elementor-panel-scheme-save">
|
||||
<button class="elementor-button elementor-button-success" disabled>
|
||||
<?php echo __( 'Apply', 'elementor' ); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="elementor-panel-box">
|
||||
<div class="elementor-panel-heading">
|
||||
<div class="elementor-panel-heading-title"><?php echo __( 'Revisions', 'elementor' ); ?></div>
|
||||
</div>
|
||||
<div id="elementor-revisions-list" class="elementor-panel-box-content"></div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-revisions-no-revisions">
|
||||
<img class="elementor-nerd-box-icon" src="<?php echo ELEMENTOR_ASSETS_URL . 'images/information.svg'; ?>" />
|
||||
<div class="elementor-nerd-box-title"><?php echo __( 'No Revisions Saved Yet', 'elementor' ); ?></div>
|
||||
<div class="elementor-nerd-box-message">{{{ elementor.translate( elementor.config.document.revisions.enabled ? 'no_revisions_1' : 'revisions_disabled_1' ) }}}</div>
|
||||
<div class="elementor-nerd-box-message">{{{ elementor.translate( elementor.config.document.revisions.enabled ? 'no_revisions_2' : 'revisions_disabled_2' ) }}}</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-revisions-loading">
|
||||
<i class="eicon-loading eicon-animation-spin" aria-hidden="true"></i>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-panel-revisions-revision-item">
|
||||
<div class="elementor-revision-item__wrapper {{ type }}">
|
||||
<div class="elementor-revision-item__gravatar">{{{ gravatar }}}</div>
|
||||
<div class="elementor-revision-item__details">
|
||||
<div class="elementor-revision-date" title="{{{ new Date( timestamp * 1000 ) }}}">{{{ date }}}</div>
|
||||
<div class="elementor-revision-meta">
|
||||
<span>{{{ elementor.translate( type ) }}}</span>
|
||||
<?php echo __( 'By', 'elementor' ); ?> {{{ author }}}
|
||||
<span>(#{{{ id }}})</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="elementor-revision-item__tools">
|
||||
<# if ( 'current' === type ) { #>
|
||||
<i class="elementor-revision-item__tools-current eicon-star" aria-hidden="true"></i>
|
||||
<span class="elementor-screen-only"><?php echo __( 'Current', 'elementor' ); ?></span>
|
||||
<# } #>
|
||||
|
||||
<i class="elementor-revision-item__tools-spinner eicon-loading eicon-animation-spin" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Library\Documents;
|
||||
|
||||
use Elementor\Core\Base\Document;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor library document.
|
||||
*
|
||||
* Elementor library document handler class is responsible for handling
|
||||
* a document of the library type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
abstract class Library_Document extends Document {
|
||||
|
||||
/**
|
||||
* The taxonomy type slug for the library document.
|
||||
*/
|
||||
const TAXONOMY_TYPE_SLUG = 'elementor_library_type';
|
||||
|
||||
/**
|
||||
* Get document properties.
|
||||
*
|
||||
* Retrieve the document properties.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return array Document properties.
|
||||
*/
|
||||
public static function get_properties() {
|
||||
$properties = parent::get_properties();
|
||||
|
||||
$properties['admin_tab_group'] = 'library';
|
||||
$properties['show_in_library'] = true;
|
||||
$properties['register_type'] = true;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get initial config.
|
||||
*
|
||||
* Retrieve the current element initial configuration.
|
||||
*
|
||||
* Adds more configuration on top of the controls list and the tabs assigned
|
||||
* to the control. This method also adds element name, type, icon and more.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access protected
|
||||
*
|
||||
* @return array The initial config.
|
||||
*/
|
||||
public function get_initial_config() {
|
||||
$config = parent::get_initial_config();
|
||||
|
||||
$config['library'] = [
|
||||
'save_as_same_type' => true,
|
||||
];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
public function print_admin_column_type() {
|
||||
$admin_filter_url = admin_url( Source_Local::ADMIN_MENU_SLUG . '&elementor_library_type=' . $this->get_name() );
|
||||
|
||||
printf( '<a href="%s">%s</a>', $admin_filter_url, $this->get_title() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save document type.
|
||||
*
|
||||
* Set new/updated document type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function save_template_type() {
|
||||
parent::save_template_type();
|
||||
|
||||
wp_set_object_terms( $this->post->ID, $this->get_name(), self::TAXONOMY_TYPE_SLUG );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Library\Documents;
|
||||
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor section library document.
|
||||
*
|
||||
* Elementor section library document handler class is responsible for
|
||||
* handling a document of a section type.
|
||||
*
|
||||
*/
|
||||
class Not_Supported extends Library_Document {
|
||||
|
||||
/**
|
||||
* Get document properties.
|
||||
*
|
||||
* Retrieve the document properties.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return array Document properties.
|
||||
*/
|
||||
public static function get_properties() {
|
||||
$properties = parent::get_properties();
|
||||
|
||||
$properties['admin_tab_group'] = '';
|
||||
$properties['register_type'] = false;
|
||||
$properties['is_editable'] = false;
|
||||
$properties['show_in_library'] = false;
|
||||
|
||||
$properties['cpt'] = [
|
||||
Source_Local::CPT,
|
||||
];
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document name.
|
||||
*
|
||||
* Retrieve the document name.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return string Document name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'not-supported';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document title.
|
||||
*
|
||||
* Retrieve the document title.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return string Document title.
|
||||
*/
|
||||
public static function get_title() {
|
||||
return __( 'Not Supported', 'elementor' );
|
||||
}
|
||||
|
||||
public function save_template_type() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
public function print_admin_column_type() {
|
||||
echo self::get_title();
|
||||
}
|
||||
|
||||
public function filter_admin_row_actions( $actions ) {
|
||||
unset( $actions['view'] );
|
||||
|
||||
return $actions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Library\Documents;
|
||||
|
||||
use Elementor\Core\DocumentTypes\Post;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor page library document.
|
||||
*
|
||||
* Elementor page library document handler class is responsible for
|
||||
* handling a document of a page type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Page extends Library_Document {
|
||||
|
||||
/**
|
||||
* Get document properties.
|
||||
*
|
||||
* Retrieve the document properties.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return array Document properties.
|
||||
*/
|
||||
public static function get_properties() {
|
||||
$properties = parent::get_properties();
|
||||
|
||||
$properties['support_wp_page_templates'] = true;
|
||||
$properties['support_kit'] = true;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document name.
|
||||
*
|
||||
* Retrieve the document name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Document name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'page';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document title.
|
||||
*
|
||||
* Retrieve the document title.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return string Document title.
|
||||
*/
|
||||
public static function get_title() {
|
||||
return __( 'Page', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.3
|
||||
* @access public
|
||||
*/
|
||||
public function get_css_wrapper_selector() {
|
||||
return 'body.elementor-page-' . $this->get_main_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function _register_controls() {
|
||||
parent::_register_controls();
|
||||
|
||||
Post::register_hide_title_control( $this );
|
||||
|
||||
Post::register_style_controls( $this );
|
||||
}
|
||||
|
||||
protected function get_remote_library_config() {
|
||||
$config = parent::get_remote_library_config();
|
||||
|
||||
$config['type'] = 'page';
|
||||
$config['default_route'] = 'templates/pages';
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Library\Documents;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor section library document.
|
||||
*
|
||||
* Elementor section library document handler class is responsible for
|
||||
* handling a document of a section type.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Section extends Library_Document {
|
||||
|
||||
public static function get_properties() {
|
||||
$properties = parent::get_properties();
|
||||
|
||||
$properties['support_kit'] = true;
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document name.
|
||||
*
|
||||
* Retrieve the document name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Document name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'section';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get document title.
|
||||
*
|
||||
* Retrieve the document title.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return string Document title.
|
||||
*/
|
||||
public static function get_title() {
|
||||
return __( 'Section', 'elementor' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Library;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Modules\Library\Documents;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor library module.
|
||||
*
|
||||
* Elementor library module handler class is responsible for registering and
|
||||
* managing Elementor library modules.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the library module name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'library';
|
||||
}
|
||||
|
||||
/**
|
||||
* Library module constructor.
|
||||
*
|
||||
* Initializing Elementor library module.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
Plugin::$instance->documents
|
||||
->register_document_type( 'not-supported', Documents\Not_Supported::get_class_full_name() )
|
||||
->register_document_type( 'page', Documents\Page::get_class_full_name() )
|
||||
->register_document_type( 'section', Documents\Section::get_class_full_name() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
<?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\DB;
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 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' ) ) {
|
||||
$template_path = $this->get_template_path( $document->get_meta( '_wp_page_template' ) );
|
||||
|
||||
if ( ! $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 => _x( 'Elementor Canvas', 'Page Template', 'elementor' ),
|
||||
self::TEMPLATE_HEADER_FOOTER => _x( 'Elementor Full Width', 'Page Template', '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 ) {
|
||||
$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' => __( 'Page Layout', 'elementor' ),
|
||||
'type' => Controls_Manager::SELECT,
|
||||
'default' => 'default',
|
||||
'options' => [
|
||||
'default' => __( '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>' . __( 'Default Page Template from your theme', 'elementor' ) . '</b>',
|
||||
'content_classes' => 'elementor-descriptor',
|
||||
'condition' => [
|
||||
$control_id => 'default',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$document->add_control(
|
||||
$control_id . '_canvas_description',
|
||||
[
|
||||
'type' => Controls_Manager::RAW_HTML,
|
||||
'raw' => '<b>' . __( '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>' . __( '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' => __( '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'] && DB::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 ) && DB::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() {
|
||||
if ( function_exists( 'wp_body_open' ) ) {
|
||||
wp_body_open();
|
||||
} else {
|
||||
do_action( '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 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
\Elementor\Plugin::$instance->frontend->add_body_class( 'elementor-template-canvas' );
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html <?php language_attributes(); ?>>
|
||||
<head>
|
||||
<meta charset="<?php bloginfo( 'charset' ); ?>">
|
||||
<?php if ( ! current_theme_supports( 'title-tag' ) ) : ?>
|
||||
<title><?php echo wp_get_document_title(); ?></title>
|
||||
<?php endif; ?>
|
||||
<?php wp_head(); ?>
|
||||
<?php
|
||||
|
||||
// Keep the following line after `wp_head()` call, to ensure it's not overridden by another templates.
|
||||
echo \Elementor\Utils::get_meta_viewport( 'canvas' );
|
||||
?>
|
||||
</head>
|
||||
<body <?php body_class(); ?>>
|
||||
<?php
|
||||
Elementor\Modules\PageTemplates\Module::body_open();
|
||||
/**
|
||||
* Before canvas page template content.
|
||||
*
|
||||
* Fires before the content of Elementor canvas page template.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
do_action( 'elementor/page_templates/canvas/before_content' );
|
||||
|
||||
\Elementor\Plugin::$instance->modules_manager->get_modules( 'page-templates' )->print_content();
|
||||
|
||||
/**
|
||||
* After canvas page template content.
|
||||
*
|
||||
* Fires after the content of Elementor canvas page template.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
do_action( 'elementor/page_templates/canvas/after_content' );
|
||||
|
||||
wp_footer();
|
||||
?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
\Elementor\Plugin::$instance->frontend->add_body_class( 'elementor-template-full-width' );
|
||||
|
||||
get_header();
|
||||
/**
|
||||
* Before Header-Footer page template content.
|
||||
*
|
||||
* Fires before the content of Elementor Header-Footer page template.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
do_action( 'elementor/page_templates/header-footer/before_content' );
|
||||
|
||||
\Elementor\Plugin::$instance->modules_manager->get_modules( 'page-templates' )->print_content();
|
||||
|
||||
/**
|
||||
* After Header-Footer page template content.
|
||||
*
|
||||
* Fires after the content of Elementor Header-Footer page template.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
do_action( 'elementor/page_templates/header-footer/after_content' );
|
||||
|
||||
get_footer();
|
||||
@@ -0,0 +1,545 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\SafeMode;
|
||||
|
||||
use Elementor\Plugin;
|
||||
use Elementor\Settings;
|
||||
use Elementor\Tools;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Module extends \Elementor\Core\Base\Module {
|
||||
|
||||
const OPTION_ENABLED = 'elementor_safe_mode';
|
||||
const OPTION_TOKEN = self::OPTION_ENABLED . '_token';
|
||||
const MU_PLUGIN_FILE_NAME = 'elementor-safe-mode.php';
|
||||
const DOCS_HELPED_URL = 'https://go.elementor.com/safe-mode-helped/';
|
||||
const DOCS_DIDNT_HELP_URL = 'https://go.elementor.com/safe-mode-didnt-helped/';
|
||||
const DOCS_MU_PLUGINS_URL = 'https://go.elementor.com/safe-mode-mu-plugins/';
|
||||
const DOCS_TRY_SAFE_MODE_URL = 'https://go.elementor.com/safe-mode/';
|
||||
|
||||
const EDITOR_NOTICE_TIMEOUT = 30000; /* ms */
|
||||
|
||||
public function get_name() {
|
||||
return 'safe-mode';
|
||||
}
|
||||
|
||||
public function register_ajax_actions( Ajax $ajax ) {
|
||||
$ajax->register_ajax_action( 'enable_safe_mode', [ $this, 'ajax_enable_safe_mode' ] );
|
||||
$ajax->register_ajax_action( 'disable_safe_mode', [ $this, 'disable_safe_mode' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tools $tools_page
|
||||
*/
|
||||
public function add_admin_button( $tools_page ) {
|
||||
$tools_page->add_fields( Settings::TAB_GENERAL, 'tools', [
|
||||
'safe_mode' => [
|
||||
'label' => __( 'Safe Mode', 'elementor' ),
|
||||
'field_args' => [
|
||||
'type' => 'select',
|
||||
'std' => $this->is_enabled(),
|
||||
'options' => [
|
||||
'' => __( 'Disable', 'elementor' ),
|
||||
'global' => __( 'Enable', 'elementor' ),
|
||||
|
||||
],
|
||||
'desc' => __( 'Safe Mode allows you to troubleshoot issues by only loading the editor, without loading the theme or any other plugin.', 'elementor' ),
|
||||
],
|
||||
],
|
||||
] );
|
||||
}
|
||||
|
||||
public function on_update_safe_mode( $value ) {
|
||||
if ( 'yes' === $value || 'global' === $value ) {
|
||||
$this->enable_safe_mode();
|
||||
} else {
|
||||
$this->disable_safe_mode();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function ajax_enable_safe_mode( $data ) {
|
||||
// It will run `$this->>update_safe_mode`.
|
||||
update_option( 'elementor_safe_mode', 'yes' );
|
||||
|
||||
$document = Plugin::$instance->documents->get( $data['editor_post_id'] );
|
||||
|
||||
if ( $document ) {
|
||||
return add_query_arg( 'elementor-mode', 'safe', $document->get_edit_url() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function enable_safe_mode() {
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
WP_Filesystem();
|
||||
|
||||
$this->update_allowed_plugins();
|
||||
|
||||
if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
|
||||
wp_mkdir_p( WPMU_PLUGIN_DIR );
|
||||
add_option( 'elementor_safe_mode_created_mu_dir', true );
|
||||
}
|
||||
|
||||
if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
|
||||
wp_die( __( 'Cannot enable Safe Mode', 'elementor' ) );
|
||||
}
|
||||
|
||||
$results = copy_dir( __DIR__ . '/mu-plugin/', WPMU_PLUGIN_DIR );
|
||||
|
||||
if ( is_wp_error( $results ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$token = md5( wp_rand() );
|
||||
|
||||
// Only who own this key can use 'elementor-safe-mode'.
|
||||
update_option( self::OPTION_TOKEN, $token );
|
||||
|
||||
// Save for later use.
|
||||
setcookie( self::OPTION_TOKEN, $token, time() + HOUR_IN_SECONDS, COOKIEPATH );
|
||||
}
|
||||
|
||||
public function disable_safe_mode() {
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file_path = WP_CONTENT_DIR . '/mu-plugins/elementor-safe-mode.php';
|
||||
if ( file_exists( $file_path ) ) {
|
||||
unlink( $file_path );
|
||||
}
|
||||
|
||||
if ( get_option( 'elementor_safe_mode_created_mu_dir' ) ) {
|
||||
// It will be removed only if it's empty and don't have other mu-plugins.
|
||||
@rmdir( WPMU_PLUGIN_DIR );
|
||||
}
|
||||
|
||||
delete_option( 'elementor_safe_mode' );
|
||||
delete_option( 'elementor_safe_mode_allowed_plugins' );
|
||||
delete_option( 'theme_mods_elementor-safe' );
|
||||
delete_option( 'elementor_safe_mode_created_mu_dir' );
|
||||
|
||||
delete_option( self::OPTION_TOKEN );
|
||||
setcookie( self::OPTION_TOKEN, '', 1 );
|
||||
}
|
||||
|
||||
public function filter_preview_url( $url ) {
|
||||
return add_query_arg( 'elementor-mode', 'safe', $url );
|
||||
}
|
||||
|
||||
public function filter_template() {
|
||||
return ELEMENTOR_PATH . 'modules/page-templates/templates/canvas.php';
|
||||
}
|
||||
|
||||
public function print_safe_mode_css() {
|
||||
?>
|
||||
<style>
|
||||
.elementor-safe-mode-toast {
|
||||
position: absolute;
|
||||
z-index: 10000; /* Over the loading layer */
|
||||
bottom: 10px;
|
||||
width: 400px;
|
||||
line-height: 30px;
|
||||
background: white;
|
||||
padding: 20px 25px 25px;
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 5px;
|
||||
font-family: Roboto, Arial, Helvetica, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
body.rtl .elementor-safe-mode-toast {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
body:not(.rtl) .elementor-safe-mode-toast {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
#elementor-try-safe-mode {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast .elementor-toast-content {
|
||||
font-size: 13px;
|
||||
line-height: 22px;
|
||||
color: #6D7882;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast .elementor-toast-content a {
|
||||
color: #138FFF;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast .elementor-toast-content hr {
|
||||
margin: 15px auto;
|
||||
border: 0 none;
|
||||
border-top: 1px solid #F1F3F5;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast header > * {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast .elementor-safe-mode-button {
|
||||
display: inline-block;
|
||||
font-weight: 500;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
line-height: 1;
|
||||
background: #A4AFB7;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#elementor-try-safe-mode .elementor-safe-mode-button {
|
||||
background: #39B54A;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast header i {
|
||||
font-size: 25px;
|
||||
color: #fcb92c;
|
||||
}
|
||||
|
||||
body:not(.rtl) .elementor-safe-mode-toast header i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
body.rtl .elementor-safe-mode-toast header i {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-toast header h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 18px;
|
||||
color: #6D7882;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-list-item {
|
||||
margin-top: 10px;
|
||||
list-style: outside;
|
||||
}
|
||||
|
||||
body:not(.rtl) .elementor-safe-mode-list-item {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
body.rtl .elementor-safe-mode-list-item {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-list-item b {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-list-item-content {
|
||||
font-style: italic;
|
||||
color: #a4afb7;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-list-item-title {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.elementor-safe-mode-mu-plugins {
|
||||
background-color: #f1f3f5;
|
||||
margin-top: 20px;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function print_safe_mode_notice() {
|
||||
echo $this->print_safe_mode_css();
|
||||
?>
|
||||
<div class="elementor-safe-mode-toast" id="elementor-safe-mode-message">
|
||||
<header>
|
||||
<i class="eicon-warning"></i>
|
||||
<h2><?php echo __( 'Safe Mode ON', 'elementor' ); ?></h2>
|
||||
<a class="elementor-safe-mode-button elementor-disable-safe-mode" target="_blank" href="<?php echo $this->get_admin_page_url(); ?>">
|
||||
<?php echo __( 'Disable Safe Mode', 'elementor' ); ?>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<div class="elementor-toast-content">
|
||||
<ul class="elementor-safe-mode-list">
|
||||
<li class="elementor-safe-mode-list-item">
|
||||
<div class="elementor-safe-mode-list-item-title"><?php echo __( 'Editor successfully loaded?', 'elementor' ); ?></div>
|
||||
<div class="elementor-safe-mode-list-item-content"><?php echo __( 'The issue was probably caused by one of your plugins or theme.', 'elementor' ); ?> <?php printf( __( '<a href="%s" target="_blank">Click here</a> to troubleshoot', 'elementor' ), self::DOCS_HELPED_URL ); ?></div>
|
||||
</li>
|
||||
<li class="elementor-safe-mode-list-item">
|
||||
<div class="elementor-safe-mode-list-item-title"><?php echo __( 'Still experiencing issues?', 'elementor' ); ?></div>
|
||||
<div class="elementor-safe-mode-list-item-content"><?php printf( __( '<a href="%s" target="_blank">Click here</a> to troubleshoot', 'elementor' ), self::DOCS_DIDNT_HELP_URL ); ?></div>
|
||||
</li>
|
||||
</ul>
|
||||
<?php
|
||||
$mu_plugins = wp_get_mu_plugins();
|
||||
|
||||
if ( 1 < count( $mu_plugins ) ) : ?>
|
||||
<div class="elementor-safe-mode-mu-plugins"><?php printf( __( 'Please note! We couldn\'t deactivate all of your plugins on Safe Mode. Please <a href="%s" target="_blank">read more</a> about this issue.', 'elementor' ), self::DOCS_MU_PLUGINS_URL ); ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ElementorSafeMode = function() {
|
||||
var attachEvents = function() {
|
||||
jQuery( '.elementor-disable-safe-mode' ).on( 'click', function( e ) {
|
||||
if ( ! elementorCommon || ! elementorCommon.ajax ) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
elementorCommon.ajax.addRequest(
|
||||
'disable_safe_mode', {
|
||||
success: function() {
|
||||
if ( -1 === location.href.indexOf( 'elementor-mode=safe' ) ) {
|
||||
location.reload();
|
||||
} else {
|
||||
// Need to remove the URL from browser history.
|
||||
location.replace( location.href.replace( '&elementor-mode=safe', '' ) );
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert( 'An error occurred' );
|
||||
},
|
||||
},
|
||||
true
|
||||
);
|
||||
} );
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
attachEvents();
|
||||
};
|
||||
|
||||
init();
|
||||
};
|
||||
|
||||
new ElementorSafeMode();
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function print_try_safe_mode() {
|
||||
if ( ! $this->is_allowed_post_type() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $this->print_safe_mode_css();
|
||||
?>
|
||||
<div class="elementor-safe-mode-toast" id="elementor-try-safe-mode">
|
||||
<?php if ( current_user_can( 'install_plugins' ) ) : ?>
|
||||
<header>
|
||||
<i class="eicon-warning"></i>
|
||||
<h2><?php echo __( 'Can\'t Edit?', 'elementor' ); ?></h2>
|
||||
<a class="elementor-safe-mode-button elementor-enable-safe-mode" target="_blank" href="<?php echo $this->get_admin_page_url(); ?>">
|
||||
<?php echo __( 'Enable Safe Mode', 'elementor' ); ?>
|
||||
</a>
|
||||
</header>
|
||||
<div class="elementor-toast-content">
|
||||
<?php echo __( 'Having problems loading Elementor? Please enable Safe Mode to troubleshoot.', 'elementor' ); ?>
|
||||
<a href="<?php echo self::DOCS_TRY_SAFE_MODE_URL; ?>" target="_blank"><?php echo __( 'Learn More', 'elementor' ); ?></a>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<header>
|
||||
<i class="eicon-warning"></i>
|
||||
<h2><?php echo __( 'Can\'t Edit?', 'elementor' ); ?></h2>
|
||||
</header>
|
||||
<div class="elementor-toast-content">
|
||||
<?php echo __( 'If you are experiencing a loading issue, contact your site administrator to troubleshoot the problem using Safe Mode.', 'elementor' ); ?>
|
||||
<a href="<?php echo self::DOCS_TRY_SAFE_MODE_URL; ?>" target="_blank"><?php echo __( 'Learn More', 'elementor' ); ?></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ElementorTrySafeMode = function() {
|
||||
var attachEvents = function() {
|
||||
jQuery( '.elementor-enable-safe-mode' ).on( 'click', function( e ) {
|
||||
if ( ! elementorCommon || ! elementorCommon.ajax ) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
elementorCommon.ajax.addRequest(
|
||||
'enable_safe_mode', {
|
||||
data: {
|
||||
editor_post_id: '<?php echo Plugin::$instance->editor->get_post_id(); ?>',
|
||||
},
|
||||
success: function( url ) {
|
||||
location.assign( url );
|
||||
},
|
||||
error: function() {
|
||||
alert( 'An error occurred' );
|
||||
},
|
||||
},
|
||||
true
|
||||
);
|
||||
} );
|
||||
};
|
||||
|
||||
var isElementorLoaded = function() {
|
||||
if ( 'undefined' === typeof elementor ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! elementor.loaded ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( jQuery( '#elementor-loading' ).is( ':visible' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var handleTrySafeModeNotice = function() {
|
||||
var $notice = jQuery( '#elementor-try-safe-mode' );
|
||||
|
||||
if ( isElementorLoaded() ) {
|
||||
$notice.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $notice.data( 'visible' ) ) {
|
||||
$notice.show().data( 'visible', true );
|
||||
}
|
||||
|
||||
// Re-check after 500ms.
|
||||
setTimeout( handleTrySafeModeNotice, 500 );
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
setTimeout( handleTrySafeModeNotice, <?php echo self::EDITOR_NOTICE_TIMEOUT; ?> );
|
||||
|
||||
attachEvents();
|
||||
};
|
||||
|
||||
init();
|
||||
};
|
||||
|
||||
new ElementorTrySafeMode();
|
||||
</script>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
public function run_safe_mode() {
|
||||
remove_action( 'elementor/editor/footer', [ $this, 'print_try_safe_mode' ] );
|
||||
|
||||
// Avoid notices like for comment.php.
|
||||
add_filter( 'deprecated_file_trigger_error', '__return_false' );
|
||||
|
||||
add_filter( 'template_include', [ $this, 'filter_template' ], 999 );
|
||||
add_filter( 'elementor/document/urls/preview', [ $this, 'filter_preview_url' ] );
|
||||
add_action( 'elementor/editor/footer', [ $this, 'print_safe_mode_notice' ] );
|
||||
add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'register_scripts' ], 11 /* After Common Scripts */ );
|
||||
}
|
||||
|
||||
public function register_scripts() {
|
||||
wp_add_inline_script( 'elementor-common', 'elementorCommon.ajax.addRequestConstant( "elementor-mode", "safe" );' );
|
||||
}
|
||||
|
||||
private function is_enabled() {
|
||||
return get_option( self::OPTION_ENABLED, '' );
|
||||
}
|
||||
|
||||
private function get_admin_page_url() {
|
||||
// A fallback URL if the Js doesn't work.
|
||||
return Tools::get_url();
|
||||
}
|
||||
|
||||
public function plugin_action_links( $actions ) {
|
||||
$actions['disable'] = '<a href="' . self::get_admin_page_url() . '">' . __( 'Disable Safe Mode', 'elementor' ) . '</a>';
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
public function on_deactivated_plugin( $plugin ) {
|
||||
if ( ELEMENTOR_PLUGIN_BASE === $plugin ) {
|
||||
$this->disable_safe_mode();
|
||||
return;
|
||||
}
|
||||
|
||||
$allowed_plugins = get_option( 'elementor_safe_mode_allowed_plugins', [] );
|
||||
$plugin_key = array_search( $plugin, $allowed_plugins, true );
|
||||
|
||||
if ( $plugin_key ) {
|
||||
unset( $allowed_plugins[ $plugin_key ] );
|
||||
update_option( 'elementor_safe_mode_allowed_plugins', $allowed_plugins );
|
||||
}
|
||||
}
|
||||
|
||||
public function update_allowed_plugins() {
|
||||
$allowed_plugins = [
|
||||
'elementor' => ELEMENTOR_PLUGIN_BASE,
|
||||
];
|
||||
|
||||
if ( defined( 'ELEMENTOR_PRO_PLUGIN_BASE' ) ) {
|
||||
$allowed_plugins['elementor_pro'] = ELEMENTOR_PRO_PLUGIN_BASE;
|
||||
}
|
||||
|
||||
if ( defined( 'WC_PLUGIN_BASENAME' ) ) {
|
||||
$allowed_plugins['woocommerce'] = WC_PLUGIN_BASENAME;
|
||||
}
|
||||
|
||||
update_option( 'elementor_safe_mode_allowed_plugins', $allowed_plugins );
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
if ( current_user_can( 'install_plugins' ) ) {
|
||||
add_action( 'elementor/admin/after_create_settings/elementor-tools', [ $this, 'add_admin_button' ] );
|
||||
}
|
||||
|
||||
add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
|
||||
|
||||
$plugin_file = self::MU_PLUGIN_FILE_NAME;
|
||||
add_filter( "plugin_action_links_{$plugin_file}", [ $this, 'plugin_action_links' ] );
|
||||
|
||||
// Use pre_update, in order to catch cases that $value === $old_value and it not updated.
|
||||
add_filter( 'pre_update_option_elementor_safe_mode', [ $this, 'on_update_safe_mode' ], 10, 2 );
|
||||
|
||||
add_action( 'elementor/safe_mode/init', [ $this, 'run_safe_mode' ] );
|
||||
add_action( 'elementor/editor/footer', [ $this, 'print_try_safe_mode' ] );
|
||||
|
||||
if ( $this->is_enabled() ) {
|
||||
add_action( 'activated_plugin', [ $this, 'update_allowed_plugins' ] );
|
||||
add_action( 'deactivated_plugin', [ $this, 'on_deactivated_plugin' ] );
|
||||
}
|
||||
}
|
||||
|
||||
private function is_allowed_post_type() {
|
||||
$allowed_post_types = [
|
||||
'post',
|
||||
'page',
|
||||
'product',
|
||||
Source_Local::CPT,
|
||||
];
|
||||
|
||||
$current_post_type = get_post_type( Plugin::$instance->editor->get_post_id() );
|
||||
|
||||
return in_array( $current_post_type, $allowed_post_types );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Name: Elementor Safe Mode
|
||||
* Description: Safe Mode allows you to troubleshoot issues by only loading the editor, without loading the theme or any other plugin.
|
||||
* Plugin URI: https://elementor.com/?utm_source=safe-mode&utm_campaign=plugin-uri&utm_medium=wp-dash
|
||||
* Author: Elementor.com
|
||||
* Version: 1.0.0
|
||||
* Author URI: https://elementor.com/?utm_source=safe-mode&utm_campaign=author-uri&utm_medium=wp-dash
|
||||
*
|
||||
* Text Domain: elementor
|
||||
*
|
||||
* @package Elementor
|
||||
* @category Safe Mode
|
||||
*
|
||||
* 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
|
||||
}
|
||||
|
||||
class Safe_Mode {
|
||||
|
||||
const OPTION_ENABLED = 'elementor_safe_mode';
|
||||
const OPTION_TOKEN = self::OPTION_ENABLED . '_token';
|
||||
|
||||
public function is_enabled() {
|
||||
return get_option( self::OPTION_ENABLED );
|
||||
}
|
||||
|
||||
public function is_valid_token() {
|
||||
$token = isset( $_COOKIE[ self::OPTION_TOKEN ] ) ? $_COOKIE[ self::OPTION_TOKEN ] : null;
|
||||
|
||||
if ( $token && get_option( self::OPTION_TOKEN ) === $token ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function is_requested() {
|
||||
return ! empty( $_REQUEST['elementor-mode'] ) && 'safe' === $_REQUEST['elementor-mode'];
|
||||
}
|
||||
|
||||
public function is_editor() {
|
||||
return is_admin() && isset( $_GET['action'] ) && 'elementor' === $_GET['action'];
|
||||
}
|
||||
|
||||
public function is_editor_preview() {
|
||||
return isset( $_GET['elementor-preview'] );
|
||||
}
|
||||
|
||||
public function is_editor_ajax() {
|
||||
return is_admin() && isset( $_POST['action'] ) && 'elementor_ajax' === $_POST['action'];
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'pre_option_active_plugins', function () {
|
||||
return get_option( 'elementor_safe_mode_allowed_plugins' );
|
||||
} );
|
||||
|
||||
add_filter( 'pre_option_stylesheet', function () {
|
||||
return 'elementor-safe';
|
||||
} );
|
||||
|
||||
add_filter( 'pre_option_template', function () {
|
||||
return 'elementor-safe';
|
||||
} );
|
||||
|
||||
add_action( 'elementor/init', function () {
|
||||
do_action( 'elementor/safe_mode/init' );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin row meta.
|
||||
*
|
||||
* Adds row meta links to the plugin list table
|
||||
*
|
||||
* Fired by `plugin_row_meta` filter.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param array $plugin_meta An array of the plugin's metadata, including
|
||||
* the version, author, author URI, and plugin URI.
|
||||
* @param string $plugin_file Path to the plugin file, relative to the plugins
|
||||
* directory.
|
||||
*
|
||||
* @return array An array of plugin row meta links.
|
||||
*/
|
||||
public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) {
|
||||
if ( basename( __FILE__ ) === $plugin_file ) {
|
||||
$row_meta = [
|
||||
'docs' => '<a href="https://go.elementor.com/safe-mode/" aria-label="' . esc_attr( __( 'Learn More', 'elementor' ) ) . '" target="_blank">' . __( 'Learn More', 'elementor' ) . '</a>',
|
||||
];
|
||||
|
||||
$plugin_meta = array_merge( $plugin_meta, $row_meta );
|
||||
}
|
||||
|
||||
return $plugin_meta;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
add_filter( 'plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 4 );
|
||||
|
||||
$enabled_type = $this->is_enabled();
|
||||
|
||||
if ( ! $enabled_type || ! $this->is_valid_token() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->is_requested() && 'global' !== $enabled_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->is_editor() && ! $this->is_editor_preview() && ! $this->is_editor_ajax() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_hooks();
|
||||
}
|
||||
}
|
||||
|
||||
new Safe_Mode();
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Helpers;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor model helper.
|
||||
*
|
||||
* Elementor model helper handler class is responsible for filtering properties.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class Model_Helper {
|
||||
|
||||
/**
|
||||
* Model helper constructor.
|
||||
*
|
||||
* Initializing the model helper class.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function __construct() {}
|
||||
|
||||
/**
|
||||
* Filter possible properties.
|
||||
*
|
||||
* Retrieve possible properties filtered by property intersect key.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param array $possible_properties All the possible properties.
|
||||
* @param array $properties Properties to filter.
|
||||
*
|
||||
* @return array Possible properties filtered by property intersect key.
|
||||
*/
|
||||
public static function filter_possible_properties( $possible_properties, $properties ) {
|
||||
$properties_keys = array_flip( $possible_properties );
|
||||
|
||||
return array_intersect_key( $properties, $properties_keys );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare properties.
|
||||
*
|
||||
* Combine the possible properties with the user properties and filter them.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param array $possible_properties All the possible properties.
|
||||
* @param array $user_properties User properties.
|
||||
*
|
||||
* @return array Possible properties and user properties filtered by property intersect key.
|
||||
*/
|
||||
public static function prepare_properties( $possible_properties, $user_properties ) {
|
||||
$properties = array_fill_keys( $possible_properties, null );
|
||||
|
||||
$properties = array_merge( $properties, $user_properties );
|
||||
|
||||
return self::filter_possible_properties( $possible_properties, $properties );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Modules\System_Info\Reporters\Base;
|
||||
use Elementor\Modules\System_Info\Helpers\Model_Helper;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor system info module.
|
||||
*
|
||||
* Elementor system info module handler class is responsible for registering and
|
||||
* managing Elementor system info reports.
|
||||
*
|
||||
* @since 2.9.0
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the system info module name.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'system-info';
|
||||
}
|
||||
|
||||
/**
|
||||
* Required user capabilities.
|
||||
*
|
||||
* Holds the user capabilities required to manage Elementor menus.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access private
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $capability = 'manage_options';
|
||||
|
||||
/**
|
||||
* Elementor system info reports.
|
||||
*
|
||||
* Holds an array of available reports in Elementor system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $reports = [
|
||||
'server' => [],
|
||||
'wordpress' => [],
|
||||
'theme' => [],
|
||||
'user' => [],
|
||||
'plugins' => [],
|
||||
'network_plugins' => [],
|
||||
'mu_plugins' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* Main system info page constructor.
|
||||
*
|
||||
* Initializing Elementor system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->add_actions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default settings.
|
||||
*
|
||||
* Retrieve the default settings. Used to reset the report settings on
|
||||
* initialization.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access protected
|
||||
*
|
||||
* @return array Default settings.
|
||||
*/
|
||||
protected function get_init_settings() {
|
||||
$settings = [];
|
||||
|
||||
$reporter_properties = Base::get_properties_keys();
|
||||
|
||||
array_push( $reporter_properties, 'category', 'name', 'class_name' );
|
||||
|
||||
$settings['reporter_properties'] = $reporter_properties;
|
||||
|
||||
$settings['reportFilePrefix'] = '';
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add actions.
|
||||
*
|
||||
* Register filters and actions for the main system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access private
|
||||
*/
|
||||
private function add_actions() {
|
||||
add_action( 'admin_menu', [ $this, 'register_menu' ], 500 );
|
||||
add_action( 'wp_ajax_elementor_system_info_download_file', [ $this, 'download_file' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register admin menu.
|
||||
*
|
||||
* Add new Elementor system info admin menu.
|
||||
*
|
||||
* Fired by `admin_menu` action.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_menu() {
|
||||
$system_info_text = __( 'System Info', 'elementor' );
|
||||
|
||||
add_submenu_page(
|
||||
'elementor',
|
||||
$system_info_text,
|
||||
$system_info_text,
|
||||
$this->capability,
|
||||
'elementor-system-info',
|
||||
[ $this, 'display_page' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display page.
|
||||
*
|
||||
* Output the content for the main system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*/
|
||||
public function display_page() {
|
||||
$reports_info = self::get_allowed_reports();
|
||||
|
||||
$reports = $this->load_reports( $reports_info, 'html' );
|
||||
|
||||
$raw_reports = $this->load_reports( $reports_info, 'raw' );
|
||||
|
||||
?>
|
||||
<div id="elementor-system-info">
|
||||
<h3><?php echo __( 'System Info', 'elementor' ); ?></h3>
|
||||
<div><?php $this->print_report( $reports, 'html' ); ?></div>
|
||||
<h3><?php echo __( 'Copy & Paste Info', 'elementor' ); ?></h3>
|
||||
<div id="elementor-system-info-raw">
|
||||
<label id="elementor-system-info-raw-code-label" for="elementor-system-info-raw-code"><?php echo __( 'You can copy the below info as simple text with Ctrl+C / Ctrl+V:', 'elementor' ); ?></label>
|
||||
<textarea id="elementor-system-info-raw-code" readonly>
|
||||
<?php
|
||||
unset( $raw_reports['wordpress']['report']['admin_email'] );
|
||||
|
||||
$this->print_report( $raw_reports, 'raw' );
|
||||
?>
|
||||
</textarea>
|
||||
<script>
|
||||
var textarea = document.getElementById( 'elementor-system-info-raw-code' );
|
||||
var selectRange = function() {
|
||||
textarea.setSelectionRange( 0, textarea.value.length );
|
||||
};
|
||||
textarea.onfocus = textarea.onblur = textarea.onclick = selectRange;
|
||||
textarea.onfocus();
|
||||
</script>
|
||||
</div>
|
||||
<hr>
|
||||
<form action="<?php echo admin_url( 'admin-ajax.php' ); ?>" method="post">
|
||||
<input type="hidden" name="action" value="elementor_system_info_download_file">
|
||||
<input type="submit" class="button button-primary" value="<?php echo __( 'Download System Info', 'elementor' ); ?>">
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Download file.
|
||||
*
|
||||
* Download the reports files.
|
||||
*
|
||||
* Fired by `wp_ajax_elementor_system_info_download_file` action.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*/
|
||||
public function download_file() {
|
||||
if ( ! current_user_can( $this->capability ) ) {
|
||||
wp_die( __( 'You don\'t have permissions to download this file', 'elementor' ) );
|
||||
}
|
||||
|
||||
$reports_info = self::get_allowed_reports();
|
||||
$reports = $this->load_reports( $reports_info, 'raw' );
|
||||
|
||||
$domain = parse_url( site_url(), PHP_URL_HOST );
|
||||
|
||||
header( 'Content-Type: text/plain' );
|
||||
header( 'Content-Disposition:attachment; filename=system-info-' . $domain . '-' . gmdate( 'd-m-Y' ) . '.txt' );
|
||||
|
||||
$this->print_report( $reports );
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report class.
|
||||
*
|
||||
* Retrieve the class of the report for any given report type.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $reporter_type The type of the report.
|
||||
*
|
||||
* @return string The class of the report.
|
||||
*/
|
||||
public function get_reporter_class( $reporter_type ) {
|
||||
return __NAMESPACE__ . '\Reporters\\' . ucfirst( $reporter_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load reports.
|
||||
*
|
||||
* Retrieve the system info reports.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $reports An array of system info reports.
|
||||
* @param string $format - possible values: 'raw' or empty string, meaning 'html'
|
||||
*
|
||||
* @return array An array of system info reports.
|
||||
*/
|
||||
public function load_reports( $reports, $format = '' ) {
|
||||
$result = [];
|
||||
|
||||
foreach ( $reports as $report_name => $report_info ) {
|
||||
$reporter_params = [
|
||||
'name' => $report_name,
|
||||
'format' => $format,
|
||||
];
|
||||
|
||||
$reporter_params = array_merge( $reporter_params, $report_info );
|
||||
|
||||
$reporter = $this->create_reporter( $reporter_params );
|
||||
|
||||
if ( ! $reporter instanceof Base ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[ $report_name ] = [
|
||||
'report' => $reporter->get_report( $format ),
|
||||
'label' => $reporter->get_title(),
|
||||
];
|
||||
|
||||
if ( ! empty( $report_info['sub'] ) ) {
|
||||
$result[ $report_name ]['sub'] = $this->load_reports( $report_info['sub'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a report.
|
||||
*
|
||||
* Register a new report that will be displayed in Elementor system info page.
|
||||
*
|
||||
* @param array $properties Report properties.
|
||||
*
|
||||
* @return \WP_Error|false|Base Base instance if the report was created,
|
||||
* False or WP_Error otherwise.
|
||||
*@since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function create_reporter( array $properties ) {
|
||||
$properties = Model_Helper::prepare_properties( $this->get_settings( 'reporter_properties' ), $properties );
|
||||
|
||||
$reporter_class = $properties['class_name'] ? $properties['class_name'] : $this->get_reporter_class( $properties['name'] );
|
||||
|
||||
$reporter = new $reporter_class( $properties );
|
||||
|
||||
if ( ! ( $reporter instanceof Base ) ) {
|
||||
return new \WP_Error( 'Each reporter must to be an instance or sub-instance of `Base` class.' );
|
||||
}
|
||||
|
||||
if ( ! $reporter->is_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print report.
|
||||
*
|
||||
* Output the system info page reports using an output template.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $reports An array of system info reports.
|
||||
* @param string $template Output type from the templates folder. Available
|
||||
* templates are `raw` and `html`. Default is `raw`.
|
||||
*/
|
||||
public function print_report( $reports, $template = 'raw' ) {
|
||||
static $tabs_count = 0;
|
||||
|
||||
static $required_plugins_properties = [
|
||||
'Name',
|
||||
'Version',
|
||||
'URL',
|
||||
'Author',
|
||||
];
|
||||
|
||||
$template_path = __DIR__ . '/templates/' . $template . '.php';
|
||||
|
||||
require $template_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowed reports.
|
||||
*
|
||||
* Retrieve the available reports in Elementor system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return array Available reports in Elementor system info page.
|
||||
*/
|
||||
public static function get_allowed_reports() {
|
||||
return self::$reports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add report.
|
||||
*
|
||||
* Register a new report to Elementor system info page.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param string $report_name The name of the report.
|
||||
* @param array $report_info Report info.
|
||||
*/
|
||||
public static function add_report( $report_name, $report_info ) {
|
||||
self::$reports[ $report_name ] = $report_info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
use Elementor\Modules\System_Info\Helpers\Model_Helper;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor base reporter.
|
||||
*
|
||||
* A base abstract class that provides the needed properties and methods to
|
||||
* manage and handle reporter in inheriting classes.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @abstract
|
||||
*/
|
||||
abstract class Base {
|
||||
|
||||
/**
|
||||
* Reporter properties.
|
||||
*
|
||||
* Holds the list of all the properties of the report.
|
||||
*
|
||||
* @access protected
|
||||
* @static
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_properties;
|
||||
|
||||
/**
|
||||
* Get report title.
|
||||
*
|
||||
* Retrieve the title of the report.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @abstract
|
||||
*/
|
||||
abstract public function get_title();
|
||||
|
||||
/**
|
||||
* Get report fields.
|
||||
*
|
||||
* Retrieve the required fields for the report.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @abstract
|
||||
*/
|
||||
abstract public function get_fields();
|
||||
|
||||
/**
|
||||
* Is report enabled.
|
||||
*
|
||||
* Whether the report is enabled.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool Whether the report is enabled.
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report.
|
||||
*
|
||||
* Retrieve the report with all it's containing fields.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @return \WP_Error | array {
|
||||
* Report fields.
|
||||
*
|
||||
* @type string $name Field name.
|
||||
* @type string $label Field label.
|
||||
* }
|
||||
*/
|
||||
final public function get_report( $format = '' ) {
|
||||
$result = [];
|
||||
|
||||
$format = ( empty( $format ) ) ? '' : $format . '_';
|
||||
|
||||
foreach ( $this->get_fields() as $field_name => $field_label ) {
|
||||
$method = 'get_' . $format . $field_name;
|
||||
|
||||
if ( ! method_exists( $this, $method ) ) {
|
||||
$method = 'get_' . $field_name;
|
||||
//fallback:
|
||||
if ( ! method_exists( $this, $method ) ) {
|
||||
return new \WP_Error( sprintf( "Getter method for the field '%s' wasn't found in %s.", $field_name, get_called_class() ) );
|
||||
}
|
||||
}
|
||||
|
||||
$reporter_field = [
|
||||
'name' => $field_name,
|
||||
'label' => $field_label,
|
||||
];
|
||||
|
||||
$reporter_field = array_merge( $reporter_field, $this->$method() );
|
||||
$result[ $field_name ] = $reporter_field;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get properties keys.
|
||||
*
|
||||
* Retrieve the keys of the properties.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @return array {
|
||||
* Property keys.
|
||||
*
|
||||
* @type string $name Property name.
|
||||
* @type string $fields Property fields.
|
||||
* }
|
||||
*/
|
||||
public static function get_properties_keys() {
|
||||
return [
|
||||
'name',
|
||||
'format',
|
||||
'fields',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter possible properties.
|
||||
*
|
||||
* Retrieve possible properties filtered by property keys.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @param array $properties Properties to filter.
|
||||
*
|
||||
* @return array Possible properties filtered by property keys.
|
||||
*/
|
||||
final public static function filter_possible_properties( $properties ) {
|
||||
return Model_Helper::filter_possible_properties( self::get_properties_keys(), $properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set properties.
|
||||
*
|
||||
* Add/update properties to the report.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $key Property key.
|
||||
* @param array $value Optional. Property value. Default is `null`.
|
||||
*/
|
||||
final public function set_properties( $key, $value = null ) {
|
||||
if ( is_array( $key ) ) {
|
||||
$key = self::filter_possible_properties( $key );
|
||||
|
||||
foreach ( $key as $sub_key => $sub_value ) {
|
||||
$this->set_properties( $sub_key, $sub_value );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! in_array( $key, self::get_properties_keys(), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->_properties[ $key ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reporter base constructor.
|
||||
*
|
||||
* Initializing the reporter base class.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $properties Optional. Properties to filter. Default is `null`.
|
||||
*/
|
||||
public function __construct( $properties = null ) {
|
||||
$this->_properties = array_fill_keys( self::get_properties_keys(), null );
|
||||
|
||||
if ( $properties ) {
|
||||
$this->set_properties( $properties, null );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor must-use plugins report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* must-use plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class MU_Plugins extends Base {
|
||||
|
||||
/**
|
||||
* Must-Use plugins.
|
||||
*
|
||||
* Holds the sites must-use plugins list.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $plugins;
|
||||
|
||||
/**
|
||||
* Get must-use plugins.
|
||||
*
|
||||
* Retrieve the must-use plugins.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @return array Must-Use plugins.
|
||||
*/
|
||||
private function get_mu_plugins() {
|
||||
if ( ! $this->plugins ) {
|
||||
$this->plugins = get_mu_plugins();
|
||||
}
|
||||
|
||||
return $this->plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is enabled.
|
||||
*
|
||||
* Whether there are must-use plugins or not.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool True if the site has must-use plugins, False otherwise.
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return ! ! $this->get_mu_plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get must-use plugins reporter title.
|
||||
*
|
||||
* Retrieve must-use plugins reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'Must-Use Plugins';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get must-use plugins report fields.
|
||||
*
|
||||
* Retrieve the required fields for the must-use plugins report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'must_use_plugins' => 'Must-Use Plugins',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get must-use plugins.
|
||||
*
|
||||
* Retrieve the sites must-use plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The must-use plugins list.
|
||||
* }
|
||||
*/
|
||||
public function get_must_use_plugins() {
|
||||
return [
|
||||
'value' => $this->get_mu_plugins(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor network plugins report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* network plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Network_Plugins extends Base {
|
||||
|
||||
/**
|
||||
* Network plugins.
|
||||
*
|
||||
* Holds the sites network plugins list.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $plugins;
|
||||
|
||||
/**
|
||||
* Get network plugins reporter title.
|
||||
*
|
||||
* Retrieve network plugins reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'Network Plugins';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active network plugins.
|
||||
*
|
||||
* Retrieve the active network plugins from the list of active site-wide plugins.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @return array Active network plugins.
|
||||
*/
|
||||
private function get_network_plugins() {
|
||||
if ( ! $this->plugins ) {
|
||||
$active_plugins = get_site_option( 'active_sitewide_plugins' );
|
||||
$this->plugins = array_intersect_key( get_plugins(), $active_plugins );
|
||||
}
|
||||
|
||||
return $this->plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is enabled.
|
||||
*
|
||||
* Whether there are active network plugins or not.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool True if the site has active network plugins, False otherwise.
|
||||
*/
|
||||
public function is_enabled() {
|
||||
if ( ! is_multisite() ) {
|
||||
return false;
|
||||
};
|
||||
|
||||
return ! ! $this->get_network_plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get network plugins report fields.
|
||||
*
|
||||
* Retrieve the required fields for the network plugins report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'network_active_plugins' => 'Network Plugins',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active network plugins.
|
||||
*
|
||||
* Retrieve the sites active network plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The active network plugins list.
|
||||
* }
|
||||
*/
|
||||
public function get_network_active_plugins() {
|
||||
return [
|
||||
'value' => $this->get_network_plugins(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor active plugins report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* active plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Plugins extends Base {
|
||||
|
||||
/**
|
||||
* Active plugins.
|
||||
*
|
||||
* Holds the sites active plugins list.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $plugins;
|
||||
|
||||
/**
|
||||
* Get active plugins.
|
||||
*
|
||||
* Retrieve the active plugins from the list of all the installed plugins.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @return array Active plugins.
|
||||
*/
|
||||
private function get_plugins() {
|
||||
if ( ! $this->plugins ) {
|
||||
// Ensure get_plugins function is loaded
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
include ABSPATH . '/wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$active_plugins = get_option( 'active_plugins' );
|
||||
$this->plugins = array_intersect_key( get_plugins(), array_flip( $active_plugins ) );
|
||||
}
|
||||
|
||||
return $this->plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active plugins reporter title.
|
||||
*
|
||||
* Retrieve active plugins reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'Active Plugins';
|
||||
}
|
||||
|
||||
/**
|
||||
* Is enabled.
|
||||
*
|
||||
* Whether there are active plugins or not.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool True if the site has active plugins, False otherwise.
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return ! ! $this->get_plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active plugins report fields.
|
||||
*
|
||||
* Retrieve the required fields for the active plugins report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'active_plugins' => 'Active Plugins',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active plugins.
|
||||
*
|
||||
* Retrieve the sites active plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The active plugins list.
|
||||
* }
|
||||
*/
|
||||
public function get_active_plugins() {
|
||||
return [
|
||||
'value' => $this->get_plugins(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
use Elementor\Api;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor server environment report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* the server environment.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Server extends Base {
|
||||
|
||||
/**
|
||||
* Get server environment reporter title.
|
||||
*
|
||||
* Retrieve server environment reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'Server Environment';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server environment report fields.
|
||||
*
|
||||
* Retrieve the required fields for the server environment report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'os' => 'Operating System',
|
||||
'software' => 'Software',
|
||||
'mysql_version' => 'MySQL version',
|
||||
'php_version' => 'PHP Version',
|
||||
'php_max_input_vars' => 'PHP Max Input Vars',
|
||||
'php_max_post_size' => 'PHP Max Post Size',
|
||||
'gd_installed' => 'GD Installed',
|
||||
'zip_installed' => 'ZIP Installed',
|
||||
'write_permissions' => 'Write Permissions',
|
||||
'elementor_library' => 'Elementor Library',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server operating system.
|
||||
*
|
||||
* Retrieve the server operating system.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Server operating system.
|
||||
* }
|
||||
*/
|
||||
public function get_os() {
|
||||
return [
|
||||
'value' => PHP_OS,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get server software.
|
||||
*
|
||||
* Retrieve the server software.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Server software.
|
||||
* }
|
||||
*/
|
||||
public function get_software() {
|
||||
return [
|
||||
'value' => $_SERVER['SERVER_SOFTWARE'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PHP version.
|
||||
*
|
||||
* Retrieve the PHP version.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value PHP version.
|
||||
* @type string $recommendation Minimum PHP version recommendation.
|
||||
* @type bool $warning Whether to display a warning.
|
||||
* }
|
||||
*/
|
||||
public function get_php_version() {
|
||||
$result = [
|
||||
'value' => PHP_VERSION,
|
||||
];
|
||||
|
||||
if ( version_compare( $result['value'], '5.4', '<' ) ) {
|
||||
$result['recommendation'] = _x( 'We recommend to use php 5.4 or higher', 'System Info', 'elementor' );
|
||||
|
||||
$result['warning'] = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PHP `max_input_vars`.
|
||||
*
|
||||
* Retrieve the value of `max_input_vars` from `php.ini` configuration file.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value PHP `max_input_vars`.
|
||||
* }
|
||||
*/
|
||||
public function get_php_max_input_vars() {
|
||||
return [
|
||||
'value' => ini_get( 'max_input_vars' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PHP `post_max_size`.
|
||||
*
|
||||
* Retrieve the value of `post_max_size` from `php.ini` configuration file.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value PHP `post_max_size`.
|
||||
* }
|
||||
*/
|
||||
public function get_php_max_post_size() {
|
||||
return [
|
||||
'value' => ini_get( 'post_max_size' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GD installed.
|
||||
*
|
||||
* Whether the GD extension is installed.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Yes if the GD extension is installed, No otherwise.
|
||||
* @type bool $warning Whether to display a warning. True if the GD extension is installed, False otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_gd_installed() {
|
||||
$gd_installed = extension_loaded( 'gd' );
|
||||
|
||||
return [
|
||||
'value' => $gd_installed ? 'Yes' : 'No',
|
||||
'warning' => ! $gd_installed,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ZIP installed.
|
||||
*
|
||||
* Whether the ZIP extension is installed.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Yes if the ZIP extension is installed, No otherwise.
|
||||
* @type bool $warning Whether to display a warning. True if the ZIP extension is installed, False otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_zip_installed() {
|
||||
$zip_installed = extension_loaded( 'zip' );
|
||||
|
||||
return [
|
||||
'value' => $zip_installed ? 'Yes' : 'No',
|
||||
'warning' => ! $zip_installed,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MySQL version.
|
||||
*
|
||||
* Retrieve the MySQL version.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value MySQL version.
|
||||
* }
|
||||
*/
|
||||
public function get_mysql_version() {
|
||||
global $wpdb;
|
||||
|
||||
$db_server_version = $wpdb->get_results( "SHOW VARIABLES WHERE `Variable_name` IN ( 'version_comment', 'innodb_version' )", OBJECT_K );
|
||||
|
||||
return [
|
||||
'value' => $db_server_version['version_comment']->Value . ' v' . $db_server_version['innodb_version']->Value,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get write permissions.
|
||||
*
|
||||
* Check whether the required folders has writing permissions.
|
||||
*
|
||||
* @since 1.9.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Writing permissions status.
|
||||
* @type bool $warning Whether to display a warning. True if some required
|
||||
* folders don't have writing permissions, False otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_write_permissions() {
|
||||
$paths_to_check = [
|
||||
ABSPATH => 'WordPress root directory',
|
||||
];
|
||||
|
||||
$write_problems = [];
|
||||
|
||||
$wp_upload_dir = wp_upload_dir();
|
||||
|
||||
if ( $wp_upload_dir['error'] ) {
|
||||
$write_problems[] = 'WordPress root uploads directory';
|
||||
}
|
||||
|
||||
$elementor_uploads_path = $wp_upload_dir['basedir'] . '/elementor';
|
||||
|
||||
if ( is_dir( $elementor_uploads_path ) ) {
|
||||
$paths_to_check[ $elementor_uploads_path ] = 'Elementor uploads directory';
|
||||
}
|
||||
|
||||
$htaccess_file = ABSPATH . '/.htaccess';
|
||||
|
||||
if ( file_exists( $htaccess_file ) ) {
|
||||
$paths_to_check[ $htaccess_file ] = '.htaccess file';
|
||||
}
|
||||
|
||||
foreach ( $paths_to_check as $dir => $description ) {
|
||||
if ( ! is_writable( $dir ) ) {
|
||||
$write_problems[] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $write_problems ) {
|
||||
$value = 'There are some writing permissions issues with the following directories/files:' . "\n\t\t - ";
|
||||
|
||||
$value .= implode( "\n\t\t - ", $write_problems );
|
||||
} else {
|
||||
$value = 'All right';
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $value,
|
||||
'warning' => ! ! $write_problems,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for elementor library connectivity.
|
||||
*
|
||||
* Check whether the remote elementor library is reachable.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The status of elementor library connectivity.
|
||||
* @type bool $warning Whether to display a warning. True if elementor
|
||||
* * library is not reachable, False otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_elementor_library() {
|
||||
$response = wp_remote_get(
|
||||
Api::$api_info_url, [
|
||||
'timeout' => 5,
|
||||
'body' => [
|
||||
// Which API version is used
|
||||
'api_version' => ELEMENTOR_VERSION,
|
||||
// Which language to return
|
||||
'site_lang' => get_bloginfo( 'language' ),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return [
|
||||
'value' => 'Not connected (' . $response->get_error_message() . ')',
|
||||
'warning' => true,
|
||||
];
|
||||
}
|
||||
|
||||
$http_response_code = wp_remote_retrieve_response_code( $response );
|
||||
|
||||
if ( 200 !== (int) $http_response_code ) {
|
||||
$error_msg = 'HTTP Error (' . $http_response_code . ')';
|
||||
|
||||
return [
|
||||
'value' => 'Not connected (' . $error_msg . ')',
|
||||
'warning' => true,
|
||||
];
|
||||
}
|
||||
|
||||
$info_data = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
|
||||
if ( empty( $info_data ) ) {
|
||||
return [
|
||||
'value' => 'Not connected (Returns invalid JSON)',
|
||||
'warning' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => 'Connected',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor theme report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* the theme.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Theme extends Base {
|
||||
|
||||
/**
|
||||
* Theme.
|
||||
*
|
||||
* Holds the sites theme object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var \WP_Theme WordPress theme object.
|
||||
*/
|
||||
private $theme = null;
|
||||
|
||||
/**
|
||||
* Get theme reporter title.
|
||||
*
|
||||
* Retrieve theme reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'Theme';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme report fields.
|
||||
*
|
||||
* Retrieve the required fields for the theme report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
$fields = [
|
||||
'name' => 'Name',
|
||||
'version' => 'Version',
|
||||
'author' => 'Author',
|
||||
'is_child_theme' => 'Child Theme',
|
||||
];
|
||||
|
||||
if ( $this->get_parent_theme() ) {
|
||||
$parent_fields = [
|
||||
'parent_name' => 'Parent Theme Name',
|
||||
'parent_version' => 'Parent Theme Version',
|
||||
'parent_author' => 'Parent Theme Author',
|
||||
];
|
||||
$fields = array_merge( $fields, $parent_fields );
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme.
|
||||
*
|
||||
* Retrieve the theme.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @return \WP_Theme WordPress theme object.
|
||||
*/
|
||||
protected function _get_theme() {
|
||||
if ( is_null( $this->theme ) ) {
|
||||
$this->theme = wp_get_theme();
|
||||
}
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent theme.
|
||||
*
|
||||
* Retrieve the parent theme.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @return \WP_Theme|false WordPress theme object, or false if the current theme is not a child theme.
|
||||
*/
|
||||
protected function get_parent_theme() {
|
||||
return $this->_get_theme()->parent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme name.
|
||||
*
|
||||
* Retrieve the theme name.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The theme name.
|
||||
* }
|
||||
*/
|
||||
public function get_name() {
|
||||
return [
|
||||
'value' => $this->_get_theme()->get( 'Name' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme author.
|
||||
*
|
||||
* Retrieve the theme author.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The theme author.
|
||||
* }
|
||||
*/
|
||||
public function get_author() {
|
||||
return [
|
||||
'value' => $this->_get_theme()->get( 'Author' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme version.
|
||||
*
|
||||
* Retrieve the theme version.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The theme version.
|
||||
* }
|
||||
*/
|
||||
public function get_version() {
|
||||
return [
|
||||
'value' => $this->_get_theme()->get( 'Version' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the theme is a child theme.
|
||||
*
|
||||
* Whether the theme is a child theme.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Yes if the theme is a child theme, No otherwise.
|
||||
* @type string $recommendation Theme source code modification recommendation.
|
||||
* }
|
||||
*/
|
||||
public function get_is_child_theme() {
|
||||
$is_child_theme = is_child_theme();
|
||||
|
||||
$result = [
|
||||
'value' => $is_child_theme ? 'Yes' : 'No',
|
||||
];
|
||||
|
||||
if ( ! $is_child_theme ) {
|
||||
$result['recommendation'] = sprintf(
|
||||
/* translators: %s: Codex URL */
|
||||
_x( 'If you want to modify the source code of your theme, we recommend using a <a href="%s">child theme</a>.', 'System Info', 'elementor' ),
|
||||
'https://go.elementor.com/wordpress-child-themes/'
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent theme version.
|
||||
*
|
||||
* Retrieve the parent theme version.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The parent theme version.
|
||||
* }
|
||||
*/
|
||||
public function get_parent_version() {
|
||||
return [
|
||||
'value' => $this->get_parent_theme()->get( 'Version' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent theme author.
|
||||
*
|
||||
* Retrieve the parent theme author.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The parent theme author.
|
||||
* }
|
||||
*/
|
||||
public function get_parent_author() {
|
||||
return [
|
||||
'value' => $this->get_parent_theme()->get( 'Author' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent theme name.
|
||||
*
|
||||
* Retrieve the parent theme name.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The parent theme name.
|
||||
* }
|
||||
*/
|
||||
public function get_parent_name() {
|
||||
return [
|
||||
'value' => $this->get_parent_theme()->get( 'Name' ),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor user report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* the user.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class User extends Base {
|
||||
|
||||
/**
|
||||
* Get user reporter title.
|
||||
*
|
||||
* Retrieve user reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'User';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user report fields.
|
||||
*
|
||||
* Retrieve the required fields for the user report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'role' => 'Role',
|
||||
'locale' => 'WP Profile lang',
|
||||
'agent' => 'User Agent',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user role.
|
||||
*
|
||||
* Retrieve the user role.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value The user role.
|
||||
* }
|
||||
*/
|
||||
public function get_role() {
|
||||
$role = null;
|
||||
|
||||
$current_user = wp_get_current_user();
|
||||
if ( ! empty( $current_user->roles ) ) {
|
||||
$role = $current_user->roles[0];
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $role,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user profile language.
|
||||
*
|
||||
* Retrieve the user profile language.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value User profile language.
|
||||
* }
|
||||
*/
|
||||
public function get_locale() {
|
||||
return [
|
||||
'value' => get_locale(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user agent.
|
||||
*
|
||||
* Retrieve user agent.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value HTTP user agent.
|
||||
* }
|
||||
*/
|
||||
public function get_agent() {
|
||||
return [
|
||||
'value' => esc_html( $_SERVER['HTTP_USER_AGENT'] ),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\System_Info\Reporters;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor WordPress environment report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* the WordPress environment.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class WordPress extends Base {
|
||||
|
||||
/**
|
||||
* Get WordPress environment reporter title.
|
||||
*
|
||||
* Retrieve WordPress environment reporter title.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Reporter title.
|
||||
*/
|
||||
public function get_title() {
|
||||
return 'WordPress Environment';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WordPress environment report fields.
|
||||
*
|
||||
* Retrieve the required fields for the WordPress environment report.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array Required report fields with field ID and field label.
|
||||
*/
|
||||
public function get_fields() {
|
||||
return [
|
||||
'version' => 'Version',
|
||||
'site_url' => 'Site URL',
|
||||
'home_url' => 'Home URL',
|
||||
'is_multisite' => 'WP Multisite',
|
||||
'max_upload_size' => 'Max Upload Size',
|
||||
'memory_limit' => 'Memory limit',
|
||||
'permalink_structure' => 'Permalink Structure',
|
||||
'language' => 'Language',
|
||||
'timezone' => 'Timezone',
|
||||
'admin_email' => 'Admin Email',
|
||||
'debug_mode' => 'Debug Mode',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WordPress memory limit.
|
||||
*
|
||||
* Retrieve the WordPress memory limit.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress memory limit.
|
||||
* @type string $recommendation Recommendation memory limit.
|
||||
* @type bool $warning Whether to display a warning. True if the limit
|
||||
* is below the recommended 64M, False otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_memory_limit() {
|
||||
$result = [
|
||||
'value' => ini_get( 'memory_limit' ),
|
||||
];
|
||||
|
||||
$min_recommended_memory = '64M';
|
||||
|
||||
$memory_limit_bytes = wp_convert_hr_to_bytes( $result['value'] );
|
||||
|
||||
$min_recommended_bytes = wp_convert_hr_to_bytes( $min_recommended_memory );
|
||||
|
||||
if ( $memory_limit_bytes < $min_recommended_bytes ) {
|
||||
$result['recommendation'] = sprintf(
|
||||
/* translators: 1: Minimum recommended_memory, 2: Codex URL */
|
||||
_x( 'We recommend setting memory to at least %1$s. For more information, read about <a href="%2$s">how to Increase memory allocated to PHP</a>.', 'System Info', 'elementor' ),
|
||||
$min_recommended_memory,
|
||||
'https://go.elementor.com/wordpress-wp-config-memory/'
|
||||
);
|
||||
|
||||
$result['warning'] = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WordPress version.
|
||||
*
|
||||
* Retrieve the WordPress version.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress version.
|
||||
* }
|
||||
*/
|
||||
public function get_version() {
|
||||
return [
|
||||
'value' => get_bloginfo( 'version' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is multisite.
|
||||
*
|
||||
* Whether multisite is enabled or not.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Yes if multisite is enabled, No otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_is_multisite() {
|
||||
return [
|
||||
'value' => is_multisite() ? 'Yes' : 'No',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get site URL.
|
||||
*
|
||||
* Retrieve WordPress site URL.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress site URL.
|
||||
* }
|
||||
*/
|
||||
public function get_site_url() {
|
||||
return [
|
||||
'value' => get_site_url(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get home URL.
|
||||
*
|
||||
* Retrieve WordPress home URL.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress home URL.
|
||||
* }
|
||||
*/
|
||||
public function get_home_url() {
|
||||
return [
|
||||
'value' => get_home_url(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get permalink structure.
|
||||
*
|
||||
* Retrieve the permalink structure
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress permalink structure.
|
||||
* }
|
||||
*/
|
||||
public function get_permalink_structure() {
|
||||
global $wp_rewrite;
|
||||
|
||||
$structure = $wp_rewrite->permalink_structure;
|
||||
|
||||
if ( ! $structure ) {
|
||||
$structure = 'Plain';
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $structure,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get site language.
|
||||
*
|
||||
* Retrieve the site language.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress site language.
|
||||
* }
|
||||
*/
|
||||
public function get_language() {
|
||||
return [
|
||||
'value' => get_bloginfo( 'language' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PHP `max_upload_size`.
|
||||
*
|
||||
* Retrieve the value of maximum upload file size defined in `php.ini` configuration file.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Maximum upload file size allowed.
|
||||
* }
|
||||
*/
|
||||
public function get_max_upload_size() {
|
||||
return [
|
||||
'value' => size_format( wp_max_upload_size() ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WordPress timezone.
|
||||
*
|
||||
* Retrieve WordPress timezone.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress timezone.
|
||||
* }
|
||||
*/
|
||||
public function get_timezone() {
|
||||
$timezone = get_option( 'timezone_string' );
|
||||
if ( ! $timezone ) {
|
||||
$timezone = get_option( 'gmt_offset' );
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $timezone,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WordPress administrator email.
|
||||
*
|
||||
* Retrieve WordPress administrator email.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value WordPress administrator email.
|
||||
* }
|
||||
*/
|
||||
public function get_admin_email() {
|
||||
return [
|
||||
'value' => get_option( 'admin_email' ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debug mode.
|
||||
*
|
||||
* Whether WordPress debug mode is enabled or not.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return array {
|
||||
* Report data.
|
||||
*
|
||||
* @type string $value Active if debug mode is enabled, Inactive otherwise.
|
||||
* }
|
||||
*/
|
||||
public function get_debug_mode() {
|
||||
return [
|
||||
'value' => WP_DEBUG ? 'Active' : 'Inactive',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array $reports
|
||||
*/
|
||||
foreach ( $reports as $report_name => $report ) : ?>
|
||||
<div class="elementor-system-info-section elementor-system-info-<?php echo esc_attr( $report_name ); ?>">
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo $report['label']; ?></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $report['report'] as $field_name => $field ) :
|
||||
if ( in_array( $report_name, [ 'plugins', 'network_plugins', 'mu_plugins' ], true ) ) {
|
||||
foreach ( $field['value'] as $plugin_info ) :
|
||||
?>
|
||||
<tr>
|
||||
<td><?php
|
||||
if ( $plugin_info['PluginURI'] ) :
|
||||
$plugin_name = "<a href='{$plugin_info['PluginURI']}'>{$plugin_info['Name']}</a>";
|
||||
else :
|
||||
$plugin_name = $plugin_info['Name'];
|
||||
endif;
|
||||
|
||||
if ( $plugin_info['Version'] ) :
|
||||
$plugin_name .= ' - ' . $plugin_info['Version'];
|
||||
endif;
|
||||
|
||||
echo $plugin_name;
|
||||
?></td>
|
||||
<td><?php
|
||||
if ( $plugin_info['Author'] ) :
|
||||
if ( $plugin_info['AuthorURI'] ) :
|
||||
$author = "<a href='{$plugin_info['AuthorURI']}'>{$plugin_info['Author']}</a>";
|
||||
else :
|
||||
$author = $plugin_info['Author'];
|
||||
endif;
|
||||
|
||||
echo "By $author";
|
||||
endif;
|
||||
?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;
|
||||
} else {
|
||||
$warning_class = ! empty( $field['warning'] ) ? ' class="elementor-warning"' : '';
|
||||
$log_label = ! empty( $field['label'] ) ? $field['label'] . ':' : '';
|
||||
?>
|
||||
<tr<?php echo $warning_class; ?>>
|
||||
<td><?php echo $log_label; ?></td>
|
||||
<td><?php echo $field['value']; ?></td>
|
||||
<td><?php
|
||||
if ( ! empty( $field['recommendation'] ) ) :
|
||||
echo $field['recommendation'];
|
||||
endif;
|
||||
?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
endforeach;
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
endforeach;
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array $reports
|
||||
* @var array $required_plugins_properties
|
||||
* @var int $tabs_count
|
||||
*/
|
||||
|
||||
$tabs_count++;
|
||||
|
||||
$required_plugins_properties = array_flip( $required_plugins_properties );
|
||||
|
||||
unset( $required_plugins_properties['Name'] );
|
||||
|
||||
foreach ( $reports as $report_name => $report ) :
|
||||
$indent = str_repeat( "\t", $tabs_count - 1 );
|
||||
|
||||
$is_plugins = in_array( $report_name, [
|
||||
'plugins',
|
||||
'network_plugins',
|
||||
'mu_plugins',
|
||||
] );
|
||||
|
||||
if ( ! $is_plugins ) :
|
||||
echo PHP_EOL . $indent . '== ' . $report['label'] . ' ==';
|
||||
endif;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
foreach ( $report['report'] as $field_name => $field ) :
|
||||
$sub_indent = str_repeat( "\t", $tabs_count );
|
||||
|
||||
if ( $is_plugins ) {
|
||||
echo "== {$field['label']} ==" . PHP_EOL;
|
||||
|
||||
foreach ( $field['value'] as $plugin_info ) :
|
||||
$plugin_properties = array_intersect_key( $plugin_info, $required_plugins_properties );
|
||||
|
||||
echo $sub_indent . $plugin_info['Name'];
|
||||
|
||||
foreach ( $plugin_properties as $property_name => $property ) :
|
||||
echo PHP_EOL . "{$sub_indent}\t{$property_name}: {$property}";
|
||||
endforeach;
|
||||
|
||||
echo PHP_EOL . PHP_EOL;
|
||||
endforeach;
|
||||
} else {
|
||||
$label = $field['label'];
|
||||
|
||||
if ( ! empty( $label ) ) {
|
||||
$label .= ': ';
|
||||
}
|
||||
echo "{$sub_indent}{$label}{$field['value']}" . PHP_EOL;
|
||||
}
|
||||
endforeach;
|
||||
|
||||
if ( ! empty( $report['sub'] ) ) :
|
||||
$this->print_report( $report['sub'], $template, true );
|
||||
endif;
|
||||
endforeach;
|
||||
|
||||
$tabs_count--;
|
||||
@@ -0,0 +1,606 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Usage;
|
||||
|
||||
use Elementor\Core\Base\Document;
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\DynamicTags\Manager;
|
||||
use Elementor\Modules\System_Info\Module as System_Info;
|
||||
use Elementor\DB;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor usage module.
|
||||
*
|
||||
* Elementor usage module handler class is responsible for registering and
|
||||
* managing Elementor usage data.
|
||||
*
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
const GENERAL_TAB = 'general';
|
||||
const META_KEY = '_elementor_controls_usage';
|
||||
const OPTION_NAME = 'elementor_controls_usage';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $is_document_saving = false;
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the usage module name.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'usage';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get doc type count.
|
||||
*
|
||||
* Get count of documents based on doc type
|
||||
*
|
||||
* Remove 'wp-' from $doc_type for BC, support doc type change since 2.7.0.
|
||||
*
|
||||
* @param \Elementor\Core\Documents_Manager $doc_class
|
||||
* @param String $doc_type
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_doc_type_count( $doc_class, $doc_type ) {
|
||||
static $posts = null;
|
||||
static $library = null;
|
||||
|
||||
if ( null === $posts ) {
|
||||
$posts = \Elementor\Tracker::get_posts_usage();
|
||||
}
|
||||
|
||||
if ( null === $library ) {
|
||||
$library = \Elementor\Tracker::get_library_usage();
|
||||
}
|
||||
|
||||
$posts_usage = $posts;
|
||||
|
||||
if ( $doc_class::get_property( 'show_in_library' ) ) {
|
||||
$posts_usage = $library;
|
||||
}
|
||||
|
||||
$doc_type_common = str_replace( 'wp-', '', $doc_type );
|
||||
|
||||
$doc_usage = isset( $posts_usage[ $doc_type_common ] ) ? $posts_usage[ $doc_type_common ] : 0;
|
||||
|
||||
return is_array( $doc_usage ) ? $doc_usage['publish'] : $doc_usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted usage.
|
||||
*
|
||||
* Retrieve formatted usage, for frontend.
|
||||
*
|
||||
* @param String format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_formatted_usage( $format = 'html' ) {
|
||||
$usage = [];
|
||||
|
||||
foreach ( get_option( self::OPTION_NAME, [] ) as $doc_type => $elements ) {
|
||||
$doc_class = Plugin::$instance->documents->get_document_type( $doc_type );
|
||||
|
||||
if ( 'html' === $format && $doc_class ) {
|
||||
$doc_title = $doc_class::get_title();
|
||||
} else {
|
||||
$doc_title = $doc_type;
|
||||
}
|
||||
|
||||
$doc_count = $this->get_doc_type_count( $doc_class, $doc_type );
|
||||
|
||||
$tab_group = $doc_class::get_property( 'admin_tab_group' );
|
||||
|
||||
if ( 'html' === $format && $tab_group ) {
|
||||
$doc_title = ucwords( $tab_group ) . ' - ' . $doc_title;
|
||||
}
|
||||
|
||||
// Replace element type with element title.
|
||||
foreach ( $elements as $element_type => $data ) {
|
||||
unset( $elements[ $element_type ] );
|
||||
|
||||
if ( in_array( $element_type, [ 'section', 'column' ], true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$widget_instance = Plugin::$instance->widgets_manager->get_widget_types( $element_type );
|
||||
|
||||
if ( 'html' === $format && $widget_instance ) {
|
||||
$widget_title = $widget_instance->get_title();
|
||||
} else {
|
||||
$widget_title = $element_type;
|
||||
}
|
||||
|
||||
$elements[ $widget_title ] = $data['count'];
|
||||
}
|
||||
|
||||
// Sort elements by key.
|
||||
ksort( $elements );
|
||||
|
||||
$usage[ $doc_type ] = [
|
||||
'title' => $doc_title,
|
||||
'elements' => $elements,
|
||||
'count' => $doc_count,
|
||||
];
|
||||
|
||||
// Sort usage by title.
|
||||
uasort( $usage, function( $a, $b ) {
|
||||
return ( $a['title'] > $b['title'] );
|
||||
} );
|
||||
|
||||
// If title includes '-' will have lower priority.
|
||||
uasort( $usage, function( $a ) {
|
||||
return strpos( $a['title'], '-' );
|
||||
} );
|
||||
}
|
||||
|
||||
return $usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Before document Save.
|
||||
*
|
||||
* Called on elementor/document/before_save, remove document from global & set saving flag.
|
||||
*
|
||||
* @param Document $document
|
||||
* @param array $data new settings to save.
|
||||
*/
|
||||
public function before_document_save( $document, $data ) {
|
||||
$current_status = get_post_status( $document->get_post() );
|
||||
$new_status = isset( $data['settings']['post_status'] ) ? $data['settings']['post_status'] : '';
|
||||
|
||||
if ( $current_status === $new_status ) {
|
||||
$this->remove_from_global( $document );
|
||||
}
|
||||
|
||||
$this->is_document_saving = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* After document save.
|
||||
*
|
||||
* Called on elementor/document/after_save, adds document to global & clear saving flag.
|
||||
*
|
||||
* @param Document $document
|
||||
*/
|
||||
public function after_document_save( $document ) {
|
||||
if ( DB::STATUS_PUBLISH === $document->get_post()->post_status || DB::STATUS_PRIVATE === $document->get_post()->post_status ) {
|
||||
$this->save_document_usage( $document );
|
||||
}
|
||||
|
||||
$this->is_document_saving = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* On status change.
|
||||
*
|
||||
* Called on transition_post_status.
|
||||
*
|
||||
* @param string $new_status
|
||||
* @param string $old_status
|
||||
* @param \WP_Post $post
|
||||
*/
|
||||
public function on_status_change( $new_status, $old_status, $post ) {
|
||||
if ( wp_is_post_autosave( $post ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's from elementor editor, the usage should be saved via `before_document_save`/`after_document_save`.
|
||||
if ( $this->is_document_saving ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$document = Plugin::$instance->documents->get( $post->ID );
|
||||
|
||||
if ( ! $document ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$is_public_unpublish = 'publish' === $old_status && 'publish' !== $new_status;
|
||||
$is_private_unpublish = 'private' === $old_status && 'private' !== $new_status;
|
||||
|
||||
if ( $is_public_unpublish || $is_private_unpublish ) {
|
||||
$this->remove_from_global( $document );
|
||||
}
|
||||
|
||||
$is_public_publish = 'publish' !== $old_status && 'publish' === $new_status;
|
||||
$is_private_publish = 'private' !== $old_status && 'private' === $new_status;
|
||||
|
||||
if ( $is_public_publish || $is_private_publish ) {
|
||||
$this->save_document_usage( $document );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On before delete post.
|
||||
*
|
||||
* Called on on_before_delete_post.
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public function on_before_delete_post( $post_id ) {
|
||||
$document = Plugin::$instance->documents->get( $post_id );
|
||||
|
||||
if ( $document->get_id() !== $document->get_main_id() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->remove_from_global( $document );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add's tracking data.
|
||||
*
|
||||
* Called on elementor/tracker/send_tracking_data_params.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_tracking_data( $params ) {
|
||||
$params['usages']['elements'] = get_option( self::OPTION_NAME );
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate usage.
|
||||
*
|
||||
* Recalculate usage for all elementor posts.
|
||||
*
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function recalc_usage( $limit = -1, $offset = 0 ) {
|
||||
// While requesting recalc_usage, data should be deleted.
|
||||
// if its in a batch the data should be deleted only on the first batch.
|
||||
if ( 0 === $offset ) {
|
||||
delete_option( self::OPTION_NAME );
|
||||
}
|
||||
|
||||
$post_types = get_post_types( array( 'public' => true ) );
|
||||
|
||||
$query = new \WP_Query( [
|
||||
'meta_key' => '_elementor_data',
|
||||
'post_type' => $post_types,
|
||||
'post_status' => [ 'publish', 'private' ],
|
||||
'posts_per_page' => $limit,
|
||||
'offset' => $offset,
|
||||
] );
|
||||
|
||||
foreach ( $query->posts as $post ) {
|
||||
$document = Plugin::$instance->documents->get( $post->ID );
|
||||
|
||||
if ( ! $document ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->after_document_save( $document );
|
||||
}
|
||||
|
||||
// Clear query memory before leave.
|
||||
wp_cache_flush();
|
||||
|
||||
return count( $query->posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase controls count.
|
||||
*
|
||||
* Increase controls count, for each element.
|
||||
*
|
||||
* @param array &$element_ref
|
||||
* @param string $tab
|
||||
* @param string $section
|
||||
* @param string $control
|
||||
* @param int $count
|
||||
*/
|
||||
private function increase_controls_count( &$element_ref, $tab, $section, $control, $count ) {
|
||||
if ( ! isset( $element_ref['controls'][ $tab ] ) ) {
|
||||
$element_ref['controls'][ $tab ] = [];
|
||||
}
|
||||
|
||||
if ( ! isset( $element_ref['controls'][ $tab ][ $section ] ) ) {
|
||||
$element_ref['controls'][ $tab ][ $section ] = [];
|
||||
}
|
||||
|
||||
if ( ! isset( $element_ref['controls'][ $tab ][ $section ][ $control ] ) ) {
|
||||
$element_ref['controls'][ $tab ][ $section ][ $control ] = 0;
|
||||
}
|
||||
|
||||
$element_ref['controls'][ $tab ][ $section ][ $control ] += $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Controls
|
||||
*
|
||||
* Add's controls to this element_ref, returns changed controls count.
|
||||
*
|
||||
* @param array $settings_controls
|
||||
* @param array $element_controls
|
||||
* @param array &$element_ref
|
||||
*
|
||||
* @return int ($changed_controls_count).
|
||||
*/
|
||||
private function add_controls( $settings_controls, $element_controls, &$element_ref ) {
|
||||
$changed_controls_count = 0;
|
||||
|
||||
// Loop over all element settings.
|
||||
foreach ( $settings_controls as $control => $value ) {
|
||||
if ( empty( $element_controls[ $control ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$control_config = $element_controls[ $control ];
|
||||
|
||||
if ( ! isset( $control_config['section'], $control_config['default'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tab = $control_config['tab'];
|
||||
$section = $control_config['section'];
|
||||
|
||||
// If setting value is not the control default.
|
||||
if ( $value !== $control_config['default'] ) {
|
||||
$this->increase_controls_count( $element_ref, $tab, $section, $control, 1 );
|
||||
|
||||
$changed_controls_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $changed_controls_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add general controls.
|
||||
*
|
||||
* Extract general controls to element ref, return clean `$settings_control`.
|
||||
*
|
||||
* @param array $settings_controls
|
||||
* @param array &$element_ref
|
||||
*
|
||||
* @return array ($settings_controls).
|
||||
*/
|
||||
private function add_general_controls( $settings_controls, &$element_ref ) {
|
||||
if ( ! empty( $settings_controls[ Manager::DYNAMIC_SETTING_KEY ] ) ) {
|
||||
$settings_controls = array_merge( $settings_controls, $settings_controls[ Manager::DYNAMIC_SETTING_KEY ] );
|
||||
|
||||
// Add dynamic count to controls under `general` tab.
|
||||
$this->increase_controls_count(
|
||||
$element_ref,
|
||||
self::GENERAL_TAB,
|
||||
Manager::DYNAMIC_SETTING_KEY,
|
||||
'count',
|
||||
count( $settings_controls[ Manager::DYNAMIC_SETTING_KEY ] )
|
||||
);
|
||||
}
|
||||
|
||||
return $settings_controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to global.
|
||||
*
|
||||
* Add's usage to global (update database).
|
||||
*
|
||||
* @param string $doc_name
|
||||
* @param array $doc_usage
|
||||
*/
|
||||
private function add_to_global( $doc_name, $doc_usage ) {
|
||||
$global_usage = get_option( self::OPTION_NAME, [] );
|
||||
|
||||
foreach ( $doc_usage as $element_type => $element_data ) {
|
||||
if ( ! isset( $global_usage[ $doc_name ] ) ) {
|
||||
$global_usage[ $doc_name ] = [];
|
||||
}
|
||||
|
||||
if ( ! isset( $global_usage[ $doc_name ][ $element_type ] ) ) {
|
||||
$global_usage[ $doc_name ][ $element_type ] = [
|
||||
'count' => 0,
|
||||
'controls' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$global_element_ref = &$global_usage[ $doc_name ][ $element_type ];
|
||||
$global_element_ref['count'] += $element_data['count'];
|
||||
|
||||
if ( empty( $element_data['controls'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $element_data['controls'] as $tab => $sections ) {
|
||||
foreach ( $sections as $section => $controls ) {
|
||||
foreach ( $controls as $control => $count ) {
|
||||
$this->increase_controls_count( $global_element_ref, $tab, $section, $control, $count );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_option( self::OPTION_NAME, $global_usage, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from global.
|
||||
*
|
||||
* Remove's usage from global (update database).
|
||||
*
|
||||
* @param Document $document
|
||||
*/
|
||||
private function remove_from_global( $document ) {
|
||||
$prev_usage = $document->get_meta( self::META_KEY );
|
||||
|
||||
if ( empty( $prev_usage ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$doc_name = $document->get_name();
|
||||
|
||||
$global_usage = get_option( self::OPTION_NAME, [] );
|
||||
|
||||
foreach ( $prev_usage as $element_type => $doc_value ) {
|
||||
if ( isset( $global_usage[ $doc_name ][ $element_type ]['count'] ) ) {
|
||||
$global_usage[ $doc_name ][ $element_type ]['count'] -= $prev_usage[ $element_type ]['count'];
|
||||
|
||||
if ( 0 === $global_usage[ $doc_name ][ $element_type ]['count'] ) {
|
||||
unset( $global_usage[ $doc_name ][ $element_type ] );
|
||||
|
||||
if ( 0 === count( $global_usage[ $doc_name ] ) ) {
|
||||
unset( $global_usage[ $doc_name ] );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $prev_usage[ $element_type ]['controls'] as $tab => $sections ) {
|
||||
foreach ( $sections as $section => $controls ) {
|
||||
foreach ( $controls as $control => $count ) {
|
||||
if ( isset( $global_usage[ $doc_name ][ $element_type ]['controls'][ $tab ][ $section ][ $control ] ) ) {
|
||||
$section_ref = &$global_usage[ $doc_name ][ $element_type ]['controls'][ $tab ][ $section ];
|
||||
|
||||
$section_ref[ $control ] -= $count;
|
||||
|
||||
if ( 0 === $section_ref[ $control ] ) {
|
||||
unset( $section_ref[ $control ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_option( self::OPTION_NAME, $global_usage, false );
|
||||
|
||||
$document->delete_meta( self::META_KEY );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get elements usage.
|
||||
*
|
||||
* Get's the current elements usage by passed elements array parameter.
|
||||
*
|
||||
* @param array $elements
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_elements_usage( $elements ) {
|
||||
$usage = [];
|
||||
|
||||
Plugin::$instance->db->iterate_data( $elements, function ( $element ) use ( &$usage ) {
|
||||
if ( empty( $element['widgetType'] ) ) {
|
||||
$type = $element['elType'];
|
||||
$element_instance = Plugin::$instance->elements_manager->get_element_types( $type );
|
||||
} else {
|
||||
$type = $element['widgetType'];
|
||||
$element_instance = Plugin::$instance->widgets_manager->get_widget_types( $type );
|
||||
}
|
||||
|
||||
if ( ! isset( $usage[ $type ] ) ) {
|
||||
$usage[ $type ] = [
|
||||
'count' => 0,
|
||||
'control_percent' => 0,
|
||||
'controls' => [],
|
||||
];
|
||||
}
|
||||
|
||||
$usage[ $type ]['count']++;
|
||||
|
||||
if ( ! $element_instance ) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
$element_controls = $element_instance->get_controls();
|
||||
|
||||
if ( isset( $element['settings'] ) ) {
|
||||
$settings_controls = $element['settings'];
|
||||
$element_ref = &$usage[ $type ];
|
||||
|
||||
// Add dynamic values.
|
||||
$settings_controls = $this->add_general_controls( $settings_controls, $element_ref );
|
||||
|
||||
$changed_controls_count = $this->add_controls( $settings_controls, $element_controls, $element_ref );
|
||||
|
||||
$percent = $changed_controls_count / ( count( $element_controls ) / 100 );
|
||||
|
||||
$usage[ $type ] ['control_percent'] = (int) round( $percent );
|
||||
}
|
||||
|
||||
return $element;
|
||||
} );
|
||||
|
||||
return $usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save document usage.
|
||||
*
|
||||
* Save requested document usage, and update global.
|
||||
*
|
||||
* @param Document $document
|
||||
*/
|
||||
private function save_document_usage( Document $document ) {
|
||||
if ( ! $document::get_property( 'is_editable' ) && ! $document->is_built_with_elementor() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data manually to avoid conflict with `\Elementor\Core\Base\Document::get_elements_data... convert_to_elementor`.
|
||||
$data = $document->get_json_meta( '_elementor_data' );
|
||||
|
||||
if ( ! empty( $data ) ) {
|
||||
try {
|
||||
$usage = $this->get_elements_usage( $document->get_elements_raw_data( $data ) );
|
||||
|
||||
$document->update_meta( self::META_KEY, $usage );
|
||||
|
||||
$this->add_to_global( $document->get_name(), $usage );
|
||||
} catch ( \Exception $exception ) {
|
||||
return; // Do nothing.
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add system info report.
|
||||
*/
|
||||
public function add_system_info_report() {
|
||||
System_Info::add_report( 'usage', [
|
||||
'file_name' => __DIR__ . '/usage-reporter.php',
|
||||
'class_name' => __NAMESPACE__ . '\Usage_Reporter',
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage module constructor.
|
||||
*
|
||||
* Initializing Elementor usage module.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'transition_post_status', [ $this, 'on_status_change' ], 10, 3 );
|
||||
add_action( 'before_delete_post', [ $this, 'on_before_delete_post' ] );
|
||||
|
||||
add_action( 'elementor/document/before_save', [ $this, 'before_document_save' ], 10, 2 );
|
||||
add_action( 'elementor/document/after_save', [ $this, 'after_document_save' ] );
|
||||
|
||||
add_filter( 'elementor/tracker/send_tracking_data_params', [ $this, 'add_tracking_data' ] );
|
||||
|
||||
add_action( 'admin_init', [ $this, 'add_system_info_report' ], 50 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Usage;
|
||||
|
||||
use Elementor\Modules\System_Info\Reporters\Base;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor usage report.
|
||||
*
|
||||
* Elementor system report handler class responsible for generating a report for
|
||||
* the user.
|
||||
*/
|
||||
class Usage_Reporter extends Base {
|
||||
|
||||
const RECALC_ACTION = 'elementor_usage_recalc';
|
||||
|
||||
public function get_title() {
|
||||
$title = 'Elements Usage';
|
||||
|
||||
if ( 'html' === $this->_properties['format'] && empty( $_GET[ self::RECALC_ACTION ] ) ) { // phpcs:ignore -- nonce validation is not require here.
|
||||
$nonce = wp_create_nonce( self::RECALC_ACTION );
|
||||
$url = add_query_arg( [
|
||||
self::RECALC_ACTION => 1,
|
||||
'_wpnonce' => $nonce,
|
||||
] );
|
||||
|
||||
$title .= '<a id="elementor-usage-recalc" href="' . esc_url( $url ) . '#elementor-usage-recalc" class="box-title-tool">Recalculate</a>';
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function get_fields() {
|
||||
return [
|
||||
'usage' => '',
|
||||
];
|
||||
}
|
||||
|
||||
public function get_usage() {
|
||||
/** @var Module $module */
|
||||
$module = Module::instance();
|
||||
|
||||
if ( ! empty( $_GET[ self::RECALC_ACTION ] ) ) {
|
||||
if ( empty( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], self::RECALC_ACTION ) ) {
|
||||
wp_die( 'Invalid Nonce', 'Invalid Nonce', [
|
||||
'back_link' => true,
|
||||
] );
|
||||
}
|
||||
|
||||
$module->recalc_usage();
|
||||
|
||||
wp_safe_redirect( remove_query_arg( self::RECALC_ACTION ) );
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
$usage = '';
|
||||
|
||||
foreach ( $module->get_formatted_usage() as $doc_type => $data ) {
|
||||
$usage .= '<tr><td>' . $data['title'] . ' ( ' . $data['count'] . ' )</td><td>';
|
||||
|
||||
foreach ( $data['elements'] as $element => $count ) {
|
||||
$usage .= $element . ': ' . $count . PHP_EOL;
|
||||
}
|
||||
|
||||
$usage .= '</td></tr>';
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $usage,
|
||||
];
|
||||
}
|
||||
|
||||
public function get_raw_usage() {
|
||||
/** @var Module $module */
|
||||
$module = Module::instance();
|
||||
$usage = PHP_EOL;
|
||||
|
||||
foreach ( $module->get_formatted_usage( 'raw' ) as $doc_type => $data ) {
|
||||
$usage .= "\t{$data['title']} : " . $data['count'] . PHP_EOL;
|
||||
|
||||
foreach ( $data['elements'] as $element => $count ) {
|
||||
$usage .= "\t\t{$element} : {$count}" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'value' => $usage,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\WpCli;
|
||||
|
||||
use Elementor\Core\Logger\Loggers\Db;
|
||||
use Elementor\Core\Logger\Items\Log_Item_Interface as Log_Item_Interface;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Cli_Logger extends Db {
|
||||
|
||||
public function save_log( Log_Item_Interface $item ) {
|
||||
$message = $item->format( 'raw' );
|
||||
switch ( $item->type ) {
|
||||
case self::LEVEL_WARNING:
|
||||
\WP_CLI::warning( $message );
|
||||
break;
|
||||
case self::LEVEL_ERROR:
|
||||
\WP_CLI::error( $message, false );
|
||||
break;
|
||||
default:
|
||||
\WP_CLI::log( $message );
|
||||
break;
|
||||
}
|
||||
|
||||
parent::save_log( $item );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\WpCli;
|
||||
|
||||
use Elementor\Api;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
use Elementor\Utils;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor Page Builder cli tools.
|
||||
*/
|
||||
class Command extends \WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Flush the Elementor Page Builder CSS Cache.
|
||||
*
|
||||
* [--network]
|
||||
* Flush CSS Cache for all the sites in the network.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor flush-css
|
||||
* - This will flush the CSS files for elementor page builder.
|
||||
*
|
||||
* 2. wp elementor flush-css --network
|
||||
* - This will flush the CSS files for elementor page builder for all the sites in the network.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
* @alias flush-css
|
||||
*/
|
||||
public function flush_css( $args, $assoc_args ) {
|
||||
$network = ! empty( $assoc_args['network'] ) && is_multisite();
|
||||
|
||||
if ( $network ) {
|
||||
/** @var \WP_Site[] $blogs */
|
||||
$blogs = get_sites();
|
||||
|
||||
foreach ( $blogs as $keys => $blog ) {
|
||||
// Cast $blog as an array instead of object
|
||||
$blog_id = $blog->blog_id;
|
||||
|
||||
switch_to_blog( $blog_id );
|
||||
|
||||
Plugin::$instance->files_manager->clear_cache();
|
||||
|
||||
\WP_CLI::success( 'Flushed the Elementor CSS Cache for site - ' . get_option( 'home' ) );
|
||||
|
||||
restore_current_blog();
|
||||
}
|
||||
} else {
|
||||
Plugin::$instance->files_manager->clear_cache();
|
||||
|
||||
\WP_CLI::success( 'Flushed the Elementor CSS Cache' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print system info powered by Elementor
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor system-info
|
||||
* - This will print the System Info in JSON format
|
||||
*
|
||||
* @since 3.0.11
|
||||
* @access public
|
||||
* @alias system-info
|
||||
*/
|
||||
public function system_info() {
|
||||
echo wp_json_encode( \Elementor\Tracker::get_tracking_data() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace old URLs with new URLs in all Elementor pages.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor replace-urls <old> <new>
|
||||
* - This will replace all <old> URLs with the <new> URL.
|
||||
*
|
||||
* @access public
|
||||
* @alias replace-urls
|
||||
*/
|
||||
public function replace_urls( $args, $assoc_args ) {
|
||||
if ( empty( $args[0] ) ) {
|
||||
\WP_CLI::error( 'Please set the `old` URL' );
|
||||
}
|
||||
|
||||
if ( empty( $args[1] ) ) {
|
||||
\WP_CLI::error( 'Please set the `new` URL' );
|
||||
}
|
||||
|
||||
try {
|
||||
$results = Utils::replace_urls( $args[0], $args[1] );
|
||||
\WP_CLI::success( $results );
|
||||
} catch ( \Exception $e ) {
|
||||
\WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync Elementor Library.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor sync-library
|
||||
* - This will sync the library with Elementor cloud library.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
* @alias sync-library
|
||||
*/
|
||||
public function sync_library( $args, $assoc_args ) {
|
||||
// TODO:
|
||||
// \WP_CLI::warning( 'command is deprecated since 2.8.0 Please use: wp elementor library sync' );
|
||||
|
||||
$data = Api::get_library_data( true );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
\WP_CLI::error( 'Cannot sync library.' );
|
||||
}
|
||||
|
||||
\WP_CLI::success( 'Library has been synced.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import template files to the Library.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor import-library <file-path>
|
||||
* - This will import a file or a zip of multiple files to the library.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
* @alias import-library
|
||||
*/
|
||||
public function import_library( $args, $assoc_args ) {
|
||||
// TODO:
|
||||
// \WP_CLI::warning( 'command is deprecated since 2.8.0 Please use: wp elementor library import' );
|
||||
|
||||
if ( empty( $args[0] ) ) {
|
||||
\WP_CLI::error( 'Please set file path.' );
|
||||
}
|
||||
|
||||
/** @var Source_Local $source */
|
||||
$source = Plugin::$instance->templates_manager->get_source( 'local' );
|
||||
|
||||
$imported_items = $source->import_template( basename( $args[0] ), $args[0] );
|
||||
|
||||
if ( is_wp_error( $imported_items ) ) {
|
||||
\WP_CLI::error( $imported_items->get_error_message() );
|
||||
}
|
||||
|
||||
\WP_CLI::success( count( $imported_items ) . ' item(s) has been imported.' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\WpCli;
|
||||
|
||||
use Elementor\Api;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor Page Builder cli tools.
|
||||
*/
|
||||
class Library extends \WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Sync Elementor Library.
|
||||
*
|
||||
* [--network]
|
||||
* Sync library in all the sites in the network.
|
||||
*
|
||||
* [--force]
|
||||
* Force sync even if it's looks like that the library is already up to date.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor library sync
|
||||
* - This will sync the library with Elementor cloud library.
|
||||
*
|
||||
* 2. wp elementor library sync --force
|
||||
* - This will sync the library with Elementor cloud even if it's looks like that the library is already up to date.
|
||||
*
|
||||
* 3. wp elementor library sync --network
|
||||
* - This will sync the library with Elementor cloud library for each site in the network if needed.
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
*/
|
||||
public function sync( $args, $assoc_args ) {
|
||||
$network = isset( $assoc_args['network'] ) && is_multisite();
|
||||
|
||||
if ( $network ) {
|
||||
/** @var \WP_Site[] $sites */
|
||||
$sites = get_sites();
|
||||
|
||||
foreach ( $sites as $keys => $blog ) {
|
||||
// Cast $blog as an array instead of object
|
||||
$blog_id = $blog->blog_id;
|
||||
|
||||
switch_to_blog( $blog_id );
|
||||
|
||||
\WP_CLI::line( 'Site #' . $blog_id . ' - ' . get_option( 'blogname' ) );
|
||||
|
||||
$this->do_sync( isset( $assoc_args['force'] ) );
|
||||
|
||||
\WP_CLI::success( 'Done! - ' . get_option( 'home' ) );
|
||||
|
||||
restore_current_blog();
|
||||
}
|
||||
} else {
|
||||
$this->do_sync( isset( $assoc_args['force'] ) );
|
||||
\WP_CLI::success( 'Done!' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import template files to the Library.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor library import <file-path>
|
||||
* - This will import a file or a zip of multiple files to the library.
|
||||
*
|
||||
* @param $args
|
||||
* @param $assoc_args
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
*/
|
||||
public function import( $args ) {
|
||||
if ( empty( $args[0] ) ) {
|
||||
\WP_CLI::error( 'Please set file path.' );
|
||||
}
|
||||
|
||||
$file = $args[0];
|
||||
|
||||
/** @var Source_Local $source */
|
||||
$source = Plugin::$instance->templates_manager->get_source( 'local' );
|
||||
|
||||
$imported_items = $source->import_template( basename( $file ), $file );
|
||||
|
||||
if ( is_wp_error( $imported_items ) ) {
|
||||
\WP_CLI::error( $imported_items->get_error_message() );
|
||||
}
|
||||
|
||||
\WP_CLI::success( count( $imported_items ) . ' item(s) has been imported.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect site to Elementor Library.
|
||||
* (Network is not supported)
|
||||
*
|
||||
* --user
|
||||
* The user to connect <id|login|email>
|
||||
*
|
||||
* --token
|
||||
* A connect token from Elementor Account Dashboard.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor library connect --user=admin --token=<connect-cli-token>
|
||||
* - This will connect the admin to Elementor library.
|
||||
*
|
||||
* @param $args
|
||||
* @param $assoc_args
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
*/
|
||||
public function connect( $args, $assoc_args ) {
|
||||
if ( ! get_current_user_id() ) {
|
||||
\WP_CLI::error( 'Please set user to connect (--user=<id|login|email>).' );
|
||||
}
|
||||
|
||||
if ( empty( $assoc_args['token'] ) ) {
|
||||
\WP_CLI::error( 'Please set connect token.' );
|
||||
}
|
||||
|
||||
$_REQUEST['mode'] = 'cli';
|
||||
$_REQUEST['token'] = $assoc_args['token'];
|
||||
|
||||
$app = $this->get_library_app();
|
||||
|
||||
$app->action_authorize();
|
||||
|
||||
$app->action_get_token();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect site from Elementor Library.
|
||||
*
|
||||
* --user
|
||||
* The user to disconnect <id|login|email>
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor library disconnect --user=admin
|
||||
* - This will disconnect the admin from Elementor library.
|
||||
*
|
||||
* @param $args
|
||||
* @param $assoc_args
|
||||
*
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
*/
|
||||
public function disconnect() {
|
||||
if ( ! get_current_user_id() ) {
|
||||
\WP_CLI::error( 'Please set user to connect (--user=<id|login|email>).' );
|
||||
}
|
||||
|
||||
$_REQUEST['mode'] = 'cli';
|
||||
|
||||
$this->get_library_app()->action_disconnect();
|
||||
}
|
||||
|
||||
private function do_sync() {
|
||||
$data = Api::get_library_data( true );
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
\WP_CLI::error( 'Cannot sync library.' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Elementor\Core\Common\Modules\Connect\Apps\Library
|
||||
*/
|
||||
private function get_library_app() {
|
||||
$connect = Plugin::$instance->common->get_component( 'connect' );
|
||||
$app = $connect->get_app( 'library' );
|
||||
// Before init.
|
||||
if ( ! $app ) {
|
||||
$connect->init();
|
||||
$app = $connect->get_app( 'library' );
|
||||
}
|
||||
|
||||
return $app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\WpCli;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\Logger\Manager as Logger;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'wp-cli';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function is_active() {
|
||||
return defined( 'WP_CLI' ) && WP_CLI;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Logger $logger
|
||||
* @access public
|
||||
*/
|
||||
public function register_cli_logger( $logger ) {
|
||||
$logger->register_logger( 'cli', 'Elementor\Modules\WpCli\Cli_Logger' );
|
||||
$logger->set_default_logger( 'cli' );
|
||||
}
|
||||
|
||||
public function init_common() {
|
||||
Plugin::$instance->init_common();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'cli_init', [ $this, 'init_common' ] );
|
||||
add_action( 'elementor/loggers/register', [ $this, 'register_cli_logger' ] );
|
||||
|
||||
\WP_CLI::add_command( 'elementor', '\Elementor\Modules\WpCli\Command' );
|
||||
\WP_CLI::add_command( 'elementor update', '\Elementor\Modules\WpCli\Update' );
|
||||
\WP_CLI::add_command( 'elementor library', '\Elementor\Modules\WpCli\Library' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\WpCli;
|
||||
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor Page Builder cli tools.
|
||||
*/
|
||||
class Update extends \WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Update the DB after plugin upgrade.
|
||||
*
|
||||
* [--network]
|
||||
* Update DB in all the sites in the network.
|
||||
*
|
||||
* [--force]
|
||||
* Force update even if it's looks like that update is in progress.
|
||||
*
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* 1. wp elementor update db
|
||||
* - This will Upgrade the DB if needed.
|
||||
*
|
||||
* 2. wp elementor update db --force
|
||||
* - This will Upgrade the DB even if another process is running.
|
||||
*
|
||||
* 3. wp elementor update db --network
|
||||
* - This will Upgrade the DB for each site in the network if needed.
|
||||
*
|
||||
* @since 2.4.0
|
||||
* @access public
|
||||
*
|
||||
* @param $args
|
||||
* @param $assoc_args
|
||||
*/
|
||||
public function db( $args, $assoc_args ) {
|
||||
$network = ! empty( $assoc_args['network'] ) && is_multisite();
|
||||
|
||||
if ( $network ) {
|
||||
/** @var \WP_Site[] $sites */
|
||||
$sites = get_sites();
|
||||
|
||||
foreach ( $sites as $keys => $blog ) {
|
||||
// Cast $blog as an array instead of object
|
||||
$blog_id = $blog->blog_id;
|
||||
|
||||
switch_to_blog( $blog_id );
|
||||
|
||||
\WP_CLI::line( 'Site #' . $blog_id . ' - ' . get_option( 'blogname' ) );
|
||||
|
||||
$this->do_db_upgrade( $assoc_args );
|
||||
|
||||
\WP_CLI::success( 'Done! - ' . get_option( 'home' ) );
|
||||
|
||||
restore_current_blog();
|
||||
}
|
||||
} else {
|
||||
$this->do_db_upgrade( $assoc_args );
|
||||
}
|
||||
}
|
||||
|
||||
protected function get_update_db_manager_class() {
|
||||
return '\Elementor\Core\Upgrade\Manager';
|
||||
}
|
||||
|
||||
protected function do_db_upgrade( $assoc_args ) {
|
||||
$manager_class = $this->get_update_db_manager_class();
|
||||
|
||||
/** @var \Elementor\Core\Upgrade\Manager $manager */
|
||||
$manager = new $manager_class();
|
||||
|
||||
$updater = $manager->get_task_runner();
|
||||
|
||||
if ( $updater->is_process_locked() && empty( $assoc_args['force'] ) ) {
|
||||
\WP_CLI::warning( 'Oops! Process is already running. Use --force to force run.' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $manager->should_upgrade() ) {
|
||||
\WP_CLI::success( 'The DB is already updated!' );
|
||||
return;
|
||||
}
|
||||
|
||||
$callbacks = $manager->get_upgrade_callbacks();
|
||||
$did_tasks = false;
|
||||
|
||||
if ( ! empty( $callbacks ) ) {
|
||||
Plugin::$instance->logger->get_logger()->info( 'Update DB has been started', [
|
||||
'meta' => [
|
||||
'plugin' => $manager->get_plugin_label(),
|
||||
'from' => $manager->get_current_version(),
|
||||
'to' => $manager->get_new_version(),
|
||||
],
|
||||
] );
|
||||
|
||||
$updater->handle_immediately( $callbacks );
|
||||
$did_tasks = true;
|
||||
}
|
||||
|
||||
$manager->on_runner_complete( $did_tasks );
|
||||
|
||||
\WP_CLI::success( count( $callbacks ) . ' updates(s) has been applied.' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user