This commit is contained in:
proelements
2025-11-13 15:18:34 +02:00
commit 9ac2bf2aa0
1178 changed files with 296944 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data;
use ElementorPro\Plugin;
use Elementor\Data\Base\Controller as Controller_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Controller extends Controller_Base {
public function get_name() {
return 'site-editor';
}
public function register_endpoints() {
$this->register_endpoint( Endpoints\Templates::class );
$this->register_endpoint( Endpoints\Conditions_Config::class );
$this->register_endpoint( Endpoints\Templates_Conditions::class );
$this->register_endpoint( Endpoints\Templates_Conditions_Conflicts::class );
}
public function get_permission_callback( $request ) {
return Plugin::elementor()->kits_manager->get_active_kit()->is_editable_by_current_user();
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use Elementor\Data\Base\Endpoint;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
abstract class Base_Endpoint extends Endpoint {
/**
* Check if post is lock.
*
* @param $post_id
*
* @return bool|false|int
*/
protected function is_post_lock( $post_id ) {
require_once ABSPATH . 'wp-admin/includes/post.php';
return wp_check_post_lock( $post_id );
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use ElementorPro\Modules\ThemeBuilder\Module as ThemeBuilderModule;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Conditions_Config extends Base_Endpoint {
/**
* @return string
*/
public function get_name() {
return 'conditions-config';
}
public function get_items( $request ) {
$conditions_manager = ThemeBuilderModule::instance()->get_conditions_manager();
return $conditions_manager->get_conditions_config();
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use ElementorPro\Plugin;
use ElementorPro\Core\App\Modules\SiteEditor\Module;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Template_Types extends Base_Endpoint {
/**
* @return string
*/
public function get_name() {
return 'template-types';
}
public function get_items( $request ) {
/** @var Module $site_editor_module */
$site_editor_module = Plugin::instance()->app->get_component( 'site-editor' );
return $site_editor_module->get_template_types();
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use ElementorPro\Plugin;
use ElementorPro\Modules\ThemeBuilder\Module;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Templates_Conditions_Conflicts extends Base_Endpoint {
/**
* @return string
*/
public function get_name() {
return 'templates-conditions-conflicts';
}
public function get_items( $request ) {
/** @var Module $theme_builder */
$theme_builder = Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
return $theme_builder
->get_conditions_manager()
->get_conditions_conflicts( intval( $request['post_id'] ), $request['condition'] );
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use ElementorPro\Plugin;
use Elementor\Core\Utils\Exceptions;
use ElementorPro\Modules\ThemeBuilder\Module;
use ElementorPro\Core\App\Modules\SiteEditor\Data\Responses\Lock_Error_Response;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Templates_Conditions extends Base_Endpoint {
/**
* @return string
*/
public function get_name() {
return 'templates-conditions';
}
protected function register() {
$this->register_item_route();
$this->register_item_route( \WP_REST_Server::EDITABLE );
}
public function get_item( $template_id, $request ) {
return $this->get_conditions( $template_id );
}
public function update_item( $template_id, $request ) {
$lock_by_user_id = $this->is_post_lock( $template_id );
if ( $lock_by_user_id ) {
return new Lock_Error_Response( $lock_by_user_id );
}
$data = $request->get_body_params();
if ( ! isset( $data['conditions'] ) ) {
$data['conditions'] = [];
}
$is_saved = $this->save_conditions( $template_id, $data['conditions'] );
if ( ! $is_saved ) {
return new \WP_Error(
'conditions',
__( 'Error while saving conditions.', 'elementor-pro' ),
[ 'status' => Exceptions::INTERNAL_SERVER_ERROR ]
);
}
return true;
}
protected function get_conditions( $post_id ) {
$document = \Elementor\Plugin::$instance->documents->get( $post_id );
/** @var Module $theme_builder */
$theme_builder = Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
return $theme_builder
->get_conditions_manager()
->get_document_conditions( $document );
}
protected function save_conditions( $post_id, $conditions ) {
/** @var Module $theme_builder */
$theme_builder = Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
$is_saved = $theme_builder
->get_conditions_manager()
->save_conditions( $post_id, $conditions );
if ( ! $is_saved ) {
return new \WP_Error(
'conditions_save',
__( 'Cannot save those conditions.', 'elementor-pro' ),
[ 'status' => Exceptions::INTERNAL_SERVER_ERROR ]
);
}
return true;
}
}

View File

@@ -0,0 +1,238 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Endpoints;
use ElementorPro\Plugin;
use Elementor\Core\Utils\Exceptions;
use Elementor\TemplateLibrary\Manager as TemplateManager;
use ElementorPro\Modules\ThemeBuilder\Documents\Theme_Document;
use ElementorPro\Modules\ThemeBuilder\Classes\Conditions_Manager;
use ElementorPro\Modules\ThemeBuilder\Module as ThemeBuilderModule;
use ElementorPro\Modules\ThemeBuilder\Classes\Templates_Types_Manager;
use ElementorPro\Core\App\Modules\SiteEditor\Render_Mode_Template_Preview;
use ElementorPro\Core\App\Modules\SiteEditor\Data\Responses\Lock_Error_Response;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Templates extends Base_Endpoint {
/**
* @var TemplateManager
*/
private $templates_manager;
/**
* @var array
*/
private $document_types;
public function __construct( $controller ) {
parent::__construct( $controller );
$this->templates_manager = Plugin::elementor()->templates_manager;
}
/**
* @return string
*/
public function get_name() {
return 'templates';
}
protected function register() {
parent::register();
$this->register_item_route( \WP_REST_Server::DELETABLE );
$this->register_item_route( \WP_REST_Server::EDITABLE );
$this->register_items_route( \WP_REST_Server::CREATABLE );
}
public function get_items( $request ) {
$templates = $this->templates_manager->get_source( 'local' )->get_items( [
'type' => array_keys( $this->get_documents_types() ),
'post_status' => 'any',
'orderby' => 'post_date',
'order' => 'DESC',
] );
return $this->normalize_templates_json( $templates );
}
public function create_items( $request ) {
$response = $this->templates_manager->import_template( $request->get_body_params() );
if ( is_wp_error( $response ) ) {
return new \WP_Error( 'file', $response->get_error_message(), [ 'status' => Exceptions::BAD_REQUEST ] );
}
return $this->normalize_templates_json( $response );
}
public function update_item( $id, $request ) {
$lock_by_user_id = $this->is_post_lock( $id );
if ( $lock_by_user_id ) {
return new Lock_Error_Response( $lock_by_user_id );
}
wp_update_post( array_merge( [
'ID' => $id,
], $request->get_body_params() ) );
return $this->normalize_template_json_item(
$this->templates_manager->get_source( 'local' )->get_item( $id )
);
}
public function delete_item( $id, $request ) {
$lock_by_user_id = $this->is_post_lock( $id );
if ( $lock_by_user_id ) {
return new Lock_Error_Response( $lock_by_user_id );
}
return ! ! wp_trash_post( $id );
}
/**
* @return array
*/
private function get_documents_types() {
if ( ! $this->document_types ) {
/** @var Templates_Types_Manager $types_manager */
$types_manager = ThemeBuilderModule::instance()->get_types_manager();
$this->document_types = $types_manager->get_types_config( [
'support_site_editor' => true,
] );
}
return $this->document_types;
}
/**
* @param $templates
*
* @return array
*/
private function normalize_templates_json( $templates ) {
return array_map( [ $this, 'normalize_template_json_item' ], $templates );
}
/**
* @param $template
*
* @return array
*/
private function normalize_template_json_item( $template ) {
/** @var Conditions_Manager $conditions_manager */
$conditions_manager = Plugin::instance()->modules_manager->get_modules( 'theme-builder' )->get_conditions_manager();
/** @var Theme_Document $document */
$document = Plugin::elementor()->documents->get( $template['template_id'] );
$supports_site_editor = $document::get_property( 'support_site_editor' );
// Supports also a non site editor parts.
if ( ! $supports_site_editor ) {
return [
'id' => $template['template_id'],
'url' => $template['url'],
'editURL' => $document->get_edit_url(),
'supportsSiteEditor' => false,
];
}
$types = $this->get_documents_types();
$template['instances'] = $conditions_manager->get_document_instances( $template['template_id'] );
$template['defaultCondition'] = $types[ $template['type'] ]['condition_type'] ?? null;
$has_instances = ! empty( $template['instances'] );
$is_active = false;
if ( ! $has_instances ) {
$template['instances'] = [ 'no_instances' => esc_html__( 'No instances', 'elementor-pro' ) ];
} else {
$is_active = 'publish' === $template['status'];
}
if ( ! $template['thumbnail'] ) {
$template['thumbnail'] = '';
}
$site_editor_config = $document->get_site_editor_config();
$data = array_merge( $template, [
'id' => $template['template_id'],
'exportLink' => $template['export_link'],
'modifiedDate' => $template['human_modified_date'],
'editURL' => $document->get_edit_url(),
'conditions' => array_map( function ( $condition ) {
return array_merge( $condition, [
'sub' => $condition['sub_name'],
'subId' => $condition['sub_id'],
] );
}, $conditions_manager->get_document_conditions( $document ) ),
'isActive' => $is_active,
'type' => $this->calculate_template_type( $template['type'], $template['instances'] ),
'previewUrl' => $this->get_preview_url( $template['template_id'] ),
'placeholderUrl' => $site_editor_config['urls']['thumbnail'],
'pageLayout' => $site_editor_config['page_layout'],
'supportsSiteEditor' => true,
'showInstances' => $site_editor_config['show_instances'],
] );
/**
* Template data.
*
* Filters the data returned by Elementor API as JSON.
*
* By default Elementor API returns data in a JSON format that enables the
* builder to work properly. This hook allows developers to alter the data
* returned by the API to add new elements.
*
* @param array $data Template data.
*/
$data = apply_filters( 'elementor-pro/site-editor/data/template', $data );
return $data;
}
/**
* @param $type
* @param $instances
*
* @return string
*/
private function calculate_template_type( $type, $instances ) {
$condition_to_type_map = [
'front_page' => 'single-page',
'child_of' => 'single-page',
'page' => 'single-page',
'not_found404' => 'error-404',
'search' => 'search-results',
];
// "single" type was split into "single-page", "single-post" and "404".
// this section supports all the old templates that was created as "single".
if ( 'single' === $type ) {
// By default show it under single-post.
$type = 'single-post';
foreach ( $instances as $condition_name => $condition_label ) {
if ( isset( $condition_to_type_map[ $condition_name ] ) ) {
$type = $condition_to_type_map[ $condition_name ];
break;
}
}
}
return $type;
}
private function get_preview_url( $post_id ) {
return Render_Mode_Template_Preview::get_url( $post_id );
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace ElementorPro\Core\App\Modules\SiteEditor\Data\Responses;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Lock_Error_Response extends \WP_Error {
public function __construct( $user_id ) {
$user = get_user_by( 'ID', $user_id );
parent::__construct(
'post_lock',
sprintf(
/* translators: %s: User display name. */
esc_html__( '%s is currently editing this template, please try again later', 'elementor-pro' ),
$user->display_name
),
[
'status' => 403,
'locked_by_user_id' => $user_id,
'locked_by_user_name' => $user->display_name,
]
);
}
}