Files
heretek-control-core/includes/admin/views/page-tools.php
T
Mian Shahzad Raza 0ce420601b style(copy): remove em dashes from plugin copy, fix mcpb display name
Sweeps shipped copy clean of em dashes: readme.txt, README.md,
CHANGELOG.md, the bundled sample prompts, and user-facing PHP strings
(tool descriptions, admin labels). PHP was swept on non-comment lines
only, so developer docblocks and inline comments are untouched.
Internal dev docs (CLAUDE.md, docs/) were deliberately left alone.

Replacements are contextual: colons for label/definition patterns,
commas for asides, en dashes for numeric ranges.

The .mcpb bundle display_name now reads "EMCP Tools - <host>" with a
plain hyphen; its test is updated to match. Fixing CHANGELOG.md also
clears the em dashes from the website's generated changelog on the
next site build, since that file is its source.

Verified: php -l clean on every touched file, pro suite 1559 pass,
public suite 102 pass. Bumps the pro submodule for the Pro-side sweep.
2026-07-21 08:03:19 +05:00

414 lines
20 KiB
PHP

<?php
/**
* Tools tab view for the MCP Tools for Elementor admin settings page.
*
* Displays all MCP tools grouped by category with toggle switches.
*
* @package EMCP_Tools
* @since 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** @var EMCP_Tools_Admin $this */
$emcp_tools_all_tools = $this->get_all_tools();
$emcp_tools_disabled = get_option( EMCP_Tools_Admin::OPTION_DISABLED_TOOLS, array() );
$emcp_tools_disabled = is_array( $emcp_tools_disabled ) ? $emcp_tools_disabled : array();
$emcp_tools_enabled_count = $this->get_enabled_tool_count();
$emcp_tools_total_count = $this->get_total_tool_count();
$emcp_tools_compact_mode = '1' === (string) get_option( EMCP_Tools_Plugin::OPTION_DISPATCHER_MODE, '0' );
$emcp_tools_tabs = EMCP_Tools_Admin::platform_tabs();
$emcp_tools_buckets = EMCP_Tools_Admin::partition_by_platform( $emcp_tools_all_tools );
$emcp_tools_elementor_active = EMCP_Tools_Bootstrap::elementor_active();
// Whether this build can run Pro code. Pro tool sections stay visible on free
// (as an upsell) but locked; get_all_tools() already flags their tools.
$emcp_tools_is_pro = function_exists( 'emcp_tools_fs' ) && emcp_tools_fs()->can_use_premium_code();
$emcp_tools_upgrade_url = function_exists( 'emcp_tools_upgrade_url' ) ? emcp_tools_upgrade_url() : 'https://emcptools.com/pricing/';
/**
* Per-tab enabled/total counts, computed from the stored disabled set.
*/
$emcp_tools_tab_counts = array();
foreach ( $emcp_tools_buckets as $emcp_tools_tab_id => $emcp_tools_tab_cats ) {
$emcp_tools_t_total = 0;
$emcp_tools_t_enabled = 0;
foreach ( $emcp_tools_tab_cats as $emcp_tools_cat ) {
foreach ( $emcp_tools_cat['tools'] as $emcp_tools_s => $emcp_tools_unused ) {
$emcp_tools_t_total++;
if ( ! in_array( $emcp_tools_s, $emcp_tools_disabled, true ) ) {
$emcp_tools_t_enabled++;
}
}
}
$emcp_tools_tab_counts[ $emcp_tools_tab_id ] = array( 'enabled' => $emcp_tools_t_enabled, 'total' => $emcp_tools_t_total );
}
// Human-readable labels for badge slugs. "pro" means the EMCP Tools Pro
// license; "elementor-pro" means the tool needs Elementor Pro (a different
// product) — kept visually distinct so the two aren't confused.
$emcp_tools_badge_labels = array(
'pro' => __( 'Pro', 'emcp-tools' ),
'elementor-pro' => __( 'Elementor Pro', 'emcp-tools' ),
'read-only' => __( 'read-only', 'emcp-tools' ),
'free' => __( 'Free', 'emcp-tools' ),
'destructive' => __( 'destructive', 'emcp-tools' ),
);
?>
<form method="post" action="options.php" id="elementor-mcp-tools-form">
<?php settings_fields( EMCP_Tools_Admin::SETTINGS_GROUP ); ?>
<div class="elementor-mcp-mode-cards">
<div class="elementor-mcp-low-mode-card">
<label class="elementor-mcp-low-mode-toggle">
<input type="hidden" name="<?php echo esc_attr( EMCP_Tools_Plugin::OPTION_DISPATCHER_MODE ); ?>" value="0" />
<input
type="checkbox"
name="<?php echo esc_attr( EMCP_Tools_Plugin::OPTION_DISPATCHER_MODE ); ?>"
value="1"
<?php checked( $emcp_tools_compact_mode ); ?>
/>
<span class="elementor-mcp-toggle" aria-hidden="true">
<span class="elementor-mcp-toggle-track"></span>
</span>
<span class="elementor-mcp-low-mode-info">
<span class="elementor-mcp-low-mode-title">
<?php esc_html_e( 'Compact tool mode', 'emcp-tools' ); ?>
</span>
<span class="elementor-mcp-low-mode-desc">
<?php esc_html_e( 'Exposes 3 dispatcher tools (list-tools, get-tool-schema, call-tool) instead of every individual tool, so MCP clients that cap the tool count can still reach the whole surface. Your per-tool toggles below stay in effect, call-tool refuses any tool you disable. Reconnect your client after changing this.', 'emcp-tools' ); ?>
</span>
</span>
</label>
</div>
<?php if ( class_exists( 'EMCP_Tools_Themer_Module' ) && EMCP_Tools_Themer_Module::is_enabled() ) : ?>
<?php $emcp_tools_themer_php_on = '1' === (string) get_option( EMCP_Tools_Themer_PHP::OPTION_ENABLED, '0' ); ?>
<div class="elementor-mcp-low-mode-card">
<label class="elementor-mcp-low-mode-toggle">
<input type="hidden" name="<?php echo esc_attr( EMCP_Tools_Themer_PHP::OPTION_ENABLED ); ?>" value="0" />
<input
type="checkbox"
name="<?php echo esc_attr( EMCP_Tools_Themer_PHP::OPTION_ENABLED ); ?>"
value="1"
<?php checked( $emcp_tools_themer_php_on ); ?>
/>
<span class="elementor-mcp-toggle" aria-hidden="true">
<span class="elementor-mcp-toggle-track"></span>
</span>
<span class="elementor-mcp-low-mode-info">
<span class="elementor-mcp-low-mode-title">
<?php esc_html_e( 'Themer PHP Templates (advanced)', 'emcp-tools' ); ?>
</span>
<span class="elementor-mcp-low-mode-desc">
<?php esc_html_e( 'Lets AI agents author raw PHP region templates (header/footer/single/archive) into a validated sandbox, which you then select on a template to take over its render. Off by default, enabling it also reveals the “PHP Templates” screen under the EMCP Themer menu and the per-template selector. The 5 MCP tools below still ship disabled until you enable them.', 'emcp-tools' ); ?>
</span>
</span>
</label>
</div>
<?php endif; ?>
</div><!-- .elementor-mcp-mode-cards -->
<?php if ( $emcp_tools_compact_mode ) : ?>
<div class="elementor-mcp-compact-banner">
<p>
<?php esc_html_e( 'Compact tool mode is active, your client sees only the 3 dispatcher tools (list-tools, get-tool-schema, call-tool). The per-tool toggles below still control what call-tool is allowed to run.', 'emcp-tools' ); ?>
</p>
</div>
<?php endif; ?>
<div class="elementor-mcp-bulk-actions">
<p class="elementor-mcp-tools-summary">
<?php
printf(
/* translators: %1$s: opening strong tag, %2$d: enabled count, %3$d: total count, %4$s: closing strong tag */
esc_html__( '%1$s%2$d of %3$d%4$s tools enabled.', 'emcp-tools' ),
'<strong>',
(int) $emcp_tools_enabled_count,
(int) $emcp_tools_total_count,
'</strong>'
);
?>
</p>
<button type="button" class="button elementor-mcp-enable-all"><?php esc_html_e( 'Enable All', 'emcp-tools' ); ?></button>
<button type="button" class="button elementor-mcp-disable-all"><?php esc_html_e( 'Disable All', 'emcp-tools' ); ?></button>
<button type="submit" class="button button-primary elementor-mcp-bulk-save"><?php esc_html_e( 'Save Changes', 'emcp-tools' ); ?></button>
</div>
<div class="elementor-mcp-subtabs" role="tablist" aria-label="<?php esc_attr_e( 'Tool platforms', 'emcp-tools' ); ?>">
<?php $emcp_tools_first = true; ?>
<?php foreach ( $emcp_tools_tabs as $emcp_tools_tab_id => $emcp_tools_tab_label ) : ?>
<button
type="button"
class="elementor-mcp-subtab <?php echo esc_attr( $emcp_tools_first ? 'is-active' : '' ); ?>"
role="tab"
data-tab="<?php echo esc_attr( $emcp_tools_tab_id ); ?>"
aria-selected="<?php echo esc_attr( $emcp_tools_first ? 'true' : 'false' ); ?>"
aria-controls="emcp-tabpanel-<?php echo esc_attr( $emcp_tools_tab_id ); ?>"
>
<span class="elementor-mcp-subtab-label"><?php echo esc_html( $emcp_tools_tab_label ); ?></span>
<span class="elementor-mcp-subtab-count">
<?php
printf(
/* translators: %1$d: enabled, %2$d: total */
esc_html__( '%1$d / %2$d', 'emcp-tools' ),
(int) $emcp_tools_tab_counts[ $emcp_tools_tab_id ]['enabled'],
(int) $emcp_tools_tab_counts[ $emcp_tools_tab_id ]['total']
);
?>
</span>
</button>
<?php $emcp_tools_first = false; ?>
<?php endforeach; ?>
</div>
<?php $emcp_tools_first_panel = true; ?>
<?php foreach ( $emcp_tools_buckets as $emcp_tools_tab_id => $emcp_tools_tab_cats ) : ?>
<div
class="elementor-mcp-tabpanel <?php echo esc_attr( $emcp_tools_first_panel ? 'is-active' : '' ); ?>"
id="emcp-tabpanel-<?php echo esc_attr( $emcp_tools_tab_id ); ?>"
role="tabpanel"
data-tab="<?php echo esc_attr( $emcp_tools_tab_id ); ?>"
>
<?php if ( 'elementor' === $emcp_tools_tab_id && ! $emcp_tools_elementor_active ) : ?>
<div class="notice notice-warning inline elementor-mcp-elementor-inactive">
<p>
<?php esc_html_e( 'Elementor is not active. Install and activate Elementor to use these tools.', 'emcp-tools' ); ?>
<a href="<?php echo esc_url( self_admin_url( 'plugin-install.php?s=Elementor&tab=search&type=term' ) ); ?>">
<?php esc_html_e( 'Install Elementor', 'emcp-tools' ); ?>
</a>
</p>
</div>
<?php endif; ?>
<?php
// Plugin-integration explainer: rendered once at the very top of the
// tab, above every category section. The note text lives on the
// category data (first category that carries one wins).
$emcp_tools_tab_note = '';
foreach ( $emcp_tools_tab_cats as $emcp_tools_note_cat ) {
if ( ! empty( $emcp_tools_note_cat['note'] ) ) {
$emcp_tools_tab_note = (string) $emcp_tools_note_cat['note'];
break;
}
}
?>
<?php if ( '' !== $emcp_tools_tab_note ) : ?>
<p class="elementor-mcp-cat-note elementor-mcp-tab-note">
<span class="elementor-mcp-cat-note-icon" aria-hidden="true">
<svg viewBox="0 0 20 20" width="15" height="15"><path fill="currentColor" d="M10 2a8 8 0 100 16 8 8 0 000-16zm1 12H9v-4h2v4zm0-6H9V6h2v2z"/></svg>
</span>
<span><?php echo esc_html( $emcp_tools_tab_note ); ?></span>
</p>
<?php endif; ?>
<?php
// Render one category (the "plugin card"): header + toggle grid.
// Defined once and reused for both ungrouped categories (inline) and
// grouped ones (nested under a group heading on the Plugins tab).
$emcp_tools_render_category = function ( $emcp_tools_category_id, $emcp_tools_category ) use ( $emcp_tools_disabled, $emcp_tools_elementor_active, $emcp_tools_badge_labels, $emcp_tools_is_pro, $emcp_tools_upgrade_url ) {
?>
<div class="elementor-mcp-category <?php echo esc_attr( ! empty( $emcp_tools_category['danger'] ) ? 'is-danger' : '' ); ?>" data-category="<?php echo esc_attr( $emcp_tools_category_id ); ?>">
<?php
$emcp_tools_cat_total = count( $emcp_tools_category['tools'] );
$emcp_tools_cat_enabled = 0;
foreach ( $emcp_tools_category['tools'] as $emcp_tools_slug => $emcp_tools_tool ) {
if ( ! in_array( $emcp_tools_slug, $emcp_tools_disabled, true ) ) {
$emcp_tools_cat_enabled++;
}
}
$emcp_tools_grid_id = 'emcp-cat-' . $emcp_tools_category_id;
$emcp_tools_cat_unavailable = ( ! $emcp_tools_elementor_active && EMCP_Tools_Admin::is_elementor_category( $emcp_tools_category ) );
?>
<div class="elementor-mcp-category-header">
<button
type="button"
class="elementor-mcp-category-toggle"
aria-expanded="true"
aria-controls="<?php echo esc_attr( $emcp_tools_grid_id ); ?>"
>
<span class="elementor-mcp-category-chevron" aria-hidden="true">
<svg viewBox="0 0 20 20" width="14" height="14"><path d="M6 8l4 4 4-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
<span class="elementor-mcp-category-title"><?php echo esc_html( $emcp_tools_category['label'] ); ?></span>
<?php if ( ! empty( $emcp_tools_category['pro'] ) ) : ?>
<span class="elementor-mcp-badge elementor-mcp-badge--pro"><?php esc_html_e( 'Pro', 'emcp-tools' ); ?></span>
<?php endif; ?>
<span class="elementor-mcp-category-count">
<?php
printf(
/* translators: %1$d: enabled, %2$d: total */
esc_html__( '%1$d / %2$d', 'emcp-tools' ),
(int) $emcp_tools_cat_enabled,
(int) $emcp_tools_cat_total
);
?>
</span>
</button>
<?php if ( ! empty( $emcp_tools_category['pro'] ) && ! $emcp_tools_is_pro ) : ?>
<a class="elementor-mcp-cat-upgrade" href="<?php echo esc_url( $emcp_tools_upgrade_url ); ?>" target="_blank" rel="noopener noreferrer">
<span class="dashicons dashicons-star-filled" aria-hidden="true"></span>
<?php esc_html_e( 'Requires EMCP Pro, Upgrade', 'emcp-tools' ); ?>
</a>
<?php endif; ?>
<?php if ( empty( $emcp_tools_category['pro'] ) || $emcp_tools_is_pro ) : ?>
<span class="elementor-mcp-cat-toggle-group" role="group" aria-label="<?php esc_attr_e( 'Toggle all tools in this section', 'emcp-tools' ); ?>">
<button type="button" class="elementor-mcp-cat-btn elementor-mcp-cat-enable-all"><?php esc_html_e( 'All', 'emcp-tools' ); ?></button>
<button type="button" class="elementor-mcp-cat-btn elementor-mcp-cat-disable-all"><?php esc_html_e( 'None', 'emcp-tools' ); ?></button>
</span>
<?php endif; ?>
</div>
<?php
// Dispatcher-style categories (plugin integrations) lay their
// cards out two-up with operation pills; the explanatory note
// is rendered once at the top of the tab (see above).
$emcp_tools_first_tool = reset( $emcp_tools_category['tools'] );
$emcp_tools_has_ops = ! empty( $emcp_tools_first_tool['operations'] );
?>
<?php
// Section-level notice (e.g. the Astra + Spectra heads-up about
// Spectra's File Generation setting). Only rendered when the category
// carries one, so it appears only when actionable.
if ( ! empty( $emcp_tools_category['notice'] ) && ! empty( $emcp_tools_category['notice']['message'] ) ) :
$emcp_tools_notice_type = $emcp_tools_category['notice']['type'] ?? 'info';
?>
<div class="elementor-mcp-cat-notice is-<?php echo esc_attr( $emcp_tools_notice_type ); ?>">
<span class="elementor-mcp-cat-notice-icon" aria-hidden="true">
<svg viewBox="0 0 20 20" width="16" height="16"><path fill="currentColor" d="M10 1.6a8.4 8.4 0 100 16.8 8.4 8.4 0 000-16.8zM11 14H9v-2h2v2zm0-4H9V5h2v5z"/></svg>
</span>
<span><?php echo esc_html( $emcp_tools_category['notice']['message'] ); ?></span>
</div>
<?php endif; ?>
<div class="elementor-mcp-tools-grid <?php echo esc_attr( $emcp_tools_has_ops ? 'is-two-up' : '' ); ?>" id="<?php echo esc_attr( $emcp_tools_grid_id ); ?>">
<?php foreach ( $emcp_tools_category['tools'] as $emcp_tools_slug => $emcp_tools_tool ) : ?>
<?php
$emcp_tools_is_enabled = ! in_array( $emcp_tools_slug, $emcp_tools_disabled, true );
// A tool is unavailable when its whole platform is off (Elementor
// inactive) OR the tool carries an explicit availability flag that
// is false (e.g. the Astra tools when Astra is not the active
// theme, the Spectra tools when the Spectra plugin is inactive).
$emcp_tools_tool_unavailable = $emcp_tools_cat_unavailable
|| ( array_key_exists( 'available', $emcp_tools_tool ) && ! $emcp_tools_tool['available'] );
?>
<label class="elementor-mcp-tool-card <?php echo esc_attr( ( $emcp_tools_is_enabled ? 'is-enabled' : 'is-disabled' ) . ( $emcp_tools_tool_unavailable ? ' is-unavailable' : '' ) ); ?>">
<input
type="checkbox"
name="<?php echo esc_attr( EMCP_Tools_Admin::OPTION_DISABLED_TOOLS ); ?>[]"
value="<?php echo esc_attr( $emcp_tools_slug ); ?>"
data-stored-enabled="<?php echo esc_attr( in_array( $emcp_tools_slug, $emcp_tools_disabled, true ) ? '0' : '1' ); ?>"
<?php checked( $emcp_tools_is_enabled ); ?>
<?php disabled( $emcp_tools_tool_unavailable ); ?>
/>
<span class="elementor-mcp-toggle" aria-hidden="true">
<span class="elementor-mcp-toggle-track"></span>
</span>
<span class="elementor-mcp-tool-info">
<span class="elementor-mcp-tool-name">
<?php echo esc_html( $emcp_tools_tool['label'] ); ?>
<?php foreach ( $emcp_tools_tool['badges'] as $emcp_tools_badge ) : ?>
<span class="elementor-mcp-badge elementor-mcp-badge--<?php echo esc_attr( $emcp_tools_badge ); ?>">
<?php echo esc_html( $emcp_tools_badge_labels[ $emcp_tools_badge ] ?? $emcp_tools_badge ); ?>
</span>
<?php endforeach; ?>
</span>
<span class="elementor-mcp-tool-desc"><?php echo esc_html( $emcp_tools_tool['description'] ); ?></span>
<?php if ( $emcp_tools_tool_unavailable && ! empty( $emcp_tools_tool['unavailable_note'] ) ) : ?>
<span class="elementor-mcp-tool-unavailable-note"><?php echo esc_html( $emcp_tools_tool['unavailable_note'] ); ?></span>
<?php endif; ?>
<?php if ( ! empty( $emcp_tools_tool['operations'] ) ) : ?>
<span class="elementor-mcp-tool-ops">
<span class="elementor-mcp-tool-ops-label">
<?php
printf(
/* translators: %d: number of operations */
esc_html( _n( '%d operation', '%d operations', count( $emcp_tools_tool['operations'] ), 'emcp-tools' ) ),
count( $emcp_tools_tool['operations'] )
);
?>
</span>
<span class="elementor-mcp-op-pills">
<?php foreach ( $emcp_tools_tool['operations'] as $emcp_tools_op ) : ?>
<span class="elementor-mcp-op-pill"><?php echo esc_html( $emcp_tools_op ); ?></span>
<?php endforeach; ?>
</span>
</span>
<?php endif; ?>
<code class="elementor-mcp-tool-slug"><?php echo esc_html( $emcp_tools_slug ); ?></code>
</span>
</label>
<?php endforeach; ?>
</div>
</div>
<?php
};
// Partition this tab's categories into plugin groups. Categories that
// carry a 'group' key (the Plugins-tab integrations) cluster under a
// group heading; everything else renders inline, ungrouped.
$emcp_tools_group_defs = EMCP_Tools_Admin::plugin_groups();
$emcp_tools_grouped = array();
$emcp_tools_ungrouped = array();
foreach ( $emcp_tools_tab_cats as $emcp_tools_cid => $emcp_tools_cat ) {
if ( ! empty( $emcp_tools_cat['group'] ) && isset( $emcp_tools_group_defs[ $emcp_tools_cat['group'] ] ) ) {
$emcp_tools_grouped[ $emcp_tools_cat['group'] ][ $emcp_tools_cid ] = $emcp_tools_cat;
} else {
$emcp_tools_ungrouped[ $emcp_tools_cid ] = $emcp_tools_cat;
}
}
// Ungrouped categories first (unchanged layout for non-Plugins tabs).
foreach ( $emcp_tools_ungrouped as $emcp_tools_category_id => $emcp_tools_category ) {
$emcp_tools_render_category( $emcp_tools_category_id, $emcp_tools_category );
}
// Then each non-empty group, in registry order.
foreach ( $emcp_tools_group_defs as $emcp_tools_gid => $emcp_tools_gdef ) :
if ( empty( $emcp_tools_grouped[ $emcp_tools_gid ] ) ) {
continue;
}
$emcp_tools_g_total = 0;
$emcp_tools_g_enabled = 0;
foreach ( $emcp_tools_grouped[ $emcp_tools_gid ] as $emcp_tools_gcat ) {
foreach ( $emcp_tools_gcat['tools'] as $emcp_tools_gslug => $emcp_tools_gunused ) {
$emcp_tools_g_total++;
if ( ! in_array( $emcp_tools_gslug, $emcp_tools_disabled, true ) ) {
$emcp_tools_g_enabled++;
}
}
}
?>
<div class="elementor-mcp-plugin-group" data-group="<?php echo esc_attr( $emcp_tools_gid ); ?>">
<div class="elementor-mcp-plugin-group-head">
<span class="elementor-mcp-plugin-group-title"><?php echo esc_html( $emcp_tools_gdef['label'] ); ?></span>
<?php if ( ! empty( $emcp_tools_gdef['desc'] ) ) : ?>
<span class="elementor-mcp-plugin-group-desc"><?php echo esc_html( $emcp_tools_gdef['desc'] ); ?></span>
<?php endif; ?>
<span class="elementor-mcp-plugin-group-count">
<?php
printf(
/* translators: %1$d: enabled, %2$d: total */
esc_html__( '%1$d / %2$d', 'emcp-tools' ),
(int) $emcp_tools_g_enabled,
(int) $emcp_tools_g_total
);
?>
</span>
</div>
<div class="elementor-mcp-plugin-group-body">
<?php
foreach ( $emcp_tools_grouped[ $emcp_tools_gid ] as $emcp_tools_category_id => $emcp_tools_category ) {
$emcp_tools_render_category( $emcp_tools_category_id, $emcp_tools_category );
}
?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php $emcp_tools_first_panel = false; ?>
<?php endforeach; ?>
<?php submit_button( __( 'Save Changes', 'emcp-tools' ) ); ?>
</form>