403Webshell
Server IP : 121.121.20.254  /  Your IP : 216.73.217.141
Web Server : Microsoft-IIS/10.0
System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64
User : IUSR ( 0)
PHP Version : 8.3.28
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  C:/inetpub/wwwroot/AIWEBSTATION/wp-content/plugins/novamira-pro/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : C:/inetpub/wwwroot/AIWEBSTATION/wp-content/plugins/novamira-pro/includes/gates.php
<?php

// includes/gates.php — plugin-scope gate helpers relocated out of each spec's runtime.php.
// SPDX-FileCopyrightText: 2026 Ovation S.r.l. <dev@novamira.ai>
// SPDX-License-Identifier: AGPL-3.0-or-later

declare(strict_types=1);

namespace Novamira\Pro {
    if (!defined('ABSPATH')) {
        exit();
    }

    // gate helpers pasted here per migration task (each keeps its original sub-namespace block).

    /**
     * Whether Etch is active AND meets the minimum supported version.
     *
     * Etch ships no version constant, so this reads the version back from the
     * plugin header via \Etch\Plugin::get_plugin_version() (which self-includes
     * wp-admin/includes/plugin.php when needed). The class_exists guard keeps the
     * static call safe, so the category registrar and the ability loader can gate
     * on this without first loading the Etch helpers file.
     */
    function novamira_pro_etch_available(): bool
    {
        return (
            defined('ETCH_PLUGIN_FILE')
            && class_exists('Etch\\Plugin')
            && version_compare(\Etch\Plugin::get_plugin_version(), NOVAMIRA_PRO_ETCH_MIN_VERSION, operator: '>=')
        );
    }

    /**
     * Whether the Divi 5 (D5) block-based builder and its module API are available.
     * Divi 4 (shortcode) content is out of scope: the abilities operate on the
     * divi/* WordPress-block module model. Kept at global plugin scope so both the
     * category registrar and the ability loader can gate on it without loading
     * the Divi helpers file.
     */
    function novamira_pro_divi_available(): bool
    {
        return (
            defined('ET_BUILDER_VERSION')
            && version_compare((string) constant('ET_BUILDER_VERSION'), NOVAMIRA_PRO_DIVI_MIN_VERSION, operator: '>=')
            && function_exists('et_builder_d5_enabled')
            && et_builder_d5_enabled()
            && class_exists('ET\Builder\Packages\ModuleLibrary\ModuleRegistration')
        );
    }
}

namespace Novamira\Pro\Abilities\Breakdance {
    /**
     * Breakdance is active at or above the minimum supported release. The
     * version check uses the `__BREAKDANCE_VERSION` constant defined in
     * `breakdance/plugin.php`; the function sentinel ensures the
     * `data/api/options.php` helpers are loaded (any ability that reads
     * settings goes through those).
     *
     * Mutually exclusive with the Oxygen specialization: Soflyy ships
     * Oxygen 6.x as the same codebase in `BREAKDANCE_MODE=oxygen`, so
     * both integrations would otherwise register against the same runtime.
     * When the plugin identifies itself as Oxygen, this gate returns
     * false and `oxygen_plugin_available()` takes over — the two never
     * co-register.
     */
    function bd_plugin_available(): bool
    {
        if (defined('BREAKDANCE_MODE') && constant('BREAKDANCE_MODE') === 'oxygen') {
            return false;
        }
        return (
            defined('__BREAKDANCE_VERSION')
            && function_exists('Breakdance\\Data\\get_global_option')
            && version_compare(
                (string) constant('__BREAKDANCE_VERSION'),
                NOVAMIRA_PRO_BREAKDANCE_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\Oxygen {
    /**
     * Oxygen 6.x is active at or above the minimum supported release. Oxygen 6
     * is the Soflyy unified codebase running in `BREAKDANCE_MODE=oxygen`: it
     * shares the `Breakdance\Data\*` namespace and the `__BREAKDANCE_VERSION`
     * constant with standalone Breakdance, but the PERSISTED identifiers are
     * mode-specific — in Oxygen mode the canvas postmeta is `_oxygen_data`,
     * template settings are `_oxygen_template_settings`, template CPTs are
     * `oxygen_*`, and global options are prefixed `oxygen_`. The abilities
     * resolve these through the engine's own mode-aware Data API. The
     * `BREAKDANCE_MODE` check distinguishes the two brands and
     * makes this gate mutually exclusive with `bd_plugin_available()` — so an
     * Oxygen site never triggers the Breakdance loader and vice versa. Oxygen
     * Classic 4.x/5.x (shortcode-based, `_ct_builder_shortcodes` storage) is
     * explicitly out of scope: the version_compare against 6.0.0 blocks it.
     */
    function oxygen_plugin_available(): bool
    {
        if (!defined('BREAKDANCE_MODE') || constant('BREAKDANCE_MODE') !== 'oxygen') {
            return false;
        }
        return (
            defined('__BREAKDANCE_VERSION')
            && function_exists('Breakdance\\Data\\get_global_option')
            && version_compare(
                (string) constant('__BREAKDANCE_VERSION'),
                NOVAMIRA_PRO_OXYGEN_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\BeaverBuilder {
    /**
     * Whether Beaver Builder's plugin runtime has loaded.
     */
    function bb_plugin_active(): bool
    {
        return defined('FL_BUILDER_VERSION') && class_exists('FLBuilder') && class_exists('FLBuilderModel');
    }

    /**
     * Beaver Builder plugin version, or empty string when inactive.
     */
    function bb_version(): string
    {
        return defined('FL_BUILDER_VERSION') ? (string) constant('FL_BUILDER_VERSION') : '';
    }

    /**
     * Whether Beaver Builder is installed, active, and at the supported runtime floor.
     */
    function bb_runtime_available(): bool
    {
        return bb_plugin_active()
        && version_compare(bb_version(), NOVAMIRA_PRO_BEAVER_BUILDER_MIN_VERSION, operator: '>=');
    }
}

namespace Novamira\Pro\Abilities\Bricksforge {
    /**
     * Whether the Bricksforge plugin runtime has loaded. Bricksforge bails out
     * before defining any constant unless the Bricks theme (or a Bricks child
     * theme) is active, so this check implies Bricks is the active theme.
     */
    function brf_plugin_active(): bool
    {
        return defined('BRICKSFORGE_VERSION');
    }

    /**
     * Bricksforge plugin version, or empty string when inactive.
     */
    function brf_version(): string
    {
        return defined('BRICKSFORGE_VERSION') ? (string) constant('BRICKSFORGE_VERSION') : '';
    }

    /**
     * Whether Bricksforge is installed, active, and at the supported runtime floor.
     */
    function brf_runtime_available(): bool
    {
        return brf_plugin_active()
        && version_compare(brf_version(), NOVAMIRA_PRO_BRICKSFORGE_MIN_VERSION, operator: '>=');
    }
}

namespace Novamira\Pro\Abilities\WPBakery {
    /**
     * Whether WPBakery Page Builder is installed, active, and at or above the
     * minimum supported version.
     *
     * Requires WPBMap (the registry class) and a version constant that meets
     * NOVAMIRA_PRO_WPBAKERY_MIN_VERSION. WPBMap::$is_init is not checked here
     * because it is set during the `init` action — after `wp_abilities_api_init`
     * fires.
     */
    function wpb_runtime_available(): bool
    {
        return (
            class_exists('WPBMap')
            && defined('WPB_VC_VERSION')
            && version_compare((string) constant('WPB_VC_VERSION'), NOVAMIRA_PRO_WPBAKERY_MIN_VERSION, operator: '>=')
        );
    }
}

namespace Novamira\Pro\Abilities\Woocommerce {
    /**
     * WooCommerce is present and at or above the minimum supported version.
     *
     * The cache is keyed by blog_id to avoid cross-blog leaks in multisite
     * environments where different blogs may have different WC versions active.
     */
    function wc_min_runtime_available(): bool
    {
        /** @var array<int, bool> $cache */
        static $cache = [];
        $blog_id = get_current_blog_id();
        if (isset($cache[$blog_id])) {
            return $cache[$blog_id];
        }
        $result =
            class_exists('WooCommerce')
            && defined('WC_VERSION')
            && version_compare((string) constant('WC_VERSION'), NOVAMIRA_PRO_WOOCOMMERCE_MIN_VERSION, operator: '>=');
        $cache[$blog_id] = $result;
        return $result;
    }
}

namespace Novamira\Pro\Abilities\Formidable {
    /**
     * Whether Formidable Forms is loaded at ALL (any version). Used to gate
     * registration of `check-setup` + the category itself, so an agent on an
     * install with an under-min Formidable still sees the discovery surface
     * and can report "upgrade Formidable" instead of silently missing the
     * integration. Every other ability registration uses `frm_runtime_available()`,
     * which additionally enforces the minimum version.
     */
    function frm_plugin_present(): bool
    {
        if (!class_exists('\FrmAppHelper') || !method_exists('\FrmAppHelper', 'plugin_version')) {
            return false;
        }
        // Multisite defensive check (audit round 1, probe #8): Formidable's
        // classes are process-global. Once Site A loads them, a subsequent
        // `switch_to_blog($B)` keeps `class_exists('\FrmAppHelper')` true even
        // if Site B does NOT have Formidable activated. Cross-blog detection
        // therefore requires an explicit per-blog plugin-active check.
        if (function_exists('is_multisite') && is_multisite()) {
            if (!function_exists('is_plugin_active')) {
                require_once ABSPATH . 'wp-admin/includes/plugin.php';
            }
            if (!is_plugin_active('formidable/formidable.php')) {
                return false;
            }
        }
        return true;
    }
}

namespace Novamira\Pro\Abilities\Mosaic {
    /**
     * Verify the core `<prefix>mosaic_*` tables exist. Mosaic creates the
     * full set of ~21 tables lazily on first admin pageview through its
     * `MosaicSchemaManager`; a freshly installed-but-never-loaded site (or
     * a partial-restore from backup) can leave the plugin "active" with
     * constants defined but tables missing. We probe the 6 tables every
     * Sprint 1/2 ability reads from — if any one is missing the schema
     * bootstrap hasn't completed.
     */
    function mo_tables_present(): bool
    {
        global $wpdb;
        /** @var \wpdb $wpdb */
        $required = ['themes', 'templates', 'components', 'collections', 'collection_variables', 'utility_classes'];
        foreach ($required as $entity) {
            $name = $wpdb->prefix . 'mosaic_' . $entity;
            /** @var mixed $found */
            // @mago-expect analysis:possibly-invalid-argument
            $found = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $name));
            if (!is_string($found) || $found !== $name) {
                return false;
            }
        }
        return true;
    }

    /**
     * Mosaic is active at or above the minimum supported release AND the
     * custom schema is installed. The version check uses the
     * `MOSAIC_VERSION` constant; the class sentinel ensures the autoloader
     * has registered the Mosaic namespace; the table check verifies the
     * schema bootstrap has created the core `<prefix>mosaic_*` tables
     * (Mosaic creates them lazily on first admin pageview, so a freshly
     * installed-but-never-loaded site would fail this check).
     */
    function mo_runtime_available(): bool
    {
        if (!defined('MOSAIC_VERSION')) {
            return false;
        }
        $version = (string) constant('MOSAIC_VERSION');
        if (!version_compare($version, NOVAMIRA_PRO_MOSAIC_MIN_VERSION, operator: '>=')) {
            return false;
        }
        if (!version_compare($version, NOVAMIRA_PRO_MOSAIC_MAX_VERSION, operator: '<')) {
            return false;
        }
        if (!class_exists('Mosaic\\Database\\MosaicDB')) {
            return false;
        }
        return mo_tables_present();
    }
}

namespace Novamira\Pro\Abilities\Pods {
    /**
     * Base Pods surface required by every ability in this category.
     */
    function pods_min_runtime_available(): bool
    {
        return (
            defined('PODS_VERSION')
            && version_compare(pods_version(), version2: NOVAMIRA_PRO_PODS_MIN_VERSION, operator: '>=')
            && function_exists('pods_api')
        );
    }

    /**
     * Reads the live Pods version constant in a static-analyzer-friendly way.
     */
    function pods_version(): string
    {
        return defined('PODS_VERSION') ? (string) constant('PODS_VERSION') : '0.0.0';
    }
}

namespace Novamira\Pro\Abilities\Metabox {
    /**
     * Meta Box core is present and at or above the minimum supported version.
     */
    function mb_min_runtime_available(): bool
    {
        /** @var bool|null $cache */
        static $cache = null;
        if ($cache !== null) {
            return $cache;
        }
        return (
            defined('RWMB_VER')
            && class_exists('RW_Meta_Box')
            && version_compare((string) constant('RWMB_VER'), NOVAMIRA_PRO_METABOX_MIN_VERSION, operator: '>=')
        );
    }
}

namespace Novamira\Pro\Abilities\Acpt {
    /**
     * ACPT core is present and at or above the minimum supported version.
     */
    function acpt_min_runtime_available(): bool
    {
        /** @var bool|null $cache */
        static $cache = null;
        if ($cache !== null) {
            return $cache;
        }
        return (
            defined('ACPT_PLUGIN_VERSION')
            && class_exists('ACPT\\Includes\\ACPT_Plugin')
            && version_compare((string) constant('ACPT_PLUGIN_VERSION'), NOVAMIRA_PRO_ACPT_MIN_VERSION, operator: '>=')
        );
    }
}

namespace Novamira\Pro\Abilities\GeneratePress {
    /**
     * The free GeneratePress theme is active and at or above the minimum
     * supported release. Combines the constant + a sentinel public function
     * (`generate_get_option`) so older releases that lack the API shape we
     * call into are excluded — defined() alone isn't enough.
     */
    function gp_theme_available(): bool
    {
        return (
            defined('GENERATE_VERSION')
            && function_exists('generate_get_option')
            && version_compare((string) constant('GENERATE_VERSION'), NOVAMIRA_PRO_GP_THEME_MIN_VERSION, operator: '>=')
        );
    }
}

namespace Novamira\Pro\Abilities\GenerateBlocks {
    /**
     * GenerateBlocks free version string, or '' when not installed / inactive.
     */
    function gb_version(): string
    {
        return defined('GENERATEBLOCKS_VERSION') ? (string) constant('GENERATEBLOCKS_VERSION') : '';
    }

    /**
     * Whether the free GenerateBlocks plugin is active at any version.
     */
    function gb_available(): bool
    {
        return gb_version() !== '';
    }
}

namespace Novamira\Pro\Abilities\Kadence {
    /**
     * Whether the Kadence theme is installed, active, and at or above the
     * minimum supported version. The minimum is the floor where the
     * Options Component template-tag API (`kadence()->option()`,
     * `kadence()->defaults()`, `kadence()->get_palette()`) is reliable.
     */
    function kadence_theme_available(): bool
    {
        return (
            defined('KADENCE_VERSION')
            && class_exists('Kadence\\Theme')
            && function_exists('Kadence\\kadence')
            && version_compare(
                (string) constant('KADENCE_VERSION'),
                NOVAMIRA_PRO_KADENCE_THEME_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\KadenceBlocks {
    /**
     * Kadence Blocks (free) version string, or '' when not installed / inactive.
     */
    function kb_version(): string
    {
        return defined('KADENCE_BLOCKS_VERSION') ? (string) constant('KADENCE_BLOCKS_VERSION') : '';
    }

    /**
     * Whether the free Kadence Blocks plugin is active.
     */
    function kb_available(): bool
    {
        return kb_version() !== '';
    }
}

namespace Novamira\Pro\Abilities\SpectraOne {
    /**
     * Whether the Spectra One theme is installed, active, and at or above
     * the minimum supported version. Combines the namespaced `Swt\SWT_VER`
     * constant with a sentinel public helper (`Swt\get_theme_json`) so older
     * 1.0/1.1 releases that lack the exposed helper surface are excluded —
     * `defined()` alone would leak stale constants after a `switch_theme()`
     * inside the same request. The per-blog stylesheet check makes sure a
     * multisite request that entered a sub-site via `switch_to_blog()` —
     * where Spectra One is loaded process-wide but is NOT the active theme
     * — is refused at the gate rather than allowed to write against a
     * foreign theme's data surfaces (audit round 6, Sprint 6 Multisite
     * probe). The theme declares its version constant inside its own `Swt`
     * namespace (`functions.php:12` → `namespace Swt;`, `:18` → `const
     * SWT_VER = ...`), so a global-scope `defined('SWT_VER')` check always
     * returns false against the shipping theme and must be namespaced.
     */
    function spectra_one_theme_available(): bool
    {
        if (!defined('Swt\\SWT_VER')) {
            return false;
        }
        if (!function_exists('Swt\\get_theme_json')) {
            return false;
        }
        if (!version_compare(
            (string) constant('Swt\\SWT_VER'),
            NOVAMIRA_PRO_SPECTRA_ONE_THEME_MIN_VERSION,
            operator: '>=',
        )) {
            return false;
        }
        $stylesheet = function_exists('get_stylesheet') ? get_stylesheet() : '';
        $template = function_exists('get_template') ? get_template() : '';
        return $stylesheet === 'spectra-one' || $template === 'spectra-one';
    }

    /**
     * Whether the Spectra plugin (UAGB) is installed, active, and at or
     * above the minimum supported version. The plugin is OPTIONAL — most
     * `spectra-one/*` abilities work without it. Only the Spectra-plugin
     * bridge (`novamira/spectra-one-list-spectra-blocks`) is gated on this.
     */
    function spectra_plugin_available(): bool
    {
        return (
            defined('UAGB_VER')
            && version_compare(
                (string) constant('UAGB_VER'),
                NOVAMIRA_PRO_SPECTRA_ONE_PLUGIN_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\Spectra {
    /**
     * Spectra (UAGB / Ultimate Addons for Gutenberg) plugin version string,
     * or '' when the plugin is inactive.
     */
    function spectra_plugin_version(): string
    {
        return defined('UAGB_VER') ? (string) constant('UAGB_VER') : '';
    }

    /**
     * Whether the Spectra plugin is installed, active, and at or above
     * NOVAMIRA_PRO_SPECTRA_MIN_VERSION. Distinct from the Spectra One theme
     * integration's own `SpectraOne\spectra_plugin_available()`, which uses a
     * lower floor (`NOVAMIRA_PRO_SPECTRA_ONE_PLUGIN_MIN_VERSION` = 2.16.0)
     * because there the plugin is optional and only one bridge ability reads it.
     * Here it drives the whole specialization surface — popup CPT, editor
     * settings, Google Fonts, form submissions — so the floor is higher (2.19.0)
     * and the abilities are gated on this at load time.
     */
    function spectra_plugin_available(): bool
    {
        return (
            defined('UAGB_VER')
            && version_compare((string) constant('UAGB_VER'), NOVAMIRA_PRO_SPECTRA_MIN_VERSION, operator: '>=')
        );
    }

    /**
     * Spectra Pro plugin version string, or '' when the Pro add-on is inactive.
     */
    function spectra_pro_version(): string
    {
        return defined('SPECTRA_PRO_VER') ? (string) constant('SPECTRA_PRO_VER') : '';
    }

    /**
     * Whether Spectra Pro (the paid add-on) is installed, active, and at or
     * above NOVAMIRA_PRO_SPECTRA_PRO_MIN_VERSION. Used by the Pro sub-loader
     * to gate registration of `novamira/spectra-pro-*` abilities, so a free-only
     * install never sees Pro abilities in `discover-abilities`.
     */
    function spectra_pro_active(): bool
    {
        return (
            defined('SPECTRA_PRO_VER')
            && version_compare(
                (string) constant('SPECTRA_PRO_VER'),
                NOVAMIRA_PRO_SPECTRA_PRO_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\Elementor {
    /**
     * Elementor version string, or the empty string when Elementor is inactive.
     */
    function el_elementor_version(): string
    {
        return defined('ELEMENTOR_VERSION') ? (string) constant('ELEMENTOR_VERSION') : '';
    }

    /**
     * Base Elementor surface required by the generic Elementor abilities.
     */
    function el_min_runtime_available(): bool
    {
        return (
            defined('ELEMENTOR_VERSION')
            && version_compare(el_elementor_version(), version2: NOVAMIRA_PRO_ELEMENTOR_MIN_VERSION, operator: '>=')
            && class_exists('Elementor\\Plugin')
        );
    }
}

namespace Novamira\Pro\Abilities\Cf7 {
    /**
     * Whether the Contact Form 7 plugin is installed, active, and at or
     * above the minimum supported version.
     *
     * `WPCF7_VERSION` is defined at the very top of the plugin bootstrap
     * (`wp-contact-form-7.php`) so it lights up as soon as CF7 is loaded;
     * `WPCF7_ContactForm` is the canonical entity class we call into.
     */
    function cf7_runtime_available(): bool
    {
        if (!defined('WPCF7_VERSION')) {
            return false;
        }
        if (!class_exists('WPCF7_ContactForm')) {
            return false;
        }
        return version_compare((string) constant('WPCF7_VERSION'), NOVAMIRA_PRO_CF7_MIN_VERSION, operator: '>=');
    }
}

namespace Novamira\Pro\Abilities\WPForms {
    /**
     * Whether WPForms is active and meets the minimum version Novamira Pro requires.
     *
     * Gates registration of the entire wpforms category, so a too-old install never
     * pollutes the agent tool list. The minimum (NOVAMIRA_PRO_WPFORMS_MIN_VERSION,
     * 1.8.0) is the line where wpforms()->obj('form'|'entry') accessors and the
     * field-type registry shape this integration depends on stabilised.
     */
    function wpforms_min_runtime_available(): bool
    {
        return (
            defined('WPFORMS_VERSION')
            && function_exists('wpforms')
            && version_compare(
                version1: (string) constant('WPFORMS_VERSION'),
                version2: \NOVAMIRA_PRO_WPFORMS_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\GravityForms {
    /**
     * Whether Gravity Forms is active and meets the minimum version Novamira Pro
     * requires.
     *
     * Gates registration of the entire gravityforms category, so a too-old install
     * never pollutes the agent tool list. The minimum (NOVAMIRA_PRO_GRAVITYFORMS_MIN_VERSION,
     * 2.7) is the line where GFAPI::current_user_can_any() and the modern field
     * registry shape this integration depends on stabilised.
     *
     * Gravity Forms is a single-SKU paid plugin (no Lite/Pro edition split), so
     * this is the only runtime gate — there is no separate Pro check.
     */
    function gravityforms_min_runtime_available(): bool
    {
        if (!class_exists('GFForms') || !class_exists('GFAPI')) {
            return false;
        }
        $installed = \GFForms::$version;
        if ($installed === '') {
            return false;
        }
        return version_compare($installed, \NOVAMIRA_PRO_GRAVITYFORMS_MIN_VERSION, operator: '>=');
    }
}

namespace Novamira\Pro\Abilities\FluentForms {
    /**
     * Whether Fluent Forms is active and meets the minimum version Novamira Pro requires.
     *
     * Free FF defines both `FLUENTFORM` (the plugin basename) and
     * `FLUENTFORM_VERSION`. FF Pro hard-depends on free and defines
     * `FLUENTFORMPRO` + `FLUENTFORMPRO_VERSION`. License status is informational
     * only — Pro abilities run unlicensed on a Pro install.
     */
    function ff_min_runtime_available(): bool
    {
        return (
            defined('FLUENTFORM_VERSION')
            && version_compare(
                version1: (string) constant('FLUENTFORM_VERSION'),
                version2: \NOVAMIRA_PRO_FLUENTFORMS_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\NinjaForms {
    /**
     * Whether Ninja Forms is loaded and at or above the minimum supported
     * version. Ninja Forms publishes its version as a class constant on
     * its main entity (`Ninja_Forms::VERSION`) rather than as a top-level
     * `define()`. The singleton class is loaded on `plugins_loaded` and is
     * the canonical "Ninja Forms is alive on this request" signal — the
     * class-constant lookup doubles as the version gate.
     */
    function ninja_forms_runtime_available(): bool
    {
        if (!class_exists('Ninja_Forms')) {
            return false;
        }
        $version = ninja_forms_version();
        if ($version === '') {
            return false;
        }
        return version_compare($version, NOVAMIRA_PRO_NINJAFORMS_MIN_VERSION, operator: '>=');
    }

    /**
     * Ninja Forms version string, or empty when the plugin is inactive.
     * Reads from the `Ninja_Forms::VERSION` class constant — Ninja Forms
     * does not expose a top-level `NF_PLUGIN_VERSION` define.
     */
    function ninja_forms_version(): string
    {
        if (!class_exists('Ninja_Forms')) {
            return '';
        }
        /** @var mixed $version */
        $version = constant('Ninja_Forms::VERSION');
        return is_string($version) ? $version : '';
    }
}

namespace Novamira\Pro\Abilities\CodeSnippets {
    /**
     * Whether the Code Snippets plugin (free or Pro) is installed and active.
     *
     * The plugin exposes a `code_snippets()` accessor in its own namespace
     * once `code-snippets.php` has loaded; we use that as the canonical
     * "is the plugin live in this request" signal.
     */
    function cs_runtime_available(): bool
    {
        if (!defined('CODE_SNIPPETS_VERSION')) {
            return false;
        }
        if (!function_exists('Code_Snippets\\code_snippets')) {
            return false;
        }
        return version_compare(
            (string) constant('CODE_SNIPPETS_VERSION'),
            NOVAMIRA_PRO_CODE_SNIPPETS_MIN_VERSION,
            operator: '>=',
        );
    }
}

namespace Novamira\Pro\Abilities\Astra {
    /**
     * The Astra theme is installed, active, and at or above the minimum
     * supported version. `ASTRA_THEME_VERSION` is defined in the theme
     * bootstrap (`functions.php`); the `astra_get_option` sentinel confirms
     * that the theme API has loaded for this request — the constant alone is
     * not enough because PHP keeps it defined after a mid-request theme switch.
     */
    function astra_theme_available(): bool
    {
        return (
            defined('ASTRA_THEME_VERSION')
            && function_exists('astra_get_option')
            && version_compare(
                (string) constant('ASTRA_THEME_VERSION'),
                NOVAMIRA_PRO_ASTRA_THEME_MIN_VERSION,
                operator: '>=',
            )
        );
    }

    /**
     * Astra Pro Addon is present and at or above the minimum supported version.
     * The authoritative presence check is the `ASTRA_EXT_VER` constant plus
     * the `Astra_Ext_Extension` class — both are defined in the addon bootstrap
     * (`astra-addon.php`) and disappear when the plugin is deactivated.
     */
    function astra_addon_available(): bool
    {
        return (
            defined('ASTRA_EXT_VER')
            && class_exists('Astra_Ext_Extension')
            && version_compare((string) constant('ASTRA_EXT_VER'), NOVAMIRA_PRO_ASTRA_ADDON_MIN_VERSION, operator: '>=')
        );
    }
}

namespace Novamira\Pro\Abilities\OceanWP {
    /**
     * The OceanWP theme is active and at or above the minimum supported
     * release. The version constant is defined inside the theme bootstrap
     * (`functions.php`) so it lights up as soon as the theme is active.
     * `oceanwp_post_layout` is the canonical render-time helper every layout
     * override path goes through — using it as the sentinel proves the API
     * shape, not just constant presence.
     */
    function oceanwp_theme_available(): bool
    {
        return (
            defined('OCEANWP_THEME_VERSION')
            && function_exists('oceanwp_post_layout')
            && version_compare(
                (string) constant('OCEANWP_THEME_VERSION'),
                \NOVAMIRA_PRO_OCEANWP_THEME_MIN_VERSION,
                operator: '>=',
            )
        );
    }

    /**
     * Whether the Ocean Extra companion plugin's bootstrap class has loaded
     * on this request. Cheaper than `is_plugin_active()` and matches the
     * sentinel OceanWP itself uses in `functions.php:166`.
     */
    function ocean_extra_active(): bool
    {
        return class_exists('Ocean_Extra');
    }

    /**
     * Ocean Extra version string, or empty when the plugin is inactive or
     * its header cannot be read. The plugin does not consistently expose a
     * top-level version constant across releases, so we read from the
     * plugin header via `get_plugin_data()` (self-including
     * `wp-admin/includes/plugin.php` when needed). Same pattern Etch uses
     * for the equivalent header read.
     */
    function ocean_extra_version(): string
    {
        if (!ocean_extra_active()) {
            return '';
        }
        if (!function_exists('get_plugin_data')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $file = WP_PLUGIN_DIR . '/ocean-extra/ocean-extra.php';
        if (!file_exists($file)) {
            return '';
        }
        /** @var array{Version?: string} $data */
        $data = get_plugin_data($file, markup: false, translate: false);
        return $data['Version'] ?? '';
    }

    /**
     * Ocean Extra is installed, active, and at or above the minimum supported
     * version. Ocean Extra is OPTIONAL: the S1–S3 abilities work theme-only
     * and self-degrade. Sprint-4 abilities (Library, Modules, Demo Import)
     * gate on this and return `oceanwp_requires_ocean_extra` when false.
     */
    function ocean_extra_available(): bool
    {
        if (!ocean_extra_active()) {
            return false;
        }
        $version = ocean_extra_version();
        if ($version === '') {
            return false;
        }
        return version_compare($version, \NOVAMIRA_PRO_OCEAN_EXTRA_MIN_VERSION, operator: '>=');
    }
}

namespace Novamira\Pro\Abilities\DynamicShortcodes {
    /**
     * Whether the Dynamic Shortcodes plugin is installed, active, and at least
     * at the version where the public lint() and Power Shortcodes facade are
     * available. Below the floor the whole specialization stays unregistered —
     * nothing (not even check-setup) is offered — so an agent never sees an
     * ability that would call a method the installed plugin does not have.
     */
    function dsh_min_runtime_available(): bool
    {
        return (
            defined('DYNAMIC_SHORTCODES_VERSION')
            && class_exists('DynamicShortcodes\\Plugin')
            && version_compare(
                (string) constant('DYNAMIC_SHORTCODES_VERSION'),
                NOVAMIRA_PRO_DYNAMIC_SHORTCODES_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\Avada {
    /**
     * Whether the Avada theme is active AND meets the minimum supported version.
     *
     * `AVADA_VERSION` is defined at the top of the theme's `functions.php`
     * (a require of `Avada/functions.php` occurs before any REST request
     * reaches abilities-api-init when Avada is the active theme). Every
     * theme-side ability gates on this — the two Fusion Builder-plugin-
     * scoped abilities (currently blocked) additionally gate on
     * `fusion_builder_available()`.
     */
    function avada_theme_available(): bool
    {
        return (
            defined('AVADA_VERSION')
            && version_compare((string) constant('AVADA_VERSION'), NOVAMIRA_PRO_AVADA_MIN_VERSION, operator: '>=')
        );
    }

    /**
     * Whether the (bundled) Fusion Builder plugin is present AND at the
     * supported floor. Distinct from `avada_theme_available()`: the theme
     * ships some capabilities on its own, but the element-tree CRUD, the
     * Template Builder runtime, and the Fusion Forms CPT live in the
     * separate `fusion-builder` companion plugin. Guarded here so the
     * eventual Pro sub-loader in `novamira_pro_load_avada_abilities()`
     * can require its own file set without a first-word `if (…)` check.
     * `FUSION_BUILDER_VERSION` is defined in the plugin's bootstrap.
     */
    function fusion_builder_available(): bool
    {
        return (
            defined('FUSION_BUILDER_VERSION')
            && version_compare(
                (string) constant('FUSION_BUILDER_VERSION'),
                NOVAMIRA_PRO_FUSION_BUILDER_MIN_VERSION,
                operator: '>=',
            )
        );
    }

    /**
     * Whether the (bundled) Fusion Core plugin is present AND at the
     * supported floor. Fusion Core registers the `slide` CPT + `slide-page`
     * taxonomy that back the Fusion Slider abilities; when it's inactive
     * the Fusion Slider ability sub-loader stays wired-off and the CPT-
     * touching helpers safely early-return. `FUSION_CORE_VERSION` is
     * defined at the top of `fusion-core.php` so the gate lights up as
     * soon as the plugin loads. Extra `class_exists('FusionCore_Plugin')`
     * check guards against the (rare) constants-defined-but-classes-not-
     * loaded window during `plugins_loaded` before Fusion Core's own
     * bootstrap has finished — the ability code calls into the class
     * (namespaced statics + singleton) so the class must exist by the
     * time any ability executes.
     */
    function fusion_core_available(): bool
    {
        return (
            defined('FUSION_CORE_VERSION')
            && class_exists('FusionCore_Plugin')
            && version_compare(
                (string) constant('FUSION_CORE_VERSION'),
                NOVAMIRA_PRO_FUSION_CORE_MIN_VERSION,
                operator: '>=',
            )
        );
    }
}

namespace Novamira\Pro\Abilities\Voxel {
    /**
     * Whether the Voxel theme is installed, active for THIS request, and its
     * API has loaded — a PRESENCE check only, NOT a version check.
     *
     * Voxel exposes no version constant, so presence is proven by the `\Voxel\get`
     * function + the `\Voxel\Post_Type` class (both defined in the theme bootstrap
     * and gone the moment Voxel is not the active theme's code). The
     * `get_template()` / `get_stylesheet()` check makes the gate multisite-safe:
     * a `switch_to_blog()` request where Voxel is loaded process-wide but is NOT
     * the active theme of the switched-to site is refused, so we never operate
     * against a foreign site's data (same reasoning as `spectra_one_theme_available`).
     *
     * The version floor is deliberately enforced per-callback
     * (`vx_require_min()`), not here, so `voxel-check-setup` remains registered on
     * an older Voxel and can report the gap. See NOVAMIRA_PRO_VOXEL_THEME_MIN_VERSION.
     */
    function voxel_theme_present(): bool
    {
        return (
            function_exists('Voxel\\get')
            && class_exists('Voxel\\Post_Type')
            && (
                function_exists('get_template')
                && get_template() === 'voxel'
                || function_exists('get_stylesheet')
                && get_stylesheet() === 'voxel'
            )
        );
    }

    /**
     * Voxel theme version, read from the `style.css` header of the parent
     * template (so a child theme's own version never masks Voxel's), or '' when
     * Voxel is not resolvable. There is no `\Voxel\VERSION` constant to read.
     */
    function voxel_theme_version(): string
    {
        if (!function_exists('wp_get_theme') || !function_exists('get_template')) {
            return '';
        }
        $version = wp_get_theme(get_template())->get('Version');

        /**
         * Override the detected Voxel version. Default is the `style.css` header
         * of the active parent template. Provided as an override seam for unusual
         * installs and to make the below-minimum gate state observable in tests;
         * it only affects the per-callback version floor, never the presence gate.
         *
         * @param string $version
         */
        /** @var mixed $filtered */
        $filtered = apply_filters('novamira/voxel/detected_version', $version);
        return is_string($filtered) ? $filtered : $version;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit