diff --git a/.gitignore b/.gitignore index 7416429..819c247 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ + diff --git a/README.md b/README.md index 3429300..146499b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
diff --git a/assets-wporg/banner-1544x500.png b/assets-wporg/banner-1544x500.png new file mode 100644 index 0000000..b517c07 Binary files /dev/null and b/assets-wporg/banner-1544x500.png differ diff --git a/assets-wporg/banner-772x250.png b/assets-wporg/banner-772x250.png new file mode 100644 index 0000000..114ff76 Binary files /dev/null and b/assets-wporg/banner-772x250.png differ diff --git a/assets-wporg/icon-128x128.png b/assets-wporg/icon-128x128.png new file mode 100644 index 0000000..8e8916a Binary files /dev/null and b/assets-wporg/icon-128x128.png differ diff --git a/assets-wporg/icon-256x256.png b/assets-wporg/icon-256x256.png new file mode 100644 index 0000000..e4aad73 Binary files /dev/null and b/assets-wporg/icon-256x256.png differ diff --git a/assets-wporg/icon.svg b/assets-wporg/icon.svg new file mode 100644 index 0000000..b781b16 --- /dev/null +++ b/assets-wporg/icon.svg @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/assets-wporg/screenshot-1.png b/assets-wporg/screenshot-1.png new file mode 100644 index 0000000..73fbd7d Binary files /dev/null and b/assets-wporg/screenshot-1.png differ diff --git a/assets-wporg/screenshot-2.png b/assets-wporg/screenshot-2.png new file mode 100644 index 0000000..35bb9da Binary files /dev/null and b/assets-wporg/screenshot-2.png differ diff --git a/bin/build-wporg-zip.sh b/bin/build-wporg-zip.sh new file mode 100755 index 0000000..75686bd --- /dev/null +++ b/bin/build-wporg-zip.sh @@ -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 "==========================================================================" diff --git a/emcp-tools.php b/emcp-tools.php index 4fd28b6..a8145e9 100644 --- a/emcp-tools.php +++ b/emcp-tools.php @@ -1,6 +1,6 @@ '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' ) ); } diff --git a/includes/class-bootstrap.php b/includes/class-bootstrap.php index 10ce552..fb0e360 100644 --- a/includes/class-bootstrap.php +++ b/includes/class-bootstrap.php @@ -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(); + } } /** diff --git a/readme.txt b/readme.txt index 59c9df5..d6e8c01 100644 --- a/readme.txt +++ b/readme.txt @@ -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. +