Plugin Directory

Changeset 3422687


Ignore:
Timestamp:
12/18/2025 09:39:57 AM (3 months ago)
Author:
eitanatbrightleaf
Message:

Update to version 1.3.6 from GitHub

Location:
mass-email-notifications-for-gravity-forms
Files:
2 added
36 edited
1 copied

Legend:

Unmodified
Added
Removed
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/class-mass-email-notifications-for-gravity-forms.php

    r3420209 r3422687  
    88use MENFGF\GravityOps\Core\Utils\AssetHelper;
    99use MENFGF\GravityOps\Core\Admin\AdminShell;
     10use function MENFGF\GravityOps\Core\Admin\gravityops_shell;
    1011if ( !defined( 'ABSPATH' ) ) {
    1112    exit;
     
    206207        parent::init_admin();
    207208        // Register the new GravityOps AdminShell page under the parent menu.
    208         AdminShell::instance()->register_plugin_page( $this->_slug, [
     209        gravityops_shell()->register_plugin_page( $this->_slug, [
    209210            'title'      => $this->_title,
    210211            'menu_title' => $this->_short_title,
     
    326327     */
    327328    public function gops_render_suppressions() {
     329        $groups = $this->get_structured_suppressions();
    328330        echo '<div class="gops-card">';
    329         echo '<h2 class="gops-title" style="margin:0 0 8px;">Suppressions</h2>';
    330         if ( !method_exists( $this, 'get_structured_suppressions' ) ) {
    331             echo '<p>Suppression list is not available.</p>';
    332             echo '</div>';
    333             return;
    334         }
    335         $groups = $this->get_structured_suppressions();
    336         if ( empty( $groups ) || !is_array( $groups ) ) {
     331        echo '<h2 class="gops-title" style="margin:0 0 8px;">Suppressions (' . count( $groups ) . ')</h2>';
     332        if ( empty( $groups ) ) {
    337333            echo '<p>No suppressed emails found.</p>';
    338334            echo '</div>';
     
    22672263        header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
    22682264        echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">' . '<title>Unsubscribed</title>' . '<style>body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;line-height:1.5;padding:40px;background:#f6f7f9;color:#1d2327} .menfgf-unsub{max-width:560px;margin:40px auto;background:#fff;border:1px solid #ccd0d4;border-radius:8px;padding:24px;box-shadow:0 3px 8px rgba(0,0,0,.05)} .menfgf-unsub h1{font-size:20px;margin:0 0 8px} .menfgf-unsub p{margin:8px 0 0;color:#3c434a}</style></head><body>' . '<div class="menfgf-unsub"><h1>You have been unsubscribed</h1><p>You will no longer receive these mass email notifications from this site. You can close this tab.</p></div>' . '</body></html>';
    2269         wp_die();
     2265        exit;
    22702266    }
    22712267
     
    29602956            false,
    29612957            false,
    2962             $disable_auto_format
     2958            !$disable_auto_format
    29632959        );
    29642960        $this->log_debug( __METHOD__ . '() - processed text ' . $processed_text );
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/mass-email-notifications-for-gf.php

    r3420881 r3422687  
    66 * Author URI: https://brightleafdigital.io/
    77 * Description: Allows you to send notifications to everyone who filled out any of your forms.
    8  * Version: 1.3.5
     8 * Version: 1.3.6
    99 * Author: BrightLeaf Digital
    1010 * License: GPL-2.0+
     
    1313 * @package MassEmailNotificationsForGravityForms
    1414 */
     15use MENFGF\GravityOps\Core\Admin\AdminShell;
    1516if ( !defined( 'ABSPATH' ) ) {
    1617    exit;
     
    1819}
    1920require_once __DIR__ . '/vendor/autoload.php';
     21// Instantiate this plugin's copy of the AdminShell early so provider negotiation can happen on plugins_loaded.
     22add_action( 'plugins_loaded', function () {
     23    AdminShell::instance();
     24}, 1 );
    2025if ( function_exists( 'menfgf_fs' ) ) {
    2126    menfgf_fs()->set_basename( false, __FILE__ );
     
    6671    }
    6772    menfgf_fs()->add_filter( 'enable_cpt_advanced_menu_logic', '__return_true' );
    68     define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.5' );
     73    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.6' );
    6974    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_BASENAME', plugin_basename( __FILE__ ) );
    7075    add_action( 'admin_notices', function () {
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/readme.txt

    r3420881 r3422687  
    22Tested up to: 6.9
    33Tags: GravityForms, notifications, email, task management, automation
    4 Stable tag: 1.3.5
     4Stable tag: 1.3.6
    55Requires PHP: 8.0
    66License: GPLv2 or later
     
    4444== Changelog ==
    4545
     46= 1.3.6 | Dec 18, 2025 =
     47* Fixed a bug in the new plugin menu where installed plugins would show as uninstalled
     48* Fixed some PHP error warnings
     49* Fixed a 500 response error returned when someone unsubscribed without a landing page configured
     50* Fixed a bug preventing auto formatting being disabled in some circumstances
     51
    4652= 1.3.5 | Dec 16, 2025 =
    4753* Fixed another bug in new plugin menu
     
    6268* Added shortocde support for premium and agency plans.
    6369* Added a GravityFlow workflow step for premium and agency plans.
    64 
    65 = 1.3.1 =
    66 * A few small quality of life improvements.
    67 
    68 = 1.3.0 =
    69 * A host of small UI/UX enhancements.
    70 * Added unsubscribe management features.
    71 * Added double opt-in management features.
    72 
    73 = 1.2.9 =
    74 * Fixed a bug where feed labels would not always display in the batch table.
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/autoload.php

    r3420881 r3422687  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808::getLoader();
     22return ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa::getLoader();
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/composer/autoload_real.php

    r3420881 r3422687  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808
     5class ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \MENFGF\Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::getInitializer($loader));
     32        call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::getInitializer($loader));
    3333
    3434        $loader->setClassMapAuthoritative(true);
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/composer/autoload_static.php

    r3420881 r3422687  
    55namespace MENFGF\Composer\Autoload;
    66
    7 class ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808
     7class ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa
    88{
    99    public static $prefixLengthsPsr4 = array (
     
    3636    {
    3737        return \Closure::bind(function () use ($loader) {
    38             $loader->prefixLengthsPsr4 = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$prefixLengthsPsr4;
    39             $loader->prefixDirsPsr4 = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$prefixDirsPsr4;
    40             $loader->classMap = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$classMap;
     38            $loader->prefixLengthsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixLengthsPsr4;
     39            $loader->prefixDirsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixDirsPsr4;
     40            $loader->classMap = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$classMap;
    4141
    4242        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/composer/installed.json

    r3420881 r3422687  
    33        "1": {
    44            "name": "gravityops/core",
    5             "version": "1.0.18",
    6             "version_normalized": "1.0.18.0",
     5            "version": "1.0.21",
     6            "version_normalized": "1.0.21.0",
    77            "source": {
    88                "type": "git",
    99                "url": "git@github.com:Eitan-brightleaf/gravityops.git",
    10                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68"
     10                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
    1111            },
    1212            "dist": {
    1313                "type": "zip",
    14                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/a74352489b658ed6a7f1c588abb2e18aae065a68",
    15                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68",
     14                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     15                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    1616                "shasum": ""
    1717            },
     
    1919                "php": ">=7.4"
    2020            },
    21             "time": "2025-12-16T09:58:09+00:00",
     21            "time": "2025-12-18T07:45:02+00:00",
    2222            "type": "library",
    2323            "installation-source": "source",
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/composer/installed.php

    r3420881 r3422687  
    55    'pretty_version' => 'dev-main',
    66    'version' => 'dev-main',
    7     'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     7    'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    88    'type' => 'library',
    99    'install_path' => __DIR__ . '/../',
     
    1717    'gravityops/core' =>
    1818    array (
    19       'pretty_version' => '1.0.18',
    20       'version' => '1.0.18.0',
    21       'reference' => 'a74352489b658ed6a7f1c588abb2e18aae065a68',
     19      'pretty_version' => '1.0.21',
     20      'version' => '1.0.21.0',
     21      'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
    2222      'type' => 'library',
    2323      'install_path' => __DIR__ . '/../gravityops/core',
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/gravityops/core/src/Admin/AdminShell.php

    r3420881 r3422687  
    1616
    1717    /**
     18     * Library/core version used for provider negotiation.
     19     * The highest version across loaded copies should be selected as provider.
     20     */
     21    public const CORE_VERSION = '1.0.21';
     22
     23    /**
    1824     * Holds the singleton instance.
    1925     *
     
    2127     */
    2228    private static ?AdminShell $instance = null;
     29
     30    /**
     31     * Tracks whether the chosen provider has already booted (registered hooks).
     32     * Prevents multiple copies from attaching side‑effect hooks.
     33     *
     34     * @var bool
     35     */
     36    private static bool $did_boot = false;
    2337
    2438    /**
     
    3549     * Get singleton instance.
    3650     */
    37     public static function instance(): AdminShell {
    38         // First, try to get a shared instance provided by any loaded copy via filter.
     51    public static function instance() {
     52        // New: negotiate best provider by highest version (cross‑namespace).
     53        $best = apply_filters( 'gravityops_shell_provider', null );
     54        if ( is_array( $best ) && isset( $best['shell'] ) ) {
     55            return $best['shell'];
     56        }
     57
     58        // Legacy: try a shared instance provided by any copy.
    3959        $shared = apply_filters( 'gravityops_shell_instance', null );
    4060        if ( $shared instanceof self ) {
    4161            return $shared;
    4262        }
     63
    4364        if ( null === self::$instance ) {
    4465            self::$instance = new self();
     
    5374     */
    5475    private function __construct() {
    55         // Cross-namespace shared instance resolver: first provider wins.
    56         $existing = apply_filters( 'gravityops_shell_instance', null );
    57         if ( $existing && $existing !== $this ) {
    58             // Another copy has already provided an instance; avoid duplicate hooks.
    59             return;
    60         }
    61 
    62         // Expose this instance for other namespaces/copies to reuse.
     76        // Expose this instance for other namespaces/copies to reuse (legacy "first copy wins").
    6377        add_filter(
    6478            'gravityops_shell_instance',
     
    6983        );
    7084
    71         // Defer adding menus until after all plugins have registered.
    72         add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
    73         // Do NOT hide submenus by default; users reported accessibility issues.
    74         // If needed in the future, this can be reintroduced behind a filter.
    75         add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     85        // Versioned provider negotiation: highest version wins.
     86        add_filter(
     87            'gravityops_shell_provider',
     88            function ( $best ) {
     89                $mine = [
     90                    'version' => self::CORE_VERSION,
     91                    'shell'   => $this,
     92                ];
     93                if ( ! is_array( $best ) || empty( $best['version'] ) ) {
     94                    return $mine;
     95                }
     96                return version_compare( (string) $mine['version'], (string) $best['version'], '>' ) ? $mine : $best;
     97            },
     98            1
     99        );
     100
     101        // Defer side‑effect hooks until we negotiate the best provider.
     102        // Each copy registers this, but only the selected provider will actually boot.
     103        // If instantiated after plugins_loaded has already fired, boot immediately.
     104        if ( function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
     105            $this->maybe_boot();
     106        } else {
     107            add_action( 'plugins_loaded', [ $this, 'maybe_boot' ], 20 );
     108        }
    76109    }
    77110
     
    84117     * @return bool True if the page exists.
    85118     */
    86     public static function has_page( string $slug ): bool {
     119    public static function has_page( $slug ) {
    87120        $provider = apply_filters( 'gravityops_shell_instance', null );
    88121        if ( $provider instanceof self ) {
     
    112145     * @return array<string,array<string,string>> Tabs config array suitable to merge with register_plugin_page() tabs.
    113146     */
    114     public static function freemius_tabs( string $plugin_slug, array $labels = [] ): array {
     147    public static function freemius_tabs( $plugin_slug, $labels = [] ) {
    115148        $default_labels = [
    116149            'account'     => 'Account',
     
    164197     * @return void
    165198     */
    166     public static function render_feeds_list( array $feeds_and_forms, string $gf_subview_slug, string $plugin_short_title, string $toggle_action ): void {
     199    public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action ) {
    167200        echo '<div class="gops-card">';
    168201        echo '<h2 class="gops-title" style="margin:0 0 10px;">' . esc_html( $plugin_short_title ) . ' Feeds</h2>';
     
    224257     * @return void
    225258     */
    226     public static function process_feed_toggle( string $action_prefix, string $return_url ) {
     259    public static function process_feed_toggle( $action_prefix, $return_url ) {
    227260        if ( empty( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) || 'POST' !== ( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ?? '' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    228261            wp_safe_redirect( admin_url( $return_url ) );
     
    262295     * @return void
    263296     */
    264     public static function render_help_tab( array $links ): void {
     297    public static function render_help_tab( $links ) {
    265298        echo '<div class="gops-card">';
    266299        echo '<h2 class="gops-title" style="margin:0 0 8px;">Help</h2>';
     
    282315     * @param array  $args Page configuration.
    283316     */
    284     public function register_plugin_page( string $slug, array $args ): void {
    285         // If another copy is the active provider, forward registration to it.
     317    public function register_plugin_page( $slug, $args ) {
     318        // If another copy is the active provider (new negotiation), forward registration to it first.
     319        $best = apply_filters( 'gravityops_shell_provider', null );
     320        if ( is_array( $best ) && isset( $best['shell'] ) && $best['shell'] !== $this && is_object( $best['shell'] ) && method_exists( $best['shell'], 'register_plugin_page' ) ) {
     321            $best['shell']->register_plugin_page( $slug, $args );
     322            return;
     323        }
     324        // Legacy shared-instance forwarding as a fallback.
    286325        $provider = apply_filters( 'gravityops_shell_instance', null );
    287326        if ( $provider && $provider !== $this && is_object( $provider ) && method_exists( $provider, 'register_plugin_page' ) ) {
    288             // Call method on the provider (may be a different class/namespace).
    289327            $provider->register_plugin_page( $slug, $args );
    290328            return;
     
    304342     * Add the submenu pages under the shared GravityOps parent.
    305343     */
    306     public function register_menus(): void {
     344    public function register_menus() {
    307345        if ( class_exists( __NAMESPACE__ . '\\SuiteMenu' ) ) {
    308346            SuiteMenu::ensure_parent_menu();
     
    342380     * @param string $hook Current admin page hook.
    343381     */
    344     public function enqueue_assets( $hook ): void {
     382    public function enqueue_assets( $hook ) {
    345383        $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    346384
     
    375413
    376414    /**
     415     * Boot the chosen provider (register side‑effect hooks). Called once.
     416     *
     417     * @return void
     418     */
     419    private function boot() {
     420        if ( self::$did_boot ) {
     421            return;
     422        }
     423        // Defer adding menus until after all plugins have registered.
     424        add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
     425        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     426        self::$did_boot = true;
     427    }
     428
     429    /**
     430     * On plugins_loaded, negotiate the best provider and boot only that one.
     431     * Each copy registers this callback, but only the selected provider acts.
     432     *
     433     * @return void
     434     */
     435    public function maybe_boot() {
     436        if ( self::$did_boot ) {
     437            return;
     438        }
     439        $best = apply_filters( 'gravityops_shell_provider', null );
     440        if ( is_array( $best ) && isset( $best['shell'] ) ) {
     441            if ( $best['shell'] === $this ) {
     442                $this->boot();
     443            }
     444            return;
     445        }
     446        // If no provider negotiation is available, fall back to local boot (legacy environments).
     447        $shared = apply_filters( 'gravityops_shell_instance', null );
     448        if ( $shared && $shared !== $this ) {
     449            // Another copy is acting as shared instance; let it boot on its own call.
     450            return;
     451        }
     452        $this->boot();
     453    }
     454
     455    /**
    377456     * Render the complete page including header, pills, and tab content.
    378457     *
     
    380459     * @param array  $args Page config.
    381460     */
    382     public function render_page( string $slug, array $args ): void {
     461    public function render_page( $slug, $args ) {
    383462        if ( ! current_user_can( $args['capability'] ?? 'manage_options' ) ) {
    384463            return;
     
    435514     * @return void
    436515     */
    437     private function render_header_only( array $args ): void {
     516    private function render_header_only( $args ) {
    438517        ?>
    439518        <header class="gops-header">
     
    471550     * @return array{css:string,js:string}
    472551     */
    473     public static function resolve_assets_urls(): array {
     552    public static function resolve_assets_urls() {
    474553        $base_url = apply_filters( 'gravityops_assets_base_url', '' );
    475554        $css      = '';
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/gravityops/core/src/Admin/SuiteMenu.php

    r3420881 r3422687  
    3030     */
    3131    private static $did_notice_hook = false;
     32
     33    /**
     34     * Track whether the parent GravityOps menu has already been registered.
     35     * Prevents duplicate add_menu_page() calls and ensures a single owner of the parent page.
     36     *
     37     * @var bool
     38     */
     39    private static $did_parent_menu = false;
    3240
    3341    /**
     
    5563     */
    5664    public static function ensure_parent_menu( $capability = '' ) {
    57         global $menu;
    58 
    59         $menu_slug = 'gravity_ops';
    60 
    61         // If another plugin in the suite has already created the menu, we don't need to do anything.
    62         if ( ! empty( $menu ) && in_array( $menu_slug, array_column( $menu, 2 ), true ) ) {
    63             return;
     65        global $menu;
     66
     67        $menu_slug = 'gravity_ops';
     68
     69        // Internal idempotency guard — if we've already added the parent once this request, bail.
     70        if ( self::$did_parent_menu ) {
     71            return;
     72        }
     73
     74        // If another plugin in the suite has already created the menu, we don't need to do anything.
     75        if ( ! empty( $menu ) && in_array( $menu_slug, array_column( $menu, 2 ), true ) ) {
     76            return;
    6477        }
    6578
     
    128141        if ( $hook ) {
    129142            add_action( 'load-' . $hook, [ self::class, 'maybe_handle_plugin_toggle' ] );
    130         }
     143        }
     144
     145        // Mark parent as registered to avoid duplicate add_menu_page calls in mixed environments.
     146        self::$did_parent_menu = true;
    131147
    132148        // Ensure assets are enqueued at the proper time and only on our screen.
     
    134150            add_action( 'admin_enqueue_scripts', [ self::class, 'enqueue_assets' ] );
    135151            self::$did_enqueue_hook = true;
    136         }
     152        }
    137153
    138154        // Register admin notices renderer (error/success messages from actions below).
     
    140156            add_action( 'admin_notices', [ self::class, 'render_admin_notices' ] );
    141157            self::$did_notice_hook = true;
    142         }
     158        }
    143159    }
    144160
     
    173189        $updates_count     = 0;
    174190
    175         // Annotate registry items with runtime state.
     191        // Annotate registry items with runtime state (supports premium/free variant pairs).
    176192        foreach ( $registry as $key => $item ) {
    177193            $type = $item['type'] ?? 'plugin';
     
    179195                continue;
    180196            }
    181 
    182             $file         = $item['plugin_file'];
    183             $is_installed = isset( $installed_plugins[ $file ] );
    184             $is_active    = $is_installed && is_plugin_active( $file );
    185             $version      = $is_installed ? ( $installed_plugins[ $file ]['Version'] ?? '' ) : '';
    186 
    187             $has_update = isset( $update_response[ $file ] );
    188             if ( $has_update ) {
     197            $primary_file = (string) $item['plugin_file'];
     198            $premium_file = isset( $item['plugin_files']['premium'] ) ? (string) $item['plugin_files']['premium'] : '';
     199            $free_file    = isset( $item['plugin_files']['free'] ) ? (string) $item['plugin_files']['free'] : '';
     200
     201            // Helper to read state for a specific plugin file
     202            $read_state = function ( string $file ) use ( $installed_plugins, $update_response ) {
     203                $installed = isset( $installed_plugins[ $file ] );
     204                $active    = $installed && is_plugin_active( $file );
     205                $version   = $installed ? ( $installed_plugins[ $file ]['Version'] ?? '' ) : '';
     206                $has_upd   = isset( $update_response[ $file ] );
     207                $new_ver   = $has_upd ? ( $update_response[ $file ]->new_version ?? '' ) : '';
     208                return [ $installed, $active, $version, $has_upd, $new_ver ];
     209            };
     210
     211            // Default path: single-file plugins
     212            if ( empty( $premium_file ) && empty( $free_file ) ) {
     213                [ $is_installed, $is_active, $version, $has_update, $new_version ] = $read_state( $primary_file );
     214                if ( $has_update ) {
     215                    ++$updates_count;
     216                }
     217                $registry[ $key ]['is_installed']       = $is_installed;
     218                $registry[ $key ]['is_active']          = $is_active;
     219                $registry[ $key ]['version']            = $version;
     220                $registry[ $key ]['has_update']         = $has_update;
     221                $registry[ $key ]['new_version']        = $new_version;
     222                $registry[ $key ]['plugin_file_active'] = $is_active ? $primary_file : '';
     223                $registry[ $key ]['plugin_file_action'] = $primary_file;
     224                $registry[ $key ]['uses_free']          = false;
     225                continue;
     226            }
     227
     228            // Variant-aware path: prefer premium when present
     229            $is_installed_prem = false;
     230            $is_active_prem    = false;
     231            $ver_prem          = '';
     232            $upd_prem          = false;
     233            $new_prem          = '';
     234            $is_installed_free = false;
     235            $is_active_free    = false;
     236            $ver_free          = '';
     237            $upd_free          = false;
     238            $new_free          = '';
     239
     240            if ( $premium_file ) {
     241                [ $is_installed_prem, $is_active_prem, $ver_prem, $upd_prem, $new_prem ] = $read_state( $premium_file );
     242            }
     243            if ( $free_file ) {
     244                [ $is_installed_free, $is_active_free, $ver_free, $upd_free, $new_free ] = $read_state( $free_file );
     245            }
     246
     247            $is_installed = $is_installed_prem || $is_installed_free;
     248            $is_active    = $is_active_prem || $is_active_free;
     249            $uses_free    = false;
     250            $version      = '';
     251            $file_active  = '';
     252            $has_update   = false;
     253            $new_version  = '';
     254
     255            // Choose versions and update flags based on precedence
     256            if ( $is_active_prem ) {
     257                $file_active = $premium_file;
     258                $version     = $ver_prem;
     259            } elseif ( $is_active_free ) {
     260                $file_active = $free_file;
     261                $version     = $ver_free;
     262                $uses_free   = true;
     263            } elseif ( $is_installed_prem ) {
     264                $version = $ver_prem;
     265            } elseif ( $is_installed_free ) {
     266                $version   = $ver_free;
     267                $uses_free = true; // Only free exists → show Free badge
     268            }
     269
     270            // Updates: consider whichever is installed; prefer premium if both
     271            if ( $upd_prem || $upd_free ) {
     272                $has_update  = $upd_prem || $upd_free;
     273                $new_version = $upd_prem ? $new_prem : $new_free;
    189274                ++$updates_count;
    190275            }
    191276
    192             $registry[ $key ]['is_installed'] = $is_installed;
    193             $registry[ $key ]['is_active']    = $is_active;
    194             $registry[ $key ]['version']      = $version;
    195             $registry[ $key ]['has_update']   = $has_update;
    196             $registry[ $key ]['new_version']  = $has_update ? ( $update_response[ $file ]->new_version ?? '' ) : '';
     277            // Activation target: if active → target the active file for deactivation.
     278            // If inactive → prefer premium when installed; else free.
     279            if ( $is_active ) {
     280                $file_action = $file_active ?: ( $is_installed_prem ? $premium_file : $free_file );
     281            } else {
     282                $file_action = $is_installed_prem ? $premium_file : ( $free_file ?: $premium_file );
     283            }
     284
     285            $registry[ $key ]['is_installed']       = $is_installed;
     286            $registry[ $key ]['is_active']          = $is_active;
     287            $registry[ $key ]['version']            = $version;
     288            $registry[ $key ]['has_update']         = $has_update;
     289            $registry[ $key ]['new_version']        = $new_version;
     290            $registry[ $key ]['plugin_file_active'] = $file_active;
     291            $registry[ $key ]['plugin_file_action'] = $file_action ?: $primary_file;
     292            $registry[ $key ]['uses_free']          = $uses_free;
    197293        }
    198294
     
    319415                                <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
    320416                            </span>
     417                            <?php if ( ! empty( $item['uses_free'] ) ) : ?>
     418                                <span class="gops-badge">Free</span>
     419                            <?php endif; ?>
    321420                            <?php if ( $version ) : ?>
    322421                                <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
     
    331430                                <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
    332431                                    <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
    333                                         <?php wp_nonce_field( 'gops_toggle_' . $item['plugin_file'], 'gops_nonce' ); ?>
     432                                        <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
    334433                                        <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
    335                                         <input type="hidden" name="plugin" value="<?php echo esc_attr( $item['plugin_file'] ); ?>" />
     434                                        <input type="hidden" name="plugin" value="<?php echo esc_attr( $is_active ? ( $item['plugin_file_active'] ?: ( $item['plugin_file_action'] ?? $item['plugin_file'] ) ) : ( $item['plugin_file_action'] ?? $item['plugin_file'] ) ); ?>" />
    336435                                        <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
    337436                                    </form>
     
    358457     * @return string Icon URL or empty string if none found.
    359458     */
    360     private static function resolve_plugin_icon_url( array $item ): string {
     459    private static function resolve_plugin_icon_url( $item ) {
    361460        $url = apply_filters( 'gravityops_plugin_icon_url', '', $item );
    362461        if ( ! empty( $url ) ) {
     
    422521     * @return void
    423522     */
    424     public static function enqueue_assets( $hook ): void {
     523    public static function enqueue_assets( $hook ) {
    425524        $page                 = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    426525        $is_gravityops_screen = ( false !== strpos( (string) $hook, 'gravity_ops' ) ) || ( 'gravity_ops' === $page );
     
    452551     * @return void
    453552     */
    454     public static function render_admin_notices(): void {
     553    public static function render_admin_notices() {
    455554        $is_gravityops_screen = isset( $_GET['page'] ) && 'gravity_ops' === sanitize_key( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    456555        if ( ! $is_gravityops_screen ) {
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/MENFGF/gravityops/core/src/SuiteRegistry.php

    r3420036 r3422687  
    2525     *               'description', 'marketing_url', 'docs_url', 'is_free', and 'icon_html'.
    2626     */
    27     public static function all(): array {
     27    public static function all() {
    2828        // NOTE: External links are placeholders. Replace with final URLs where marked.
    2929        return [
     
    5454                'slug'          => 'integrate-asana-with-gravity-forms',
    5555                'plugin_file'   => 'integrate-asana-with-gravity-forms/integrate-asana-with-gravity-forms.php',
     56                // Free + Premium variants: prefer premium folder when present
     57                'plugin_files'  => [
     58                    'premium' => 'integrate-asana-with-gravity-forms-premium/integrate-asana-with-gravity-forms.php',
     59                    'free'    => 'integrate-asana-with-gravity-forms/integrate-asana-with-gravity-forms.php',
     60                ],
    5661                'name'          => 'Integrate Asana with Gravity Forms',
    5762                'description'   => 'Turn form submissions into Asana tasks instantly.',
     
    6570                'slug'          => 'mass_email_notifications_for_gf',
    6671                'plugin_file'   => 'mass-email-notifications-for-gravity-forms/mass-email-notifications-for-gf.php',
     72                // Free + Premium variants: prefer premium folder when present
     73                'plugin_files'  => [
     74                    'premium' => 'mass-email-notifications-for-gravity-forms-premium/mass-email-notifications-for-gf.php',
     75                    'free'    => 'mass-email-notifications-for-gravity-forms/mass-email-notifications-for-gf.php',
     76                ],
    6777                'name'          => 'Mass Email Notifications',
    6878                'description'   => 'Send bulk emails to Gravity Forms entries.',
     
    7585                'type'          => 'plugin',
    7686                'slug'          => 'kanban-view-for-gravity-view',
    77                 'plugin_file'   => 'kanban-view-for-gravity-view/kanban-view-for-gv.php',
     87                'plugin_file'   => 'kanban-view-for-gravity-view-premium/kanban-view-for-gv.php',
    7888                'name'          => 'Kanban View for GravityView',
    7989                'description'   => 'Turn GravityView into a kanban project board.',
     
    8696                'type'          => 'plugin',
    8797                'slug'          => 'Recurring_Form_Submissions_For_Gravity_Form',
    88                 'plugin_file'   => 'recurring-form-submissions-for-gravity-forms/recurring-form-submissions-for-gravity-form.php',
     98                'plugin_file'   => 'recurring-form-submissions-for-gravity-forms-premium/recurring-form-submissions-for-gravity-form.php',
    8999                'name'          => 'Recurring Form Submissions',
    90100                'description'   => 'Schedule recurring Gravity Forms submissions.',
     
    97107                'type'          => 'plugin',
    98108                'slug'          => 'gravity_ops_global_variables',
    99                 'plugin_file'   => 'global-variables-for-gravity-math/global-variables-for-gravity-math.php',
     109                // Premium-only plugin uses a -premium folder suffix
     110                'plugin_file'   => 'global-variables-for-gravity-math-premium/global-variables-for-gravity-math.php',
    100111                'name'          => 'Global Variables',
    101112                'description'   => 'Create shared variables for GravityMath formulas.',
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/autoload.php

    r3420881 r3422687  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522::getLoader();
     22return ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e::getLoader();
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/autoload_aliases.php

    r3420036 r3422687  
    11<?php
    22
     3// Functions and constants
     4namespace GravityOps\Core\Admin {
     5    if(!function_exists('\\GravityOps\\Core\\Admin\\gravityops_shell')){
     6        function gravityops_shell(...$args) {
     7            return \MENFGF\GravityOps\Core\Admin\gravityops_shell(...func_get_args());
     8        }
     9    }
     10}
    311
    412
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/autoload_files.php

    r3420036 r3422687  
    99    '8d50dc88e56bace65e1e72f6017983ed' => $vendorDir . '/freemius/wordpress-sdk/start.php',
    1010    '9387666eac3fc37c9ef87deb087980c6' => $vendorDir . '/MENFGF/autoload.php',
     11    '79fa1c9a31d9f4c8c1a536bd9e014492' => $vendorDir . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1112);
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/autoload_real.php

    r3420881 r3422687  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522
     5class ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::getInitializer($loader));
    3333
    3434        $loader->register(true);
    3535
    36         $filesToLoad = \Composer\Autoload\ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::$files;
     36        $filesToLoad = \Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$files;
    3737        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
    3838            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/autoload_static.php

    r3420881 r3422687  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522
     7class ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e
    88{
    99    public static $files = array (
    1010        '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php',
    1111        '9387666eac3fc37c9ef87deb087980c6' => __DIR__ . '/..' . '/MENFGF/autoload.php',
     12        '79fa1c9a31d9f4c8c1a536bd9e014492' => __DIR__ . '/..' . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1213    );
    1314
     
    1920    {
    2021        return \Closure::bind(function () use ($loader) {
    21             $loader->classMap = ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::$classMap;
     22            $loader->classMap = ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$classMap;
    2223
    2324        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/installed.json

    r3420881 r3422687  
    5959        {
    6060            "name": "gravityops/core",
    61             "version": "1.0.18",
    62             "version_normalized": "1.0.18.0",
     61            "version": "1.0.21",
     62            "version_normalized": "1.0.21.0",
    6363            "source": {
    6464                "type": "git",
    6565                "url": "git@github.com:Eitan-brightleaf/gravityops.git",
    66                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68"
     66                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
    6767            },
    6868            "dist": {
    6969                "type": "zip",
    70                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/a74352489b658ed6a7f1c588abb2e18aae065a68",
    71                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68",
     70                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     71                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    7272                "shasum": ""
    7373            },
     
    7575                "php": ">=7.4"
    7676            },
    77             "time": "2025-12-16T09:58:09+00:00",
     77            "time": "2025-12-18T07:45:02+00:00",
    7878            "type": "library",
    7979            "installation-source": "source",
  • mass-email-notifications-for-gravity-forms/tags/1.3.6/vendor/composer/installed.php

    r3420881 r3422687  
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     6        'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
     
    1414            'pretty_version' => 'dev-main',
    1515            'version' => 'dev-main',
    16             'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     16            'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    1717            'type' => 'library',
    1818            'install_path' => __DIR__ . '/../../',
     
    3030        ),
    3131        'gravityops/core' => array(
    32             'pretty_version' => '1.0.18',
    33             'version' => '1.0.18.0',
    34             'reference' => 'a74352489b658ed6a7f1c588abb2e18aae065a68',
     32            'pretty_version' => '1.0.21',
     33            'version' => '1.0.21.0',
     34            'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
    3535            'type' => 'library',
    3636            'install_path' => __DIR__ . '/../gravityops/core',
  • mass-email-notifications-for-gravity-forms/trunk/class-mass-email-notifications-for-gravity-forms.php

    r3420209 r3422687  
    88use MENFGF\GravityOps\Core\Utils\AssetHelper;
    99use MENFGF\GravityOps\Core\Admin\AdminShell;
     10use function MENFGF\GravityOps\Core\Admin\gravityops_shell;
    1011if ( !defined( 'ABSPATH' ) ) {
    1112    exit;
     
    206207        parent::init_admin();
    207208        // Register the new GravityOps AdminShell page under the parent menu.
    208         AdminShell::instance()->register_plugin_page( $this->_slug, [
     209        gravityops_shell()->register_plugin_page( $this->_slug, [
    209210            'title'      => $this->_title,
    210211            'menu_title' => $this->_short_title,
     
    326327     */
    327328    public function gops_render_suppressions() {
     329        $groups = $this->get_structured_suppressions();
    328330        echo '<div class="gops-card">';
    329         echo '<h2 class="gops-title" style="margin:0 0 8px;">Suppressions</h2>';
    330         if ( !method_exists( $this, 'get_structured_suppressions' ) ) {
    331             echo '<p>Suppression list is not available.</p>';
    332             echo '</div>';
    333             return;
    334         }
    335         $groups = $this->get_structured_suppressions();
    336         if ( empty( $groups ) || !is_array( $groups ) ) {
     331        echo '<h2 class="gops-title" style="margin:0 0 8px;">Suppressions (' . count( $groups ) . ')</h2>';
     332        if ( empty( $groups ) ) {
    337333            echo '<p>No suppressed emails found.</p>';
    338334            echo '</div>';
     
    22672263        header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
    22682264        echo '<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">' . '<title>Unsubscribed</title>' . '<style>body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;line-height:1.5;padding:40px;background:#f6f7f9;color:#1d2327} .menfgf-unsub{max-width:560px;margin:40px auto;background:#fff;border:1px solid #ccd0d4;border-radius:8px;padding:24px;box-shadow:0 3px 8px rgba(0,0,0,.05)} .menfgf-unsub h1{font-size:20px;margin:0 0 8px} .menfgf-unsub p{margin:8px 0 0;color:#3c434a}</style></head><body>' . '<div class="menfgf-unsub"><h1>You have been unsubscribed</h1><p>You will no longer receive these mass email notifications from this site. You can close this tab.</p></div>' . '</body></html>';
    2269         wp_die();
     2265        exit;
    22702266    }
    22712267
     
    29602956            false,
    29612957            false,
    2962             $disable_auto_format
     2958            !$disable_auto_format
    29632959        );
    29642960        $this->log_debug( __METHOD__ . '() - processed text ' . $processed_text );
  • mass-email-notifications-for-gravity-forms/trunk/mass-email-notifications-for-gf.php

    r3420881 r3422687  
    66 * Author URI: https://brightleafdigital.io/
    77 * Description: Allows you to send notifications to everyone who filled out any of your forms.
    8  * Version: 1.3.5
     8 * Version: 1.3.6
    99 * Author: BrightLeaf Digital
    1010 * License: GPL-2.0+
     
    1313 * @package MassEmailNotificationsForGravityForms
    1414 */
     15use MENFGF\GravityOps\Core\Admin\AdminShell;
    1516if ( !defined( 'ABSPATH' ) ) {
    1617    exit;
     
    1819}
    1920require_once __DIR__ . '/vendor/autoload.php';
     21// Instantiate this plugin's copy of the AdminShell early so provider negotiation can happen on plugins_loaded.
     22add_action( 'plugins_loaded', function () {
     23    AdminShell::instance();
     24}, 1 );
    2025if ( function_exists( 'menfgf_fs' ) ) {
    2126    menfgf_fs()->set_basename( false, __FILE__ );
     
    6671    }
    6772    menfgf_fs()->add_filter( 'enable_cpt_advanced_menu_logic', '__return_true' );
    68     define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.5' );
     73    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.6' );
    6974    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_BASENAME', plugin_basename( __FILE__ ) );
    7075    add_action( 'admin_notices', function () {
  • mass-email-notifications-for-gravity-forms/trunk/readme.txt

    r3420881 r3422687  
    22Tested up to: 6.9
    33Tags: GravityForms, notifications, email, task management, automation
    4 Stable tag: 1.3.5
     4Stable tag: 1.3.6
    55Requires PHP: 8.0
    66License: GPLv2 or later
     
    4444== Changelog ==
    4545
     46= 1.3.6 | Dec 18, 2025 =
     47* Fixed a bug in the new plugin menu where installed plugins would show as uninstalled
     48* Fixed some PHP error warnings
     49* Fixed a 500 response error returned when someone unsubscribed without a landing page configured
     50* Fixed a bug preventing auto formatting being disabled in some circumstances
     51
    4652= 1.3.5 | Dec 16, 2025 =
    4753* Fixed another bug in new plugin menu
     
    6268* Added shortocde support for premium and agency plans.
    6369* Added a GravityFlow workflow step for premium and agency plans.
    64 
    65 = 1.3.1 =
    66 * A few small quality of life improvements.
    67 
    68 = 1.3.0 =
    69 * A host of small UI/UX enhancements.
    70 * Added unsubscribe management features.
    71 * Added double opt-in management features.
    72 
    73 = 1.2.9 =
    74 * Fixed a bug where feed labels would not always display in the batch table.
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/autoload.php

    r3420881 r3422687  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808::getLoader();
     22return ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa::getLoader();
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/autoload_real.php

    r3420881 r3422687  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808
     5class ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \MENFGF\Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit0fa87d9e4ab62c721e5fc11d03c1d808', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::getInitializer($loader));
     32        call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::getInitializer($loader));
    3333
    3434        $loader->setClassMapAuthoritative(true);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/autoload_static.php

    r3420881 r3422687  
    55namespace MENFGF\Composer\Autoload;
    66
    7 class ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808
     7class ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa
    88{
    99    public static $prefixLengthsPsr4 = array (
     
    3636    {
    3737        return \Closure::bind(function () use ($loader) {
    38             $loader->prefixLengthsPsr4 = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$prefixLengthsPsr4;
    39             $loader->prefixDirsPsr4 = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$prefixDirsPsr4;
    40             $loader->classMap = ComposerStaticInit0fa87d9e4ab62c721e5fc11d03c1d808::$classMap;
     38            $loader->prefixLengthsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixLengthsPsr4;
     39            $loader->prefixDirsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixDirsPsr4;
     40            $loader->classMap = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$classMap;
    4141
    4242        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/installed.json

    r3420881 r3422687  
    33        "1": {
    44            "name": "gravityops/core",
    5             "version": "1.0.18",
    6             "version_normalized": "1.0.18.0",
     5            "version": "1.0.21",
     6            "version_normalized": "1.0.21.0",
    77            "source": {
    88                "type": "git",
    99                "url": "git@github.com:Eitan-brightleaf/gravityops.git",
    10                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68"
     10                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
    1111            },
    1212            "dist": {
    1313                "type": "zip",
    14                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/a74352489b658ed6a7f1c588abb2e18aae065a68",
    15                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68",
     14                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     15                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    1616                "shasum": ""
    1717            },
     
    1919                "php": ">=7.4"
    2020            },
    21             "time": "2025-12-16T09:58:09+00:00",
     21            "time": "2025-12-18T07:45:02+00:00",
    2222            "type": "library",
    2323            "installation-source": "source",
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/installed.php

    r3420881 r3422687  
    55    'pretty_version' => 'dev-main',
    66    'version' => 'dev-main',
    7     'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     7    'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    88    'type' => 'library',
    99    'install_path' => __DIR__ . '/../',
     
    1717    'gravityops/core' =>
    1818    array (
    19       'pretty_version' => '1.0.18',
    20       'version' => '1.0.18.0',
    21       'reference' => 'a74352489b658ed6a7f1c588abb2e18aae065a68',
     19      'pretty_version' => '1.0.21',
     20      'version' => '1.0.21.0',
     21      'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
    2222      'type' => 'library',
    2323      'install_path' => __DIR__ . '/../gravityops/core',
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/AdminShell.php

    r3420881 r3422687  
    1616
    1717    /**
     18     * Library/core version used for provider negotiation.
     19     * The highest version across loaded copies should be selected as provider.
     20     */
     21    public const CORE_VERSION = '1.0.21';
     22
     23    /**
    1824     * Holds the singleton instance.
    1925     *
     
    2127     */
    2228    private static ?AdminShell $instance = null;
     29
     30    /**
     31     * Tracks whether the chosen provider has already booted (registered hooks).
     32     * Prevents multiple copies from attaching side‑effect hooks.
     33     *
     34     * @var bool
     35     */
     36    private static bool $did_boot = false;
    2337
    2438    /**
     
    3549     * Get singleton instance.
    3650     */
    37     public static function instance(): AdminShell {
    38         // First, try to get a shared instance provided by any loaded copy via filter.
     51    public static function instance() {
     52        // New: negotiate best provider by highest version (cross‑namespace).
     53        $best = apply_filters( 'gravityops_shell_provider', null );
     54        if ( is_array( $best ) && isset( $best['shell'] ) ) {
     55            return $best['shell'];
     56        }
     57
     58        // Legacy: try a shared instance provided by any copy.
    3959        $shared = apply_filters( 'gravityops_shell_instance', null );
    4060        if ( $shared instanceof self ) {
    4161            return $shared;
    4262        }
     63
    4364        if ( null === self::$instance ) {
    4465            self::$instance = new self();
     
    5374     */
    5475    private function __construct() {
    55         // Cross-namespace shared instance resolver: first provider wins.
    56         $existing = apply_filters( 'gravityops_shell_instance', null );
    57         if ( $existing && $existing !== $this ) {
    58             // Another copy has already provided an instance; avoid duplicate hooks.
    59             return;
    60         }
    61 
    62         // Expose this instance for other namespaces/copies to reuse.
     76        // Expose this instance for other namespaces/copies to reuse (legacy "first copy wins").
    6377        add_filter(
    6478            'gravityops_shell_instance',
     
    6983        );
    7084
    71         // Defer adding menus until after all plugins have registered.
    72         add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
    73         // Do NOT hide submenus by default; users reported accessibility issues.
    74         // If needed in the future, this can be reintroduced behind a filter.
    75         add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     85        // Versioned provider negotiation: highest version wins.
     86        add_filter(
     87            'gravityops_shell_provider',
     88            function ( $best ) {
     89                $mine = [
     90                    'version' => self::CORE_VERSION,
     91                    'shell'   => $this,
     92                ];
     93                if ( ! is_array( $best ) || empty( $best['version'] ) ) {
     94                    return $mine;
     95                }
     96                return version_compare( (string) $mine['version'], (string) $best['version'], '>' ) ? $mine : $best;
     97            },
     98            1
     99        );
     100
     101        // Defer side‑effect hooks until we negotiate the best provider.
     102        // Each copy registers this, but only the selected provider will actually boot.
     103        // If instantiated after plugins_loaded has already fired, boot immediately.
     104        if ( function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
     105            $this->maybe_boot();
     106        } else {
     107            add_action( 'plugins_loaded', [ $this, 'maybe_boot' ], 20 );
     108        }
    76109    }
    77110
     
    84117     * @return bool True if the page exists.
    85118     */
    86     public static function has_page( string $slug ): bool {
     119    public static function has_page( $slug ) {
    87120        $provider = apply_filters( 'gravityops_shell_instance', null );
    88121        if ( $provider instanceof self ) {
     
    112145     * @return array<string,array<string,string>> Tabs config array suitable to merge with register_plugin_page() tabs.
    113146     */
    114     public static function freemius_tabs( string $plugin_slug, array $labels = [] ): array {
     147    public static function freemius_tabs( $plugin_slug, $labels = [] ) {
    115148        $default_labels = [
    116149            'account'     => 'Account',
     
    164197     * @return void
    165198     */
    166     public static function render_feeds_list( array $feeds_and_forms, string $gf_subview_slug, string $plugin_short_title, string $toggle_action ): void {
     199    public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action ) {
    167200        echo '<div class="gops-card">';
    168201        echo '<h2 class="gops-title" style="margin:0 0 10px;">' . esc_html( $plugin_short_title ) . ' Feeds</h2>';
     
    224257     * @return void
    225258     */
    226     public static function process_feed_toggle( string $action_prefix, string $return_url ) {
     259    public static function process_feed_toggle( $action_prefix, $return_url ) {
    227260        if ( empty( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) || 'POST' !== ( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ?? '' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    228261            wp_safe_redirect( admin_url( $return_url ) );
     
    262295     * @return void
    263296     */
    264     public static function render_help_tab( array $links ): void {
     297    public static function render_help_tab( $links ) {
    265298        echo '<div class="gops-card">';
    266299        echo '<h2 class="gops-title" style="margin:0 0 8px;">Help</h2>';
     
    282315     * @param array  $args Page configuration.
    283316     */
    284     public function register_plugin_page( string $slug, array $args ): void {
    285         // If another copy is the active provider, forward registration to it.
     317    public function register_plugin_page( $slug, $args ) {
     318        // If another copy is the active provider (new negotiation), forward registration to it first.
     319        $best = apply_filters( 'gravityops_shell_provider', null );
     320        if ( is_array( $best ) && isset( $best['shell'] ) && $best['shell'] !== $this && is_object( $best['shell'] ) && method_exists( $best['shell'], 'register_plugin_page' ) ) {
     321            $best['shell']->register_plugin_page( $slug, $args );
     322            return;
     323        }
     324        // Legacy shared-instance forwarding as a fallback.
    286325        $provider = apply_filters( 'gravityops_shell_instance', null );
    287326        if ( $provider && $provider !== $this && is_object( $provider ) && method_exists( $provider, 'register_plugin_page' ) ) {
    288             // Call method on the provider (may be a different class/namespace).
    289327            $provider->register_plugin_page( $slug, $args );
    290328            return;
     
    304342     * Add the submenu pages under the shared GravityOps parent.
    305343     */
    306     public function register_menus(): void {
     344    public function register_menus() {
    307345        if ( class_exists( __NAMESPACE__ . '\\SuiteMenu' ) ) {
    308346            SuiteMenu::ensure_parent_menu();
     
    342380     * @param string $hook Current admin page hook.
    343381     */
    344     public function enqueue_assets( $hook ): void {
     382    public function enqueue_assets( $hook ) {
    345383        $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    346384
     
    375413
    376414    /**
     415     * Boot the chosen provider (register side‑effect hooks). Called once.
     416     *
     417     * @return void
     418     */
     419    private function boot() {
     420        if ( self::$did_boot ) {
     421            return;
     422        }
     423        // Defer adding menus until after all plugins have registered.
     424        add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
     425        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     426        self::$did_boot = true;
     427    }
     428
     429    /**
     430     * On plugins_loaded, negotiate the best provider and boot only that one.
     431     * Each copy registers this callback, but only the selected provider acts.
     432     *
     433     * @return void
     434     */
     435    public function maybe_boot() {
     436        if ( self::$did_boot ) {
     437            return;
     438        }
     439        $best = apply_filters( 'gravityops_shell_provider', null );
     440        if ( is_array( $best ) && isset( $best['shell'] ) ) {
     441            if ( $best['shell'] === $this ) {
     442                $this->boot();
     443            }
     444            return;
     445        }
     446        // If no provider negotiation is available, fall back to local boot (legacy environments).
     447        $shared = apply_filters( 'gravityops_shell_instance', null );
     448        if ( $shared && $shared !== $this ) {
     449            // Another copy is acting as shared instance; let it boot on its own call.
     450            return;
     451        }
     452        $this->boot();
     453    }
     454
     455    /**
    377456     * Render the complete page including header, pills, and tab content.
    378457     *
     
    380459     * @param array  $args Page config.
    381460     */
    382     public function render_page( string $slug, array $args ): void {
     461    public function render_page( $slug, $args ) {
    383462        if ( ! current_user_can( $args['capability'] ?? 'manage_options' ) ) {
    384463            return;
     
    435514     * @return void
    436515     */
    437     private function render_header_only( array $args ): void {
     516    private function render_header_only( $args ) {
    438517        ?>
    439518        <header class="gops-header">
     
    471550     * @return array{css:string,js:string}
    472551     */
    473     public static function resolve_assets_urls(): array {
     552    public static function resolve_assets_urls() {
    474553        $base_url = apply_filters( 'gravityops_assets_base_url', '' );
    475554        $css      = '';
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/SuiteMenu.php

    r3420881 r3422687  
    3030     */
    3131    private static $did_notice_hook = false;
     32
     33    /**
     34     * Track whether the parent GravityOps menu has already been registered.
     35     * Prevents duplicate add_menu_page() calls and ensures a single owner of the parent page.
     36     *
     37     * @var bool
     38     */
     39    private static $did_parent_menu = false;
    3240
    3341    /**
     
    5563     */
    5664    public static function ensure_parent_menu( $capability = '' ) {
    57         global $menu;
    58 
    59         $menu_slug = 'gravity_ops';
    60 
    61         // If another plugin in the suite has already created the menu, we don't need to do anything.
    62         if ( ! empty( $menu ) && in_array( $menu_slug, array_column( $menu, 2 ), true ) ) {
    63             return;
     65        global $menu;
     66
     67        $menu_slug = 'gravity_ops';
     68
     69        // Internal idempotency guard — if we've already added the parent once this request, bail.
     70        if ( self::$did_parent_menu ) {
     71            return;
     72        }
     73
     74        // If another plugin in the suite has already created the menu, we don't need to do anything.
     75        if ( ! empty( $menu ) && in_array( $menu_slug, array_column( $menu, 2 ), true ) ) {
     76            return;
    6477        }
    6578
     
    128141        if ( $hook ) {
    129142            add_action( 'load-' . $hook, [ self::class, 'maybe_handle_plugin_toggle' ] );
    130         }
     143        }
     144
     145        // Mark parent as registered to avoid duplicate add_menu_page calls in mixed environments.
     146        self::$did_parent_menu = true;
    131147
    132148        // Ensure assets are enqueued at the proper time and only on our screen.
     
    134150            add_action( 'admin_enqueue_scripts', [ self::class, 'enqueue_assets' ] );
    135151            self::$did_enqueue_hook = true;
    136         }
     152        }
    137153
    138154        // Register admin notices renderer (error/success messages from actions below).
     
    140156            add_action( 'admin_notices', [ self::class, 'render_admin_notices' ] );
    141157            self::$did_notice_hook = true;
    142         }
     158        }
    143159    }
    144160
     
    173189        $updates_count     = 0;
    174190
    175         // Annotate registry items with runtime state.
     191        // Annotate registry items with runtime state (supports premium/free variant pairs).
    176192        foreach ( $registry as $key => $item ) {
    177193            $type = $item['type'] ?? 'plugin';
     
    179195                continue;
    180196            }
    181 
    182             $file         = $item['plugin_file'];
    183             $is_installed = isset( $installed_plugins[ $file ] );
    184             $is_active    = $is_installed && is_plugin_active( $file );
    185             $version      = $is_installed ? ( $installed_plugins[ $file ]['Version'] ?? '' ) : '';
    186 
    187             $has_update = isset( $update_response[ $file ] );
    188             if ( $has_update ) {
     197            $primary_file = (string) $item['plugin_file'];
     198            $premium_file = isset( $item['plugin_files']['premium'] ) ? (string) $item['plugin_files']['premium'] : '';
     199            $free_file    = isset( $item['plugin_files']['free'] ) ? (string) $item['plugin_files']['free'] : '';
     200
     201            // Helper to read state for a specific plugin file
     202            $read_state = function ( string $file ) use ( $installed_plugins, $update_response ) {
     203                $installed = isset( $installed_plugins[ $file ] );
     204                $active    = $installed && is_plugin_active( $file );
     205                $version   = $installed ? ( $installed_plugins[ $file ]['Version'] ?? '' ) : '';
     206                $has_upd   = isset( $update_response[ $file ] );
     207                $new_ver   = $has_upd ? ( $update_response[ $file ]->new_version ?? '' ) : '';
     208                return [ $installed, $active, $version, $has_upd, $new_ver ];
     209            };
     210
     211            // Default path: single-file plugins
     212            if ( empty( $premium_file ) && empty( $free_file ) ) {
     213                [ $is_installed, $is_active, $version, $has_update, $new_version ] = $read_state( $primary_file );
     214                if ( $has_update ) {
     215                    ++$updates_count;
     216                }
     217                $registry[ $key ]['is_installed']       = $is_installed;
     218                $registry[ $key ]['is_active']          = $is_active;
     219                $registry[ $key ]['version']            = $version;
     220                $registry[ $key ]['has_update']         = $has_update;
     221                $registry[ $key ]['new_version']        = $new_version;
     222                $registry[ $key ]['plugin_file_active'] = $is_active ? $primary_file : '';
     223                $registry[ $key ]['plugin_file_action'] = $primary_file;
     224                $registry[ $key ]['uses_free']          = false;
     225                continue;
     226            }
     227
     228            // Variant-aware path: prefer premium when present
     229            $is_installed_prem = false;
     230            $is_active_prem    = false;
     231            $ver_prem          = '';
     232            $upd_prem          = false;
     233            $new_prem          = '';
     234            $is_installed_free = false;
     235            $is_active_free    = false;
     236            $ver_free          = '';
     237            $upd_free          = false;
     238            $new_free          = '';
     239
     240            if ( $premium_file ) {
     241                [ $is_installed_prem, $is_active_prem, $ver_prem, $upd_prem, $new_prem ] = $read_state( $premium_file );
     242            }
     243            if ( $free_file ) {
     244                [ $is_installed_free, $is_active_free, $ver_free, $upd_free, $new_free ] = $read_state( $free_file );
     245            }
     246
     247            $is_installed = $is_installed_prem || $is_installed_free;
     248            $is_active    = $is_active_prem || $is_active_free;
     249            $uses_free    = false;
     250            $version      = '';
     251            $file_active  = '';
     252            $has_update   = false;
     253            $new_version  = '';
     254
     255            // Choose versions and update flags based on precedence
     256            if ( $is_active_prem ) {
     257                $file_active = $premium_file;
     258                $version     = $ver_prem;
     259            } elseif ( $is_active_free ) {
     260                $file_active = $free_file;
     261                $version     = $ver_free;
     262                $uses_free   = true;
     263            } elseif ( $is_installed_prem ) {
     264                $version = $ver_prem;
     265            } elseif ( $is_installed_free ) {
     266                $version   = $ver_free;
     267                $uses_free = true; // Only free exists → show Free badge
     268            }
     269
     270            // Updates: consider whichever is installed; prefer premium if both
     271            if ( $upd_prem || $upd_free ) {
     272                $has_update  = $upd_prem || $upd_free;
     273                $new_version = $upd_prem ? $new_prem : $new_free;
    189274                ++$updates_count;
    190275            }
    191276
    192             $registry[ $key ]['is_installed'] = $is_installed;
    193             $registry[ $key ]['is_active']    = $is_active;
    194             $registry[ $key ]['version']      = $version;
    195             $registry[ $key ]['has_update']   = $has_update;
    196             $registry[ $key ]['new_version']  = $has_update ? ( $update_response[ $file ]->new_version ?? '' ) : '';
     277            // Activation target: if active → target the active file for deactivation.
     278            // If inactive → prefer premium when installed; else free.
     279            if ( $is_active ) {
     280                $file_action = $file_active ?: ( $is_installed_prem ? $premium_file : $free_file );
     281            } else {
     282                $file_action = $is_installed_prem ? $premium_file : ( $free_file ?: $premium_file );
     283            }
     284
     285            $registry[ $key ]['is_installed']       = $is_installed;
     286            $registry[ $key ]['is_active']          = $is_active;
     287            $registry[ $key ]['version']            = $version;
     288            $registry[ $key ]['has_update']         = $has_update;
     289            $registry[ $key ]['new_version']        = $new_version;
     290            $registry[ $key ]['plugin_file_active'] = $file_active;
     291            $registry[ $key ]['plugin_file_action'] = $file_action ?: $primary_file;
     292            $registry[ $key ]['uses_free']          = $uses_free;
    197293        }
    198294
     
    319415                                <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
    320416                            </span>
     417                            <?php if ( ! empty( $item['uses_free'] ) ) : ?>
     418                                <span class="gops-badge">Free</span>
     419                            <?php endif; ?>
    321420                            <?php if ( $version ) : ?>
    322421                                <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
     
    331430                                <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
    332431                                    <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
    333                                         <?php wp_nonce_field( 'gops_toggle_' . $item['plugin_file'], 'gops_nonce' ); ?>
     432                                        <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
    334433                                        <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
    335                                         <input type="hidden" name="plugin" value="<?php echo esc_attr( $item['plugin_file'] ); ?>" />
     434                                        <input type="hidden" name="plugin" value="<?php echo esc_attr( $is_active ? ( $item['plugin_file_active'] ?: ( $item['plugin_file_action'] ?? $item['plugin_file'] ) ) : ( $item['plugin_file_action'] ?? $item['plugin_file'] ) ); ?>" />
    336435                                        <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
    337436                                    </form>
     
    358457     * @return string Icon URL or empty string if none found.
    359458     */
    360     private static function resolve_plugin_icon_url( array $item ): string {
     459    private static function resolve_plugin_icon_url( $item ) {
    361460        $url = apply_filters( 'gravityops_plugin_icon_url', '', $item );
    362461        if ( ! empty( $url ) ) {
     
    422521     * @return void
    423522     */
    424     public static function enqueue_assets( $hook ): void {
     523    public static function enqueue_assets( $hook ) {
    425524        $page                 = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    426525        $is_gravityops_screen = ( false !== strpos( (string) $hook, 'gravity_ops' ) ) || ( 'gravity_ops' === $page );
     
    452551     * @return void
    453552     */
    454     public static function render_admin_notices(): void {
     553    public static function render_admin_notices() {
    455554        $is_gravityops_screen = isset( $_GET['page'] ) && 'gravity_ops' === sanitize_key( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    456555        if ( ! $is_gravityops_screen ) {
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/SuiteRegistry.php

    r3420036 r3422687  
    2525     *               'description', 'marketing_url', 'docs_url', 'is_free', and 'icon_html'.
    2626     */
    27     public static function all(): array {
     27    public static function all() {
    2828        // NOTE: External links are placeholders. Replace with final URLs where marked.
    2929        return [
     
    5454                'slug'          => 'integrate-asana-with-gravity-forms',
    5555                'plugin_file'   => 'integrate-asana-with-gravity-forms/integrate-asana-with-gravity-forms.php',
     56                // Free + Premium variants: prefer premium folder when present
     57                'plugin_files'  => [
     58                    'premium' => 'integrate-asana-with-gravity-forms-premium/integrate-asana-with-gravity-forms.php',
     59                    'free'    => 'integrate-asana-with-gravity-forms/integrate-asana-with-gravity-forms.php',
     60                ],
    5661                'name'          => 'Integrate Asana with Gravity Forms',
    5762                'description'   => 'Turn form submissions into Asana tasks instantly.',
     
    6570                'slug'          => 'mass_email_notifications_for_gf',
    6671                'plugin_file'   => 'mass-email-notifications-for-gravity-forms/mass-email-notifications-for-gf.php',
     72                // Free + Premium variants: prefer premium folder when present
     73                'plugin_files'  => [
     74                    'premium' => 'mass-email-notifications-for-gravity-forms-premium/mass-email-notifications-for-gf.php',
     75                    'free'    => 'mass-email-notifications-for-gravity-forms/mass-email-notifications-for-gf.php',
     76                ],
    6777                'name'          => 'Mass Email Notifications',
    6878                'description'   => 'Send bulk emails to Gravity Forms entries.',
     
    7585                'type'          => 'plugin',
    7686                'slug'          => 'kanban-view-for-gravity-view',
    77                 'plugin_file'   => 'kanban-view-for-gravity-view/kanban-view-for-gv.php',
     87                'plugin_file'   => 'kanban-view-for-gravity-view-premium/kanban-view-for-gv.php',
    7888                'name'          => 'Kanban View for GravityView',
    7989                'description'   => 'Turn GravityView into a kanban project board.',
     
    8696                'type'          => 'plugin',
    8797                'slug'          => 'Recurring_Form_Submissions_For_Gravity_Form',
    88                 'plugin_file'   => 'recurring-form-submissions-for-gravity-forms/recurring-form-submissions-for-gravity-form.php',
     98                'plugin_file'   => 'recurring-form-submissions-for-gravity-forms-premium/recurring-form-submissions-for-gravity-form.php',
    8999                'name'          => 'Recurring Form Submissions',
    90100                'description'   => 'Schedule recurring Gravity Forms submissions.',
     
    97107                'type'          => 'plugin',
    98108                'slug'          => 'gravity_ops_global_variables',
    99                 'plugin_file'   => 'global-variables-for-gravity-math/global-variables-for-gravity-math.php',
     109                // Premium-only plugin uses a -premium folder suffix
     110                'plugin_file'   => 'global-variables-for-gravity-math-premium/global-variables-for-gravity-math.php',
    100111                'name'          => 'Global Variables',
    101112                'description'   => 'Create shared variables for GravityMath formulas.',
  • mass-email-notifications-for-gravity-forms/trunk/vendor/autoload.php

    r3420881 r3422687  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522::getLoader();
     22return ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e::getLoader();
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/autoload_aliases.php

    r3420036 r3422687  
    11<?php
    22
     3// Functions and constants
     4namespace GravityOps\Core\Admin {
     5    if(!function_exists('\\GravityOps\\Core\\Admin\\gravityops_shell')){
     6        function gravityops_shell(...$args) {
     7            return \MENFGF\GravityOps\Core\Admin\gravityops_shell(...func_get_args());
     8        }
     9    }
     10}
    311
    412
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/autoload_files.php

    r3420036 r3422687  
    99    '8d50dc88e56bace65e1e72f6017983ed' => $vendorDir . '/freemius/wordpress-sdk/start.php',
    1010    '9387666eac3fc37c9ef87deb087980c6' => $vendorDir . '/MENFGF/autoload.php',
     11    '79fa1c9a31d9f4c8c1a536bd9e014492' => $vendorDir . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1112);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/autoload_real.php

    r3420881 r3422687  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522
     5class ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit9d2e53dbd8e249f7f93d214afa9c4522', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::getInitializer($loader));
    3333
    3434        $loader->register(true);
    3535
    36         $filesToLoad = \Composer\Autoload\ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::$files;
     36        $filesToLoad = \Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$files;
    3737        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
    3838            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/autoload_static.php

    r3420881 r3422687  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522
     7class ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e
    88{
    99    public static $files = array (
    1010        '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php',
    1111        '9387666eac3fc37c9ef87deb087980c6' => __DIR__ . '/..' . '/MENFGF/autoload.php',
     12        '79fa1c9a31d9f4c8c1a536bd9e014492' => __DIR__ . '/..' . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1213    );
    1314
     
    1920    {
    2021        return \Closure::bind(function () use ($loader) {
    21             $loader->classMap = ComposerStaticInit9d2e53dbd8e249f7f93d214afa9c4522::$classMap;
     22            $loader->classMap = ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$classMap;
    2223
    2324        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/installed.json

    r3420881 r3422687  
    5959        {
    6060            "name": "gravityops/core",
    61             "version": "1.0.18",
    62             "version_normalized": "1.0.18.0",
     61            "version": "1.0.21",
     62            "version_normalized": "1.0.21.0",
    6363            "source": {
    6464                "type": "git",
    6565                "url": "git@github.com:Eitan-brightleaf/gravityops.git",
    66                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68"
     66                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
    6767            },
    6868            "dist": {
    6969                "type": "zip",
    70                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/a74352489b658ed6a7f1c588abb2e18aae065a68",
    71                 "reference": "a74352489b658ed6a7f1c588abb2e18aae065a68",
     70                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     71                "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    7272                "shasum": ""
    7373            },
     
    7575                "php": ">=7.4"
    7676            },
    77             "time": "2025-12-16T09:58:09+00:00",
     77            "time": "2025-12-18T07:45:02+00:00",
    7878            "type": "library",
    7979            "installation-source": "source",
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/installed.php

    r3420881 r3422687  
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     6        'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
     
    1414            'pretty_version' => 'dev-main',
    1515            'version' => 'dev-main',
    16             'reference' => 'f0ab76d4401e26cd5563866f07e0110432efba26',
     16            'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    1717            'type' => 'library',
    1818            'install_path' => __DIR__ . '/../../',
     
    3030        ),
    3131        'gravityops/core' => array(
    32             'pretty_version' => '1.0.18',
    33             'version' => '1.0.18.0',
    34             'reference' => 'a74352489b658ed6a7f1c588abb2e18aae065a68',
     32            'pretty_version' => '1.0.21',
     33            'version' => '1.0.21.0',
     34            'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
    3535            'type' => 'library',
    3636            'install_path' => __DIR__ . '/../gravityops/core',
Note: See TracChangeset for help on using the changeset viewer.