first commit
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common;
|
||||
|
||||
use Elementor\Core\Base\App as BaseApp;
|
||||
use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
|
||||
use Elementor\Core\Common\Modules\Finder\Module as Finder;
|
||||
use Elementor\Core\Common\Modules\Connect\Module as Connect;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* App
|
||||
*
|
||||
* Elementor's common app that groups shared functionality, components and configuration
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class App extends BaseApp {
|
||||
|
||||
private $templates = [];
|
||||
|
||||
/**
|
||||
* App constructor.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->add_default_templates();
|
||||
|
||||
add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'register_scripts' ] );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'register_scripts' ] );
|
||||
add_action( 'wp_enqueue_scripts', [ $this, 'register_scripts' ] );
|
||||
|
||||
add_action( 'elementor/editor/before_enqueue_styles', [ $this, 'register_styles' ] );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'register_styles' ] );
|
||||
add_action( 'wp_enqueue_scripts', [ $this, 'register_styles' ], 9 );
|
||||
|
||||
add_action( 'elementor/editor/footer', [ $this, 'print_templates' ] );
|
||||
add_action( 'admin_footer', [ $this, 'print_templates' ] );
|
||||
add_action( 'wp_footer', [ $this, 'print_templates' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Init components
|
||||
*
|
||||
* Initializing common components.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function init_components() {
|
||||
$this->add_component( 'ajax', new Ajax() );
|
||||
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
if ( ! is_customize_preview() ) {
|
||||
$this->add_component( 'finder', new Finder() );
|
||||
}
|
||||
}
|
||||
|
||||
$this->add_component( 'connect', new Connect() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* Retrieve the app name.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Common app name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'common';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register scripts.
|
||||
*
|
||||
* Register common scripts.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_scripts() {
|
||||
wp_register_script(
|
||||
'elementor-common-modules',
|
||||
$this->get_js_assets_url( 'common-modules' ),
|
||||
[],
|
||||
ELEMENTOR_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'backbone-marionette',
|
||||
$this->get_js_assets_url( 'backbone.marionette', 'assets/lib/backbone/' ),
|
||||
[
|
||||
'backbone',
|
||||
],
|
||||
'2.4.5',
|
||||
true
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'backbone-radio',
|
||||
$this->get_js_assets_url( 'backbone.radio', 'assets/lib/backbone/' ),
|
||||
[
|
||||
'backbone',
|
||||
],
|
||||
'1.0.4',
|
||||
true
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'elementor-dialog',
|
||||
$this->get_js_assets_url( 'dialog', 'assets/lib/dialog/' ),
|
||||
[
|
||||
'jquery-ui-position',
|
||||
],
|
||||
'4.8.1',
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'elementor-common',
|
||||
$this->get_js_assets_url( 'common' ),
|
||||
[
|
||||
'jquery',
|
||||
'jquery-ui-draggable',
|
||||
'backbone-marionette',
|
||||
'backbone-radio',
|
||||
'elementor-common-modules',
|
||||
'elementor-dialog',
|
||||
'wp-api-request',
|
||||
],
|
||||
ELEMENTOR_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
$this->print_config();
|
||||
|
||||
// Used for external plugins.
|
||||
do_action( 'elementor/common/after_register_scripts', $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register styles.
|
||||
*
|
||||
* Register common styles.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_styles() {
|
||||
wp_register_style(
|
||||
'elementor-icons',
|
||||
$this->get_css_assets_url( 'elementor-icons', 'assets/lib/eicons/css/' ),
|
||||
[],
|
||||
'5.9.1'
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'elementor-common',
|
||||
$this->get_css_assets_url( 'common', null, 'default', true ),
|
||||
[
|
||||
'elementor-icons',
|
||||
],
|
||||
ELEMENTOR_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add template.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $template Can be either a link to template file or template
|
||||
* HTML content.
|
||||
* @param string $type Optional. Whether to handle the template as path
|
||||
* or text. Default is `path`.
|
||||
*/
|
||||
public function add_template( $template, $type = 'path' ) {
|
||||
if ( 'path' === $type ) {
|
||||
ob_start();
|
||||
|
||||
include $template;
|
||||
|
||||
$template = ob_get_clean();
|
||||
}
|
||||
|
||||
$this->templates[] = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print Templates
|
||||
*
|
||||
* Prints all registered templates.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function print_templates() {
|
||||
foreach ( $this->templates as $template ) {
|
||||
echo $template;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get init settings.
|
||||
*
|
||||
* Define the default/initial settings of the common app.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_init_settings() {
|
||||
return [
|
||||
'version' => ELEMENTOR_VERSION,
|
||||
'isRTL' => is_rtl(),
|
||||
'isDebug' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
|
||||
'isElementorDebug' => ( defined( 'ELEMENTOR_DEBUG' ) && ELEMENTOR_DEBUG ),
|
||||
'activeModules' => array_keys( $this->get_components() ),
|
||||
'urls' => [
|
||||
'assets' => ELEMENTOR_ASSETS_URL,
|
||||
'rest' => get_rest_url(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add default templates.
|
||||
*
|
||||
* Register common app default templates.
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*/
|
||||
private function add_default_templates() {
|
||||
$default_templates = [
|
||||
'includes/editor-templates/library-layout.php',
|
||||
];
|
||||
|
||||
foreach ( $default_templates as $template ) {
|
||||
$this->add_template( ELEMENTOR_PATH . $template );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Ajax;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\Utils\Exceptions;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor ajax manager.
|
||||
*
|
||||
* Elementor ajax manager handler class is responsible for handling Elementor
|
||||
* ajax requests, ajax responses and registering actions applied on them.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
|
||||
const NONCE_KEY = 'elementor_ajax';
|
||||
|
||||
/**
|
||||
* Ajax actions.
|
||||
*
|
||||
* Holds all the register ajax action.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $ajax_actions = [];
|
||||
|
||||
/**
|
||||
* Ajax requests.
|
||||
*
|
||||
* Holds all the register ajax requests.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $requests = [];
|
||||
|
||||
/**
|
||||
* Ajax response data.
|
||||
*
|
||||
* Holds all the response data for all the ajax requests.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $response_data = [];
|
||||
|
||||
/**
|
||||
* Current ajax action ID.
|
||||
*
|
||||
* Holds all the ID for the current ajax action.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access private
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $current_action_id = null;
|
||||
|
||||
/**
|
||||
* Ajax manager constructor.
|
||||
*
|
||||
* Initializing Elementor ajax manager.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_elementor_ajax', [ $this, 'handle_ajax_request' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module name.
|
||||
*
|
||||
* Retrieve the module name.
|
||||
*
|
||||
* @since 1.7.0
|
||||
* @access public
|
||||
*
|
||||
* @return string Module name.
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'ajax';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register ajax action.
|
||||
*
|
||||
* Add new actions for a specific ajax request and the callback function to
|
||||
* be handle the response.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $tag Ajax request name/tag.
|
||||
* @param callable $callback The callback function.
|
||||
*/
|
||||
public function register_ajax_action( $tag, $callback ) {
|
||||
if ( ! did_action( 'elementor/ajax/register_actions' ) ) {
|
||||
_doing_it_wrong( __METHOD__, esc_html( sprintf( 'Use `%s` hook to register ajax action.', 'elementor/ajax/register_actions' ) ), '2.0.0' );
|
||||
}
|
||||
|
||||
$this->ajax_actions[ $tag ] = compact( 'tag', 'callback' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ajax request.
|
||||
*
|
||||
* Verify ajax nonce, and run all the registered actions for this request.
|
||||
*
|
||||
* Fired by `wp_ajax_elementor_ajax` action.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function handle_ajax_request() {
|
||||
if ( ! $this->verify_request_nonce() ) {
|
||||
$this->add_response_data( false, __( 'Token Expired.', 'elementor' ) )
|
||||
->send_error( Exceptions::UNAUTHORIZED );
|
||||
}
|
||||
|
||||
$editor_post_id = 0;
|
||||
|
||||
if ( ! empty( $_REQUEST['editor_post_id'] ) ) {
|
||||
$editor_post_id = absint( $_REQUEST['editor_post_id'] );
|
||||
|
||||
Plugin::$instance->db->switch_to_post( $editor_post_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register ajax actions.
|
||||
*
|
||||
* Fires when an ajax request is received and verified.
|
||||
*
|
||||
* Used to register new ajax action handles.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param self $this An instance of ajax manager.
|
||||
*/
|
||||
do_action( 'elementor/ajax/register_actions', $this );
|
||||
|
||||
$this->requests = json_decode( stripslashes( $_REQUEST['actions'] ), true );
|
||||
|
||||
foreach ( $this->requests as $id => $action_data ) {
|
||||
$this->current_action_id = $id;
|
||||
|
||||
if ( ! isset( $this->ajax_actions[ $action_data['action'] ] ) ) {
|
||||
$this->add_response_data( false, __( 'Action not found.', 'elementor' ), Exceptions::BAD_REQUEST );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $editor_post_id ) {
|
||||
$action_data['data']['editor_post_id'] = $editor_post_id;
|
||||
}
|
||||
|
||||
try {
|
||||
$results = call_user_func( $this->ajax_actions[ $action_data['action'] ]['callback'], $action_data['data'], $this );
|
||||
|
||||
if ( false === $results ) {
|
||||
$this->add_response_data( false );
|
||||
} else {
|
||||
$this->add_response_data( true, $results );
|
||||
}
|
||||
} catch ( \Exception $e ) {
|
||||
$this->add_response_data( false, $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
$this->current_action_id = null;
|
||||
|
||||
$this->send_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current action data.
|
||||
*
|
||||
* Retrieve the data for the current ajax request.
|
||||
*
|
||||
* @since 2.0.1
|
||||
* @access public
|
||||
*
|
||||
* @return bool|mixed Ajax request data if action exist, False otherwise.
|
||||
*/
|
||||
public function get_current_action_data() {
|
||||
if ( ! $this->current_action_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->requests[ $this->current_action_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create nonce.
|
||||
*
|
||||
* Creates a cryptographic token to
|
||||
* give the user an access to Elementor ajax actions.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string The nonce token.
|
||||
*/
|
||||
public function create_nonce() {
|
||||
return wp_create_nonce( self::NONCE_KEY );
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify request nonce.
|
||||
*
|
||||
* Whether the request nonce verified or not.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool True if request nonce verified, False otherwise.
|
||||
*/
|
||||
public function verify_request_nonce() {
|
||||
return ! empty( $_REQUEST['_nonce'] ) && wp_verify_nonce( $_REQUEST['_nonce'], self::NONCE_KEY );
|
||||
}
|
||||
|
||||
protected function get_init_settings() {
|
||||
return [
|
||||
'url' => admin_url( 'admin-ajax.php' ),
|
||||
'nonce' => $this->create_nonce(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax success response.
|
||||
*
|
||||
* Send a JSON response data back to the ajax request, indicating success.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access protected
|
||||
*/
|
||||
private function send_success() {
|
||||
$response = [
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'responses' => $this->response_data,
|
||||
],
|
||||
];
|
||||
|
||||
$json = wp_json_encode( $response );
|
||||
|
||||
while ( ob_get_status() ) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
if ( function_exists( 'gzencode' ) ) {
|
||||
$response = gzencode( $json );
|
||||
|
||||
header( 'Content-Type: application/json; charset=utf-8' );
|
||||
header( 'Content-Encoding: gzip' );
|
||||
header( 'Content-Length: ' . strlen( $response ) );
|
||||
|
||||
echo $response;
|
||||
} else {
|
||||
echo $json;
|
||||
}
|
||||
|
||||
wp_die( '', '', [ 'response' => null ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax failure response.
|
||||
*
|
||||
* Send a JSON response data back to the ajax request, indicating failure.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param null $code
|
||||
*/
|
||||
private function send_error( $code = null ) {
|
||||
wp_send_json_error( [
|
||||
'responses' => $this->response_data,
|
||||
], $code );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add response data.
|
||||
*
|
||||
* Add new response data to the array of all the ajax requests.
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param bool $success True if the requests returned successfully, False
|
||||
* otherwise.
|
||||
* @param mixed $data Optional. Response data. Default is null.
|
||||
*
|
||||
* @param int $code Optional. Response code. Default is 200.
|
||||
*
|
||||
* @return Module An instance of ajax manager.
|
||||
*/
|
||||
private function add_response_data( $success, $data = null, $code = 200 ) {
|
||||
$this->response_data[ $this->current_action_id ] = [
|
||||
'success' => $success,
|
||||
'code' => $code,
|
||||
'data' => $data,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect;
|
||||
|
||||
use Elementor\Plugin;
|
||||
use Elementor\Settings;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Admin {
|
||||
|
||||
const PAGE_ID = 'elementor-connect';
|
||||
|
||||
public static $url = '';
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_admin_menu() {
|
||||
$submenu_page = add_submenu_page(
|
||||
Settings::PAGE_ID,
|
||||
__( 'Connect', 'elementor' ),
|
||||
__( 'Connect', 'elementor' ),
|
||||
'edit_posts',
|
||||
self::PAGE_ID,
|
||||
[ $this, 'render_page' ]
|
||||
);
|
||||
|
||||
add_action( 'load-' . $submenu_page, [ $this, 'on_load_page' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function hide_menu_item() {
|
||||
remove_submenu_page( Settings::PAGE_ID, self::PAGE_ID );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function on_load_page() {
|
||||
if ( isset( $_GET['action'], $_GET['app'] ) ) {
|
||||
$manager = Plugin::$instance->common->get_component( 'connect' );
|
||||
$app_slug = $_GET['app'];
|
||||
$app = $manager->get_app( $app_slug );
|
||||
$nonce_action = $_GET['app'] . $_GET['action'];
|
||||
|
||||
if ( ! $app ) {
|
||||
wp_die( 'Unknown app: ' . esc_attr( $app_slug ) );
|
||||
}
|
||||
|
||||
if ( empty( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], $nonce_action ) ) {
|
||||
wp_die( 'Invalid Nonce', 'Invalid Nonce', [
|
||||
'back_link' => true,
|
||||
] );
|
||||
}
|
||||
|
||||
$method = 'action_' . $_GET['action'];
|
||||
|
||||
if ( method_exists( $app, $method ) ) {
|
||||
call_user_func( [ $app, $method ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function render_page() {
|
||||
$apps = Plugin::$instance->common->get_component( 'connect' )->get_apps();
|
||||
?>
|
||||
<style>
|
||||
.elementor-connect-app-wrapper{
|
||||
margin-bottom: 50px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<div class="wrap">
|
||||
<?php
|
||||
|
||||
/** @var \Elementor\Core\Common\Modules\Connect\Apps\Base_App $app */
|
||||
foreach ( $apps as $app ) {
|
||||
echo '<div class="elementor-connect-app-wrapper">';
|
||||
$app->render_admin_widget();
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
?>
|
||||
</div><!-- /.wrap -->
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
self::$url = admin_url( 'admin.php?page=' . self::PAGE_ID );
|
||||
|
||||
add_action( 'admin_menu', [ $this, 'register_admin_menu' ], 206 );
|
||||
add_action( 'admin_head', [ $this, 'hide_menu_item' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect\Apps;
|
||||
|
||||
use Elementor\Core\Common\Modules\Connect\Admin;
|
||||
use Elementor\Tracker;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
abstract class Base_App {
|
||||
|
||||
const OPTION_NAME_PREFIX = 'elementor_connect_';
|
||||
|
||||
const SITE_URL = 'https://my.elementor.com/connect/v1';
|
||||
|
||||
const API_URL = 'https://my.elementor.com/api/connect/v1';
|
||||
|
||||
protected $data = [];
|
||||
|
||||
protected $auth_mode = '';
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
* @abstract
|
||||
* TODO: make it public.
|
||||
*/
|
||||
abstract protected function get_slug();
|
||||
|
||||
/**
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
* TODO: make it abstract.
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->get_slug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
* @abstract
|
||||
*/
|
||||
abstract protected function update_settings();
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function get_class_name() {
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* @access public
|
||||
* @abstract
|
||||
*/
|
||||
public function render_admin_widget() {
|
||||
echo '<h2>' . $this->get_title() . '</h2>';
|
||||
|
||||
if ( $this->is_connected() ) {
|
||||
$remote_user = $this->get( 'user' );
|
||||
$title = sprintf( __( 'Connected as %s', 'elementor' ), '<strong>' . $remote_user->email . '</strong>' );
|
||||
$label = __( 'Disconnect', 'elementor' );
|
||||
$url = $this->get_admin_url( 'disconnect' );
|
||||
$attr = '';
|
||||
|
||||
echo sprintf( '%s <a %s href="%s">%s</a>', $title, $attr, esc_attr( $url ), esc_html( $label ) );
|
||||
} else {
|
||||
echo 'Not Connected';
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
|
||||
$this->print_app_info();
|
||||
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
printf( '<div><a href="%s">%s</a></div>', $this->get_admin_url( 'reset' ), __( 'Reset Data', 'elementor' ) );
|
||||
}
|
||||
|
||||
echo '<hr>';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_option_name() {
|
||||
return static::OPTION_NAME_PREFIX . $this->get_slug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function admin_notice() {
|
||||
$notices = $this->get( 'notices' );
|
||||
|
||||
if ( ! $notices ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->print_notices( $notices );
|
||||
|
||||
$this->delete( 'notices' );
|
||||
}
|
||||
|
||||
|
||||
public function get_app_token_from_cli_token( $cli_token ) {
|
||||
$response = $this->request( 'get_app_token_from_cli_token', [
|
||||
'cli_token' => $cli_token,
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
wp_die( $response, $response->get_error_message() );
|
||||
}
|
||||
|
||||
// Use state as usual.
|
||||
$_REQUEST['state'] = $this->get( 'state' );
|
||||
$_REQUEST['code'] = $response->code;
|
||||
}
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function action_authorize() {
|
||||
if ( $this->is_connected() ) {
|
||||
$this->add_notice( __( 'Already connected.', 'elementor' ), 'info' );
|
||||
$this->redirect_to_admin_page();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set_client_id();
|
||||
$this->set_request_state();
|
||||
|
||||
$this->redirect_to_remote_authorize_url();
|
||||
}
|
||||
|
||||
public function action_reset() {
|
||||
delete_user_option( get_current_user_id(), 'elementor_connect_common_data' );
|
||||
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
delete_option( 'elementor_connect_site_key' );
|
||||
delete_option( 'elementor_remote_info_library' );
|
||||
}
|
||||
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function action_get_token() {
|
||||
if ( $this->is_connected() ) {
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
if ( empty( $_REQUEST['state'] ) || $_REQUEST['state'] !== $this->get( 'state' ) ) {
|
||||
$this->add_notice( 'Get Token: Invalid Request.', 'error' );
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
$response = $this->request( 'get_token', [
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $_REQUEST['code'],
|
||||
'redirect_uri' => rawurlencode( $this->get_admin_url( 'get_token' ) ),
|
||||
'client_id' => $this->get( 'client_id' ),
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$notice = 'Cannot Get Token:' . $response->get_error_message();
|
||||
$this->add_notice( $notice, 'error' );
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
if ( ! empty( $response->data_share_opted_in ) && current_user_can( 'manage_options' ) ) {
|
||||
Tracker::set_opt_in( true );
|
||||
}
|
||||
|
||||
$this->delete( 'state' );
|
||||
$this->set( (array) $response );
|
||||
|
||||
$this->after_connect();
|
||||
|
||||
// Add the notice *after* the method `after_connect`, so an app can redirect without the notice.
|
||||
$this->add_notice( __( 'Connected Successfully.', 'elementor' ) );
|
||||
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function action_disconnect() {
|
||||
if ( $this->is_connected() ) {
|
||||
$this->disconnect();
|
||||
$this->add_notice( __( 'Disconnected Successfully.', 'elementor' ) );
|
||||
}
|
||||
|
||||
$this->redirect_to_admin_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.8.0
|
||||
* @access public
|
||||
*/
|
||||
public function action_reconnect() {
|
||||
$this->disconnect();
|
||||
|
||||
$this->action_authorize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function get_admin_url( $action, $params = [] ) {
|
||||
$params = [
|
||||
'app' => $this->get_slug(),
|
||||
'action' => $action,
|
||||
'nonce' => wp_create_nonce( $this->get_slug() . $action ),
|
||||
] + $params;
|
||||
|
||||
// Encode base url, the encode is limited to 64 chars.
|
||||
$admin_url = \Requests_IDNAEncoder::encode( get_admin_url() );
|
||||
|
||||
$admin_url .= 'admin.php?page=' . Admin::PAGE_ID;
|
||||
|
||||
return add_query_arg( $params, $admin_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function is_connected() {
|
||||
return (bool) $this->get( 'access_token' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function init() {}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function init_data() {}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function after_connect() {}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function get( $key, $default = null ) {
|
||||
$this->init_data();
|
||||
|
||||
return isset( $this->data[ $key ] ) ? $this->data[ $key ] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function set( $key, $value = null ) {
|
||||
$this->init_data();
|
||||
|
||||
if ( is_array( $key ) ) {
|
||||
$this->data = array_replace_recursive( $this->data, $key );
|
||||
} else {
|
||||
$this->data[ $key ] = $value;
|
||||
}
|
||||
|
||||
$this->update_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function delete( $key = null ) {
|
||||
$this->init_data();
|
||||
|
||||
if ( $key ) {
|
||||
unset( $this->data[ $key ] );
|
||||
} else {
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
$this->update_settings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function add( $key, $value, $default = '' ) {
|
||||
$new_value = $this->get( $key, $default );
|
||||
|
||||
if ( is_array( $new_value ) ) {
|
||||
$new_value[] = $value;
|
||||
} elseif ( is_string( $new_value ) ) {
|
||||
$new_value .= $value;
|
||||
} elseif ( is_numeric( $new_value ) ) {
|
||||
$new_value += $value;
|
||||
}
|
||||
|
||||
$this->set( $key, $new_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function add_notice( $content, $type = 'success' ) {
|
||||
$this->add( 'notices', compact( 'content', 'type' ), [] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function request( $action, $request_body = [], $as_array = false ) {
|
||||
$request_body = [
|
||||
'app' => $this->get_slug(),
|
||||
'access_token' => $this->get( 'access_token' ),
|
||||
'client_id' => $this->get( 'client_id' ),
|
||||
'local_id' => get_current_user_id(),
|
||||
'site_key' => $this->get_site_key(),
|
||||
'home_url' => trailingslashit( home_url() ),
|
||||
] + $request_body;
|
||||
|
||||
$headers = [];
|
||||
|
||||
if ( $this->is_connected() ) {
|
||||
$headers['X-Elementor-Signature'] = hash_hmac( 'sha256', wp_json_encode( $request_body, JSON_NUMERIC_CHECK ), $this->get( 'access_token_secret' ) );
|
||||
}
|
||||
|
||||
$response = wp_remote_post( $this->get_api_url() . '/' . $action, [
|
||||
'body' => $request_body,
|
||||
'headers' => $headers,
|
||||
'timeout' => 25,
|
||||
] );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
wp_die( $response, [
|
||||
'back_link' => true,
|
||||
] );
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body( $response );
|
||||
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
|
||||
if ( ! $response_code ) {
|
||||
return new \WP_Error( 500, 'No Response' );
|
||||
|
||||
}
|
||||
|
||||
// Server sent a success message without content.
|
||||
if ( 'null' === $body ) {
|
||||
$body = true;
|
||||
}
|
||||
|
||||
$body = json_decode( $body, $as_array );
|
||||
|
||||
if ( false === $body ) {
|
||||
return new \WP_Error( 422, 'Wrong Server Response' );
|
||||
}
|
||||
|
||||
if ( 200 !== $response_code ) {
|
||||
// In case $as_array = true.
|
||||
$body = (object) $body;
|
||||
|
||||
$message = isset( $body->message ) ? $body->message : wp_remote_retrieve_response_message( $response );
|
||||
$code = isset( $body->code ) ? $body->code : $response_code;
|
||||
|
||||
if ( 401 === $code ) {
|
||||
$this->delete();
|
||||
$this->action_authorize();
|
||||
}
|
||||
|
||||
return new \WP_Error( $code, $message );
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_api_url() {
|
||||
return static::API_URL . '/' . $this->get_slug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_remote_site_url() {
|
||||
return static::SITE_URL . '/' . $this->get_slug();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_remote_authorize_url() {
|
||||
$redirect_uri = $this->get_auth_redirect_uri();
|
||||
|
||||
$url = add_query_arg( [
|
||||
'action' => 'authorize',
|
||||
'response_type' => 'code',
|
||||
'client_id' => $this->get( 'client_id' ),
|
||||
'auth_secret' => $this->get( 'auth_secret' ),
|
||||
'state' => $this->get( 'state' ),
|
||||
'redirect_uri' => rawurlencode( $redirect_uri ),
|
||||
'may_share_data' => current_user_can( 'manage_options' ) && ! Tracker::is_allow_track(),
|
||||
'reconnect_nonce' => wp_create_nonce( $this->get_slug() . 'reconnect' ),
|
||||
], $this->get_remote_site_url() );
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function redirect_to_admin_page( $url = '' ) {
|
||||
if ( ! $url ) {
|
||||
$url = Admin::$url;
|
||||
}
|
||||
|
||||
switch ( $this->auth_mode ) {
|
||||
case 'popup':
|
||||
$this->print_popup_close_script( $url );
|
||||
break;
|
||||
|
||||
case 'cli':
|
||||
$this->admin_notice();
|
||||
die;
|
||||
|
||||
default:
|
||||
wp_safe_redirect( $url );
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function set_client_id() {
|
||||
if ( $this->get( 'client_id' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$response = $this->request( 'get_client_id' );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
wp_die( $response, $response->get_error_message() );
|
||||
}
|
||||
|
||||
$this->set( 'client_id', $response->client_id );
|
||||
$this->set( 'auth_secret', $response->auth_secret );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function set_request_state() {
|
||||
$this->set( 'state', wp_generate_password( 12, false ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function print_popup_close_script( $url ) {
|
||||
?>
|
||||
<script>
|
||||
if ( opener && opener !== window ) {
|
||||
opener.jQuery( 'body' ).trigger( 'elementor/connect/success/<?php echo esc_attr( $_REQUEST['callback_id'] ); ?>' );
|
||||
window.close();
|
||||
opener.focus();
|
||||
} else {
|
||||
location = '<?php echo $url; ?>';
|
||||
}
|
||||
</script>
|
||||
<?php
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function disconnect() {
|
||||
if ( $this->is_connected() ) {
|
||||
// Try update the server, but not needed to handle errors.
|
||||
$this->request( 'disconnect' );
|
||||
}
|
||||
|
||||
$this->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_site_key() {
|
||||
$site_key = get_option( 'elementor_connect_site_key' );
|
||||
|
||||
if ( ! $site_key ) {
|
||||
$site_key = md5( uniqid( wp_generate_password() ) );
|
||||
update_option( 'elementor_connect_site_key', $site_key );
|
||||
}
|
||||
|
||||
return $site_key;
|
||||
}
|
||||
|
||||
protected function redirect_to_remote_authorize_url() {
|
||||
switch ( $this->auth_mode ) {
|
||||
case 'cli':
|
||||
$this->get_app_token_from_cli_token( $_REQUEST['token'] );
|
||||
return;
|
||||
default:
|
||||
wp_redirect( $this->get_remote_authorize_url() );
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
protected function get_auth_redirect_uri() {
|
||||
$redirect_uri = $this->get_admin_url( 'get_token' );
|
||||
|
||||
switch ( $this->auth_mode ) {
|
||||
case 'popup':
|
||||
$redirect_uri = add_query_arg( [
|
||||
'mode' => 'popup',
|
||||
'callback_id' => esc_attr( $_REQUEST['callback_id'] ),
|
||||
], $redirect_uri );
|
||||
break;
|
||||
}
|
||||
|
||||
return $redirect_uri;
|
||||
}
|
||||
|
||||
|
||||
protected function print_notices( $notices ) {
|
||||
switch ( $this->auth_mode ) {
|
||||
case 'cli':
|
||||
foreach ( $notices as $notice ) {
|
||||
printf( '[%s] %s', $notice['type'], $notice['content'] );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>';
|
||||
|
||||
foreach ( $notices as $notice ) {
|
||||
echo wp_kses_post( sprintf( '<div class="%s"><p>%s</p></div>', $notice['type'], wpautop( $notice['content'] ) ) );
|
||||
}
|
||||
|
||||
echo '</p><button type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss', 'elementor' ) . '</span></button></div>';
|
||||
}
|
||||
}
|
||||
|
||||
protected function get_app_info() {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function print_app_info() {
|
||||
$app_info = $this->get_app_info();
|
||||
|
||||
foreach ( $app_info as $key => $item ) {
|
||||
if ( $item['value'] ) {
|
||||
$status = 'Exist';
|
||||
$color = 'green';
|
||||
} else {
|
||||
$status = 'Empty';
|
||||
$color = 'red';
|
||||
}
|
||||
|
||||
printf( '%s: <strong style="color:%s">%s</strong><br>', $item['label'], $color, $status );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'admin_notices', [ $this, 'admin_notice' ] );
|
||||
|
||||
if ( isset( $_REQUEST['mode'] ) ) { // phpcs:ignore -- nonce validation is not require here.
|
||||
$allowed_auth_modes = [
|
||||
'popup',
|
||||
];
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
$allowed_auth_modes[] = 'cli';
|
||||
}
|
||||
|
||||
$mode = $_REQUEST['mode']; // phpcs:ignore -- nonce validation is not require here.
|
||||
|
||||
if ( in_array( $mode, $allowed_auth_modes, true ) ) {
|
||||
$this->auth_mode = $mode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow extended apps to customize the __construct without call parent::__construct.
|
||||
*/
|
||||
$this->init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect\Apps;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
abstract class Base_User_App extends Base_App {
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function update_settings() {
|
||||
update_user_option( get_current_user_id(), $this->get_option_name(), $this->data );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function init_data() {
|
||||
$this->data = get_user_option( $this->get_option_name() );
|
||||
|
||||
if ( ! $this->data ) {
|
||||
$this->data = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect\Apps;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
abstract class Common_App extends Base_User_App {
|
||||
|
||||
protected static $common_data = null;
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function get_option_name() {
|
||||
return static::OPTION_NAME_PREFIX . 'common_data';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function init_data() {
|
||||
if ( is_null( self::$common_data ) ) {
|
||||
self::$common_data = get_user_option( static::get_option_name() );
|
||||
|
||||
if ( ! self::$common_data ) {
|
||||
self::$common_data = [];
|
||||
};
|
||||
}
|
||||
|
||||
$this->data = & self::$common_data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect\Apps;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Connect extends Common_App {
|
||||
|
||||
public function get_title() {
|
||||
return __( 'Connect', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
protected function get_slug() {
|
||||
return 'connect';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function render_admin_widget() {}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect\Apps;
|
||||
|
||||
use Elementor\User;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Library extends Common_App {
|
||||
public function get_title() {
|
||||
return __( 'Library', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function get_slug() {
|
||||
return 'library';
|
||||
}
|
||||
|
||||
public function get_template_content( $id ) {
|
||||
if ( ! $this->is_connected() ) {
|
||||
return new \WP_Error( '401', __( 'Connecting to the Library failed. Please try reloading the page and try again', 'elementor' ) );
|
||||
}
|
||||
|
||||
$body_args = [
|
||||
'id' => $id,
|
||||
|
||||
// Which API version is used.
|
||||
'api_version' => ELEMENTOR_VERSION,
|
||||
// Which language to return.
|
||||
'site_lang' => get_bloginfo( 'language' ),
|
||||
];
|
||||
|
||||
/**
|
||||
* API: Template body args.
|
||||
*
|
||||
* Filters the body arguments send with the GET request when fetching the content.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $body_args Body arguments.
|
||||
*/
|
||||
$body_args = apply_filters( 'elementor/api/get_templates/body_args', $body_args );
|
||||
|
||||
$template_content = $this->request( 'get_template_content', $body_args, true );
|
||||
|
||||
return $template_content;
|
||||
}
|
||||
|
||||
public function localize_settings( $settings ) {
|
||||
$is_connected = $this->is_connected();
|
||||
|
||||
return array_replace_recursive( $settings, [
|
||||
'i18n' => [
|
||||
// Route: library/connect
|
||||
'library/connect:title' => __( 'Connect to Template Library', 'elementor' ),
|
||||
'library/connect:message' => __( 'Access this template and our entire library by creating a free personal account', 'elementor' ),
|
||||
'library/connect:button' => __( 'Get Started', 'elementor' ),
|
||||
],
|
||||
'library_connect' => [
|
||||
'is_connected' => $is_connected,
|
||||
],
|
||||
] );
|
||||
}
|
||||
|
||||
public function library_connect_popup_seen() {
|
||||
User::set_introduction_viewed( [
|
||||
'introductionKey' => 'library_connect',
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Elementor\Core\Common\Modules\Ajax\Module $ajax_manager
|
||||
*/
|
||||
public function register_ajax_actions( $ajax_manager ) {
|
||||
$ajax_manager->register_ajax_action( 'library_connect_popup_seen', [ $this, 'library_connect_popup_seen' ] );
|
||||
}
|
||||
|
||||
protected function get_app_info() {
|
||||
return [
|
||||
'user_common_data' => [
|
||||
'label' => 'User Common Data',
|
||||
'value' => get_user_option( $this->get_option_name(), get_current_user_id() ),
|
||||
],
|
||||
'connect_site_key' => [
|
||||
'label' => 'Site Key',
|
||||
'value' => get_option( 'elementor_connect_site_key' ),
|
||||
],
|
||||
'remote_info_library' => [
|
||||
'label' => 'Remote Library Info',
|
||||
'value' => get_option( 'elementor_remote_info_library' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function init() {
|
||||
add_filter( 'elementor/editor/localize_settings', [ $this, 'localize_settings' ] );
|
||||
add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Connect;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\Common\Modules\Connect\Apps\Base_App;
|
||||
use Elementor\Core\Common\Modules\Connect\Apps\Connect;
|
||||
use Elementor\Core\Common\Modules\Connect\Apps\Library;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'connect';
|
||||
}
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $registered_apps = [];
|
||||
|
||||
/**
|
||||
* Apps Instances.
|
||||
*
|
||||
* Holds the list of all the apps instances.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @var Base_App[]
|
||||
*/
|
||||
protected $apps = [];
|
||||
|
||||
/**
|
||||
* Registered apps categories.
|
||||
*
|
||||
* Holds the list of all the registered apps categories.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $categories = [];
|
||||
|
||||
protected $admin_page;
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->registered_apps = [
|
||||
'connect' => Connect::get_class_name(),
|
||||
'library' => Library::get_class_name(),
|
||||
];
|
||||
|
||||
// Note: The priority 11 is for allowing plugins to add their register callback on elementor init.
|
||||
add_action( 'elementor/init', [ $this, 'init' ], 11 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register default apps.
|
||||
*
|
||||
* Registers the default apps.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function init() {
|
||||
if ( is_admin() ) {
|
||||
$this->admin_page = new Admin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Elementor apps.
|
||||
*
|
||||
* Fires after Elementor registers the default apps.
|
||||
*
|
||||
* @since 2.3.0
|
||||
*
|
||||
* @param self $this The apps manager instance.
|
||||
*/
|
||||
do_action( 'elementor/connect/apps/register', $this );
|
||||
|
||||
foreach ( $this->registered_apps as $slug => $class ) {
|
||||
$this->apps[ $slug ] = new $class();
|
||||
}
|
||||
|
||||
add_filter( 'elementor/editor/localize_settings', [ $this, 'localize_settings' ] );
|
||||
}
|
||||
|
||||
public function localize_settings( $settings ) {
|
||||
return array_replace_recursive( $settings, [
|
||||
'i18n' => [
|
||||
'connect_error' => __( 'Unable to connect', 'elementor' ),
|
||||
'connected_successfully' => __( 'Connected successfully', 'elementor' ),
|
||||
],
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register app.
|
||||
*
|
||||
* Registers an app.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param string $slug App slug.
|
||||
* @param string $class App full class name.
|
||||
*
|
||||
* @return self The updated apps manager instance.
|
||||
*/
|
||||
public function register_app( $slug, $class ) {
|
||||
$this->registered_apps[ $slug ] = $class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get app instance.
|
||||
*
|
||||
* Retrieve the app instance.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param $slug
|
||||
*
|
||||
* @return Base_App|null
|
||||
*/
|
||||
public function get_app( $slug ) {
|
||||
if ( isset( $this->apps[ $slug ] ) ) {
|
||||
return $this->apps[ $slug ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @return Base_App[]
|
||||
*/
|
||||
public function get_apps() {
|
||||
return $this->apps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_category( $slug, $args ) {
|
||||
$this->categories[ $slug ] = $args;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function get_categories() {
|
||||
return $this->categories;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder;
|
||||
|
||||
use Elementor\Core\Base\Base_Object;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Base Category
|
||||
*
|
||||
* Base class for Elementor Finder categories.
|
||||
*/
|
||||
abstract class Base_Category extends Base_Object {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @abstract
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_title();
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @abstract
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_category_items( array $options = [] );
|
||||
|
||||
/**
|
||||
* Is dynamic.
|
||||
*
|
||||
* Determine if the category is dynamic.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_dynamic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get init settings.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_init_settings() {
|
||||
$settings = [
|
||||
'title' => $this->get_title(),
|
||||
'dynamic' => $this->is_dynamic(),
|
||||
];
|
||||
|
||||
if ( ! $settings['dynamic'] ) {
|
||||
$settings['items'] = $this->get_category_items();
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class Categories_Manager {
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @var Base_Category[]
|
||||
*/
|
||||
private $categories;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $categories_list = [
|
||||
'edit',
|
||||
'general',
|
||||
'create',
|
||||
'site',
|
||||
'settings',
|
||||
'tools',
|
||||
];
|
||||
|
||||
/**
|
||||
* Add category.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @param string $category_name
|
||||
* @param Base_Category $category
|
||||
*/
|
||||
public function add_category( $category_name, Base_Category $category ) {
|
||||
$this->categories[ $category_name ] = $category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get categories.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
* @param string $category
|
||||
*
|
||||
* @return Base_Category|Base_Category[]|null
|
||||
*/
|
||||
public function get_categories( $category = '' ) {
|
||||
if ( ! $this->categories ) {
|
||||
$this->init_categories();
|
||||
}
|
||||
|
||||
if ( $category ) {
|
||||
if ( isset( $this->categories[ $category ] ) ) {
|
||||
return $this->categories[ $category ];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init categories.
|
||||
*
|
||||
* Used to initialize finder default categories.
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*/
|
||||
private function init_categories() {
|
||||
foreach ( $this->categories_list as $category_name ) {
|
||||
$class_name = __NAMESPACE__ . '\Categories\\' . $category_name;
|
||||
|
||||
$this->add_category( $category_name, new $class_name() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Elementor Finder categories init.
|
||||
*
|
||||
* Fires after Elementor Finder initialize it's native categories.
|
||||
*
|
||||
* This hook should be used to add your own Finder categories.
|
||||
*
|
||||
* @since 2.3.0
|
||||
*
|
||||
* @param Categories_Manager $this.
|
||||
*/
|
||||
do_action( 'elementor/finder/categories/init', $this );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
use Elementor\Utils;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Category
|
||||
*
|
||||
* Provides items related to creation of new posts/pages/templates etc.
|
||||
*/
|
||||
class Create extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'Create', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
$elementor_supported_post_types = get_post_types_by_support( 'elementor' );
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ( $elementor_supported_post_types as $post_type ) {
|
||||
$post_type_object = get_post_type_object( $post_type );
|
||||
|
||||
// If there is an old post type from inactive plugins
|
||||
if ( ! $post_type_object ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( Source_Local::CPT === $post_type ) {
|
||||
$url = admin_url( Source_Local::ADMIN_MENU_SLUG . '#add_new' );
|
||||
} else {
|
||||
$url = Utils::get_create_new_post_url( $post_type );
|
||||
}
|
||||
|
||||
$items[ $post_type ] = [
|
||||
/* translators: %s the title of the post type */
|
||||
'title' => sprintf( __( 'Add New %s', 'elementor' ), $post_type_object->labels->singular_name ),
|
||||
'icon' => 'plus-circle-o',
|
||||
'url' => $url,
|
||||
'keywords' => [ 'post', 'page', 'template', 'new', 'create' ],
|
||||
];
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Base\Document;
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Category
|
||||
*
|
||||
* Provides items related to editing of posts/pages/templates etc.
|
||||
*/
|
||||
class Edit extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'Edit', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is dynamic.
|
||||
*
|
||||
* Determine if the category is dynamic.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_dynamic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
$post_types = get_post_types( [
|
||||
'exclude_from_search' => false,
|
||||
] );
|
||||
|
||||
$post_types[] = Source_Local::CPT;
|
||||
|
||||
$document_types = Plugin::$instance->documents->get_document_types( [
|
||||
'is_editable' => true,
|
||||
'show_in_finder' => true,
|
||||
] );
|
||||
|
||||
// TODO: Remove on 2.4.0.
|
||||
unset( $document_types['widget'] );
|
||||
|
||||
$recently_edited_query_args = [
|
||||
'post_type' => $post_types,
|
||||
'post_status' => [ 'publish', 'draft', 'private', 'pending', 'future' ],
|
||||
'posts_per_page' => '10',
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => '_elementor_edit_mode',
|
||||
'value' => 'builder',
|
||||
],
|
||||
[
|
||||
'relation' => 'or',
|
||||
[
|
||||
'key' => Document::TYPE_META_KEY,
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => Document::TYPE_META_KEY,
|
||||
'value' => array_keys( $document_types ),
|
||||
],
|
||||
],
|
||||
],
|
||||
'orderby' => 'modified',
|
||||
's' => $options['filter'],
|
||||
];
|
||||
|
||||
$recently_edited_query = new \WP_Query( $recently_edited_query_args );
|
||||
|
||||
$items = [];
|
||||
|
||||
/** @var \WP_Post $post */
|
||||
foreach ( $recently_edited_query->posts as $post ) {
|
||||
$document = Plugin::$instance->documents->get( $post->ID );
|
||||
|
||||
if ( ! $document ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$is_template = Source_Local::CPT === $post->post_type;
|
||||
|
||||
$description = $document->get_title();
|
||||
|
||||
$icon = 'document-file';
|
||||
|
||||
if ( $is_template ) {
|
||||
$description = __( 'Template', 'elementor' ) . ' / ' . $description;
|
||||
|
||||
$icon = 'post-title';
|
||||
}
|
||||
|
||||
$items[] = [
|
||||
'icon' => $icon,
|
||||
'title' => esc_html( $post->post_title ),
|
||||
'description' => $description,
|
||||
'url' => $document->get_edit_url(),
|
||||
'actions' => [
|
||||
[
|
||||
'name' => 'view',
|
||||
'url' => $document->get_permalink(),
|
||||
'icon' => 'preview-medium',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
use Elementor\Core\RoleManager\Role_Manager;
|
||||
use Elementor\TemplateLibrary\Source_Local;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* General Category
|
||||
*
|
||||
* Provides general items related to Elementor Admin.
|
||||
*/
|
||||
class General extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'General', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
return [
|
||||
'saved-templates' => [
|
||||
'title' => _x( 'Saved Templates', 'Template Library', 'elementor' ),
|
||||
'icon' => 'library-save',
|
||||
'url' => Source_Local::get_admin_url(),
|
||||
'keywords' => [ 'template', 'section', 'page', 'library' ],
|
||||
],
|
||||
'system-info' => [
|
||||
'title' => __( 'System Info', 'elementor' ),
|
||||
'icon' => 'info-circle-o',
|
||||
'url' => admin_url( 'admin.php?page=elementor-system-info' ),
|
||||
'keywords' => [ 'system', 'info', 'environment', 'elementor' ],
|
||||
],
|
||||
'role-manager' => [
|
||||
'title' => __( 'Role Manager', 'elementor' ),
|
||||
'icon' => 'person',
|
||||
'url' => Role_Manager::get_url(),
|
||||
'keywords' => [ 'role', 'manager', 'user', 'elementor' ],
|
||||
],
|
||||
'knowledge-base' => [
|
||||
'title' => __( 'Knowledge Base', 'elementor' ),
|
||||
'url' => admin_url( 'admin.php?page=go_knowledge_base_site' ),
|
||||
'keywords' => [ 'help', 'knowledge', 'docs', 'elementor' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
use Elementor\Settings as ElementorSettings;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings Category
|
||||
*
|
||||
* Provides items related to Elementor's settings.
|
||||
*/
|
||||
class Settings extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'Settings', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
$settings_url = ElementorSettings::get_url();
|
||||
|
||||
return [
|
||||
'general-settings' => [
|
||||
'title' => __( 'General Settings', 'elementor' ),
|
||||
'url' => $settings_url,
|
||||
'keywords' => [ 'general', 'settings', 'elementor' ],
|
||||
],
|
||||
'advanced' => [
|
||||
'title' => __( 'Advanced', 'elementor' ),
|
||||
'url' => $settings_url . '#tab-advanced',
|
||||
'keywords' => [ 'advanced', 'settings', 'elementor' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Site Category
|
||||
*
|
||||
* Provides general site items.
|
||||
*/
|
||||
class Site extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'Site', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
return [
|
||||
'homepage' => [
|
||||
'title' => __( 'Homepage', 'elementor' ),
|
||||
'url' => home_url(),
|
||||
'icon' => 'home-heart',
|
||||
'keywords' => [ 'home', 'page' ],
|
||||
],
|
||||
'wordpress-dashboard' => [
|
||||
'title' => __( 'Dashboard', 'elementor' ),
|
||||
'icon' => 'dashboard',
|
||||
'url' => admin_url(),
|
||||
'keywords' => [ 'dashboard', 'wordpress' ],
|
||||
],
|
||||
'wordpress-menus' => [
|
||||
'title' => __( 'Menus', 'elementor' ),
|
||||
'icon' => 'wordpress',
|
||||
'url' => admin_url( 'nav-menus.php' ),
|
||||
'keywords' => [ 'menu', 'wordpress' ],
|
||||
],
|
||||
'wordpress-themes' => [
|
||||
'title' => __( 'Themes', 'elementor' ),
|
||||
'icon' => 'wordpress',
|
||||
'url' => admin_url( 'themes.php' ),
|
||||
'keywords' => [ 'themes', 'wordpress' ],
|
||||
],
|
||||
'wordpress-customizer' => [
|
||||
'title' => __( 'Customizer', 'elementor' ),
|
||||
'icon' => 'wordpress',
|
||||
'url' => admin_url( 'customize.php' ),
|
||||
'keywords' => [ 'customizer', 'wordpress' ],
|
||||
],
|
||||
'wordpress-plugins' => [
|
||||
'title' => __( 'Plugins', 'elementor' ),
|
||||
'icon' => 'wordpress',
|
||||
'url' => admin_url( 'plugins.php' ),
|
||||
'keywords' => [ 'plugins', 'wordpress' ],
|
||||
],
|
||||
'wordpress-users' => [
|
||||
'title' => __( 'Users', 'elementor' ),
|
||||
'icon' => 'wordpress',
|
||||
'url' => admin_url( 'users.php' ),
|
||||
'keywords' => [ 'users', 'profile', 'wordpress' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder\Categories;
|
||||
|
||||
use Elementor\Core\Common\Modules\Finder\Base_Category;
|
||||
use Elementor\Tools as ElementorTools;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Tools Category
|
||||
*
|
||||
* Provides items related to Elementor's tools.
|
||||
*/
|
||||
class Tools extends Base_Category {
|
||||
|
||||
/**
|
||||
* Get title.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return __( 'Tools', 'elementor' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_category_items( array $options = [] ) {
|
||||
$tools_url = ElementorTools::get_url();
|
||||
|
||||
return [
|
||||
'tools' => [
|
||||
'title' => __( 'Tools', 'elementor' ),
|
||||
'icon' => 'tools',
|
||||
'url' => $tools_url,
|
||||
'keywords' => [ 'tools', 'regenerate css', 'safe mode', 'debug bar', 'sync library', 'elementor' ],
|
||||
],
|
||||
'replace-url' => [
|
||||
'title' => __( 'Replace URL', 'elementor' ),
|
||||
'icon' => 'tools',
|
||||
'url' => $tools_url . '#tab-replace_url',
|
||||
'keywords' => [ 'tools', 'replace url', 'domain', 'elementor' ],
|
||||
],
|
||||
'version-control' => [
|
||||
'title' => __( 'Version Control', 'elementor' ),
|
||||
'icon' => 'time-line',
|
||||
'url' => $tools_url . '#tab-versions',
|
||||
'keywords' => [ 'tools', 'version', 'control', 'rollback', 'beta', 'elementor' ],
|
||||
],
|
||||
'maintenance-mode' => [
|
||||
'title' => __( 'Maintenance Mode', 'elementor' ),
|
||||
'icon' => 'tools',
|
||||
'url' => $tools_url . '#tab-maintenance_mode',
|
||||
'keywords' => [ 'tools', 'maintenance', 'coming soon', 'elementor' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Core\Common\Modules\Finder;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
|
||||
use Elementor\Plugin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Finder Module
|
||||
*
|
||||
* Responsible for initializing Elementor Finder functionality
|
||||
*/
|
||||
class Module extends BaseModule {
|
||||
|
||||
/**
|
||||
* Categories manager.
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @var Categories_Manager
|
||||
*/
|
||||
private $categories_manager;
|
||||
|
||||
/**
|
||||
* Module constructor.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->categories_manager = new Categories_Manager();
|
||||
|
||||
$this->add_template();
|
||||
|
||||
add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'finder';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add template.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*/
|
||||
public function add_template() {
|
||||
Plugin::$instance->common->add_template( __DIR__ . '/template.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register ajax actions.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param Ajax $ajax
|
||||
*/
|
||||
public function register_ajax_actions( Ajax $ajax ) {
|
||||
$ajax->register_ajax_action( 'finder_get_category_items', [ $this, 'ajax_get_category_items' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get category items.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ajax_get_category_items( array $data ) {
|
||||
$category = $this->categories_manager->get_categories( $data['category'] );
|
||||
|
||||
return $category->get_category_items( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get init settings.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access protected
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_init_settings() {
|
||||
$categories = $this->categories_manager->get_categories();
|
||||
|
||||
$categories_data = [];
|
||||
|
||||
foreach ( $categories as $category_name => $category ) {
|
||||
$categories_data[ $category_name ] = array_merge( $category->get_settings(), [ 'name' => $category_name ] );
|
||||
}
|
||||
|
||||
$categories_data = apply_filters( 'elementor/finder/categories', $categories_data );
|
||||
|
||||
return [
|
||||
'data' => $categories_data,
|
||||
'i18n' => [
|
||||
'finder' => __( 'Finder', 'elementor' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Modules\Finder;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
?>
|
||||
<script type="text/template" id="tmpl-elementor-finder">
|
||||
<div id="elementor-finder__search">
|
||||
<i class="eicon-search"></i>
|
||||
<input id="elementor-finder__search__input" placeholder="<?php echo __( 'Type to find anything in Elementor', 'elementor' ); ?>">
|
||||
</div>
|
||||
<div id="elementor-finder__content"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-finder-results-container">
|
||||
<div id="elementor-finder__no-results"><?php echo __( 'No Results Found', 'elementor' ); ?></div>
|
||||
<div id="elementor-finder__results"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-finder__results__category">
|
||||
<div class="elementor-finder__results__category__title">{{{ title }}}</div>
|
||||
<div class="elementor-finder__results__category__items"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-elementor-finder__results__item">
|
||||
<a href="{{ url }}" class="elementor-finder__results__item__link">
|
||||
<div class="elementor-finder__results__item__icon">
|
||||
<i class="eicon-{{{ icon }}}"></i>
|
||||
</div>
|
||||
<div class="elementor-finder__results__item__title">{{{ title }}}</div>
|
||||
<# if ( description ) { #>
|
||||
<div class="elementor-finder__results__item__description">- {{{ description }}}</div>
|
||||
<# } #>
|
||||
</a>
|
||||
<# if ( actions.length ) { #>
|
||||
<div class="elementor-finder__results__item__actions">
|
||||
<# jQuery.each( actions, function() { #>
|
||||
<a class="elementor-finder__results__item__action elementor-finder__results__item__action--{{ this.name }}" href="{{ this.url }}" target="_blank">
|
||||
<i class="eicon-{{{ this.icon }}}"></i>
|
||||
</a>
|
||||
<# } ); #>
|
||||
</div>
|
||||
<# } #>
|
||||
</script>
|
||||
Reference in New Issue
Block a user