dvadf
File manager - Edit - /home/centroca/public_html/mcp.tar
Back
module.php 0000644 00000006145 15252526357 0006564 0 ustar 00 <?php namespace Elementor\Modules\Mcp; use Elementor\Core\Base\Module as BaseModule; use Elementor\Plugin; use Elementor\Core\Experiments\Manager as ExperimentsManager; use WP\MCP\Core\McpAdapter; if ( ! defined( 'ABSPATH' ) ) { exit; } class Module extends BaseModule { const EXPERIMENT_NAME = 'e_wp_abilities_api'; public function get_name() { return 'mcp'; } public static function is_active() { return class_exists( McpAdapter::class ) && function_exists( 'wp_register_ability' ) && Plugin::instance()->experiments->is_feature_active( self::EXPERIMENT_NAME ); } public static function get_experimental_data() { return [ 'name' => self::EXPERIMENT_NAME, 'title' => __( 'Elementor MCP WP Abilities API', 'elementor' ), 'description' => __( 'Enable Elementor MCP WP Abilities API. Requirements: 1. WordPress 7.0 or higher. 2. Create an application password for your agent user. 3. Add to your MCP config: {url: "https://<your-site-url>/wp-json/elementor/mcp", headers: {Authorization: "Basic <base64(user:application-password)>"}}', 'elementor' ), 'hidden' => true, 'default' => ExperimentsManager::STATE_INACTIVE, ]; } public function __construct() { parent::__construct(); if ( ! $this->is_active() ) { return; } McpAdapter::instance(); add_action( 'wp_abilities_api_categories_init', [ $this, 'register_ability_category' ] ); add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] ); add_action( 'mcp_adapter_init', [ $this, 'register_server' ] ); } public function register_ability_category() { if ( ! function_exists( 'wp_register_ability_category' ) ) { return; } wp_register_ability_category( 'elementor', [ 'label' => __( 'Elementor', 'elementor' ), 'description' => __( 'Elementor page builder data, global classes, and variables.', 'elementor' ), ] ); } public function register_abilities() { if ( ! function_exists( 'wp_register_ability' ) ) { return; } ( new Abilities\List_Pages_Ability() )->register(); ( new Abilities\Get_Structure_Ability() )->register(); ( new Abilities\Update_Settings_Ability() )->register(); ( new Abilities\Create_Page_Ability() )->register(); ( new Abilities\Get_Globals_Ability() )->register(); } public function register_server( $adapter ) { if ( ! $adapter instanceof McpAdapter ) { return; } $result = $adapter->create_server( 'elementor-mcp-server', 'elementor', 'mcp', 'Elementor MCP', 'Read and modify Elementor Editor abilities.', 'v1.0.0', [ \WP\MCP\Transport\HttpTransport::class ], \WP\MCP\Infrastructure\ErrorHandling\ErrorLogMcpErrorHandler::class, \WP\MCP\Infrastructure\Observability\NullMcpObservabilityHandler::class, [ 'elementor/list-pages', 'elementor/get-page-structure', 'elementor/update-page-settings', 'elementor/create-page', 'elementor/get-globals', ], [], [] ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( sprintf( '[Elementor MCP] Server registration failed: %s', $result->get_error_message() ) ); return; } } } abilities/get-globals-ability.php 0000644 00000004204 15252526357 0013071 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; use Elementor\Modules\GlobalClasses\Global_Classes_Repository; use Elementor\Modules\Variables\Services\Batch_Operations\Batch_Processor; use Elementor\Modules\Variables\Services\Variables_Service; use Elementor\Modules\Variables\Storage\Variables_Repository; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; } class Get_Globals_Ability extends Abstract_Ability { protected function get_ability_id(): string { return 'elementor/get-globals'; } protected function get_definition(): Ability_Definition { return new Ability_Definition( __( 'Get Elementor Globals', 'elementor' ), __( 'Returns site-wide Elementor design data: global classes (shared CSS classes from the kit) and variables (design tokens such as colors and fonts tied to the active kit). Use when you need kit-level styling context, not a single page tree.', 'elementor' ), 'elementor', [ 'type' => 'object', 'properties' => [ 'global_classes' => [ 'type' => 'object', 'description' => 'Global class definitions and order from the active kit.', ], 'variables' => [ 'type' => 'object', 'description' => 'Variables list, total count, and watermark from the active kit.', ], ], ], [ 'annotations' => [ 'readonly' => true, 'idempotent' => true, 'destructive' => false, ], ], function () { return current_user_can( 'edit_posts' ); } // No input_schema — this ability takes no input. ); } public function execute( $input = [] ) { $kit = Plugin::$instance->kits_manager->get_active_kit(); $classes_payload = Global_Classes_Repository::make( $kit )->all()->get(); $variables_service = new Variables_Service( new Variables_Repository( $kit ), new Batch_Processor() ); $variables_payload = $variables_service->load(); return [ 'global_classes' => $classes_payload, 'variables' => [ 'variables' => $variables_payload['data'] ?? [], 'total' => isset( $variables_payload['data'] ) ? count( $variables_payload['data'] ) : 0, 'watermark' => $variables_payload['watermark'] ?? null, ], ]; } } abilities/create-page-ability.php 0000644 00000006742 15252526357 0013057 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; } class Create_Page_Ability extends Abstract_Ability { protected function get_ability_id(): string { return 'elementor/create-page'; } protected function get_definition(): Ability_Definition { return new Ability_Definition( __( 'Create Elementor Page', 'elementor' ), __( 'Creates a new draft post or page and marks it as built with Elementor (blank canvas in the editor). Use when the user wants a new layout shell to design in Elementor. Returns the new post ID and edit URL.', 'elementor' ), 'elementor', [ 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'integer' ], 'edit_url' => [ 'type' => 'string' ], 'status' => [ 'type' => 'string' ], 'type' => [ 'type' => 'string' ], ], ], [ 'annotations' => [ 'readonly' => false, 'idempotent' => false, 'destructive' => false, ], ], function () { return current_user_can( 'edit_posts' ); }, [ 'type' => 'object', 'properties' => [ 'title' => [ 'type' => 'string', 'description' => 'Optional title for the new post.', ], 'post_type' => [ 'type' => 'string', 'description' => 'Post type slug; must support Elementor. Defaults to page.', 'default' => 'page', ], ], ] ); } public function execute( $input = [] ) { $input = is_array( $input ) ? $input : []; $post_type = ! empty( $input['post_type'] ) ? sanitize_key( $input['post_type'] ) : 'page'; $type_error = $this->validate_post_type( $post_type ); if ( $type_error ) { return $type_error; } $permission_error = $this->check_create_permission( $post_type ); if ( $permission_error ) { return $permission_error; } $title = isset( $input['title'] ) && is_string( $input['title'] ) ? $input['title'] : ''; return $this->create_post( $post_type, $title ); } private function validate_post_type( string $post_type ): ?\WP_Error { if ( ! post_type_exists( $post_type ) || ! post_type_supports( $post_type, 'elementor' ) ) { return new \WP_Error( 'invalid_post_type', __( 'This post type does not support Elementor.', 'elementor' ), [ 'status' => \WP_Http::BAD_REQUEST ] ); } return null; } private function check_create_permission( string $post_type ): ?\WP_Error { $post_type_object = get_post_type_object( $post_type ); if ( ! $post_type_object || ! current_user_can( $post_type_object->cap->create_posts ) ) { return new \WP_Error( 'rest_cannot_create', __( 'Sorry, you are not allowed to create posts of this type.', 'elementor' ), [ 'status' => \WP_Http::FORBIDDEN ] ); } return null; } private function create_post( string $post_type, string $title ) { $post_id = wp_insert_post( [ 'post_title' => $title ? $title : __( 'Elementor Draft', 'elementor' ), 'post_status' => 'draft', 'post_type' => $post_type, ], true ); if ( is_wp_error( $post_id ) ) { return $post_id; } $document = Plugin::$instance->documents->get( $post_id ); if ( ! $document ) { return new \WP_Error( 'document_not_found', __( 'Document could not be loaded.', 'elementor' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] ); } $document->set_is_built_with_elementor( true ); return [ 'id' => (int) $post_id, 'edit_url' => $document->get_edit_url(), 'status' => get_post_status( $post_id ), 'type' => $post_type, ]; } } abilities/update-settings-ability.php 0000644 00000005470 15252526357 0014017 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; } class Update_Settings_Ability extends Abstract_Ability { protected function get_ability_id(): string { return 'elementor/update-page-settings'; } protected function get_definition(): Ability_Definition { return new Ability_Definition( __( 'Update Elementor Page Settings', 'elementor' ), __( 'Updates Elementor document-level settings for a post (for example page layout, title visibility, or custom page settings). Pass only the keys you want to change. Use list-pages to resolve IDs and get-page-structure when you also need the element tree. Requires permission to edit the target post.', 'elementor' ), 'elementor', [ 'type' => 'object', 'properties' => [ 'success' => [ 'type' => 'boolean' ], 'post_id' => [ 'type' => 'integer' ], ], ], [ 'annotations' => [ 'readonly' => false, 'idempotent' => false, 'destructive' => false, ], ], function () { return current_user_can( 'edit_posts' ); }, [ 'type' => 'object', 'required' => [ 'post_id', 'settings' ], 'properties' => [ 'post_id' => [ 'type' => 'integer', 'description' => 'WordPress post ID of the Elementor document.', ], 'settings' => [ 'type' => 'object', 'description' => 'Partial document settings object; merged into existing settings. Schema enforcement is delegated to document->save().', 'additionalProperties' => true, ], ], ] ); } public function execute( $input = [] ) { $post_id = isset( $input['post_id'] ) ? absint( $input['post_id'] ) : 0; $settings = isset( $input['settings'] ) && is_array( $input['settings'] ) ? $input['settings'] : null; if ( ! $post_id ) { return new \WP_Error( 'invalid_post_id', __( 'A valid post_id is required.', 'elementor' ), [ 'status' => \WP_Http::BAD_REQUEST ] ); } if ( null === $settings ) { return new \WP_Error( 'invalid_settings', __( 'The settings object is required.', 'elementor' ), [ 'status' => \WP_Http::BAD_REQUEST ] ); } $document = Plugin::$instance->documents->get( $post_id ); if ( ! $document ) { return new \WP_Error( 'document_not_found', __( 'Document not found.', 'elementor' ), [ 'status' => \WP_Http::NOT_FOUND ] ); } if ( ! $document->is_editable_by_current_user() ) { return new \WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this document.', 'elementor' ), [ 'status' => \WP_Http::FORBIDDEN ] ); } $saved = $document->save( [ 'settings' => $settings ] ); if ( ! $saved ) { return new \WP_Error( 'save_failed', __( 'Could not save document settings.', 'elementor' ), [ 'status' => \WP_Http::INTERNAL_SERVER_ERROR ] ); } return [ 'success' => true, 'post_id' => $post_id, ]; } } abilities/get-structure-ability.php 0000644 00000005746 15252526357 0013522 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; use Elementor\Plugin; if ( ! defined( 'ABSPATH' ) ) { exit; } class Get_Structure_Ability extends Abstract_Ability { protected function get_ability_id(): string { return 'elementor/get-page-structure'; } protected function get_definition(): Ability_Definition { return new Ability_Definition( __( 'Get Elementor Page Structure', 'elementor' ), __( 'Returns the Elementor element tree (widgets, containers, and nested content) for a single post or page ID. Use after list-pages when you need the live JSON structure to reason about layout, widget types, or to plan edits. Only works for posts that were saved with Elementor.', 'elementor' ), 'elementor', [ 'type' => 'object', 'properties' => [ 'elements' => [ 'type' => 'array', 'description' => 'Root-level Elementor elements for the document.', ], ], ], [ 'annotations' => [ 'readonly' => true, 'idempotent' => true, 'destructive' => false, ], ], function () { return current_user_can( 'edit_posts' ); }, [ 'type' => 'object', 'required' => [ 'post_id' ], 'properties' => [ 'post_id' => [ 'type' => 'integer', 'description' => 'WordPress post ID of the Elementor document.', ], ], ] ); } public function execute( $input = [] ) { $post_id = $this->resolve_post_id( $input ); if ( is_wp_error( $post_id ) ) { return $post_id; } $document = $this->get_editable_document( $post_id ); if ( is_wp_error( $document ) ) { return $document; } $elements = $document->get_elements_data(); return [ 'elements' => is_array( $elements ) ? $elements : [], ]; } private function resolve_post_id( $input ) { $post_id = isset( $input['post_id'] ) ? absint( $input['post_id'] ) : 0; if ( ! $post_id ) { return new \WP_Error( 'invalid_post_id', __( 'A valid post_id is required.', 'elementor' ), [ 'status' => \WP_Http::BAD_REQUEST ] ); } if ( ! current_user_can( 'edit_post', $post_id ) ) { return new \WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to access this document.', 'elementor' ), [ 'status' => \WP_Http::FORBIDDEN ] ); } return $post_id; } private function get_editable_document( int $post_id ) { $document = Plugin::$instance->documents->get( $post_id ); if ( ! $document ) { return new \WP_Error( 'document_not_found', __( 'Document not found.', 'elementor' ), [ 'status' => \WP_Http::NOT_FOUND ] ); } if ( ! $document->is_built_with_elementor() ) { return new \WP_Error( 'not_elementor', __( 'This post is not built with Elementor.', 'elementor' ), [ 'status' => \WP_Http::BAD_REQUEST ] ); } if ( ! $document->is_editable_by_current_user() ) { return new \WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to edit this document.', 'elementor' ), [ 'status' => \WP_Http::FORBIDDEN ] ); } return $document; } } abilities/abstract-ability.php 0000644 00000001006 15252526357 0012471 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; if ( ! defined( 'ABSPATH' ) ) { exit; } abstract class Abstract_Ability { abstract protected function get_ability_id(): string; abstract protected function get_definition(): Ability_Definition; abstract public function execute( $input = [] ); public function register(): void { $definition = $this->get_definition()->to_array(); $definition['execute_callback'] = [ $this, 'execute' ]; wp_register_ability( $this->get_ability_id(), $definition ); } } abilities/ability-definition.php 0000644 00000002253 15252526357 0013023 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; if ( ! defined( 'ABSPATH' ) ) { exit; } class Ability_Definition { public string $label; public string $description; public string $category; public array $output_schema; public array $meta; /** @var callable */ public $permission_callback; public array $input_schema; public function __construct( string $label, string $description, string $category, array $output_schema, array $meta, callable $permission_callback, array $input_schema = [] ) { $this->label = $label; $this->description = $description; $this->category = $category; $this->output_schema = $output_schema; $this->meta = $meta; $this->permission_callback = $permission_callback; $this->input_schema = $input_schema; } public function to_array(): array { $definition = [ 'label' => $this->label, 'description' => $this->description, 'category' => $this->category, 'output_schema' => $this->output_schema, 'meta' => $this->meta, 'permission_callback' => $this->permission_callback, ]; if ( ! empty( $this->input_schema ) ) { $definition['input_schema'] = $this->input_schema; } return $definition; } } abilities/list-pages-ability.php 0000644 00000004715 15252526357 0012750 0 ustar 00 <?php namespace Elementor\Modules\Mcp\Abilities; if ( ! defined( 'ABSPATH' ) ) { exit; } class List_Pages_Ability extends Abstract_Ability { protected function get_ability_id(): string { return 'elementor/list-pages'; } protected function get_definition(): Ability_Definition { return new Ability_Definition( __( 'List Elementor Pages', 'elementor' ), __( 'Returns pages and posts built with Elementor on this WordPress site. Each item includes ID, title, status (publish/draft), URL, and post type. Use this first to discover which pages exist before fetching their structure or modifying settings.', 'elementor' ), 'elementor', [ 'type' => 'array', 'items' => [ 'type' => 'object', 'properties' => [ 'id' => [ 'type' => 'integer' ], 'title' => [ 'type' => 'string' ], 'status' => [ 'type' => 'string' ], 'url' => [ 'type' => 'string' ], 'type' => [ 'type' => 'string' ], ], ], ], [ 'annotations' => [ 'readonly' => true, 'idempotent' => true, 'destructive' => false, ], ], function () { return current_user_can( 'edit_posts' ); }, [ 'type' => 'object', 'properties' => [ 'status' => [ 'type' => 'string', 'enum' => [ 'publish', 'draft', 'any' ], 'default' => 'any', ], 'post_type' => [ 'type' => 'string', 'description' => 'Filter by post type. Omit for all Elementor-supported types.', ], ], ] ); } public function execute( $input = [] ) { $input = is_array( $input ) ? $input : []; $args = [ 'post_type' => get_post_types_by_support( 'elementor' ), 'meta_key' => '_elementor_edit_mode', 'meta_value' => 'builder', 'post_status' => isset( $input['status'] ) ? $input['status'] : 'any', 'fields' => 'ids', 'posts_per_page' => -1, 'orderby' => 'date', 'order' => 'DESC', 'suppress_filters' => false, ]; if ( ! empty( $input['post_type'] ) ) { $args['post_type'] = sanitize_key( $input['post_type'] ); } $ids = get_posts( $args ); $ids = array_values( array_filter( array_map( 'absint', $ids ), function ( $id ) { return $id && current_user_can( 'edit_post', $id ); } ) ); return array_map( function ( $id ) { return [ 'id' => $id, 'title' => get_the_title( $id ), 'status' => get_post_status( $id ), 'url' => (string) get_permalink( $id ), 'type' => get_post_type( $id ), ]; }, $ids ); } }
dvadf
dvadf
| ver. 1.4 |
Github
|
.
| PHP 7.3.33 | Generation time: 0 |
proxy
|
phpinfo
|
Settings