build(wporg): standardize manifest, generate assets, and add release packager for WordPress.org
@@ -105,3 +105,7 @@ freemius.env
|
||||
# exploits for released versions, so they must never reach the public repo.
|
||||
SECURITY-REMEDIATION-*.md
|
||||
PRODUCTION-SECURITY-HANDOVER-*.md
|
||||
|
||||
# Release distribution builds
|
||||
dist/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<h1 align="center">
|
||||
<img src="assets/img/icon-sm.png" width="80" alt="Heretek Control Core logo"><br>
|
||||
MCP Tools for Elementor & WordPress (Pro)
|
||||
MCP Tools for Elementor & WordPress
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
|
||||
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="256" height="256">
|
||||
<rect width="256" height="256" rx="44" fill="#0f172a" stroke="#dc2626" stroke-width="4"/>
|
||||
<circle cx="128" cy="128" r="70" fill="none" stroke="#dc2626" stroke-width="6" opacity="0.8"/>
|
||||
<text x="128" y="142" font-family="DejaVu Sans, Arial, sans-serif" font-size="42" font-weight="bold" fill="#ffffff" text-anchor="middle">EMCP</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# build-wporg-zip.sh
|
||||
# Packages a 100% compliant release ZIP for the WordPress.org Plugin Directory.
|
||||
#
|
||||
# Excludes development artifacts, git metadata, tests, third-party updaters,
|
||||
# and legacy commercial SDKs per WordPress.org Guidelines 1, 5, 8, and 17.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PLUGIN_SLUG="mcp-tools-for-elementor"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
DIST_DIR="${ROOT_DIR}/dist"
|
||||
STAGE_DIR="${DIST_DIR}/staging/${PLUGIN_SLUG}"
|
||||
ZIP_PATH="${DIST_DIR}/${PLUGIN_SLUG}.zip"
|
||||
|
||||
echo "=== [1/5] Validating PHP Syntax ==="
|
||||
cd "${ROOT_DIR}"
|
||||
find . -maxdepth 4 -name "*.php" \
|
||||
! -path "./vendor/*" \
|
||||
! -path "./dist/*" \
|
||||
! -path "./tests/*" \
|
||||
! -path "./includes/vendors/*" \
|
||||
-exec php -l {} + > /dev/null
|
||||
echo "✓ PHP syntax validation passed."
|
||||
|
||||
echo "=== [2/5] Running Automated Test Suite ==="
|
||||
for t in tests/test-*.php; do
|
||||
php "$t" > /dev/null || { echo "Test failed: $t"; exit 1; }
|
||||
done
|
||||
echo "✓ All test suites passed 100%."
|
||||
|
||||
echo "=== [3/5] Staging WordPress.org Production Files ==="
|
||||
rm -rf "${DIST_DIR}"
|
||||
mkdir -p "${STAGE_DIR}"
|
||||
|
||||
# Copy all production files to staging
|
||||
rsync -a --delete \
|
||||
--exclude='.git*' \
|
||||
--exclude='.github' \
|
||||
--exclude='.agents' \
|
||||
--exclude='review' \
|
||||
--exclude='tests' \
|
||||
--exclude='dist' \
|
||||
--exclude='bin' \
|
||||
--exclude='assets-wporg' \
|
||||
--exclude='sonar-project.properties' \
|
||||
--exclude='CLAUDE.md' \
|
||||
--exclude='.emcp-pro' \
|
||||
--exclude='.DS_Store' \
|
||||
--exclude='Thumbs.db' \
|
||||
--exclude='includes/class-github-updater.php' \
|
||||
--exclude='includes/vendors/fremius' \
|
||||
"${ROOT_DIR}/" "${STAGE_DIR}/"
|
||||
|
||||
echo "✓ Staged files to ${STAGE_DIR}"
|
||||
|
||||
echo "=== [4/5] Building Release Archive: ${ZIP_PATH} ==="
|
||||
cd "${DIST_DIR}/staging"
|
||||
zip -q -r "${ZIP_PATH}" "${PLUGIN_SLUG}"
|
||||
|
||||
echo "=== [5/5] Pre-Flight Archive Inspection ==="
|
||||
if [ ! -f "${ZIP_PATH}" ]; then
|
||||
echo "ERROR: Archive was not created!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ZIP_SIZE=$(stat -c%s "${ZIP_PATH}" 2>/dev/null || stat -f%z "${ZIP_PATH}")
|
||||
FILE_COUNT=$(unzip -l "${ZIP_PATH}" | tail -n 1 | awk '{print $2}')
|
||||
|
||||
echo "Archive: ${ZIP_PATH}"
|
||||
echo "Size: $(awk "BEGIN {printf \"%.2f MB\", ${ZIP_SIZE}/1048576}") (${ZIP_SIZE} bytes)"
|
||||
echo "Total files: ${FILE_COUNT}"
|
||||
|
||||
# Compliance checks on the archive
|
||||
echo "Verifying guideline compliance inside zip..."
|
||||
|
||||
# Check 1: Plugin headers exist
|
||||
unzip -l "${ZIP_PATH}" | grep -q "${PLUGIN_SLUG}/emcp-tools.php" || { echo "ERROR: Main plugin file missing!"; exit 1; }
|
||||
unzip -l "${ZIP_PATH}" | grep -q "${PLUGIN_SLUG}/readme.txt" || { echo "ERROR: readme.txt missing!"; exit 1; }
|
||||
|
||||
# Check 2: No GitHub updater (Guideline 8)
|
||||
if unzip -l "${ZIP_PATH}" | grep -q "class-github-updater.php"; then
|
||||
echo "ERROR: class-github-updater.php found in archive (violates Guideline 8)!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check 3: No Freemius SDK (Guideline 5)
|
||||
if unzip -l "${ZIP_PATH}" | grep -q "vendors/fremius"; then
|
||||
echo "ERROR: Freemius SDK found in archive (violates Guideline 5)!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check 4: No git metadata
|
||||
if unzip -l "${ZIP_PATH}" | grep -q "\.git"; then
|
||||
echo "ERROR: Git metadata found in archive!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Guideline compliance checks PASSED!"
|
||||
echo ""
|
||||
echo "=========================================================================="
|
||||
echo " SUCCESS: ${ZIP_PATH} is ready for submission to:"
|
||||
echo " https://wordpress.org/plugins/developers/add/"
|
||||
echo "=========================================================================="
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: MCP Tools for Elementor & WordPress (Pro)
|
||||
* Plugin Name: MCP Tools for Elementor & WordPress
|
||||
* Plugin URI: https://github.com/Heretek-AI/heretek-control-core
|
||||
* Description: Professional Model Context Protocol (MCP) server connecting WordPress, Elementor & Gutenberg to AI assistants (Claude, Cursor, ChatGPT, Antigravity).
|
||||
* Version: 3.16.1
|
||||
@@ -176,99 +176,108 @@ require_once EMCP_TOOLS_DIR . 'includes/class-mcp-adapter-bootstrap.php';
|
||||
EMCP_Tools_Adapter_Bootstrap::preload_bundled_namespace();
|
||||
|
||||
if ( ! function_exists( 'emcp_tools_fs' ) ) {
|
||||
// Create a helper function for easy SDK access.
|
||||
function emcp_tools_fs() {
|
||||
global $emcp_tools_fs;
|
||||
if ( file_exists( dirname( __FILE__ ) . '/includes/vendors/fremius/start.php' ) && ! defined( 'EMCP_WPORG_BUILD' ) ) {
|
||||
// Create a helper function for easy SDK access.
|
||||
function emcp_tools_fs() {
|
||||
global $emcp_tools_fs;
|
||||
|
||||
if ( ! isset( $emcp_tools_fs ) ) {
|
||||
// Activate multisite network integration.
|
||||
if ( ! defined( 'WP_FS__PRODUCT_30577_MULTISITE' ) ) {
|
||||
define( 'WP_FS__PRODUCT_30577_MULTISITE', true );
|
||||
if ( ! isset( $emcp_tools_fs ) ) {
|
||||
// Activate multisite network integration.
|
||||
if ( ! defined( 'WP_FS__PRODUCT_30577_MULTISITE' ) ) {
|
||||
define( 'WP_FS__PRODUCT_30577_MULTISITE', true );
|
||||
}
|
||||
|
||||
// Include Freemius SDK.
|
||||
require_once dirname( __FILE__ ) . '/includes/vendors/fremius/start.php';
|
||||
|
||||
$emcp_tools_is_premium = file_exists( dirname( __FILE__ ) . '/.emcp-pro' );
|
||||
|
||||
$emcp_tools_fs = fs_dynamic_init( array(
|
||||
'id' => '30577',
|
||||
'slug' => 'emcp-tools',
|
||||
'premium_slug' => 'emcp-pro',
|
||||
'type' => 'plugin',
|
||||
'public_key' => 'pk_2b2a026d5c27655581635abcd4556',
|
||||
'is_premium' => $emcp_tools_is_premium,
|
||||
'premium_suffix' => 'Pro',
|
||||
'has_premium_version' => false,
|
||||
'has_addons' => false,
|
||||
'has_paid_plans' => false,
|
||||
'is_org_compliant' => false,
|
||||
'has_affiliation' => false,
|
||||
'menu' => array(
|
||||
'slug' => 'emcp-tools',
|
||||
'support' => false,
|
||||
),
|
||||
) );
|
||||
}
|
||||
|
||||
// Include Freemius SDK.
|
||||
require_once dirname( __FILE__ ) . '/includes/vendors/fremius/start.php';
|
||||
|
||||
// The premium build ships a `.emcp-pro` marker file at the plugin
|
||||
// root; the free build does not. Freemius needs is_premium=true on
|
||||
// the premium build so it shows the LICENSE-ACTIVATION flow (gated
|
||||
// on is_premium()) instead of the free connect/opt-in screen. With
|
||||
// it hardcoded false, the premium zip behaved like the free version
|
||||
// and never offered license activation.
|
||||
$emcp_tools_is_premium = file_exists( dirname( __FILE__ ) . '/.emcp-pro' );
|
||||
|
||||
$emcp_tools_fs = fs_dynamic_init( array(
|
||||
'id' => '30577',
|
||||
'slug' => 'emcp-tools',
|
||||
'premium_slug' => 'emcp-pro',
|
||||
'type' => 'plugin',
|
||||
'public_key' => 'pk_2b2a026d5c27655581635abcd4556',
|
||||
'is_premium' => $emcp_tools_is_premium,
|
||||
'premium_suffix' => 'Pro',
|
||||
'has_premium_version' => false,
|
||||
'has_addons' => false,
|
||||
'has_paid_plans' => false,
|
||||
'is_org_compliant' => false,
|
||||
'has_affiliation' => false,
|
||||
'menu' => array(
|
||||
'slug' => 'emcp-tools',
|
||||
'support' => false,
|
||||
),
|
||||
) );
|
||||
return $emcp_tools_fs;
|
||||
}
|
||||
|
||||
return $emcp_tools_fs;
|
||||
}
|
||||
// Init Freemius.
|
||||
emcp_tools_fs();
|
||||
// Signal that SDK was initiated.
|
||||
do_action( 'emcp_tools_fs_loaded' );
|
||||
|
||||
// Init Freemius.
|
||||
emcp_tools_fs();
|
||||
// Signal that SDK was initiated.
|
||||
do_action( 'emcp_tools_fs_loaded' );
|
||||
|
||||
// Disarm any stale Freemius upsells cached in the WordPress update_plugins transient.
|
||||
if ( is_admin() ) {
|
||||
add_action(
|
||||
'admin_init',
|
||||
static function () {
|
||||
$updates = get_site_transient( 'update_plugins' );
|
||||
if ( is_object( $updates ) && isset( $updates->response[ EMCP_TOOLS_BASENAME ] ) ) {
|
||||
$entry = $updates->response[ EMCP_TOOLS_BASENAME ];
|
||||
// If the update package is empty or points to Freemius checkout/license purchase, purge it
|
||||
if ( empty( $entry->package ) || ( isset( $entry->url ) && false !== strpos( $entry->url, 'freemius' ) ) ) {
|
||||
unset( $updates->response[ EMCP_TOOLS_BASENAME ] );
|
||||
set_site_transient( 'update_plugins', $updates );
|
||||
// Disarm any stale Freemius upsells cached in the WordPress update_plugins transient.
|
||||
if ( is_admin() ) {
|
||||
add_action(
|
||||
'admin_init',
|
||||
static function () {
|
||||
$updates = get_site_transient( 'update_plugins' );
|
||||
if ( is_object( $updates ) && isset( $updates->response[ EMCP_TOOLS_BASENAME ] ) ) {
|
||||
$entry = $updates->response[ EMCP_TOOLS_BASENAME ];
|
||||
if ( empty( $entry->package ) || ( isset( $entry->url ) && false !== strpos( $entry->url, 'freemius' ) ) ) {
|
||||
unset( $updates->response[ EMCP_TOOLS_BASENAME ] );
|
||||
set_site_transient( 'update_plugins', $updates );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
5
|
||||
);
|
||||
}
|
||||
},
|
||||
5
|
||||
);
|
||||
}
|
||||
|
||||
// Trim the Freemius-injected submenu items we surface elsewhere: Contact Us
|
||||
// (Help & Support lives in the plugin header), Affiliation (shown in the
|
||||
// header next to Changelog), and Pricing for licensed Pro users (free users
|
||||
// keep the upgrade link). Freemius keeps the underlying pages reachable by
|
||||
// URL, so the header links still work.
|
||||
emcp_tools_fs()->add_filter(
|
||||
'is_submenu_visible',
|
||||
function ( $is_visible, $menu_id ) {
|
||||
if ( 'contact' === $menu_id || 'affiliation' === $menu_id ) {
|
||||
return false;
|
||||
emcp_tools_fs()->add_filter(
|
||||
'is_submenu_visible',
|
||||
function ( $is_visible, $menu_id ) {
|
||||
if ( 'contact' === $menu_id || 'affiliation' === $menu_id ) {
|
||||
return false;
|
||||
}
|
||||
if ( 'pricing' === $menu_id && emcp_tools_fs()->can_use_premium_code() ) {
|
||||
return false;
|
||||
}
|
||||
return $is_visible;
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
} else {
|
||||
// Zero-dependency unlocked stub for official WordPress.org distribution.
|
||||
function emcp_tools_fs() {
|
||||
static $emcp_fs_stub = null;
|
||||
if ( null === $emcp_fs_stub ) {
|
||||
$emcp_fs_stub = new class {
|
||||
public function can_use_premium_code(): bool { return true; }
|
||||
public function is_premium(): bool { return true; }
|
||||
public function is_plan(): bool { return true; }
|
||||
public function has_features(): bool { return true; }
|
||||
public function add_filter( $hook, $callback, $priority = 10, $accepted_args = 1 ): void {}
|
||||
public function add_action( $hook, $callback, $priority = 10, $accepted_args = 1 ): void {}
|
||||
public function _get_license() { return (object) array( 'secret_key' => 'unlocked' ); }
|
||||
public function get_upgrade_url(): string { return 'https://github.com/Heretek-AI/heretek-control-core'; }
|
||||
};
|
||||
}
|
||||
if ( 'pricing' === $menu_id && emcp_tools_fs()->can_use_premium_code() ) {
|
||||
return false;
|
||||
}
|
||||
return $is_visible;
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
return $emcp_fs_stub;
|
||||
}
|
||||
|
||||
do_action( 'emcp_tools_fs_loaded' );
|
||||
}
|
||||
}
|
||||
|
||||
// Uninstall cleanup runs via Freemius's after_uninstall action (uninstall.php
|
||||
// was removed in v1.6.1 — Freemius rejects builds containing it).
|
||||
// Uninstall cleanup runs via Freemius's after_uninstall action or WordPress uninstaller.
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-uninstaller.php';
|
||||
if ( function_exists( 'emcp_tools_fs' ) ) {
|
||||
if ( function_exists( 'emcp_tools_fs' ) && method_exists( emcp_tools_fs(), 'add_action' ) ) {
|
||||
emcp_tools_fs()->add_action( 'after_uninstall', array( 'EMCP_Tools_Uninstaller', 'run' ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,9 @@ class EMCP_Tools_Bootstrap {
|
||||
require_once EMCP_TOOLS_DIR . 'includes/redirects/class-redirect-handler.php';
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-content-mirror.php';
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-admin-bar.php';
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-github-updater.php';
|
||||
if ( file_exists( EMCP_TOOLS_DIR . 'includes/class-github-updater.php' ) && ! defined( 'EMCP_WPORG_BUILD' ) ) {
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-github-updater.php';
|
||||
}
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-notifications.php';
|
||||
require_once EMCP_TOOLS_DIR . 'includes/class-nav-menu-shortcode.php';
|
||||
// Editor-side auto-repair for AI-inserted static-save blocks (Kadence).
|
||||
@@ -494,9 +496,10 @@ class EMCP_Tools_Bootstrap {
|
||||
// self-gates on capability + is_admin_bar_showing()).
|
||||
( new EMCP_Tools_Admin_Bar() )->init();
|
||||
|
||||
// Free-tier updates from GitHub releases (self-disables on premium builds,
|
||||
// where Freemius owns updates).
|
||||
( new EMCP_Tools_GitHub_Updater() )->init();
|
||||
// Free-tier updates from GitHub releases (self-disables on WordPress.org builds).
|
||||
if ( class_exists( 'EMCP_Tools_GitHub_Updater' ) && ! defined( 'EMCP_WPORG_BUILD' ) ) {
|
||||
( new EMCP_Tools_GitHub_Updater() )->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
=== MCP Tools for Elementor & WordPress (Pro) ===
|
||||
=== MCP Tools for Elementor & WordPress ===
|
||||
Contributors: Heretek-AI, mianshahzadraza
|
||||
Tags: elementor, mcp, ai, gutenberg, claude
|
||||
Requires at least: 6.9
|
||||
@@ -177,6 +177,11 @@ On shared LiteSpeed hosting (e.g. Hostinger) this is usually the host caching/bu
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 3.16.1 =
|
||||
* Added: Native Ad Monetization & ExoClick MCP engine (emcp-tools/ads-read and ads-write) with automated zone provisioning, WP Quads dual-write synchronization, ads.txt validation, and cache invalidation.
|
||||
* Changed: Standardized all administrative navigation, dashboard cards, views, and documentation to official professional WordPress and AI terminology.
|
||||
* Fixed: AI Chat settings card layout resets to prevent form table vertical stretching under admin forms.
|
||||
|
||||
= 3.16.0 =
|
||||
Backup, Restore & Migrate become real: honest .emcp archives, a working restore path, a site-wide serialized-safe URL search-replace, and a genuine HMAC connector for migrate-site push.
|
||||
* Added: the Backup & Migrate tab can now Restore an archive (manifest-hash verified), Download it, or Delete it (admin-only, nonce + capability-gated), with a restore-history panel.
|
||||
@@ -777,3 +782,9 @@ The first major release of the rebranded EMCP Tools, a step beyond Elementor int
|
||||
* 1 composite build-page tool.
|
||||
* Admin settings page with tool toggles and connection info.
|
||||
* Node.js HTTP proxy for remote connections.
|
||||
|
||||
== Upgrade Notice ==
|
||||
|
||||
= 3.16.1 =
|
||||
Adds full Ad Monetization tools, professional interface terminology, and layout stability fixes.
|
||||
|
||||
|
||||