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/loaders.php
<?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();
}

/**
 * Load every Etch ability file. check-setup is the read-only baseline; the
 * content abilities (list-elements, get-content, set-content) read and rewrite
 * the page element tree; manage-components handles the reusable component
 * library (wp_block patterns). Later sprints add the style and dynamic-data
 * abilities.
 */
function novamira_pro_load_etch_abilities(): void
{
    $etch_dir = __DIR__ . '/abilities/etch/';
    require_once $etch_dir . 'helpers.php';
    require_once $etch_dir . 'check-setup.php';
    require_once $etch_dir . 'list-elements.php';
    require_once $etch_dir . 'get-content.php';
    require_once $etch_dir . 'set-content.php';
    require_once $etch_dir . 'manage-nodes.php';
    require_once $etch_dir . 'manage-components.php';
    require_once $etch_dir . 'manage-styles.php';
    require_once $etch_dir . 'manage-loops.php';
    require_once $etch_dir . 'manage-post-types.php';
    require_once $etch_dir . 'manage-taxonomies.php';
    require_once $etch_dir . 'manage-queries.php';
    require_once $etch_dir . 'manage-custom-fields.php';
    require_once $etch_dir . 'manage-templates.php';

    // Per-post custom field VALUES — gated on Etch 1.5.0+ (the CustomFieldValues
    // REST API). Registered only when supported so the agent's tool list isn't
    // polluted on older Etch; every ability above works on all supported Etch.
    if (\Novamira\Pro\Abilities\Etch\etch_supports_field_values()) {
        require_once $etch_dir . 'manage-custom-field-values.php';
    }
}

/**
 * Load every ASE ability file.
 *
 * Extracted out of the `wp_abilities_api_init` closure to keep that
 * registration handler small and to give the ASE block a single named entry
 * point. Additional ability files (field groups, values, CPTs, taxonomies)
 * will be added here by their respective tasks.
 */
function novamira_pro_load_ase_abilities(): void
{
    $dir = __DIR__ . '/abilities/ase/';
    require_once $dir . 'helpers.php';

    // check-setup is always available — even on ASE Free — so an agent can
    // introspect the install and learn that the other abilities require Pro.
    require_once $dir . 'check-setup.php';

    // All other ASE abilities are Pro-only. We gate them at registration
    // rather than only at runtime so the agent's tool list isn't polluted
    // with 17 abilities that would all return ase_pro_required on a Free
    // install.
    if (!\Novamira\Pro\Abilities\ASE\ase_pro_active()) {
        return;
    }

    require_once $dir . 'list-field-groups.php';
    require_once $dir . 'get-field-group.php';
    require_once $dir . 'manage-field-groups.php';
    require_once $dir . 'read-values.php';
    require_once $dir . 'write-values.php';

    require_once $dir . 'list-post-types.php';
    require_once $dir . 'get-post-type.php';
    require_once $dir . 'manage-post-types.php';

    require_once $dir . 'list-taxonomies.php';
    require_once $dir . 'get-taxonomy.php';
    require_once $dir . 'manage-taxonomies.php';
}

/**
 * Load every Elementor ability file in the right order.
 *
 * Extracted out of the `wp_abilities_api_init` closure to keep that
 * registration handler small and to give the Elementor block a single
 * named entry point.
 */
function novamira_pro_load_elementor_abilities(): void
{
    $elementor_dir = __DIR__ . '/abilities/elementor/';
    require_once $elementor_dir . 'runtime.php';
    // Extraction library must load before helpers, write abilities, or the
    // unified schema ability so every caller sees the same functions.
    require_once $elementor_dir . 'schema-extractor.php';
    require_once $elementor_dir . 'helpers.php';
    require_once $elementor_dir . 'get-content.php';
    require_once $elementor_dir . 'pipeline.php';
    require_once $elementor_dir . 'set-content.php';
    require_once $elementor_dir . 'add-element.php';
    require_once $elementor_dir . 'edit-element.php';
    require_once $elementor_dir . 'delete-element.php';
    require_once $elementor_dir . 'delete-element-style.php';
    require_once $elementor_dir . 'get-widget-schema.php';
    require_once $elementor_dir . 'manage-global-styles-v3.php';
    require_once $elementor_dir . 'manage-dynamic-tags.php';
    require_once $elementor_dir . 'check-setup.php';
    require_once $elementor_dir . 'clear-document-cache.php';

    if (\Novamira\Pro\Abilities\Elementor\el_atomic_runtime_available()) {
        require_once $elementor_dir . 'validate-widget.php';
        require_once $elementor_dir . 'create-atomic-widget.php';
    }

    if (\Novamira\Pro\Abilities\Elementor\el_style_schema_available()) {
        require_once $elementor_dir . 'get-style-schema.php';
    }

    if (\Novamira\Pro\Abilities\Elementor\el_global_classes_available()) {
        require_once $elementor_dir . 'manage-global-classes.php';
    }

    if (\Novamira\Pro\Abilities\Elementor\el_variables_available()) {
        require_once $elementor_dir . 'manage-variables.php';
    }

    if (\Novamira\Pro\Abilities\Elementor\el_interactions_available()) {
        require_once $elementor_dir . 'manage-interactions.php';
    }
}

/**
 * Load every Pods ability file in order. Pods-specific feature gates (the
 * Advanced Content Types component) are checked at the loader level so that
 * an ACT-disabled site does not register `pods-create-act` and the agent
 * sees an honest tool surface.
 */
function novamira_pro_load_pods_abilities(): void
{
    $pods_dir = __DIR__ . '/abilities/pods/';
    require_once $pods_dir . 'runtime.php';
    require_once $pods_dir . 'helpers.php';
    require_once $pods_dir . 'check-setup.php';
    require_once $pods_dir . 'list-pods.php';
    require_once $pods_dir . 'get-pod.php';
    require_once $pods_dir . 'get-field-type-schema.php';
    require_once $pods_dir . 'create-cpt.php';
    require_once $pods_dir . 'create-taxonomy.php';
    require_once $pods_dir . 'create-settings.php';
    require_once $pods_dir . 'extend-builtin.php';
    require_once $pods_dir . 'edit-pod.php';
    require_once $pods_dir . 'delete-pod.php';
    require_once $pods_dir . 'manage-fields.php';
    require_once $pods_dir . 'manage-groups.php';
    require_once $pods_dir . 'list-items.php';
    require_once $pods_dir . 'get-item.php';
    require_once $pods_dir . 'create-item.php';
    require_once $pods_dir . 'edit-item.php';
    require_once $pods_dir . 'delete-item.php';

    if (\Novamira\Pro\Abilities\Pods\pods_act_runtime_available()) {
        require_once $pods_dir . 'create-act.php';
    }
}

/**
 * Load every ACF ability file in the right order.
 *
 * Extracted out of the `wp_abilities_api_init` closure to keep that
 * registration handler small and to give the ACF block a single
 * named entry point.
 */
function novamira_pro_load_acf_abilities(): void
{
    $acf_dir = __DIR__ . '/abilities/acf/';
    require_once $acf_dir . 'helpers.php';
    require_once $acf_dir . 'check-setup.php';
    require_once $acf_dir . 'list-fieldgroups.php';
    require_once $acf_dir . 'get-fieldgroup-schema.php';
    require_once $acf_dir . 'read-values.php';
    require_once $acf_dir . 'write-values.php';
    require_once $acf_dir . 'manage-fieldgroups.php';

    // Internal post-type management abilities require ACF Pro 6.5+ (the
    // documented minimum). The acf_get_internal_post_type_posts() API is not
    // present in ACF Free; on Pro below 6.5 the runtime guard inside the
    // abilities returns acf_version_unsupported. Skip registration on Free so
    // the abilities never appear in discover-abilities on unsupported installs.
    if (function_exists('acf_get_internal_post_type_posts')) {
        require_once $acf_dir . 'list-post-types.php';
        require_once $acf_dir . 'get-post-type.php';
        require_once $acf_dir . 'manage-post-types.php';
        require_once $acf_dir . 'list-taxonomies.php';
        require_once $acf_dir . 'get-taxonomy.php';
        require_once $acf_dir . 'manage-taxonomies.php';
        require_once $acf_dir . 'list-options-pages.php';
        require_once $acf_dir . 'get-options-page.php';
        require_once $acf_dir . 'manage-options-pages.php';
    }
}

/**
 * Load every Yoast SEO ability file in the right order. Sprint 1 is read-only:
 * setup discovery plus per-post, per-term, and site-wide settings readers.
 */
function novamira_pro_load_yoast_abilities(): void
{
    $yoast_dir = __DIR__ . '/abilities/yoast/';
    require_once $yoast_dir . 'helpers.php';
    require_once $yoast_dir . 'check-setup.php';
    require_once $yoast_dir . 'get-post-seo.php';
    require_once $yoast_dir . 'get-term-seo.php';
    require_once $yoast_dir . 'get-settings.php';
    require_once $yoast_dir . 'edit-post-seo.php';
    require_once $yoast_dir . 'edit-term-seo.php';

    // Redirect abilities require Yoast SEO Premium (the redirect module). The
    // abilities also guard at runtime via yoast_redirect_premium(), but skipping
    // registration keeps them out of discover-abilities on the free edition.
    if (defined('WPSEO_PREMIUM_VERSION')) {
        require_once $yoast_dir . 'list-redirects.php';
        require_once $yoast_dir . 'create-redirect.php';
        require_once $yoast_dir . 'edit-redirect.php';
        require_once $yoast_dir . 'delete-redirect.php';
    }
}

/**
 * Load every Rank Math ability file (discovery + per-post/term SEO read & write
 * + site-wide settings readers).
 */
function novamira_pro_load_rank_math_abilities(): void
{
    $rm_dir = __DIR__ . '/abilities/rank-math/';
    require_once $rm_dir . 'helpers.php';
    require_once $rm_dir . 'check-setup.php';
    require_once $rm_dir . 'get-post-seo.php';
    require_once $rm_dir . 'get-term-seo.php';
    require_once $rm_dir . 'get-settings.php';
    require_once $rm_dir . 'edit-post-seo.php';
    require_once $rm_dir . 'edit-term-seo.php';

    // Schema abilities require the rich-snippet module. They also guard at
    // runtime via rm_module_active(); skipping registration keeps them out of
    // discover-abilities when the module is off.
    if (\Novamira\Pro\Abilities\RankMath\rm_module_active('rich-snippet')) {
        require_once $rm_dir . 'get-post-schema.php';
        require_once $rm_dir . 'edit-post-schema.php';
    }
}

/**
 * Load every All in One SEO ability file in the right order. AIOSEO_VERSION is
 * defined by both the free and Pro editions; Pro-only surfaces (term SEO,
 * redirects) gate again at runtime on aioseo()->pro.
 */
function novamira_pro_load_aioseo_abilities(): void
{
    $aioseo_dir = __DIR__ . '/abilities/aioseo/';
    require_once $aioseo_dir . 'helpers.php';
    require_once $aioseo_dir . 'check-setup.php';
    require_once $aioseo_dir . 'get-post-seo.php';
    require_once $aioseo_dir . 'get-term-seo.php';
    require_once $aioseo_dir . 'get-settings.php';
    require_once $aioseo_dir . 'edit-post-seo.php';
    require_once $aioseo_dir . 'edit-term-seo.php';
    require_once $aioseo_dir . 'get-post-schema.php';
    require_once $aioseo_dir . 'edit-post-schema.php';

    // Redirect abilities require AIOSEO Pro (the redirect model). The abilities
    // also guard at runtime via aio_supports_redirects(), but skipping
    // registration keeps them out of discover-abilities on the free edition.
    if (\Novamira\Pro\Abilities\AIOSEO\aio_supports_redirects()) {
        require_once $aioseo_dir . 'list-redirects.php';
        require_once $aioseo_dir . 'create-redirect.php';
        require_once $aioseo_dir . 'edit-redirect.php';
        require_once $aioseo_dir . 'delete-redirect.php';
    }
}

/**
 * Load every WPForms ability file in order. Sprint 1 is read-only (check-setup
 * + discovery). Write paths and entries (Pro-only) land in later sprints, gated
 * inside this loader.
 */
function novamira_pro_load_wpforms_abilities(): void
{
    require_once __DIR__ . '/abilities/wpforms/runtime.php';
    $dir = __DIR__ . '/abilities/wpforms/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'get-form-canonical.php';
    require_once $dir . 'get-field-types-schema.php';
    require_once $dir . 'get-field-type-schema.php';
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'delete-form.php';
    require_once $dir . 'duplicate-form.php';
    require_once $dir . 'manage-fields.php';
    require_once $dir . 'manage-notifications.php';
    require_once $dir . 'manage-confirmations.php';
    require_once $dir . 'edit-form-settings.php';

    // Entries CRUD (Pro-only). Skipping registration on Lite keeps these
    // abilities out of discover-abilities — agents see an honest tool list
    // that matches the edition actually installed.
    if (\Novamira\Pro\Abilities\WPForms\wpforms_pro_active()) {
        require_once $dir . 'list-entries.php';
        require_once $dir . 'get-entry.php';
        require_once $dir . 'edit-entry.php';
        require_once $dir . 'delete-entry.php';
        require_once $dir . 'mark-entry.php';
    }
}

/**
 * Load every SeoPress ability file in the right order. SEOPRESS_VERSION is
 * defined by both the free and Pro editions (Pro hard-depends on free); Pro-only
 * surfaces (redirects, structured data) gate on SEOPRESS_PRO_VERSION.
 */
function novamira_pro_load_seopress_abilities(): void
{
    $sp_dir = __DIR__ . '/abilities/seopress/';
    require_once $sp_dir . 'helpers.php';
    require_once $sp_dir . 'check-setup.php';
    require_once $sp_dir . 'get-post-seo.php';
    require_once $sp_dir . 'get-term-seo.php';
    require_once $sp_dir . 'edit-post-seo.php';
    require_once $sp_dir . 'edit-term-seo.php';
    require_once $sp_dir . 'get-settings.php';

    // Structured-data (manual rich snippets) abilities require SeoPress Pro but
    // NOT the seopress_404 CPT — they read/write the `_seopress_pro_schemas_manual`
    // postmeta directly. They also guard at runtime via sp_detect_setup()['pro'],
    // but skipping registration keeps them out of discover-abilities on free.
    if (\Novamira\Pro\Abilities\SeoPress\sp_detect_setup()['pro']) {
        require_once $sp_dir . 'get-post-schema.php';
        require_once $sp_dir . 'set-post-schema-type.php';
        require_once $sp_dir . 'edit-post-schema.php';
        require_once $sp_dir . 'list-schema-fields.php';
        require_once $sp_dir . 'list-schema-templates.php';
    }

    // Redirect abilities require SeoPress Pro (the seopress_404 CPT redirect
    // manager). They also guard at runtime via sp_redirect_supported(), but
    // skipping registration keeps them out of discover-abilities on free.
    if (\Novamira\Pro\Abilities\SeoPress\sp_redirect_supported()) {
        require_once $sp_dir . 'list-redirects.php';
        require_once $sp_dir . 'get-redirect.php';
        require_once $sp_dir . 'create-redirect.php';
        require_once $sp_dir . 'edit-redirect.php';
        require_once $sp_dir . 'delete-redirect.php';
    }
}

/**
 * Load every Weglot ability file in the right order: setup discovery, settings
 * snapshot, supported-language catalog, cloud project status, language and
 * button configuration, URL rules, and the cloud sync / cache surfaces.
 *
 * Plan-gated surfaces (glossary, etc.) gate again at runtime on the plan
 * reported by check-setup via the user-info endpoint.
 */
function novamira_pro_load_weglot_abilities(): void
{
    $weglot_dir = __DIR__ . '/abilities/weglot/';
    require_once $weglot_dir . 'helpers.php';
    require_once $weglot_dir . 'check-setup.php';
    require_once $weglot_dir . 'get-settings.php';
    require_once $weglot_dir . 'list-languages.php';
    require_once $weglot_dir . 'get-status.php';
    require_once $weglot_dir . 'list-exclude-urls.php';
    require_once $weglot_dir . 'set-api-key.php';
    require_once $weglot_dir . 'set-original-language.php';
    require_once $weglot_dir . 'add-destination-language.php';
    require_once $weglot_dir . 'delete-destination-language.php';
    require_once $weglot_dir . 'edit-button-settings.php';
    require_once $weglot_dir . 'add-exclude-url.php';
    require_once $weglot_dir . 'delete-exclude-url.php';
    require_once $weglot_dir . 'list-translated-urls.php';
    require_once $weglot_dir . 'add-translated-url.php';
    require_once $weglot_dir . 'delete-translated-url.php';
    require_once $weglot_dir . 'push-options-to-cloud.php';
    require_once $weglot_dir . 'refresh-from-cloud.php';
    require_once $weglot_dir . 'clear-translation-cache.php';
    require_once $weglot_dir . 'get-translation-cache-state.php';
}

/**
 * Load every JetEngine ability file in the right order.
 *
 * Extracted out of the wp_abilities_api_init closure to keep that
 * registration handler small and to give the JetEngine block a single
 * named entry point.
 */
function novamira_pro_load_jetengine_abilities(): void
{
    $dir = __DIR__ . '/abilities/jetengine/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-meta-boxes.php';
    require_once $dir . 'get-meta-box.php';
    require_once $dir . 'manage-meta-boxes.php';
    require_once $dir . 'list-options-pages.php';
    require_once $dir . 'get-options-page.php';
    require_once $dir . 'manage-options-pages.php';
    require_once $dir . 'list-post-types.php';
    require_once $dir . 'get-post-type.php';
    require_once $dir . 'manage-post-types.php';

    $modules = function_exists('jet_engine') ? jet_engine()->modules : null;
    if ($modules instanceof \Jet_Engine_Modules && $modules->is_module_active('custom-content-types')) {
        require_once $dir . 'list-ccts.php';
        require_once $dir . 'get-cct.php';
        require_once $dir . 'manage-ccts.php';
        require_once $dir . 'list-cct-records.php';
        require_once $dir . 'get-cct-record.php';
        require_once $dir . 'manage-cct-records.php';
    }
}

/**
 * Load every Meta Box ability file in the right order. Pro-extension-specific
 * sub-features (MB CPT, MB Settings Page, MB Relationships) are gated at the
 * loader level so abilities only register when their underlying extension is
 * actually active. MB Builder is gated callback-level inside the field-group
 * write abilities — read-side abilities are always available.
 */
function novamira_pro_load_metabox_abilities(): void
{
    $dir = __DIR__ . '/abilities/metabox/';

    require_once $dir . 'runtime.php';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-field-groups.php';
    require_once $dir . 'get-field-group-schema.php';
    require_once $dir . 'get-field-type-schema.php';
    require_once $dir . 'read-values.php';
    require_once $dir . 'write-values.php';
    require_once $dir . 'manage-field-groups.php';

    // MB Custom Post Type extension handles both CPTs and Custom Taxonomies.
    if (\Novamira\Pro\Abilities\Metabox\mb_cpt_available()) {
        require_once $dir . 'list-post-types.php';
        require_once $dir . 'get-post-type.php';
        require_once $dir . 'manage-post-types.php';
        require_once $dir . 'list-taxonomies.php';
        require_once $dir . 'get-taxonomy.php';
        require_once $dir . 'manage-taxonomies.php';
    }
    if (\Novamira\Pro\Abilities\Metabox\mb_settings_page_available()) {
        require_once $dir . 'list-settings-pages.php';
        require_once $dir . 'get-settings-page.php';
        require_once $dir . 'manage-settings-pages.php';
    }
    if (\Novamira\Pro\Abilities\Metabox\mb_relationships_available()) {
        require_once $dir . 'list-relationships.php';
        require_once $dir . 'get-relationship.php';
        require_once $dir . 'manage-relationships.php';
        require_once $dir . 'connect-objects.php';
        require_once $dir . 'disconnect-objects.php';
        require_once $dir . 'list-connected-objects.php';
    }
}

/**
 * Load every ACPT ability file in the right order. All v1 abilities register
 * uniformly (no per-feature sub-gating) because the v1 scope is the license-
 * agnostic core of ACPT — CPTs, taxonomies, meta groups, option pages.
 */
function novamira_pro_load_acpt_abilities(): void
{
    $dir = __DIR__ . '/abilities/acpt/';

    require_once $dir . 'runtime.php';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-post-types.php';
    require_once $dir . 'get-post-type.php';
    require_once $dir . 'manage-post-types.php';
    require_once $dir . 'list-taxonomies.php';
    require_once $dir . 'get-taxonomy.php';
    require_once $dir . 'manage-taxonomies.php';
    require_once $dir . 'list-field-groups.php';
    require_once $dir . 'get-field-group-schema.php';
    require_once $dir . 'get-field-type-schema.php';
    require_once $dir . 'read-values.php';
    require_once $dir . 'write-values.php';
    require_once $dir . 'manage-field-groups.php';
    require_once $dir . 'list-option-pages.php';
    require_once $dir . 'get-option-page.php';
    require_once $dir . 'manage-option-pages.php';
}

/**
 * Load every Ninja Forms ability file. Ninja Forms ships its own 32
 * `ninjaforms/*` abilities at 3.14+, so Novamira Pro only adds the
 * two wrappers the cross-plugin migration framework needs: the
 * Phase-1 setup gate and the Phase-2 canonical reader. CRUD stays
 * with the native abilities.
 */
function novamira_pro_load_ninja_forms_abilities(): void
{
    require_once __DIR__ . '/abilities/ninja-forms/runtime.php';
    $dir = __DIR__ . '/abilities/ninja-forms/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-field-types-schema.php';
    require_once $dir . 'get-field-type-schema.php';
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'delete-form.php';
    require_once $dir . 'duplicate-form.php';
    require_once $dir . 'manage-fields.php';
    require_once $dir . 'manage-notifications.php';
    require_once $dir . 'list-submissions.php';
    require_once $dir . 'get-submission.php';
    require_once $dir . 'delete-submission.php';
    require_once $dir . 'get-form-canonical.php';
}

/**
 * Load every WPBakery ability file in the right order.
 */
function novamira_pro_load_wpbakery_abilities(): void
{
    $dir = __DIR__ . '/abilities/wpbakery/';
    require_once $dir . 'runtime.php';
    require_once $dir . 'schema-extractor.php';
    require_once $dir . 'helpers/parse.php';
    require_once $dir . 'helpers/serialize.php';
    require_once $dir . 'helpers/tree.php';
    require_once $dir . 'helpers/post-io.php';
    require_once $dir . 'helpers/templates.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-elements.php';
    require_once $dir . 'get-element-schema.php';
    require_once $dir . 'list-grid-item-elements.php';
    require_once $dir . 'get-content.php';
    require_once $dir . 'inspect-page.php';
    require_once $dir . 'set-content.php';
    require_once $dir . 'add-element.php';
    require_once $dir . 'edit-element.php';
    require_once $dir . 'edit-elements.php';
    require_once $dir . 'delete-element.php';
    require_once $dir . 'move-element.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'set-settings.php';
    require_once $dir . 'manage-templates.php';
    require_once $dir . 'apply-template.php';

    // WPBakery registers the vc_grid_item CPT only in admin. Mirror it on
    // non-admin request surfaces (REST, MCP, wp-cli) so the canonical
    // create-post(post_type=vc_grid_item) → set-content workflow succeeds
    // regardless of context. wp_abilities_api_init fires after init, so we
    // register directly instead of hooking another init callback.
    \Novamira\Pro\Abilities\WPBakery\wpb_register_grid_item_cpt();
}

/**
 * Breakdance abilities loader. Gated on bd_plugin_available() — every
 * sub-group below can additionally gate on license mode (pro vs free)
 * or on individual subsystems (templates, dynamic data, …) as the
 * scope grows.
 */
function novamira_pro_load_breakdance_abilities(): void
{
    require_once __DIR__ . '/abilities/breakdance/runtime.php';
    $dir = __DIR__ . '/abilities/breakdance/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'query-helpers.php';
    require_once $dir . 'tree-helpers.php';
    require_once $dir . 'design-helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-templates.php';
    require_once $dir . 'get-template.php';
    require_once $dir . 'create-template.php';
    require_once $dir . 'edit-template.php';
    require_once $dir . 'delete-template.php';
    require_once $dir . 'manage-template-conditions.php';
    require_once $dir . 'get-element-tree.php';
    require_once $dir . 'get-element.php';
    require_once $dir . 'list-element-types.php';
    require_once $dir . 'get-element-schema.php';
    require_once $dir . 'add-element.php';
    require_once $dir . 'set-content.php';
    require_once $dir . 'edit-element.php';
    require_once $dir . 'delete-element.php';
    require_once $dir . 'move-element.php';
    require_once $dir . 'list-variables.php';
    require_once $dir . 'create-variable.php';
    require_once $dir . 'edit-variable.php';
    require_once $dir . 'delete-variable.php';
    require_once $dir . 'manage-global-classes.php';
    require_once $dir . 'manage-global-settings.php';
    require_once $dir . 'list-dynamic-data-fields.php';
    require_once $dir . 'get-dynamic-data-field.php';
    require_once $dir . 'manage-form-submissions.php';
}

/**
 * Oxygen 6 abilities loader. Gated on `oxygen_plugin_available()` — the
 * gate verifies `BREAKDANCE_MODE === 'oxygen'` plus the version floor,
 * so this loader is mutually exclusive with the Breakdance loader (only
 * one of the two can run per request). Oxygen shares the Soflyy engine
 * with Breakdance but is registered under its own `oxygen` category with
 * its own `novamira/oxygen-*` slugs so the persona sees a coherent
 * Oxygen surface.
 */
function novamira_pro_load_oxygen_abilities(): void
{
    require_once __DIR__ . '/abilities/oxygen/runtime.php';
    $dir = __DIR__ . '/abilities/oxygen/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'tree-helpers.php';
    require_once $dir . 'design-helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-templates.php';
    require_once $dir . 'get-template.php';
    require_once $dir . 'create-template.php';
    require_once $dir . 'edit-template.php';
    require_once $dir . 'delete-template.php';
    require_once $dir . 'manage-template-conditions.php';
    require_once $dir . 'list-element-types.php';
    require_once $dir . 'get-element-schema.php';
    require_once $dir . 'get-element-tree.php';
    require_once $dir . 'get-element.php';
    require_once $dir . 'add-element.php';
    require_once $dir . 'edit-element.php';
    require_once $dir . 'delete-element.php';
    require_once $dir . 'move-element.php';
    require_once $dir . 'set-content.php';
    require_once $dir . 'set-loop.php';
    require_once $dir . 'list-variables.php';
    require_once $dir . 'create-variable.php';
    require_once $dir . 'edit-variable.php';
    require_once $dir . 'delete-variable.php';
    require_once $dir . 'manage-global-classes.php';
    require_once $dir . 'apply-global-class.php';
    require_once $dir . 'manage-global-settings.php';
    require_once $dir . 'list-dynamic-data-fields.php';
    require_once $dir . 'get-dynamic-data-field.php';
    require_once $dir . 'apply-dynamic-data.php';
    require_once $dir . 'manage-form-submissions.php';
}

/**
 * Load every Code Snippets ability file in the right order. The runtime
 * helper guards the per-type surface (css / js / cond are Pro-only).
 */
function novamira_pro_load_code_snippets_abilities(): void
{
    require_once __DIR__ . '/abilities/code-snippets/runtime.php';
    $dir = __DIR__ . '/abilities/code-snippets/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-types-schema.php';
    require_once $dir . 'get-conditions-schema.php';
    require_once $dir . 'list-snippets.php';
    require_once $dir . 'get-snippet.php';
    require_once $dir . 'create-snippet.php';
    require_once $dir . 'edit-snippet.php';
    require_once $dir . 'delete-snippet.php';
    require_once $dir . 'enable-snippet.php';
    require_once $dir . 'disable-snippet.php';
    require_once $dir . 'validate-snippet.php';
}

/**
 * Load every Dynamic Shortcodes ability file. The whole specialization is
 * gated on `dsh_min_runtime_available()` (DSH active and at or above
 * `NOVAMIRA_PRO_DYNAMIC_SHORTCODES_MIN_VERSION`) by the manifest engine, so
 * below the floor this loader is never called and no dynamic-shortcodes
 * ability (not even check-setup) is registered.
 */
function novamira_pro_load_dynamic_shortcodes_abilities(): void
{
    $dir = __DIR__ . '/abilities/dynamic-shortcodes/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'validate-shortcode.php';
    require_once $dir . 'compose-shortcode.php';
    require_once $dir . 'evaluate-shortcode.php';
    require_once $dir . 'get-context.php';
    require_once $dir . 'list-power-shortcodes.php';
    require_once $dir . 'create-power-shortcode.php';
    require_once $dir . 'edit-power-shortcode.php';
    require_once $dir . 'delete-power-shortcode.php';
}

/**
 * Load every Contact Form 7 ability file. All abilities gate on
 * `cf7_runtime_available()` (CF7 active + at or above
 * `NOVAMIRA_PRO_CF7_MIN_VERSION`). Submissions are intentionally NOT
 * covered in this surface — CF7 doesn't persist them and Flamingo is a
 * separate plugin.
 */
function novamira_pro_load_cf7_abilities(): void
{
    require_once __DIR__ . '/abilities/cf7/runtime.php';
    $dir = __DIR__ . '/abilities/cf7/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-tags-schema.php';
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'get-form-canonical.php';
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'delete-form.php';
    require_once $dir . 'duplicate-form.php';
}

/**
 * Load every Kadence theme ability file. All abilities gate on the
 * `kadence_theme_available()` runtime check; per-ability sub-gating
 * (e.g. an ability that touches kadence_form CPT) happens inside the
 * ability itself so a missing module returns a clean error rather than
 * a fatal at load time.
 */
function novamira_pro_load_kadence_abilities(): void
{
    require_once __DIR__ . '/abilities/kadence/runtime.php';
    $dir = __DIR__ . '/abilities/kadence/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-customizer-settings.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'edit-settings.php';
    require_once $dir . 'get-theme-json.php';
}

/**
 * Load every Kadence Blocks introspection ability file. Reads the WP block
 * registry to surface the catalogue and per-block attribute schemas;
 * never writes post_content. Reads and writes of block trees on a post
 * go through the `novamira/gutenberg-*` abilities exposed by the base
 * Novamira plugin.
 */
function novamira_pro_load_kadenceblocks_abilities(): void
{
    require_once __DIR__ . '/abilities/kadenceblocks/runtime.php';
    $dir = __DIR__ . '/abilities/kadenceblocks/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-blocks.php';
    require_once $dir . 'get-block-schema.php';
}

/**
 * Load every Spectra One theme ability file. All abilities gate on the
 * `spectra_one_theme_available()` runtime check (theme active at ≥ min
 * version). The Spectra plugin (UAGB) bridge ability additionally sub-gates
 * on `spectra_plugin_available()` at registration time, keeping it out of
 * `discover-abilities` on installs where the companion plugin is absent so
 * the agent's tool list matches the actual capability surface.
 *
 * Sprint 0 is infrastructure-only — it loads the shared runtime + helpers
 * so later sprints can `require_once` individual ability files without
 * duplicating the setup.
 */
function novamira_pro_load_spectra_one_abilities(): void
{
    require_once __DIR__ . '/abilities/spectra-one/runtime.php';
    $dir = __DIR__ . '/abilities/spectra-one/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-theme-info.php';
    require_once $dir . 'list-hooks.php';
    require_once $dir . 'list-style-variations.php';
    require_once $dir . 'list-templates.php';
    require_once $dir . 'get-color-palette.php';
    require_once $dir . 'get-typography-settings.php';
    require_once $dir . 'get-theme-settings.php';
    require_once $dir . 'list-patterns.php';
    require_once $dir . 'set-color-palette.php';
    require_once $dir . 'set-typography.php';
    require_once $dir . 'set-theme-settings.php';
    require_once $dir . 'apply-style-variation.php';
    require_once $dir . 'add-font-family.php';
    require_once $dir . 'edit-navigation.php';
    require_once $dir . 'edit-template-part.php';
    require_once $dir . 'get-post-display-settings.php';
    require_once $dir . 'list-posts-with-display-overrides.php';
    require_once $dir . 'set-post-display-settings.php';
    require_once $dir . 'export-design.php';
    require_once $dir . 'apply-design.php';
    // list-spectra-blocks is gated on the companion Spectra (UAGB)
    // plugin — register only when the plugin is active so the ability
    // never surfaces on installs that would only return
    // spectra_one_requires_plugin.
    if (\Novamira\Pro\Abilities\SpectraOne\spectra_plugin_available()) {
        require_once $dir . 'list-spectra-blocks.php';
    }
}

/**
 * Load every Spectra (UAGB / Ultimate Addons for Gutenberg) ability file. The
 * whole surface gates on `spectra_plugin_available()` (UAGB active at ≥
 * `NOVAMIRA_PRO_SPECTRA_MIN_VERSION`). The Pro sub-loader additionally gates on
 * `spectra_pro_active()`, keeping Pro abilities out of `discover-abilities` on
 * installs that only have the free UAGB — the agent's tool list stays honest.
 *
 * S1 (Discovery + catalogue) is read-only and validates the runtime helpers +
 * check-setup contract before any write path lands in S2.
 */
function novamira_pro_load_spectra_abilities(): void
{
    require_once __DIR__ . '/abilities/spectra/runtime.php';
    $dir = __DIR__ . '/abilities/spectra/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';

    // S1 — Discovery + catalogue.
    require_once $dir . 'list-blocks.php';
    require_once $dir . 'get-block-schema.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'list-popups.php';

    // S2 — Popup CRUD + settings write + block activation.
    require_once $dir . 'get-popup.php';
    require_once $dir . 'create-popup.php';
    require_once $dir . 'edit-popup.php';
    require_once $dir . 'delete-popup.php';
    require_once $dir . 'duplicate-popup.php';
    require_once $dir . 'enable-popup.php';
    require_once $dir . 'disable-popup.php';
    require_once $dir . 'set-editor-settings.php';
    require_once $dir . 'set-block-activation.php';

    // S3 — Google Fonts + form-block discovery.
    require_once $dir . 'list-google-fonts.php';
    require_once $dir . 'set-google-fonts-mode.php';
    require_once $dir . 'list-form-blocks.php';

    // Pro layer — separate spectra-pro/ plugin. Loaded only when active + at
    // or above `NOVAMIRA_PRO_SPECTRA_PRO_MIN_VERSION`, so the free tool
    // surface never advertises Pro-only abilities.
    if (\Novamira\Pro\Abilities\Spectra\spectra_pro_active()) {
        $pro_dir = __DIR__ . '/abilities/spectra/pro/';
        require_once $pro_dir . 'runtime.php';

        // S4 — Pro layer discovery + popup display conditions.
        require_once $pro_dir . 'check-setup.php';
        require_once $pro_dir . 'list-popup-conditions.php';
        require_once $pro_dir . 'set-popup-conditions.php';
    }
}

/**
 * Load every GeneratePress ability file. Group A (theme settings) runs
 * on any GeneratePress install. Groups B (Elements), C (Site Library)
 * and D (Font Library) are sub-gated by the matching GP Premium module
 * detector and conditionally required.
 */
function novamira_pro_load_generatepress_abilities(): void
{
    require_once __DIR__ . '/abilities/generatepress/runtime.php';
    $dir = __DIR__ . '/abilities/generatepress/';

    // Group A — Theme Settings (no GP Premium required).
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'set-settings.php';
    require_once $dir . 'get-defaults.php';
    require_once $dir . 'get-layout.php';
    require_once $dir . 'list-hooks.php';

    // Group B — Elements CRUD + conditions (requires GP Premium Elements).
    if (\Novamira\Pro\Abilities\GeneratePress\gp_elements_active()) {
        require_once $dir . 'list-elements.php';
        require_once $dir . 'get-element.php';
        require_once $dir . 'create-element.php';
        require_once $dir . 'edit-element.php';
        require_once $dir . 'delete-element.php';
        require_once $dir . 'manage-element-conditions.php';
    }

    // Group C — Site Library (requires GP Premium Site Library module).
    if (\Novamira\Pro\Abilities\GeneratePress\gp_site_library_active()) {
        require_once $dir . 'list-sites.php';
        require_once $dir . 'get-site.php';
        require_once $dir . 'apply-site.php';
        require_once $dir . 'restore-site.php';
    }

    // Group D — Font Library (requires GP Premium Font Library module).
    if (\Novamira\Pro\Abilities\GeneratePress\gp_font_library_active()) {
        require_once $dir . 'list-fonts.php';
        require_once $dir . 'add-font.php';
        require_once $dir . 'delete-font.php';
    }

    // Group E — Utility / introspection (theme always-on).
    require_once $dir . 'list-modules.php';
    require_once $dir . 'get-css-output.php';
    require_once $dir . 'get-customizer-schema.php';
}

/**
 * Load every GenerateBlocks ability file. Introspection-only — these
 * abilities read the WP block registry to surface the catalogue and
 * per-block attribute schemas; they never write post_content. Reads
 * and writes of block trees on a post go through the
 * `novamira/gutenberg-*` abilities exposed by the base Novamira plugin.
 */
function novamira_pro_load_generateblocks_abilities(): void
{
    require_once __DIR__ . '/abilities/generateblocks/runtime.php';
    $dir = __DIR__ . '/abilities/generateblocks/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-blocks.php';
    require_once $dir . 'get-block-schema.php';
}

/**
 * Load every OceanWP ability file. All abilities gate on
 * `oceanwp_theme_available()` (OceanWP active + at or above
 * NOVAMIRA_PRO_OCEANWP_THEME_MIN_VERSION). Ocean-Extra-gated abilities
 * (S4: Library + Modules) sub-gate on `ocean_extra_available()` so they
 * only register when the companion plugin is present and at or above its
 * floor — agents on a theme-only install see an honest tool list.
 */
function novamira_pro_load_oceanwp_abilities(): void
{
    $dir = __DIR__ . '/abilities/oceanwp/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-customizer-panels.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'list-hooks.php';
    require_once $dir . 'set-customizer-settings.php';
    require_once $dir . 'set-header-config.php';
    require_once $dir . 'set-typography-preset.php';
    require_once $dir . 'get-page-overrides.php';
    require_once $dir . 'set-page-overrides.php';
    require_once $dir . 'set-woo-features.php';
    require_once $dir . 'list-library-items.php';
    require_once $dir . 'apply-library-template.php';
    require_once $dir . 'list-modules.php';
    require_once $dir . 'enable-module.php';
    require_once $dir . 'disable-module.php';
}

/**
 * Load WooCommerce abilities. Driven by the specialization manifest's
 * `woocommerce` loader entry, gated on the version floor
 * (wc_min_runtime_available()).
 */
function novamira_pro_load_woocommerce_abilities(): void
{
    require_once __DIR__ . '/abilities/woocommerce/helpers.php';
    require_once __DIR__ . '/abilities/woocommerce/runtime.php';
    $wc_dir = __DIR__ . '/abilities/woocommerce/';
    foreach ([
        'check-setup.php',
        'list-products.php',
        'get-product.php',
        'list-product-categories.php',
        'list-product-tags.php',
        'list-product-attributes.php',
        'list-product-types.php',
        'list-product-statuses.php',
        'get-store-settings.php',
        'create-product.php',
        'edit-product.php',
        'delete-product.php',
        'list-product-variations.php',
        'get-product-variation.php',
        'create-product-variation.php',
        'edit-product-variation.php',
        'delete-product-variation.php',
        'create-product-category.php',
        'edit-product-category.php',
        'delete-product-category.php',
        'create-product-tag.php',
        'edit-product-tag.php',
        'delete-product-tag.php',
        'list-product-attribute-terms.php',
        'list-product-shipping-classes.php',
        'create-product-attribute.php',
        'edit-product-attribute.php',
        'delete-product-attribute.php',
        'create-product-attribute-term.php',
        'edit-product-attribute-term.php',
        'delete-product-attribute-term.php',
        'create-product-shipping-class.php',
        'edit-product-shipping-class.php',
        'delete-product-shipping-class.php',
    ] as $file) {
        $path = $wc_dir . $file;
        if (file_exists($path)) {
            require_once $path;
        }
    }
}

/**
 * Load every Formidable Forms ability file. Group A (baseline + discovery)
 * runs on any Formidable install at the minimum version. Group B (form
 * CRUD) reads/writes the wp_frm_forms row. Pro-only surfaces (applications,
 * Pro-only payment ops like cancel-subscription) are sub-gated on
 * frm_pro_active(); the read-only Stripe Lite payment surfaces are gated
 * on frm_payments_supported() so they ship on free installs that have
 * Stripe Lite configured (wp_frm_payments / wp_frm_subscriptions present).
 *
 * Each ability is registered in its own file to keep input schemas sharp
 * and discoverability clean. Files that host multiple closely-related abilities
 * (manage-fields.php, manage-notifications.php) are named after the noun
 * and keep every wp_register_ability() call together.
 */
function novamira_pro_load_formidable_abilities(): void
{
    require_once __DIR__ . '/abilities/formidable/runtime.php';
    $dir = __DIR__ . '/abilities/formidable/';

    // Discovery surface is loaded on `frm_plugin_present()` (any version) so
    // an install with an under-min Formidable can still report state via
    // check-setup. Every OTHER ability is loaded only on `frm_runtime_available()`
    // (≥ min version) — they would crash or behave incorrectly on a 5.x install.
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';

    if (!\Novamira\Pro\Abilities\Formidable\frm_runtime_available()) {
        return;
    }

    // S1 — remaining discovery surfaces (gated on min version).
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'get-form-canonical.php';
    require_once $dir . 'get-field-types-schema.php';

    // S2 — form CRUD.
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'delete-form.php';

    // S3 — field CRUD (3 abilities in one file).
    require_once $dir . 'manage-fields.php';

    // S4 — notifications (5 email-action abilities in one file) +
    // on-submit action (one PUT-style ability).
    require_once $dir . 'manage-notifications.php';
    require_once $dir . 'set-on-submit-action.php';

    // S5 — settings + generic actions read/delete + styles.
    require_once $dir . 'edit-form-settings.php';
    require_once $dir . 'manage-form-actions.php';
    require_once $dir . 'list-styles.php';
    require_once $dir . 'apply-style.php';

    // S6 — entries CRUD (5 abilities in one file).
    require_once $dir . 'manage-entries.php';

    // S7 — applications (6 abilities, Pro-only — sub-gated inside the file).
    if (\Novamira\Pro\Abilities\Formidable\frm_pro_active()) {
        require_once $dir . 'manage-applications.php';
    }

    // S8 — payments (5 abilities, Stripe Lite + Pro). The first 4 read
    // surfaces ship as soon as the wp_frm_payments table exists; cancel
    // additionally gates on Pro inside the callback.
    if (\Novamira\Pro\Abilities\Formidable\frm_payments_supported()) {
        require_once $dir . 'manage-payments.php';
    }
}

/**
 * Load every Gravity Forms ability file in order. Sprint 1 is read-only
 * (check-setup + discovery). Write paths land in later sprints, gated inside
 * this loader.
 */
function novamira_pro_load_gravityforms_abilities(): void
{
    require_once __DIR__ . '/abilities/gravityforms/runtime.php';
    $dir = __DIR__ . '/abilities/gravityforms/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'get-form-canonical.php';
    require_once $dir . 'get-field-types-schema.php';
    require_once $dir . 'get-field-type-schema.php';
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'edit-form-settings.php';
    require_once $dir . 'delete-form.php';
    require_once $dir . 'duplicate-form.php';
    require_once $dir . 'manage-fields.php';
    require_once $dir . 'manage-notifications.php';
    require_once $dir . 'manage-confirmations.php';
    require_once $dir . 'list-entries.php';
    require_once $dir . 'get-entry.php';
    require_once $dir . 'edit-entry.php';
    require_once $dir . 'mark-entry.php';
    require_once $dir . 'delete-entry.php';
}

/**
 * Load every Fluent Forms ability file in the right order. `FLUENTFORM` is
 * defined by both the free and Pro editions (Pro hard-depends on free), so
 * the runtime gate covers both; Pro-only surfaces gate AGAIN at registration
 * inside this loader on `ff_pro_runtime_available()`, keeping them out of
 * `discover-abilities` on free installs.
 */
function novamira_pro_load_fluentforms_abilities(): void
{
    require_once __DIR__ . '/abilities/fluentforms/runtime.php';
    $dir = __DIR__ . '/abilities/fluentforms/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'get-field-types-schema.php';
    require_once $dir . 'list-forms.php';
    require_once $dir . 'get-form.php';
    require_once $dir . 'get-form-canonical.php';
    require_once $dir . 'create-form.php';
    require_once $dir . 'edit-form.php';
    require_once $dir . 'delete-form.php';
    require_once $dir . 'duplicate-form.php';
    require_once $dir . 'manage-fields.php';
    require_once $dir . 'list-submissions.php';
    require_once $dir . 'get-submission.php';
    require_once $dir . 'mark-submission.php';
    require_once $dir . 'delete-submission.php';
    require_once $dir . 'export-submissions.php';
    require_once $dir . 'manage-form-settings.php';
    require_once $dir . 'manage-notifications.php';
    require_once $dir . 'manage-confirmations.php';

    // Sprint 4 — Pro CRUD. Each file early-returns at the top when
    // ff_pro_runtime_available() is false, so the abilities never
    // register on a free FF install. Including the files is still safe
    // because the Pro model stubs cover the worst case where the file
    // is loaded but the runtime isn't there.
    require_once $dir . 'list-transactions.php';
    require_once $dir . 'get-transaction.php';
    require_once $dir . 'list-subscriptions.php';
    require_once $dir . 'get-subscription.php';
    require_once $dir . 'cancel-subscription.php';
    require_once $dir . 'list-draft-submissions.php';
    require_once $dir . 'delete-draft-submission.php';

    // Sprint 5 (optional) — Pro-only quiz + integrations index.
    require_once $dir . 'list-integrations.php';
    require_once $dir . 'list-quiz-questions.php';
    require_once $dir . 'get-quiz-report.php';
}

/**
 * Load Bricks Builder ability files. Called by the manifest loader; caller
 * must gate on defined('BRICKS_VERSION').
 */
function novamira_pro_load_bricks_abilities(): void
{
    $bricks_dir = __DIR__ . '/abilities/bricks/';
    require_once $bricks_dir . 'helpers.php';
    require_once $bricks_dir . 'list-elements.php';
    require_once $bricks_dir . 'list-settings.php';
    require_once $bricks_dir . 'get-content.php';
    require_once $bricks_dir . 'set-content.php';
    require_once $bricks_dir . 'insert-content.php';
    require_once $bricks_dir . 'remove-content.php';
    require_once $bricks_dir . 'patch-elements.php';
    require_once $bricks_dir . 'list-templates.php';
    require_once $bricks_dir . 'create-template.php';
    require_once $bricks_dir . 'manage-template-conditions.php';
    require_once $bricks_dir . 'get-settings.php';
    require_once $bricks_dir . 'set-settings.php';
    require_once $bricks_dir . 'set-post-types.php';
    require_once $bricks_dir . 'manage-dynamic-data.php';
    require_once $bricks_dir . 'manage-components.php';
    require_once $bricks_dir . 'manage-interactions.php';
    require_once $bricks_dir . 'manage-color-palette.php';
    require_once $bricks_dir . 'manage-global-classes.php';
    require_once $bricks_dir . 'manage-variables.php';
    require_once $bricks_dir . 'manage-theme-styles.php';
    require_once $bricks_dir . 'check-setup.php';
}

/**
 * Load Bricksforge abilities. Gated on
 * \Novamira\Pro\Abilities\Bricksforge\brf_runtime_available().
 */
function novamira_pro_load_bricksforge_abilities(): void
{
    $dir = __DIR__ . '/abilities/bricksforge/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-tools.php';
    require_once $dir . 'list-custom-elements.php';
    require_once $dir . 'enable-tool.php';
    require_once $dir . 'disable-tool.php';
    require_once $dir . 'enable-element.php';
    require_once $dir . 'disable-element.php';
    require_once $dir . 'manage-popups.php';
    require_once $dir . 'manage-email-templates.php';
    require_once $dir . 'manage-email-themes.php';
}

/**
 * Load Beaver Builder abilities. Gated on
 * \Novamira\Pro\Abilities\BeaverBuilder\bb_runtime_available().
 */
function novamira_pro_load_beaver_builder_abilities(): void
{
    require_once __DIR__ . '/abilities/beaver-builder/runtime.php';
    $dir = __DIR__ . '/abilities/beaver-builder/';
    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-modules.php';
    require_once $dir . 'get-module.php';
    require_once $dir . 'get-structure-schema.php';
    require_once $dir . 'list-layouts.php';
    require_once $dir . 'get-layout.php';
    require_once $dir . 'set-layout.php';
    require_once $dir . 'add-node.php';
    require_once $dir . 'edit-node.php';
    require_once $dir . 'delete-node.php';
    require_once $dir . 'move-node.php';
    require_once $dir . 'manage-global-colors.php';
    require_once $dir . 'manage-global-typography.php';
    require_once $dir . 'manage-templates.php';
}

/**
 * Load the always-available core abilities (generic WordPress, Skills) and
 * the optional Memory abilities.
 */
/**
 * Load the generic WordPress abilities (always available). Gating is handled by
 * the manifest entry; this loader only requires the files.
 */
function novamira_pro_load_wordpress_abilities(): void
{
    $wordpress_dir = __DIR__ . '/abilities/wordpress/';
    require_once $wordpress_dir . 'helpers.php';
    require_once $wordpress_dir . 'create-post.php';
    require_once $wordpress_dir . 'update-post.php';
    require_once $wordpress_dir . 'delete-post.php';
}

/**
 * Load the canonical `novamira/skill-get` ability. `bootstrap.php` (skill_scan +
 * parser) and `source-filter.php` (the `novamira_skill_lookup_sources` callback)
 * are loaded earlier at `plugins_loaded` priority 20 so the Skills admin page can
 * see Pro's catalog even when nothing has touched the abilities registry yet.
 *
 * The skip when Novamira free owns the ability itself lives in the manifest entry
 * `load_gate` — free routes Pro lookups through the lookup-sources filter that
 * source-filter.php already feeds.
 */
function novamira_pro_load_skill_abilities(): void
{
    require_once __DIR__ . '/abilities/skill/get.php';
}

/**
 * Load the memory abilities (backed by a custom post type). The
 * `nvp_memory_enabled` toggle is enforced by the manifest entry `gate`; this
 * loader only requires the files.
 */
function novamira_pro_load_memory_abilities(): void
{
    $memory_dir = __DIR__ . '/abilities/memory/';
    require_once $memory_dir . 'list.php';
    require_once $memory_dir . 'get.php';
    require_once $memory_dir . 'save.php';
    require_once $memory_dir . 'delete.php';
}

/**
 * Load every Mosaic ability for the current request. Gated by
 * mo_runtime_available() at the caller — this function trusts that the
 * runtime + schema are ready.
 */
function novamira_pro_load_mosaic_abilities(): void
{
    require_once __DIR__ . '/abilities/mosaic/runtime.php';
    $dir = __DIR__ . '/abilities/mosaic/';

    require_once $dir . 'helpers.php';
    require_once $dir . 'check-setup.php';
    require_once $dir . 'check-design-system.php';
    require_once $dir . 'list-themes.php';
    require_once $dir . 'list-templates.php';
    require_once $dir . 'list-components.php';
    require_once $dir . 'list-collections.php';
    require_once $dir . 'list-variables.php';
    require_once $dir . 'list-utility-classes.php';
    require_once $dir . 'get-theme.php';
    require_once $dir . 'get-template.php';
    require_once $dir . 'get-element-tree.php';
    require_once $dir . 'manage-elements.php';
    require_once $dir . 'edit-component-instance-override.php';
    require_once $dir . 'manage-templates.php';
    require_once $dir . 'manage-template-assigns.php';
    require_once $dir . 'manage-theme-settings.php';
    require_once $dir . 'manage-utility-classes.php';
    require_once $dir . 'manage-collections.php';
    require_once $dir . 'manage-variables.php';
}

/**
 * Load the Divi 5 builder ability files. Caller must gate on
 * {@see novamira_pro_divi_available()}.
 */
function novamira_pro_load_divi_abilities(): void
{
    $divi_dir = __DIR__ . '/abilities/divi/';
    require_once $divi_dir . 'helpers.php';
    require_once $divi_dir . 'tree.php';
    require_once $divi_dir . 'check-setup.php';
    require_once $divi_dir . 'list-modules.php';
    require_once $divi_dir . 'get-module-schema.php';
    require_once $divi_dir . 'get-content.php';
    require_once $divi_dir . 'set-content.php';
    require_once $divi_dir . 'add-module.php';
    require_once $divi_dir . 'edit-module.php';
    require_once $divi_dir . 'delete-module.php';
    require_once $divi_dir . 'move-module.php';
    require_once $divi_dir . 'list-dynamic-sources.php';
    require_once $divi_dir . 'apply-dynamic-content.php';
    require_once $divi_dir . 'clear-dynamic-content.php';
    require_once $divi_dir . 'list-loop-query-types.php';
    require_once $divi_dir . 'enable-loop.php';
    require_once $divi_dir . 'disable-loop.php';
    require_once $divi_dir . 'edit-loop.php';
    require_once $divi_dir . 'manage-global-presets.php';
    require_once $divi_dir . 'manage-global-colors.php';
    require_once $divi_dir . 'manage-variables.php';
    require_once $divi_dir . 'manage-global-fonts.php';
    require_once $divi_dir . 'manage-display-conditions.php';
    require_once $divi_dir . 'manage-interactions.php';
    require_once $divi_dir . 'manage-library.php';
    require_once $divi_dir . 'get-style-schema.php';
    require_once $divi_dir . 'list-theme-builder-templates.php';
    require_once $divi_dir . 'manage-theme-builder.php';
}

/**
 * Load the Avada theme ability files. Caller must gate on
 * {@see \Novamira\Pro\Abilities\Avada\avada_theme_available()}.
 *
 * Theme-side layer only (Fusion Settings, AWB global tokens, Portfolio + FAQ
 * CPTs, Fusion hook discovery). A separate Fusion Builder plugin-scoped
 * sub-loader (element tree CRUD, Template Builder, Fusion Forms) is not
 * implemented today and is intentionally not scaffolded here — no dangling
 * conditional includes.
 */
function novamira_pro_load_avada_abilities(): void
{
    $avada_dir = __DIR__ . '/abilities/avada/';
    require_once $avada_dir . 'runtime.php';
    require_once $avada_dir . 'helpers.php';
    require_once $avada_dir . 'check-setup.php';
    require_once $avada_dir . 'list-hooks.php';
    require_once $avada_dir . 'get-theme-options.php';
    require_once $avada_dir . 'list-portfolio-items.php';
    require_once $avada_dir . 'list-faqs.php';
    require_once $avada_dir . 'list-global-colors.php';
    require_once $avada_dir . 'list-global-typography.php';
    require_once $avada_dir . 'edit-global-color.php';
    require_once $avada_dir . 'edit-global-typography.php';
    require_once $avada_dir . 'set-theme-options.php';

    // Fusion Core Slider surface. Registered only when the companion plugin
    // is active at the version floor — the theme-side surface above stays
    // available regardless. `fusion_core_available()` guards against the
    // constants-defined-but-classes-not-loaded window during plugins_loaded.
    if (\Novamira\Pro\Abilities\Avada\fusion_core_available()) {
        require_once $avada_dir . 'list-sliders.php';
        require_once $avada_dir . 'get-slider.php';
        require_once $avada_dir . 'list-slides.php';
        require_once $avada_dir . 'get-slide.php';
        require_once $avada_dir . 'edit-slide.php';
        require_once $avada_dir . 'edit-slider-settings.php';
    }
}

/**
 * One-shot data repair for empty `data` / `conditions` blobs that
 * mismatch Mosaic's per-column revision-record property type:
 *
 *   - wp_mosaic_templates.conditions → TemplateRevisionRecord::$conditions
 *     is `?array`. Decoded with `json_decode($raw)` (no assoc). A `{}`
 *     literal lands as stdClass and crashes with a TypeError on every
 *     URL the template resolves to AND the admin Templates list.
 *     Empty must be `[]`.
 *
 *   - wp_mosaic_nodes.data → NodeRevisionRecord::$data is strictly `object`.
 *     A `[]` literal would decode to a PHP array and crash on assign to
 *     the object-typed property — same TypeError vector. Empty must be `{}`.
 *
 * Pre-Round-2 builds got both wrong (Round 1 normalised everything to
 * `{}` then Round 2 flipped everything to `[]`). The fix below converges
 * each table to the column's correct empty literal idempotently. Guarded
 * by a versioned sentinel so we don't re-scan on every request.
 *
 * Round 7 G4 timing fix: the repair MUST run before Mosaic's own
 * `init` hook reads `wp_mosaic_themes.data`. A corrupted `data='[]'`
 * row crashes `ThemeRevisionRecord` with a TypeError before any other
 * code in the request runs — including the abilities surface that
 * would have healed it. Five independent round-7 probes (G3, G4, G5,
 * G7, G1) hit this crash mid-session. The hook below is `plugins_loaded`
 * priority 1, which fires before `init` and gives us a chance to heal
 * data before Mosaic touches it.
 *
 * Round 7 G2 defense: the function also re-checks that the 4 target
 * tables exist before running queries. If a Mosaic schema bootstrap
 * partially failed (e.g. on a multisite subsite where Mosaic has not
 * yet provisioned its tables), we exit early WITHOUT arming the
 * sentinel — so a future request retries once Mosaic finishes
 * provisioning.
 */
function novamira_pro_mosaic_repair_legacy_empty_blobs(): void
{
    $sentinel = 'novamira_pro_mosaic_repair_v2';
    if (get_option($sentinel) === '1') {
        return;
    }
    if (!defined('MOSAIC_VERSION')) {
        // Mosaic is not loaded on this site (likely a multisite subsite
        // without the plugin network-activated). Nothing to repair.
        return;
    }
    global $wpdb;
    /** @var \wpdb $wpdb */
    $templates = $wpdb->prefix . 'mosaic_templates';
    $nodes = $wpdb->prefix . 'mosaic_nodes';
    $themes = $wpdb->prefix . 'mosaic_themes';
    $utility = $wpdb->prefix . 'mosaic_utility_classes';
    // Verify all 4 target tables exist before issuing UPDATEs. Bypassing
    // the outer mo_tables_present() gate (which lives in the abilities
    // layer that isn't loaded yet at plugins_loaded priority 1) — use
    // INFORMATION_SCHEMA so we don't need the helpers file.
    $expected = [$templates, $nodes, $themes, $utility];
    $placeholders = implode(', ', array_fill(start_index: 0, count: count($expected), value: '%s'));
    $count_sql = (string) $wpdb->prepare(
        "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN ({$placeholders})",
        $expected,
    );
    $present = (int) $wpdb->get_var($count_sql);
    if ($present !== count($expected)) {
        // Mosaic schema incomplete — likely lazy-provisioning hasn't fired
        // on this subsite yet. Do NOT arm the sentinel; retry next request.
        return;
    }
    // Array-typed columns: `{}` -> `[]`
    $wpdb->query("UPDATE `{$templates}` SET `conditions` = '[]' WHERE `conditions` = '{}'");
    // Object-typed columns: `[]` -> `{}`
    $wpdb->query("UPDATE `{$nodes}` SET `data` = '{}' WHERE `data` = '[]'");
    $wpdb->query("UPDATE `{$themes}` SET `data` = '{}' WHERE `data` = '[]'");
    $wpdb->query("UPDATE `{$utility}` SET `data` = '{}' WHERE `data` = '[]'");
    update_option($sentinel, value: '1', autoload: false);
}

/**
 * Load every Astra ability. Sprint 1 (discovery + read-only) is always loaded
 * on any active Astra install. Later sprints (S2 global CRUD, S3 HFB, S4 per-post
 * overrides, S5 Advanced Hooks, S6 Advanced Headers, S7 WooCommerce styling)
 * will extend this function; module gates for the addon-specific abilities live
 * inside the callbacks themselves via `astra_module_active()`.
 */
function novamira_pro_load_astra_abilities(): void
{
    require_once __DIR__ . '/abilities/astra/runtime.php';
    $dir = __DIR__ . '/abilities/astra/';
    require_once $dir . 'helpers.php';

    // Sprint 1 — Discovery + read-only globals.
    require_once $dir . 'check-setup.php';
    require_once $dir . 'list-modules.php';
    require_once $dir . 'get-settings.php';
    require_once $dir . 'get-defaults.php';
    require_once $dir . 'get-layout.php';
    require_once $dir . 'list-customizer-settings.php';
    require_once $dir . 'get-css-output.php';

    // Sprint 2 — Global settings CRUD + palette + typography + module toggle.
    require_once $dir . 'edit-settings.php';
    require_once $dir . 'set-color-palette.php';
    require_once $dir . 'get-color-palette.php';
    require_once $dir . 'set-typography.php';
    require_once $dir . 'enable-module.php';
    require_once $dir . 'disable-module.php';

    // Sprint 3 — Header/Footer Builder.
    require_once $dir . 'get-header-layout.php';
    require_once $dir . 'get-footer-layout.php';
    require_once $dir . 'set-header-layout.php';
    require_once $dir . 'set-footer-layout.php';
    require_once $dir . 'reorder-header-row.php';

    // Per-post display overrides.
    require_once $dir . 'get-post-settings.php';
    require_once $dir . 'set-post-settings.php';
    require_once $dir . 'clear-post-settings.php';
    require_once $dir . 'set-post-background.php';

    // Advanced Hooks CPT (addon-gated advanced-hooks module).
    if (\Novamira\Pro\Abilities\Astra\astra_module_active('advanced-hooks')) {
        require_once $dir . 'list-hooks.php';
        require_once $dir . 'get-hook.php';
        require_once $dir . 'create-hook.php';
        require_once $dir . 'edit-hook.php';
        require_once $dir . 'delete-hook.php';
    }

    // Advanced Headers CPT (addon-gated advanced-headers module).
    if (\Novamira\Pro\Abilities\Astra\astra_module_active('advanced-headers')) {
        require_once $dir . 'list-page-headers.php';
        require_once $dir . 'get-page-header.php';
        require_once $dir . 'create-page-header.php';
        require_once $dir . 'edit-page-header.php';
        require_once $dir . 'delete-page-header.php';
    }

    // WooCommerce Astra Pro styling (addon + module + WC gated).
    if (
        \Novamira\Pro\Abilities\Astra\astra_module_active('woocommerce')
        && \Novamira\Pro\Abilities\Woocommerce\wc_min_runtime_available()
    ) {
        require_once $dir . 'get-woocommerce-settings.php';
        require_once $dir . 'edit-woocommerce-settings.php';
    }
}

/**
 * Load the Voxel theme ability files. check-setup is the presence-gated
 * baseline (it reports the version gap even below the minimum); the read-only
 * discovery abilities (list-post-types, get-post-type, get-field, list-posts,
 * get-post) each refuse below the floor via vx_require_min(). Later sprints add
 * content CRUD, taxonomies, commerce, and community abilities.
 */
function novamira_pro_load_voxel_abilities(): void
{
    $dir = __DIR__ . '/abilities/voxel/';
    $files = [
        'runtime.php',
        'helpers.php',
        'write-helpers.php',
        'term-helpers.php',
        'config-helpers.php',

        // Sprint 1 — Baseline + discovery (read-only).
        'check-setup.php',
        'list-post-types.php',
        'get-post-type.php',
        'get-field.php',
        'list-posts.php',
        'get-post.php',

        // Sprint 2 — Listing/content CRUD (writes postmeta per post).
        'create-post.php',
        'edit-post.php',
        'delete-post.php',

        // Sprint 3 — Taxonomies + terms.
        'list-taxonomies.php',
        'get-taxonomy.php',
        'list-terms.php',
        'get-term.php',
        'create-term.php',
        'edit-term.php',
        'delete-term.php',

        // Sprint 4 — Site config / builder (mutates the shared voxel:post_types /
        // voxel:taxonomies option blobs under a lock; excludes search-filter/index edits).
        'create-taxonomy.php',
        'edit-taxonomy.php',
        'delete-taxonomy.php',
        'create-post-type.php',
        'edit-post-type.php',
        'delete-post-type.php',
        'add-field.php',
        'edit-field.php',
        'delete-field.php',
        'reorder-fields.php',

        // Sprint 5 — Commerce (read-only: orders, product types, plans, roles,
        // membership). No writes, no Stripe calls; orders/membership are scoped to
        // the site's current payments mode.
        'commerce-helpers.php',
        'list-orders.php',
        'get-order.php',
        'list-product-types.php',
        'get-product-type.php',
        'list-plans.php',
        'get-plan.php',
        'list-roles.php',
        'get-role.php',
        'get-user-membership.php',

        // Sprint 6 — Community + templates + settings. Reads are strict (approved
        // content only, secrets redacted); the only writes are a per-row notification
        // seen flip and lock-wrapped template assignment. Private messages are
        // excluded entirely (PII), as are settings secrets and destructive/moderation
        // community operations.
        'community-helpers.php',
        'list-timeline.php',
        'get-status.php',
        'list-replies.php',
        'list-notifications.php',
        'get-notification.php',
        'mark-notification.php',
        'list-followers.php',
        'get-follow-status.php',
        'list-templates.php',
        'apply-template.php',
        'clear-template.php',
        'list-settings.php',
        'get-setting.php',

        // Audit additions — read-only introspection: the field-type prop reference
        // and the post-relation graph.
        'get-field-type-schema.php',
        'list-related-posts.php',

        // Sprint 7 — Dynamic data (VoxelScript). Discovery is read-only via Voxel's
        // own exporter; rendering binds explicit entity contexts (the query_var
        // site method still reads Voxel's ambient visibility-context stack, then
        // $_GET — documented, warned about, not sandboxed).
        'list-dynamic-data.php',
        'render-dynamic-data.php',

        // Per-post-type base templates — create the Elementor documents (or the
        // form page) for a post type's single/card/archive/form slots and
        // bind/unbind them (config write under the post_types lock, document-type
        // fixup mirroring Voxel's admin).
        'post-type-template-helpers.php',
        'create-post-type-template.php',
        'apply-post-type-template.php',
        'clear-post-type-template.php',
    ];
    foreach ($files as $file) {
        require_once $dir . $file;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit