__('AI to Elementor', 'aitoel-html-importer'), 'description' => __('Import existing HTML as native Elementor templates.', 'aitoel-html-importer'), )); } public static function register() { if (!self::enabled() || !self::available() || wp_has_ability(self::ABILITY)) { return; } wp_register_ability(self::ABILITY, array( 'label' => __('Convert HTML to an Elementor template', 'aitoel-html-importer'), 'description' => __('Converts a complete HTML page, its CSS included, into a native, editable Elementor template in one call and saves it in this site\'s Elementor template library. Use it whenever the page already exists as HTML, instead of rebuilding it element by element. Pass the full HTML document, or the public URL of the page. Returns the template\'s id and its edit URL; the template can then be inserted into any page from the Elementor library. Each call counts as one conversion of the site\'s AI to Elementor allowance.', 'aitoel-html-importer'), 'category' => self::CATEGORY, 'input_schema' => array( 'type' => 'object', 'properties' => array( 'html' => array( 'type' => 'string', 'description' => 'The full HTML document, CSS included, or the public URL of the page.', ), 'title' => array( 'type' => 'string', 'description' => 'A title for the saved template. Defaults to "Imported Page".', ), 'intent' => array( 'type' => 'string', 'enum' => array('header', 'footer'), 'description' => 'Set only when the HTML is a site header or a site footer rather than a page.', ), ), 'required' => array('html'), ), 'output_schema' => array( 'type' => 'object', 'properties' => array( 'template_id' => array('type' => 'integer', 'description' => 'The saved template\'s post id.'), 'edit_url' => array('type' => 'string', 'description' => 'Opens the template in the Elementor editor.'), 'library_url' => array('type' => 'string', 'description' => 'The site\'s Elementor template library.'), 'element_count' => array('type' => 'integer', 'description' => 'Elementor elements in the template.'), 'message' => array('type' => 'string'), ), ), 'permission_callback' => array(__CLASS__, 'may_convert'), 'execute_callback' => array('HTEL_Converter', 'ability_convert'), 'meta' => array( 'show_in_rest' => true, 'mcp' => array('public' => true), 'annotations' => array('readonly' => false, 'idempotent' => false, 'destructive' => false), ), )); } /** * The capability the plugin's own page and its Convert button ask for. The conversion then asks for * the right to save unfiltered HTML and says so when it is missing, which a refusal here could not. */ public static function may_convert() { return current_user_can('edit_posts'); } /** * Elementor builds its MCP server from a list of ability slugs and passes that list through this * filter for other plugins to add to. * * @param mixed $tools The slugs so far. * @return array */ public static function list_on_elementor_server($tools) { $tools = is_array($tools) ? $tools : array(); if (self::enabled() && !in_array(self::ABILITY, $tools, true)) { $tools[] = self::ABILITY; } return $tools; } }