Plugin Directory

Changeset 3444395


Ignore:
Timestamp:
01/21/2026 08:36:05 PM (4 weeks ago)
Author:
eitanatbrightleaf
Message:

Update to version 1.3.7 from GitHub

Location:
mass-email-notifications-for-gravity-forms
Files:
190 added
10 deleted
46 edited
1 copied

Legend:

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

    r3422687 r3444395  
    241241                ],
    242242                // Freemius pages use the SDK menu slug (underscored) even if our AdminShell page uses a hyphenated slug.
    243                 AdminShell::freemius_tabs( $this->_slug )
     243                $this->get_freemius_tabs()
    244244             ),
    245245        ] );
    246246        // Admin actions to toggle feed activation and unsuppress emails from the GravityOps tabs.
    247247        add_action( 'admin_post_menfgf_toggle_feed', [$this, 'handle_toggle_feed'] );
     248        add_action( 'admin_post_menfgf_toggle_workflow_step', [$this, 'handle_toggle_workflow_step'] );
    248249        add_action( 'admin_post_menfgf_unsuppress', [$this, 'handle_unsuppress'] );
    249250        $param = 'https://wordpress.org/support/plugin/mass-email-notifications-for-gravity-forms/reviews/#new-post';
     
    315316            ];
    316317        }
     318        $workflow_steps = [];
     319        if ( class_exists( AdminShell::class ) ) {
     320            $workflow_steps = AdminShell::get_workflow_steps_by_type( 'menfgf_create_batch' );
     321        }
    317322        AdminShell::render_feeds_list(
    318323            $feeds_and_forms,
    319324            $this->_slug,
    320325            $this->_short_title,
    321             'menfgf_toggle_feed'
     326            'menfgf_toggle_feed',
     327            $workflow_steps
    322328        );
    323329    }
     
    402408
    403409    /**
     410     * Handle: Toggle workflow step activation from the Feeds tab (AdminShell)
     411     *
     412     * @return void
     413     */
     414    public function handle_toggle_workflow_step() {
     415        AdminShell::process_feed_toggle( 'menfgf_toggle_workflow_step', 'admin.php?page=mass_email_notifications_for_gf&tab=feeds' );
     416    }
     417
     418    /**
    404419     * Handle: Unsuppress an email from the Suppressions tab
    405420     *
     
    452467        $plan = menfgf_fs()->get_plan();
    453468        return ( is_object( $plan ) ? $plan->name : (( menfgf_fs()->is_free_plan() ? 'free' : 'unknown' )) );
     469    }
     470
     471    /**
     472     * Filter the AdminShell tabs to hide the Account tab if the user is not registered.
     473     *
     474     * @return array
     475     */
     476    private function get_freemius_tabs() {
     477        $tabs = AdminShell::freemius_tabs( $this->_slug );
     478        if ( !menfgf_fs()->is_registered() ) {
     479            unset($tabs['account']);
     480        }
     481        return $tabs;
    454482    }
    455483
     
    537565     */
    538566    public function get_menu_icon() {
    539         return $this->get_base_url() . '/includes/images/icon.svg';
     567        return ( SuiteMenu::get_plugin_icon_url( $this->_slug ) ?: $this->get_base_url() . '/includes/images/icon.svg' );
    540568    }
    541569
     
    549577     */
    550578    public function get_app_menu_icon() {
    551         return SuiteMenu::get_icon();
     579        return ( SuiteMenu::get_plugin_icon_url( $this->_slug ) ?: SuiteMenu::get_icon() );
    552580    }
    553581
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/mass-email-notifications-for-gf.php

    r3422687 r3444395  
    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.6
     8 * Version: 1.3.7
    99 * Author: BrightLeaf Digital
    1010 * License: GPL-2.0+
     
    1313 * @package MassEmailNotificationsForGravityForms
    1414 */
    15 use MENFGF\GravityOps\Core\Admin\AdminShell;
     15use function MENFGF\GravityOps\Core\Admin\gravityops_shell;
    1616if ( !defined( 'ABSPATH' ) ) {
    1717    exit;
     
    1919}
    2020require_once __DIR__ . '/vendor/autoload.php';
     21if ( file_exists( __DIR__ . '/vendor/MENFGF/autoload.php' ) ) {
     22    require_once __DIR__ . '/vendor/MENFGF/autoload.php';
     23}
    2124// Instantiate this plugin's copy of the AdminShell early so provider negotiation can happen on plugins_loaded.
    2225add_action( 'plugins_loaded', function () {
    23     AdminShell::instance();
     26    gravityops_shell();
    2427}, 1 );
    2528if ( function_exists( 'menfgf_fs' ) ) {
     
    7174    }
    7275    menfgf_fs()->add_filter( 'enable_cpt_advanced_menu_logic', '__return_true' );
    73     define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.6' );
     76    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.7' );
    7477    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_BASENAME', plugin_basename( __FILE__ ) );
    7578    add_action( 'admin_notices', function () {
     
    100103    // Ensure GravityOps shared assets resolve when library is vendor-installed in this plugin.
    101104    add_filter( 'gravityops_assets_base_url', function ( $url ) {
    102         if ( !empty( $url ) && is_string( $url ) ) {
     105        if ( $url ) {
    103106            return $url;
    104107        }
    105         return plugins_url( 'vendor/MENFGF/gravityops/core/assets/', __FILE__ );
     108        if ( file_exists( __DIR__ . '/vendor/MENFGF/gravityops/core/assets/' ) ) {
     109            return plugins_url( 'vendor/MENFGF/gravityops/core/assets/', __FILE__ );
     110        }
     111        return plugins_url( 'vendor/gravityops/core/assets/', __FILE__ );
    106112    } );
    107113    add_action(
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/readme.txt

    r3422687 r3444395  
    22Tested up to: 6.9
    33Tags: GravityForms, notifications, email, task management, automation
    4 Stable tag: 1.3.6
     4Stable tag: 1.3.7
    55Requires PHP: 8.0
    66License: GPLv2 or later
     
    4444== Changelog ==
    4545
     46= 1.3.7 | Jan 21, 2026 =
     47* Bumped version of core GravityOps library to fix some bugs regarding the plugin admin menus and integrate [TrustedLogin](https://www.trustedlogin.com/about/easy-and-safe/)
     48
    4649= 1.3.6 | Dec 18, 2025 =
    4750* Fixed a bug in the new plugin menu where installed plugins would show as uninstalled
     
    6467* Added better support for viewing email content previews in the admin panel and strengthened CSV file handling for more accurate imports.
    6568* Tweaked permissions and review prompts to make the plugin even more user-friendly, plus a few behind-the-scenes updates for better performance.
    66 
    67 = 1.3.2 =
    68 * Added shortocde support for premium and agency plans.
    69 * Added a GravityFlow workflow step for premium and agency plans.
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/autoload.php

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

    r3420036 r3444395  
    1313    'MENFGF\\GravityOps\\Core\\Admin\\SuiteMenu' => $vendorDir . '/gravityops/core/src/Admin/SuiteMenu.php',
    1414    'MENFGF\\GravityOps\\Core\\Admin\\SurveyPrompter' => $vendorDir . '/gravityops/core/src/Admin/SurveyPrompter.php',
     15    'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin' => $vendorDir . '/gravityops/core/src/Admin/TrustedLogin.php',
    1516    'MENFGF\\GravityOps\\Core\\SuiteRegistry' => $vendorDir . '/gravityops/core/src/SuiteRegistry.php',
    1617    'MENFGF\\GravityOps\\Core\\Traits\\SingletonTrait' => $vendorDir . '/gravityops/core/src/Traits/SingletonTrait.php',
    1718    'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper' => $vendorDir . '/gravityops/core/src/Utils/AssetHelper.php',
     19    'MENFGF\\TrustedLogin\\Admin' => $vendorDir . '/trustedlogin/client/src/Admin.php',
     20    'MENFGF\\TrustedLogin\\Ajax' => $vendorDir . '/trustedlogin/client/src/Ajax.php',
     21    'MENFGF\\TrustedLogin\\Client' => $vendorDir . '/trustedlogin/client/src/Client.php',
     22    'MENFGF\\TrustedLogin\\Config' => $vendorDir . '/trustedlogin/client/src/Config.php',
     23    'MENFGF\\TrustedLogin\\Cron' => $vendorDir . '/trustedlogin/client/src/Cron.php',
     24    'MENFGF\\TrustedLogin\\Encryption' => $vendorDir . '/trustedlogin/client/src/Encryption.php',
     25    'MENFGF\\TrustedLogin\\Endpoint' => $vendorDir . '/trustedlogin/client/src/Endpoint.php',
     26    'MENFGF\\TrustedLogin\\Envelope' => $vendorDir . '/trustedlogin/client/src/Envelope.php',
     27    'MENFGF\\TrustedLogin\\Form' => $vendorDir . '/trustedlogin/client/src/Form.php',
     28    'MENFGF\\TrustedLogin\\Logger' => $vendorDir . '/trustedlogin/client/src/Logger.php',
     29    'MENFGF\\TrustedLogin\\Logging' => $vendorDir . '/trustedlogin/client/src/Logging.php',
     30    'MENFGF\\TrustedLogin\\Remote' => $vendorDir . '/trustedlogin/client/src/Remote.php',
     31    'MENFGF\\TrustedLogin\\SecurityChecks' => $vendorDir . '/trustedlogin/client/src/SecurityChecks.php',
     32    'MENFGF\\TrustedLogin\\SiteAccess' => $vendorDir . '/trustedlogin/client/src/SiteAccess.php',
     33    'MENFGF\\TrustedLogin\\SupportRole' => $vendorDir . '/trustedlogin/client/src/SupportRole.php',
     34    'MENFGF\\TrustedLogin\\SupportUser' => $vendorDir . '/trustedlogin/client/src/SupportUser.php',
     35    'MENFGF\\TrustedLogin\\Utils' => $vendorDir . '/trustedlogin/client/src/Utils.php',
    1836);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/composer/autoload_psr4.php

    r3420036 r3444395  
    77
    88return array(
     9    'MENFGF\\TrustedLogin\\' => array($vendorDir . '/trustedlogin/client/src'),
    910    'MENFGF\\GravityOps\\Core\\' => array($vendorDir . '/gravityops/core/src'),
    1011);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/composer/autoload_real.php

    r3422687 r3444395  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa
     5class ComposerAutoloaderInit576698bb6db496a6b33a55636c894704
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit576698bb6db496a6b33a55636c894704', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \MENFGF\Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit576698bb6db496a6b33a55636c894704', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::getInitializer($loader));
     32        call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInit576698bb6db496a6b33a55636c894704::getInitializer($loader));
    3333
    3434        $loader->setClassMapAuthoritative(true);
    3535        $loader->register(true);
    3636
     37        $filesToLoad = \MENFGF\Composer\Autoload\ComposerStaticInit576698bb6db496a6b33a55636c894704::$files;
     38        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
     39            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
     40                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
     41
     42                require $file;
     43            }
     44        }, null, null);
     45        foreach ($filesToLoad as $fileIdentifier => $file) {
     46            $requireFile($fileIdentifier, $file);
     47        }
     48
    3749        return $loader;
    3850    }
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/composer/autoload_static.php

    r3422687 r3444395  
    55namespace MENFGF\Composer\Autoload;
    66
    7 class ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa
     7class ComposerStaticInit576698bb6db496a6b33a55636c894704
    88{
     9    public static $files = array (
     10        '6450a9b713c361c66ed3f0575f164e85' => __DIR__ . '/..' . '/gravityops/core/src/Admin/functions.php',
     11    );
     12
    913    public static $prefixLengthsPsr4 = array (
    1014        'M' =>
    1115        array (
     16            'MENFGF\\TrustedLogin\\' => 20,
    1217            'MENFGF\\GravityOps\\Core\\' => 23,
    1318        ),
     
    1520
    1621    public static $prefixDirsPsr4 = array (
     22        'MENFGF\\TrustedLogin\\' =>
     23        array (
     24            0 => __DIR__ . '/..' . '/trustedlogin/client/src',
     25        ),
    1726        'MENFGF\\GravityOps\\Core\\' =>
    1827        array (
     
    2837        'MENFGF\\GravityOps\\Core\\Admin\\SuiteMenu' => __DIR__ . '/..' . '/gravityops/core/src/Admin/SuiteMenu.php',
    2938        'MENFGF\\GravityOps\\Core\\Admin\\SurveyPrompter' => __DIR__ . '/..' . '/gravityops/core/src/Admin/SurveyPrompter.php',
     39        'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin' => __DIR__ . '/..' . '/gravityops/core/src/Admin/TrustedLogin.php',
    3040        'MENFGF\\GravityOps\\Core\\SuiteRegistry' => __DIR__ . '/..' . '/gravityops/core/src/SuiteRegistry.php',
    3141        'MENFGF\\GravityOps\\Core\\Traits\\SingletonTrait' => __DIR__ . '/..' . '/gravityops/core/src/Traits/SingletonTrait.php',
    3242        'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper' => __DIR__ . '/..' . '/gravityops/core/src/Utils/AssetHelper.php',
     43        'MENFGF\\TrustedLogin\\Admin' => __DIR__ . '/..' . '/trustedlogin/client/src/Admin.php',
     44        'MENFGF\\TrustedLogin\\Ajax' => __DIR__ . '/..' . '/trustedlogin/client/src/Ajax.php',
     45        'MENFGF\\TrustedLogin\\Client' => __DIR__ . '/..' . '/trustedlogin/client/src/Client.php',
     46        'MENFGF\\TrustedLogin\\Config' => __DIR__ . '/..' . '/trustedlogin/client/src/Config.php',
     47        'MENFGF\\TrustedLogin\\Cron' => __DIR__ . '/..' . '/trustedlogin/client/src/Cron.php',
     48        'MENFGF\\TrustedLogin\\Encryption' => __DIR__ . '/..' . '/trustedlogin/client/src/Encryption.php',
     49        'MENFGF\\TrustedLogin\\Endpoint' => __DIR__ . '/..' . '/trustedlogin/client/src/Endpoint.php',
     50        'MENFGF\\TrustedLogin\\Envelope' => __DIR__ . '/..' . '/trustedlogin/client/src/Envelope.php',
     51        'MENFGF\\TrustedLogin\\Form' => __DIR__ . '/..' . '/trustedlogin/client/src/Form.php',
     52        'MENFGF\\TrustedLogin\\Logger' => __DIR__ . '/..' . '/trustedlogin/client/src/Logger.php',
     53        'MENFGF\\TrustedLogin\\Logging' => __DIR__ . '/..' . '/trustedlogin/client/src/Logging.php',
     54        'MENFGF\\TrustedLogin\\Remote' => __DIR__ . '/..' . '/trustedlogin/client/src/Remote.php',
     55        'MENFGF\\TrustedLogin\\SecurityChecks' => __DIR__ . '/..' . '/trustedlogin/client/src/SecurityChecks.php',
     56        'MENFGF\\TrustedLogin\\SiteAccess' => __DIR__ . '/..' . '/trustedlogin/client/src/SiteAccess.php',
     57        'MENFGF\\TrustedLogin\\SupportRole' => __DIR__ . '/..' . '/trustedlogin/client/src/SupportRole.php',
     58        'MENFGF\\TrustedLogin\\SupportUser' => __DIR__ . '/..' . '/trustedlogin/client/src/SupportUser.php',
     59        'MENFGF\\TrustedLogin\\Utils' => __DIR__ . '/..' . '/trustedlogin/client/src/Utils.php',
    3360    );
    3461
     
    3663    {
    3764        return \Closure::bind(function () use ($loader) {
    38             $loader->prefixLengthsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixLengthsPsr4;
    39             $loader->prefixDirsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixDirsPsr4;
    40             $loader->classMap = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$classMap;
     65            $loader->prefixLengthsPsr4 = ComposerStaticInit576698bb6db496a6b33a55636c894704::$prefixLengthsPsr4;
     66            $loader->prefixDirsPsr4 = ComposerStaticInit576698bb6db496a6b33a55636c894704::$prefixDirsPsr4;
     67            $loader->classMap = ComposerStaticInit576698bb6db496a6b33a55636c894704::$classMap;
    4168
    4269        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/composer/installed.json

    r3422687 r3444395  
    33        "1": {
    44            "name": "gravityops/core",
    5             "version": "1.0.21",
    6             "version_normalized": "1.0.21.0",
     5            "version": "1.1.0",
     6            "version_normalized": "1.1.0.0",
    77            "source": {
    88                "type": "git",
    99                "url": "[email protected]:Eitan-brightleaf/gravityops.git",
    10                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
     10                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e"
    1111            },
    1212            "dist": {
    1313                "type": "zip",
    14                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    15                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     14                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/cee27f55738670dc141b58af37d0feb74d4ce47e",
     15                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e",
    1616                "shasum": ""
    1717            },
    1818            "require": {
    19                 "php": ">=7.4"
     19                "php": ">=7.4",
     20                "trustedlogin/client": "^v1.9"
    2021            },
    21             "time": "2025-12-18T07:45:02+00:00",
     22            "time": "2026-01-21T19:42:14+00:00",
    2223            "type": "library",
    2324            "installation-source": "source",
     
    2526                "psr-4": {
    2627                    "MENFGF\\GravityOps\\Core\\": "src/"
    27                 }
     28                },
     29                "files": [
     30                    "src/Admin/functions.php"
     31                ]
    2832            },
    2933            "license": [
     
    3236            "description": "Shared core library for GravityOps plugins",
    3337            "install-path": "../gravityops/core"
     38        },
     39        "2": {
     40            "name": "trustedlogin/client",
     41            "version": "v1.9.0",
     42            "version_normalized": "1.9.0.0",
     43            "source": {
     44                "type": "git",
     45                "url": "https://github.com/trustedlogin/client.git",
     46                "reference": "b913058ae57b512a7766f449ab8d55952500fe72"
     47            },
     48            "dist": {
     49                "type": "zip",
     50                "url": "https://api.github.com/repos/trustedlogin/client/zipball/b913058ae57b512a7766f449ab8d55952500fe72",
     51                "reference": "b913058ae57b512a7766f449ab8d55952500fe72",
     52                "shasum": ""
     53            },
     54            "require-dev": {
     55                "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
     56                "ext-curl": "*",
     57                "ext-json": "*",
     58                "php": ">=5.3.0",
     59                "phpcompatibility/phpcompatibility-wp": "^2.1",
     60                "phpstan/extension-installer": "^1.3",
     61                "phpstan/phpstan": "^1.10",
     62                "szepeviktor/phpstan-wordpress": "^1.3",
     63                "wp-coding-standards/wpcs": "^3.0",
     64                "yoast/phpunit-polyfills": "^1.0.0"
     65            },
     66            "time": "2024-08-26T01:13:42+00:00",
     67            "bin": [
     68                "bin/build-sass"
     69            ],
     70            "type": "library",
     71            "installation-source": "dist",
     72            "autoload": {
     73                "psr-4": {
     74                    "MENFGF\\TrustedLogin\\": "src/"
     75                }
     76            },
     77            "notification-url": "https://packagist.org/downloads/",
     78            "license": [
     79                "GPL-2.0-or-later"
     80            ],
     81            "authors": [
     82                {
     83                    "name": "TrustedLogin",
     84                    "email": "[email protected]",
     85                    "homepage": "https://www.trustedlogin.com"
     86                }
     87            ],
     88            "description": "Easily and securely log in to your customers sites when providing support.",
     89            "homepage": "https://www.trustedlogin.com",
     90            "keywords": [
     91                "login",
     92                "security",
     93                "support"
     94            ],
     95            "support": {
     96                "issues": "https://github.com/trustedlogin/client/issues",
     97                "source": "https://github.com/trustedlogin/client/tree/v1.9.0"
     98            },
     99            "install-path": "../trustedlogin/client"
    34100        }
    35101    },
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/composer/installed.php

    r3422687 r3444395  
    22  'root' =>
    33  array (
    4     'name' => '__root__',
     4    'name' => 'gravityops/mass-email',
    55    'pretty_version' => 'dev-main',
    66    'version' => 'dev-main',
    7     'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
     7    'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
    88    'type' => 'library',
    99    'install_path' => __DIR__ . '/../',
     
    1717    'gravityops/core' =>
    1818    array (
    19       'pretty_version' => '1.0.21',
    20       'version' => '1.0.21.0',
    21       'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
     19      'pretty_version' => '1.1.0',
     20      'version' => '1.1.0.0',
     21      'reference' => 'cee27f55738670dc141b58af37d0feb74d4ce47e',
    2222      'type' => 'library',
    2323      'install_path' => __DIR__ . '/../gravityops/core',
     
    2727      'dev_requirement' => false,
    2828    ),
     29    'trustedlogin/client' =>
     30    array (
     31      'pretty_version' => 'v1.9.0',
     32      'version' => '1.9.0.0',
     33      'reference' => 'b913058ae57b512a7766f449ab8d55952500fe72',
     34      'type' => 'library',
     35      'install_path' => __DIR__ . '/../trustedlogin/client',
     36      'aliases' =>
     37      array (
     38      ),
     39      'dev_requirement' => false,
     40    ),
    2941  ),
    3042);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/composer.json

    r3420036 r3444395  
    55  "license": "GPL-2.0-or-later",
    66  "require": {
    7     "php": ">=7.4"
     7    "php": ">=7.4",
     8    "trustedlogin/client": "^v1.9"
    89  },
    910  "autoload": {
    1011    "psr-4": {
    1112      "GravityOps\\Core\\": "src/"
    12     }
     13    },
     14    "files": [
     15      "src/Admin/functions.php"
     16    ]
    1317  }
    1418}
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/src/Admin/AdminShell.php

    r3422687 r3444395  
    22
    33namespace MENFGF\GravityOps\Core\Admin;
     4
     5use GFAPI;
     6use MENFGF\GravityOps\Core\SuiteRegistry;
    47
    58if ( ! defined( 'ABSPATH' ) ) {
     
    1922     * The highest version across loaded copies should be selected as provider.
    2023     */
    21     public const CORE_VERSION = '1.0.21';
     24    public const CORE_VERSION = '1.1.0';
    2225
    2326    /**
     
    102105        // Each copy registers this, but only the selected provider will actually boot.
    103106        // If instantiated after plugins_loaded has already fired, boot immediately.
    104         if ( function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
     107        global $wp_filter;
     108        $has_run_already  = did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' );
     109        $is_past_priority = false;
     110
     111        if ( doing_action( 'plugins_loaded' ) && isset( $wp_filter['plugins_loaded'] ) ) {
     112            $is_past_priority = $wp_filter['plugins_loaded']->current_priority() > 20;
     113        }
     114
     115        if ( $has_run_already || $is_past_priority ) {
    105116            $this->maybe_boot();
    106117        } else {
     
    155166        // differs from the SDK menu slug (e.g., hyphenated vs underscored).
    156167        $fs_slug = $plugin_slug;
    157         // Built-in mapping for known cases.
    158         if ( 'mass-email-from-gf-notification' === $plugin_slug ) {
    159             $fs_slug = 'mass_email_notifications_for_gf';
    160         }
    161168        // External override if needed.
    162169        $fs_slug = apply_filters( 'gravityops_freemius_base_slug', $fs_slug, $plugin_slug );
     
    194201     * @param string $plugin_short_title Short plugin title used for the header, e.g., "Asana Integration".
    195202     * @param string $toggle_action     The admin_post action to handle toggle, used for form action and nonce prefix.
     203     * @param array  $workflow_steps    Optional array of workflow steps to display in the feed list.
    196204     *
    197205     * @return void
    198206     */
    199     public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action ) {
     207    public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action, $workflow_steps = [] ) {
    200208        echo '<div class="gops-card">';
    201209        echo '<h2 class="gops-title" style="margin:0 0 10px;">' . esc_html( $plugin_short_title ) . ' Feeds</h2>';
     
    203211        if ( empty( $feeds_and_forms ) ) {
    204212            echo '<p>No feeds found. Create one from a form’s settings.</p>';
    205             echo '</div>';
    206             return;
    207         }
    208 
    209         echo '<ul style="margin:0; padding-left:18px;">';
    210         foreach ( $feeds_and_forms as $feed_and_form ) {
    211             $feed      = $feed_and_form['feed'];
    212             $form      = $feed_and_form['form'];
    213             $form_id   = $form['id'];
    214             $form_name = $form['title'];
    215             $feed_id   = $feed['id'];
    216             $is_active = (bool) $feed['is_active'];
    217             $name      = $feed['meta']['feedName'];
    218 
    219             $edit_form = admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id );
    220             $edit_feed = add_query_arg(
     213        } else {
     214            echo '<ul style="margin:0; padding-left:18px;">';
     215            foreach ( $feeds_and_forms as $feed_and_form ) {
     216                $feed      = $feed_and_form['feed'];
     217                $form      = $feed_and_form['form'];
     218                $form_id   = $form['id'];
     219                $form_name = $form['title'];
     220                $feed_id   = $feed['id'];
     221                $is_active = (bool) $feed['is_active'];
     222                $name      = $feed['meta']['feedName'];
     223
     224                $edit_form = admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id );
     225                $edit_feed = add_query_arg(
    221226                    [
    222                         'page'    => 'gf_edit_forms',
    223                         'view'    => 'settings',
    224                         'subview' => $gf_subview_slug,
    225                         'fid'     => $feed_id,
    226                         'id'      => $form_id,
     227                        'page'    => 'gf_edit_forms',
     228                        'view'    => 'settings',
     229                        'subview' => $gf_subview_slug,
     230                        'fid'     => $feed_id,
     231                        'id'      => $form_id,
    227232                    ],
    228233                    admin_url( 'admin.php' )
    229             );
    230 
    231             echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
    232             echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_feed ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
    233             echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
    234             echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_form ) . '">' . esc_html( $form_name ) . '</a>';
    235             // Toggle button
    236             echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
    237             echo '<input type="hidden" name="action" value="' . esc_attr( $toggle_action ) . '" />';
    238             echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $feed_id ) . '" />';
    239             echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $toggle_action . '_' . $feed_id ) ) . '" />';
    240             $label = $is_active ? 'Deactivate' : 'Activate';
    241             $cls   = $is_active ? 'button' : 'button button-primary';
    242             echo '<button class="' . esc_attr( $cls ) . '" type="submit">' . esc_html( $label ) . '</button>';
    243             echo '</form>';
    244             echo '</li>';
    245         }
    246         echo '</ul>';
     234                );
     235
     236                echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
     237                echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_feed ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
     238                echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
     239                echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_form ) . '">' . esc_html( $form_name ) . '</a>';
     240                // Toggle button
     241                echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
     242                echo '<input type="hidden" name="action" value="' . esc_attr( $toggle_action ) . '" />';
     243                echo '<input type="hidden" name="return_url" value="' . esc_attr( 'admin.php?page=' . $gf_subview_slug . '&tab=feeds' ) . '" />';
     244                echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $feed_id ) . '" />';
     245                echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $toggle_action . '_' . $feed_id ) ) . '" />';
     246                $label = $is_active ? 'Deactivate' : 'Activate';
     247                $cls   = $is_active ? 'button' : 'button button-primary';
     248                echo '<button class="' . esc_attr( $cls ) . '" type="submit">' . esc_html( $label ) . '</button>';
     249                echo '</form>';
     250                echo '</li>';
     251            }
     252            echo '</ul>';
     253        }
    247254        echo '</div>';
     255
     256        if ( ! empty( $workflow_steps ) ) {
     257            echo '<div class="gops-card" style="margin-top:20px;">';
     258            echo '<h2 class="gops-title" style="margin:0 0 10px;">Workflow Steps</h2>';
     259            echo '<ul style="margin:0; padding-left:18px;">';
     260            $workflow_toggle_action = str_replace( '_toggle_feed', '_toggle_workflow_step', $toggle_action );
     261            if ( $workflow_toggle_action === $toggle_action ) {
     262                $workflow_toggle_action = 'gravityops_toggle_workflow_step';
     263            }
     264
     265            foreach ( $workflow_steps as $item ) {
     266                $step      = $item['step'];
     267                $form      = $item['form'];
     268                $form_id   = $form['id'];
     269                $form_name = $form['title'];
     270                $step_id   = $step['id'];
     271                $is_active = (bool) ( $step['is_active'] ?? true );
     272                $name      = $step['step_label'] ?? ( 'Step #' . $step_id );
     273
     274                $edit_step = add_query_arg(
     275                    [
     276                        'page'    => 'gf_edit_forms',
     277                        'view'    => 'settings',
     278                        'subview' => 'gravityflow',
     279                        'fid'     => $step_id,
     280                        'id'      => $form_id,
     281                    ],
     282                    admin_url( 'admin.php' )
     283                );
     284
     285                echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
     286                echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_step ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
     287                echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
     288                echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id ) ) . '">' . esc_html( $form_name ) . '</a>';
     289                // Toggle button for workflow step
     290                echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
     291                echo '<input type="hidden" name="action" value="' . esc_attr( $workflow_toggle_action ) . '" />';
     292                echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $step_id ) . '" />';
     293                echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $workflow_toggle_action . '_' . $step_id ) ) . '" />';
     294
     295                echo '<input type="hidden" name="return_url" value="' . esc_attr( 'admin.php?page=' . $gf_subview_slug . '&tab=feeds' ) . '" />';
     296                $step_label = $is_active ? 'Deactivate' : 'Activate';
     297                $step_cls   = $is_active ? 'button' : 'button button-primary';
     298                echo '<button class="' . esc_attr( $step_cls ) . '" type="submit">' . esc_html( $step_label ) . '</button>';
     299                echo '</form>';
     300
     301                echo '</li>';
     302            }
     303            echo '</ul>';
     304            echo '</div>';
     305        }
    248306    }
    249307
     
    263321        }
    264322
    265         $fid   = isset( $_POST['feed_id'] ) ? (int) $_POST['feed_id'] : 0; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
     323        $fid             = isset( $_POST['feed_id'] ) ? (int) $_POST['feed_id'] : 0; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
     324        $post_return_url = isset( $_POST['return_url'] ) ? sanitize_text_field( wp_unslash( $_POST['return_url'] ) ) : '';
     325        if ( ! empty( $post_return_url ) ) {
     326            $return_url = $post_return_url;
     327        }
     328
    266329        $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['_wpnonce'] ) ) : '';
    267330        if ( ! $fid || ! wp_verify_nonce( $nonce, $action_prefix . '_' . $fid ) ) {
     
    290353
    291354    /**
     355     * Helper to fetch workflow steps for specific types across all forms.
     356     *
     357     * @param string|array $step_types The step type(s) to filter by (e.g. 'iawgf_update_task' or ['type1', 'type2']).
     358     * @return array Array of items, each having 'step' (array) and 'form' (array).
     359     */
     360    public static function get_workflow_steps_by_type( $step_types ) {
     361        if ( ! function_exists( 'gravity_flow' ) || ! class_exists( 'GFAPI' ) ) {
     362            return [];
     363        }
     364
     365        $step_types = (array) $step_types;
     366
     367        global $wpdb;
     368        $table_name = $wpdb->prefix . 'gf_addon_feed';
     369
     370        // phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     371        // Check if table exists
     372        $has_table = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) === $table_name;
     373        if ( ! $has_table ) {
     374            return [];
     375        }
     376
     377        // Workflow steps in Gravity Flow are stored as feeds for the 'gravityflow' addon.
     378        $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE addon_slug = %s", 'gravityflow' ), ARRAY_A );
     379        // phpcs:enable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     380
     381        if ( empty( $results ) ) {
     382            return [];
     383        }
     384
     385        $steps = [];
     386        foreach ( $results as $row ) {
     387            $meta = json_decode( (string) $row['meta'], true );
     388            if ( ! is_array( $meta ) ) {
     389                continue;
     390            }
     391
     392            $current_type = $meta['step_type'] ?? '';
     393            if ( in_array( $current_type, $step_types, true ) ) {
     394                $form_id = isset( $row['form_id'] ) ? (int) $row['form_id'] : 0;
     395                if ( ! $form_id ) {
     396                    continue;
     397                }
     398                $form = GFAPI::get_form( $form_id );
     399                if ( $form ) {
     400                    $steps[] = [
     401                        'step' => [
     402                            'id'         => $row['id'],
     403                            'form_id'    => $row['form_id'],
     404                            'is_active'  => $row['is_active'],
     405                            'step_label' => $meta['step_name'] ?? ( 'Step #' . $row['id'] ),
     406                        ],
     407                        'form' => $form,
     408                    ];
     409                }
     410            }
     411        }
     412
     413        return $steps;
     414    }
     415
     416    /**
    292417     * Render a standard Help tab card.
    293418     *
     
    306431        }
    307432        echo '</ul>';
     433        echo '<div style="margin-top: 20px;">';
     434        echo '<a class="button button-primary" href="' . esc_url( admin_url( 'admin.php?page=gravity_ops_support' ) ) . '">Grant Support Access</a>';
    308435        echo '</div>';
     436        echo '</div>';
     437    }
     438
     439    /**
     440     * Show coupons on the GravityOps dashboard for plugins that aren't installed as premium.
     441     *
     442     * @param string $content Existing content.
     443     * @param array  $item    Plugin registry item.
     444     * @return string
     445     */
     446    public function maybe_render_dashboard_coupon( $content, $item ) {
     447        // Folders and Search are free-only, no coupons.
     448        if ( ! empty( $item['is_free'] ) ) {
     449            return $content;
     450        }
     451
     452        // If premium version is installed, don't show coupon.
     453        if ( ! empty( $item['is_installed_prem'] ) ) {
     454            return $content;
     455        }
     456
     457        $coupons = [
     458            'integrate-asana-with-gravity-forms'          => 'GRAVITYASANA10GIFT',
     459            'mass_email_notifications_for_gf'             => 'MASSEMAIL10GIFT',
     460            'Recurring_Form_Submissions_For_Gravity_Form' => 'RECURSUB10GIFT',
     461            'gravity_ops_global_variables'                => 'GLOBVAR10GIFT',
     462            'kanban-view-for-gravity-view'                => 'KANBANVIEW10GIFT',
     463        ];
     464
     465        $slug   = $item['slug'] ?? '';
     466        $coupon = $coupons[ $slug ] ?? '';
     467
     468        if ( $coupon ) {
     469            $content .= '<div class="gops-tile-coupon" style="margin-top:10px; font-size: 0.7em; color: #2271b1; font-weight: 500;">';
     470            $content .= '<p><small>Special Gift: Get 10% Off Premium!</small></p>';
     471            $content .= '<p><small>Use coupon code <code><small>' . esc_html( $coupon ) . '</small></code> at checkout.</small></p>';
     472            $content .= '</div>';
     473        }
     474
     475        return $content;
    309476    }
    310477
     
    329496        }
    330497        $defaults             = [
     498            'slug'       => $slug,
    331499            'title'      => $slug,
    332500            'menu_title' => $slug,
     
    335503            'links'      => [],
    336504            'tabs'       => [], // array id => [ 'label' => '', 'type' => 'render|link', 'callback' => callable, 'url' => '' ]
     505            'render'     => null, // callable to render the whole page content (used if no tabs)
    337506        ];
    338507        $this->pages[ $slug ] = array_merge( $defaults, $args );
     
    362531            }
    363532
     533            $parent = 'gravity_ops';
     534            if ( 'gravity_ops_support' === $slug ) {
     535                $parent = null;
     536            }
     537
    364538            add_submenu_page(
    365                 'gravity_ops',
     539                $parent,
    366540                $args['title'] ?? $slug,
    367541                $args['menu_title'] ?? ( $args['title'] ?? $slug ),
     
    384558
    385559        $pages_lower_case = array_change_key_case( $this->pages );
    386         $is_shell_page    = isset( $pages_lower_case[ $page ] ) || ( false !== strpos( (string) $hook, 'gravity_ops' ) );
     560        $is_shell_page    = isset( $pages_lower_case[ $page ] ) || 'toplevel_page_gravity_ops' === $hook;
     561        $is_shell_page    = apply_filters( 'gravityops_is_shell_page', $is_shell_page, $page, $hook );
    387562
    388563        // Optionally style Freemius pages in-place.
     
    394569        }
    395570
    396         if ( ! $is_shell_page && ! $is_freemius ) {
     571        $is_gf_page = ( 0 === strpos( $page, 'gf_' ) ) || ( false !== strpos( (string) $hook, 'forms_page_gf' ) );
     572
     573        // Always load on our pages, Freemius pages, and GF pages.
     574        // Also load globally by default to ensure the sidebar menu icon is consistently styled.
     575        $load_globally = (bool) apply_filters( 'gravityops_load_admin_assets_globally', true );
     576
     577        if ( ! $is_shell_page && ! $is_freemius && ! $is_gf_page && ! $load_globally ) {
    397578            return;
    398579        }
    399580
    400581        $assets = self::resolve_assets_urls();
    401         if ( ! empty( $assets['css'] ) ) {
    402             wp_enqueue_style( 'gravityops-admin', $assets['css'], [], '1.0.0' );
    403         }
     582
     583        // Load minimal menu/icon CSS globally or on GF pages.
     584        if ( ! empty( $assets['menu_css'] ) ) {
     585            wp_enqueue_style( 'gravityops-menu', $assets['menu_css'], [], self::CORE_VERSION );
     586        }
     587
     588        // Load the full admin UI CSS only on our shell or Freemius pages.
     589        if ( ! empty( $assets['css'] ) && ( $is_shell_page || $is_freemius ) ) {
     590            wp_enqueue_style( 'gravityops-admin', $assets['css'], [ 'gravityops-menu' ], self::CORE_VERSION );
     591        }
     592
    404593        // On Freemius pages also load a small override stylesheet to hide native tabs safely.
    405594        if ( $is_freemius ) {
    406595            $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
    407             wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], '1.0.0' );
     596            wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], self::CORE_VERSION );
    408597        }
    409598        if ( ! empty( $assets['js'] ) ) {
    410             wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], '1.0.0', true );
     599            // We only need the JS on our shell pages or Freemius pages where we inject tabs.
     600            if ( ! $is_shell_page && ! $is_freemius ) {
     601                return;
     602            }
     603
     604            wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], self::CORE_VERSION, true );
     605
     606            // Identify the plugin and pass its config to JS
     607            $config       = null;
     608            $current_slug = '';
     609
     610            if ( $is_freemius ) {
     611                foreach ( $this->pages as $slug => $args ) {
     612                    $fs_slug = $slug;
     613                    $fs_slug = apply_filters( 'gravityops_freemius_base_slug', $fs_slug, $slug );
     614
     615                    $normalized_page = str_replace( '_', '-', $page );
     616                    $bases           = [
     617                        str_replace( '_', '-', strtolower( $fs_slug ) ),
     618                        str_replace( '_', '-', strtolower( $slug ) ),
     619                    ];
     620
     621                    $suffixes      = [ '-account', '-pricing', '-affiliation' ];
     622                    $valid_targets = array_merge(
     623                            ...array_map( fn( $b ) => array_map( fn( $s ) => $b . $s, $suffixes ), $bases )
     624                    );
     625
     626                    if ( in_array( $normalized_page, $valid_targets, true ) ) {
     627                        $current_slug = $slug;
     628                        break;
     629                    }
     630                }
     631            } elseif ( $is_shell_page && isset( $this->pages[ $page ] ) ) {
     632                $current_slug = $page;
     633            }
     634
     635            if ( $current_slug && isset( $this->pages[ $current_slug ] ) ) {
     636                $args     = $this->pages[ $current_slug ];
     637                $tabs     = [];
     638                $base_url = admin_url( 'admin.php?page=' . $current_slug );
     639
     640                foreach ( ( $args['tabs'] ?? [] ) as $id => $tab ) {
     641                    $tabs[] = [
     642                        'id'    => $id,
     643                        'label' => $tab['label'] ?? $id,
     644                        'url'   => ( ( $tab['type'] ?? 'render' ) === 'link' ) ? ( $tab['url'] ?? '#' ) : add_query_arg( 'tab', $id, $base_url ),
     645                    ];
     646                }
     647
     648                $config = apply_filters(
     649                    'gravityops_admin_config',
     650                    [
     651                        'slug'  => $current_slug,
     652                        'title' => $args['title'] ?? '',
     653                        'tabs'  => $tabs,
     654                    ],
     655                    $current_slug
     656                    );
     657            }
     658
     659            if ( $config ) {
     660                wp_localize_script( 'gravityops-admin', 'gops_admin_config', $config );
     661            }
    411662        }
    412663    }
     
    424675        add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
    425676        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     677        add_filter( 'gravityops_tile_after_description', [ $this, 'maybe_render_dashboard_coupon' ], 10, 2 );
     678
     679        // Initialize TrustedLogin on all page loads (for auth redirects and background tasks).
     680        if ( class_exists( __NAMESPACE__ . '\MENFGF\TrustedLogin' ) ) {
     681            TrustedLogin::get_instance();
     682        }
     683
     684        // Register the shared Support page.
     685        $this->register_support_page();
     686
    426687        self::$did_boot = true;
     688    }
     689
     690    /**
     691     * Register the shared Support page under the GravityOps menu.
     692     *
     693     * @return void
     694     */
     695    private function register_support_page() {
     696        $this->register_plugin_page(
     697            'gravity_ops_support',
     698            [
     699                'title'       => 'Grant Support Access',
     700                'menu_title'  => 'Support Access',
     701                'capability'  => class_exists( __NAMESPACE__ . '\SuiteMenu' ) ? SuiteMenu::get_parent_capability() : 'manage_options',
     702                'hide_header' => true,
     703                'render'      => [ TrustedLogin::get_instance(), 'render_support_screen' ],
     704            ]
     705        );
    427706    }
    428707
     
    470749        }
    471750
    472         $base_url = menu_page_url( $slug, false );
     751        $base_url    = menu_page_url( $slug, false );
     752        $hide_header = ! empty( $args['hide_header'] );
     753
    473754        // Always render full wrapper + header here; notices will be relocated via JS beneath the header.
    474         echo '<div class="wrap gops-admin">';
    475         $this->render_header_only( $args );
     755        echo '<div class="wrap gops-admin' . ( $hide_header ? ' gops-hide-header' : '' ) . '">';
     756        if ( ! $hide_header ) {
     757            $this->render_header_only( $args );
     758        }
    476759        // Dedicated notices container prevents margin-collapsing into the header
    477760        echo '<div class="gops-notices" aria-live="polite"></div>';
     
    495778
    496779        echo '<section class="gops-content">';
    497         if ( isset( $tabs[ $active ] ) ) {
     780        if ( ! empty( $tabs ) && isset( $tabs[ $active ] ) ) {
    498781            $tab  = $tabs[ $active ];
    499782            $type = $tab['type'] ?? 'render';
     
    501784                call_user_func( $tab['callback'] );
    502785            }
     786        } elseif ( isset( $args['render'] ) && is_callable( $args['render'] ) ) {
     787            call_user_func( $args['render'] );
    503788        }
    504789        echo '</section>';
     
    514799     * @return void
    515800     */
    516     private function render_header_only( $args ) {
     801    public function render_header_only( $args ) {
     802        $icon_url = '';
     803        if ( ! empty( $args['slug'] ) && class_exists( __NAMESPACE__ . '\SuiteMenu' ) ) {
     804            $registry = SuiteRegistry::all();
     805            $item     = null;
     806            foreach ( $registry as $r ) {
     807                if ( ( $r['slug'] ?? '' ) === $args['slug'] ) {
     808                    $item = $r;
     809                    break;
     810                }
     811            }
     812            if ( $item ) {
     813                $icon_url = SuiteMenu::resolve_plugin_icon_url( $item );
     814            }
     815        }
    517816        ?>
    518         <header class="gops-header">
    519             <div class="gops-header__left">
    520                 <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
    521                 <div class="gops-headings">
    522                     <h1 class="gops-title"><?php echo esc_html( $args['title'] ?? '' ); ?></h1>
    523                     <?php if ( ! empty( $args['subtitle'] ) ) : ?>
    524                         <p class="gops-subtitle"><?php echo esc_html( $args['subtitle'] ); ?></p>
    525                     <?php endif; ?>
     817        <div class="gops-header-wrapper">
     818            <?php if ( $icon_url ) : ?>
     819                <img class="gops-header-icon" src="<?php echo esc_url( $icon_url ); ?>" alt="" width="80" height="80" />
     820            <?php endif; ?>
     821            <header class="gops-header">
     822                <div class="gops-header__left">
     823                    <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
     824                    <div class="gops-headings">
     825                        <h1 class="gops-title"><?php echo esc_html( $args['title'] ?? '' ); ?></h1>
     826                        <?php if ( ! empty( $args['subtitle'] ) ) : ?>
     827                            <p class="gops-subtitle"><?php echo esc_html( $args['subtitle'] ); ?></p>
     828                        <?php endif; ?>
     829                    </div>
    526830                </div>
    527             </div>
    528             <?php if ( ! empty( $args['links'] ) && is_array( $args['links'] ) ) : ?>
    529                 <div class="gops-header__right">
    530                     <?php foreach ( $args['links'] as $label => $url ) : ?>
    531                         <a class="gops-link" target="_blank" href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $label ); ?></a>
    532                     <?php endforeach; ?>
    533                 </div>
    534             <?php endif; ?>
    535         </header>
     831                <?php if ( ! empty( $args['links'] ) && is_array( $args['links'] ) ) : ?>
     832                    <div class="gops-header__right">
     833                        <?php foreach ( $args['links'] as $label => $url ) : ?>
     834                            <a class="gops-link" target="_blank" href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $label ); ?></a>
     835                        <?php endforeach; ?>
     836                    </div>
     837                <?php endif; ?>
     838            </header>
     839        </div>
    536840        <?php
    537841    }
     
    548852     *  - Fallback to site_url('gravityops/assets/') if present
    549853     *
    550      * @return array{css:string,js:string}
     854     * @return array{css:string,menu_css:string,js:string,base_url:string}
    551855     */
    552856    public static function resolve_assets_urls() {
    553857        $base_url = apply_filters( 'gravityops_assets_base_url', '' );
    554858        $css      = '';
     859        $menu_css = '';
    555860        $js       = '';
    556861
    557862        if ( is_string( $base_url ) && '' !== $base_url ) {
    558863            $base_url = trailingslashit( $base_url );
    559             $css      = $base_url . 'admin.css';
    560             $js       = $base_url . 'admin.js';
     864            $css      = $base_url . 'css/admin.css';
     865            $menu_css = $base_url . 'css/menu.css';
     866            $js       = $base_url . 'js/admin.js';
    561867            return [
    562                 'css' => $css,
    563                 'js'  => $js,
     868                'css'      => $css,
     869                'menu_css' => $menu_css,
     870                'js'       => $js,
     871                'base_url' => $base_url,
    564872            ];
    565873        }
     
    567875        // Try resolving relative to this class file (../../assets)
    568876        $assets_path = wp_normalize_path( dirname( __DIR__, 2 ) . '/assets' );
    569         $css_path    = $assets_path . '/admin.css';
    570         $js_path     = $assets_path . '/admin.js';
    571 
    572         if ( file_exists( $css_path ) || file_exists( $js_path ) ) {
     877        $css_path    = $assets_path . '/css/admin.css';
     878        $menu_path   = $assets_path . '/css/menu.css';
     879        $js_path     = $assets_path . '/js/admin.js';
     880
     881        if ( file_exists( $css_path ) || file_exists( $js_path ) || file_exists( $menu_path ) ) {
    573882            $content_dir = wp_normalize_path( WP_CONTENT_DIR );
    574883            if ( 0 === strpos( $assets_path, $content_dir ) ) {
     
    583892            }
    584893            if ( $base_url ) {
    585                 $css = file_exists( $css_path ) ? $base_url . 'admin.css' : '';
    586                 $js  = file_exists( $js_path ) ? $base_url . 'admin.js' : '';
     894                $css      = file_exists( $css_path ) ? $base_url . 'css/admin.css' : '';
     895                $menu_css = file_exists( $menu_path ) ? $base_url . 'css/menu.css' : '';
     896                $js       = file_exists( $js_path ) ? $base_url . 'js/admin.js' : '';
    587897                return [
    588                     'css' => $css,
    589                     'js'  => $js,
     898                    'css'      => $css,
     899                    'menu_css' => $menu_css,
     900                    'js'       => $js,
     901                    'base_url' => $base_url,
    590902                ];
    591903            }
     
    594906        // Fallback to root-level gravityops/assets
    595907        $root_assets = 'gravityops/assets/';
    596         if ( file_exists( ABSPATH . $root_assets . 'admin.css' ) ) {
    597             $css = site_url( $root_assets . 'admin.css' );
    598         }
    599         if ( file_exists( ABSPATH . $root_assets . 'admin.js' ) ) {
    600             $js = site_url( $root_assets . 'admin.js' );
     908        $base_url    = trailingslashit( site_url( $root_assets ) );
     909        if ( file_exists( ABSPATH . $root_assets . 'css/admin.css' ) ) {
     910            $css = $base_url . 'css/admin.css';
     911        }
     912        if ( file_exists( ABSPATH . $root_assets . 'css/menu.css' ) ) {
     913            $menu_css = $base_url . 'css/menu.css';
     914        }
     915        if ( file_exists( ABSPATH . $root_assets . 'js/admin.js' ) ) {
     916            $js = $base_url . 'js/admin.js';
    601917        }
    602918        return [
    603             'css' => $css,
    604             'js'  => $js,
     919            'css'      => $css,
     920            'menu_css' => $menu_css,
     921            'js'       => $js,
     922            'base_url' => $base_url,
    605923        ];
    606924    }
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/src/Admin/ReviewPrompter.php

    r3420036 r3444395  
    7777
    7878        if ( $current_count > $threshold ) {
    79             add_action( 'admin_notices', [ $this, 'render_notice' ] );
     79            $this->render_notice();
    8080        }
    8181    }
     
    120120        }
    121121
    122         $nonce = wp_create_nonce( $this->prefix . 'rating_asked' );
    123         ?>
    124         <div class="notice notice-success is-dismissible">
    125             <h3>Thank you for using <?php echo esc_html( $this->plugin_title ); ?>! I noticed you've used it a lot!</h3>
    126             <h4>
    127                 If you like the plugin and find it helpful, can you do us a big favor and <a
    128                         href="<?php echo esc_url( $url ); ?>"
    129                         target="_blank" rel="noreferrer">rate it</a> with ⭐⭐⭐⭐⭐?
    130                 It helps us spread the word and boost our motivation.
    131             </h4>
    132             <form method="post" action="">
    133                 <input type="hidden" name="<?php echo esc_attr( $this->prefix . 'rating_nonce' ); ?>" value="<?php echo esc_attr( $nonce ); ?>">
    134                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="remind">Remind me later</button>
    135                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="done">Done!</button>
    136                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="done">Not Interested</button>
    137             </form>
    138         </div>
    139         <?php
     122        $nonce_field  = $this->prefix . 'rating_nonce';
     123        $action_field = $this->prefix . 'rating_action';
     124        $nonce_action = $this->prefix . 'rating_asked';
     125        $plugin_title = $this->plugin_title;
     126
     127        $nonce = wp_create_nonce( $nonce_action );
     128
     129        $current_page   = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     130        $is_gops_page   = ( 'gravity_ops' === $current_page || AdminShell::has_page( $current_page ) );
     131        $notice_classes = 'notice notice-success is-dismissible';
     132        if ( $is_gops_page ) {
     133            $notice_classes .= ' inline';
     134        }
     135        add_action(
     136            'admin_notices',
     137            function () use ( $nonce, $action_field, $nonce_field, $plugin_title, $url, $notice_classes ) {
     138                ?>
     139            <div class="<?= esc_attr( $notice_classes ); ?>">
     140                <h3>Thank you for using <?php echo esc_html( $plugin_title ); ?>! I noticed you've used it a lot!</h3>
     141                <h4>
     142                    If you like the plugin and find it helpful, can you do us a big favor and <a
     143                            href="<?php echo esc_url( $url ); ?>"
     144                            target="_blank" rel="noreferrer">rate it</a> with ⭐⭐⭐⭐⭐?
     145                    It helps us spread the word and boost our motivation.
     146                </h4>
     147                <form method="post" action="">
     148                    <input type="hidden" name="<?php echo esc_attr( $nonce_field ); ?>" value="<?php echo esc_attr( $nonce ); ?>">
     149                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="remind">Remind me later</button>
     150                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="done">Done!</button>
     151                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="done">Not Interested</button>
     152                </form>
     153            </div>
     154                <?php
     155            }
     156            );
    140157    }
    141158
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/src/Admin/SuiteMenu.php

    r3422687 r3444395  
    216216                }
    217217                $registry[ $key ]['is_installed']       = $is_installed;
     218                $registry[ $key ]['is_installed_prem']  = ! empty( $item['is_free'] ) ? false : $is_installed;
     219                $registry[ $key ]['is_installed_free']  = ! empty( $item['is_free'] ) ? $is_installed : false;
    218220                $registry[ $key ]['is_active']          = $is_active;
    219221                $registry[ $key ]['version']            = $version;
     
    270272            // Updates: consider whichever is installed; prefer premium if both
    271273            if ( $upd_prem || $upd_free ) {
    272                 $has_update  = $upd_prem || $upd_free;
    273                 $new_version = $upd_prem ? $new_prem : $new_free;
    274                 ++$updates_count;
     274                $has_update  = $upd_prem || ( $upd_free && ! $is_installed_prem );
     275                $new_version = $upd_prem ? $new_prem : ( $is_installed_prem ? '' : $new_free );
     276                if ( $has_update ) {
     277                    ++$updates_count;
     278                }
    275279            }
    276280
     
    284288
    285289            $registry[ $key ]['is_installed']       = $is_installed;
     290            $registry[ $key ]['is_installed_prem']  = $is_installed_prem;
     291            $registry[ $key ]['is_installed_free']  = $is_installed_free;
    286292            $registry[ $key ]['is_active']          = $is_active;
    287293            $registry[ $key ]['version']            = $version;
     
    328334        ?>
    329335        <div class="wrap gops-admin">
    330             <header class="gops-header">
    331                 <div class="gops-header__left">
    332                     <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
    333                     <div class="gops-headings">
    334                         <h1 class="gops-title">Run Your Business on WordPress</h1>
    335                         <p class="gops-subtitle">All your GravityOps tools in one place.</p>
     336            <div class="gops-header-wrapper">
     337                <img class="gops-header-icon" src="<?php echo esc_url( self::get_icon() ); ?>" alt="" width="80" height="80" />
     338                <header class="gops-header">
     339                    <div class="gops-header__left">
     340                        <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
     341                        <div class="gops-headings">
     342                            <h1 class="gops-title">Run Your Business on WordPress</h1>
     343                            <p class="gops-subtitle">All your GravityOps tools in one place.</p>
     344                        </div>
    336345                    </div>
    337                 </div>
    338                 <div class="gops-header__right">
    339                     <a class="button button-primary" target="_blank" rel="noopener" href="https://brightleafdigital.io/plugintomember">Join Community</a>
    340                 </div>
    341             </header>
     346                    <div class="gops-header__right">
     347                        <a class="button button-primary" target="_blank" rel="noopener" href="https://brightleafdigital.io/plugintomember">Join Community</a>
     348                    </div>
     349                </header>
     350            </div>
    342351            <div class="gops-notices" aria-live="polite"></div>
    343352
     
    404413                            if ( $icon_url ) :
    405414                                ?>
    406                                 <img class="gops-tile__iconimg" width="22" height="22" src="<?php echo esc_url( $icon_url ); ?>" alt=""/>
     415                                <img class="gops-tile__iconimg" width="48" height="48" src="<?php echo esc_url( $icon_url ); ?>" alt=""/>
    407416                            <?php else : ?>
    408417                                <div class="gops-tile__icon" aria-hidden="true"><?php echo isset( $item['icon_html'] ) ? wp_kses_post( $item['icon_html'] ) : '🔧'; ?></div>
     
    411420                        </div>
    412421                        <p class="gops-tile__desc"><?php echo esc_html( $item['description'] ); ?></p>
     422                        <?php echo wp_kses_post( apply_filters( 'gravityops_tile_after_description', '', $item ) ); ?>
    413423                        <div class="gops-tile__meta">
    414                             <span class="gops-badge<?php echo $is_active ? ' gops-badge--ok' : ' gops-badge--warn'; ?>">
    415                                 <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
    416                             </span>
    417424                            <?php if ( ! empty( $item['uses_free'] ) ) : ?>
    418425                                <span class="gops-badge">Free</span>
    419                             <?php endif; ?>
    420                             <?php if ( $version ) : ?>
    421                                 <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
    422426                            <?php endif; ?>
    423427                            <?php if ( $has_update ) : ?>
     
    427431
    428432                        <div class="gops-tile__actions">
    429                             <?php if ( $is_installed ) : ?>
    430                                 <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
    431                                     <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
    432                                         <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
    433                                         <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
    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'] ) ); ?>" />
    435                                         <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
    436                                     </form>
     433                            <div class="gops-tile__action-group">
     434                                <?php if ( $version ) : ?>
     435                                    <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
    437436                                <?php endif; ?>
    438                             <?php else : ?>
    439                                 <a class="button button-primary" target="_blank" href="<?php echo esc_url( ( $item['marketing_url'] ?? '' ) . '#pricing' ); ?>">Buy</a>
    440                             <?php endif; ?>
    441 
    442                             <a class="gops-link" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Learn More →</a>
     437                                <span class="gops-badge<?php echo $is_active ? ' gops-badge--ok' : ' gops-badge--warn'; ?>">
     438                                    <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
     439                                </span>
     440
     441                                <?php if ( $is_installed ) : ?>
     442                                    <?php
     443                                    if ( $has_update && current_user_can( 'update_plugins' ) ) :
     444                                        // Use the file that actually has the update (prefer premium if both, though Issue 3 might have simplified this).
     445                                        $update_file = ( isset( $upd_prem ) && $upd_prem ) ? $premium_file : ( ( isset( $upd_free ) && $upd_free ) ? $free_file : $item['plugin_file_action'] );
     446                                        $update_url  = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . rawurlencode( $update_file ) ), 'upgrade-plugin_' . $update_file );
     447                                        ?>
     448                                        <a class="button button-primary" href="<?php echo esc_url( $update_url ); ?>">Update Now</a>
     449                                    <?php endif; ?>
     450
     451                                    <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
     452                                        <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
     453                                            <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
     454                                            <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
     455                                            <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'] ) ); ?>" />
     456                                            <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
     457                                        </form>
     458                                    <?php endif; ?>
     459                                <?php else : ?>
     460                                    <?php if ( ! empty( $item['is_free'] ) ) : ?>
     461                                        <a class="button button-primary" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Download Now</a>
     462                                    <?php else : ?>
     463                                        <a class="button button-primary" target="_blank" href="<?php echo esc_url( ( $item['marketing_url'] ?? '' ) . '#pricing' ); ?>">Buy</a>
     464                                    <?php endif; ?>
     465                                <?php endif; ?>
     466                            </div>
     467
     468                            <a class="gops-link gops-tile__learn-more" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Learn More →</a>
    443469                        </div>
    444470                    </div>
     
    452478
    453479    /**
     480     * Helper to get a plugin's icon URL by its slug.
     481     *
     482     * @param string $slug Plugin slug as defined in SuiteRegistry.
     483     * @return string Icon URL or empty string.
     484     */
     485    public static function get_plugin_icon_url( $slug ) {
     486        $registry = SuiteRegistry::all();
     487        foreach ( $registry as $item ) {
     488            if ( ( $item['slug'] ?? '' ) === $slug ) {
     489                return self::resolve_plugin_icon_url( $item );
     490            }
     491        }
     492        return '';
     493    }
     494
     495    /**
    454496     * Resolve a plugin icon URL from common asset locations, with filter override.
    455497     *
     
    457499     * @return string Icon URL or empty string if none found.
    458500     */
    459     private static function resolve_plugin_icon_url( $item ) {
     501    public static function resolve_plugin_icon_url( $item ) {
    460502        $url = apply_filters( 'gravityops_plugin_icon_url', '', $item );
    461503        if ( ! empty( $url ) ) {
     
    463505        }
    464506
    465         if ( empty( $item['plugin_file'] ) ) {
    466             return '';
    467         }
    468 
    469         $plugin_main = WP_PLUGIN_DIR . '/' . $item['plugin_file'];
    470         if ( ! file_exists( $plugin_main ) ) {
    471             return '';
    472         }
    473 
    474         // Base plugin URL for building asset URLs.
    475         $base_url = plugins_url( '', $plugin_main );
    476         $base_dir = dirname( $plugin_main );
    477 
    478         $candidates = [
    479             'assets/icon.svg',
    480             'assets/icon.png',
    481             'assets/images/icon.svg',
    482             'assets/images/icon.png',
    483             'includes/images/icon.svg',
    484             'includes/images/icon.png',
    485             'assets/img/icon.svg',
    486             'assets/img/icon.png',
    487         ];
    488         foreach ( $candidates as $rel ) {
    489             $path = $base_dir . '/' . $rel;
    490             if ( file_exists( $path ) ) {
    491                 return $base_url . '/' . $rel;
    492             }
    493         }
    494 
    495         // Wildcard: first match like assets/img/*-icon.svg|png
    496         $wild_dirs = [ 'assets/img' ];
    497         foreach ( $wild_dirs as $wd ) {
    498             $dir = $base_dir . '/' . $wd;
    499             if ( is_dir( $dir ) ) {
    500                 $matches = array_merge( glob( $dir . '/*-icon.svg' ) ?: [], glob( $dir . '/*-icon.png' ) ?: [] );
    501                 if ( ! empty( $matches ) ) {
    502                     // Return the first match
    503                     $first = $matches[0];
    504                     return $base_url . '/' . $wd . '/' . basename( $first );
     507        if ( ! empty( $item['icon_filename'] ) ) {
     508            $assets = class_exists( __NAMESPACE__ . '\AdminShell' ) ? AdminShell::resolve_assets_urls() : [];
     509            $base   = ! empty( $assets['base_url'] ) ? $assets['base_url'] : ( ! empty( $assets['css'] ) ? trailingslashit( dirname( $assets['css'], 2 ) ) : '' );
     510            if ( $base ) {
     511                return $base . 'images/' . $item['icon_filename'];
     512            }
     513        }
     514
     515        $files_to_check = [];
     516        if ( ! empty( $item['plugin_files'] ) ) {
     517            if ( isset( $item['plugin_files']['premium'] ) ) {
     518                $files_to_check[] = $item['plugin_files']['premium'];
     519            }
     520            if ( isset( $item['plugin_files']['free'] ) ) {
     521                $files_to_check[] = $item['plugin_files']['free'];
     522            }
     523        }
     524        if ( ! empty( $item['plugin_file'] ) ) {
     525            $files_to_check[] = (string) $item['plugin_file'];
     526        }
     527
     528        $files_to_check = array_unique( $files_to_check );
     529
     530        foreach ( $files_to_check as $plugin_rel_file ) {
     531            $plugin_main = WP_PLUGIN_DIR . '/' . $plugin_rel_file;
     532            if ( ! file_exists( $plugin_main ) ) {
     533                continue;
     534            }
     535
     536            // Base plugin URL for building asset URLs.
     537            $base_url = plugins_url( '', $plugin_main );
     538            $base_dir = dirname( $plugin_main );
     539
     540            $candidates = [
     541                'assets/icon.svg',
     542                'assets/icon.png',
     543                'assets/images/icon.svg',
     544                'assets/images/icon.png',
     545                'includes/images/icon.svg',
     546                'includes/images/icon.png',
     547                'assets/img/icon.svg',
     548                'assets/img/icon.png',
     549            ];
     550            foreach ( $candidates as $rel ) {
     551                $path = $base_dir . '/' . $rel;
     552                if ( file_exists( $path ) ) {
     553                    return $base_url . '/' . $rel;
    505554                }
    506555            }
    507         }
     556
     557            // Wildcard: first match like assets/img/*-icon.svg|png
     558            $wild_dirs = [ 'assets/img', 'assets/images' ];
     559            foreach ( $wild_dirs as $wd ) {
     560                $dir = $base_dir . '/' . $wd;
     561                if ( is_dir( $dir ) ) {
     562                    $matches = array_merge( glob( $dir . '/*-icon.svg' ) ?: [], glob( $dir . '/*-icon.png' ) ?: [] );
     563                    if ( ! empty( $matches ) ) {
     564                        // Return the first match
     565                        $first = $matches[0];
     566                        return $base_url . '/' . $wd . '/' . basename( $first );
     567                    }
     568                }
     569            }
     570        }
     571
    508572        return '';
    509573    }
     
    525589        $is_gravityops_screen = ( false !== strpos( (string) $hook, 'gravity_ops' ) ) || ( 'gravity_ops' === $page );
    526590        $is_freemius          = (bool) preg_match( '/\-(account|pricing|affiliation)$/', $page );
    527         if ( ! $is_gravityops_screen && ! $is_freemius ) {
     591        $is_gf_page           = ( 0 === strpos( $page, 'gf_' ) ) || ( false !== strpos( (string) $hook, 'forms_page_gf' ) );
     592
     593        // Always load on our pages, Freemius pages, and GF pages.
     594        // Also load globally by default to ensure the sidebar menu icon is consistently styled.
     595        $load_globally = (bool) apply_filters( 'gravityops_load_admin_assets_globally', true );
     596
     597        if ( ! $is_gravityops_screen && ! $is_freemius && ! $is_gf_page && ! $load_globally ) {
    528598            return;
    529599        }
     
    531601        // Reuse AdminShell asset resolution to support both root and vendor installs.
    532602        if ( class_exists( __NAMESPACE__ . '\\AdminShell' ) ) {
    533             $assets = AdminShell::resolve_assets_urls();
    534             if ( ! empty( $assets['css'] ) ) {
    535                 wp_enqueue_style( 'gravityops-admin', $assets['css'], [], '1.0.0' );
    536             }
    537             if ( ! empty( $assets['js'] ) ) {
    538                 wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], '1.0.0', true );
    539             }
    540             // If this is a Freemius page, also enqueue the freemius.css override to hide native tabs.
    541             if ( $is_freemius ) {
    542                 $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
    543                 wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], '1.0.0' );
     603            $assets  = AdminShell::resolve_assets_urls();
     604            $version = defined( AdminShell::class . '::CORE_VERSION' ) ? AdminShell::CORE_VERSION : '1.0.0';
     605
     606            // Load minimal menu/icon CSS globally or on GF pages.
     607            if ( ! empty( $assets['menu_css'] ) ) {
     608                wp_enqueue_style( 'gravityops-menu', $assets['menu_css'], [], $version );
     609            }
     610
     611            // Load the full admin UI CSS only on our screens or Freemius screens.
     612            if ( ! empty( $assets['css'] ) && ( $is_gravityops_screen || $is_freemius ) ) {
     613                wp_enqueue_style( 'gravityops-admin', $assets['css'], [ 'gravityops-menu' ], $version );
     614            }
     615
     616            // We only need the JS on our screens or Freemius screens.
     617            if ( $is_gravityops_screen || $is_freemius ) {
     618                if ( ! empty( $assets['js'] ) ) {
     619                    wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], $version, true );
     620                }
     621                // If this is a Freemius page, also enqueue the freemius.css override to hide native tabs.
     622                if ( $is_freemius ) {
     623                    $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
     624                    wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], $version );
     625                }
    544626            }
    545627        }
     
    637719    public static function get_icon() {
    638720        $assets    = class_exists( __NAMESPACE__ . '\AdminShell' ) ? AdminShell::resolve_assets_urls() : [
    639             'css' => '',
    640             'js'  => '',
     721            'css'      => '',
     722            'js'       => '',
     723            'base_url' => '',
    641724        ];
    642         $base      = ! empty( $assets['css'] ) ? trailingslashit( dirname( $assets['css'] ) ) : '';
    643         $candidate = 'images/icon.png';
     725        $base      = ! empty( $assets['base_url'] ) ? $assets['base_url'] : ( ! empty( $assets['css'] ) ? trailingslashit( dirname( dirname( $assets['css'] ) ) ) : '' );
     726        $candidate = 'images/ops-icon.svg';
    644727        $url       = $base ? $base . $candidate : '';
    645728        return apply_filters( 'gravityops_menu_icon_url', $url );
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/src/Admin/SurveyPrompter.php

    r3420036 r3444395  
    125125        $nonce_action     = "{$this->prefix}do_survey";
    126126
     127        $current_page   = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     128        $is_gops_page   = ( 'gravity_ops' === $current_page || AdminShell::has_page( $current_page ) );
     129        $notice_classes = 'notice notice-info is-dismissible';
     130        if ( $is_gops_page ) {
     131            $notice_classes .= ' inline';
     132        }
    127133        add_action(
    128134            'admin_notices',
    129             function () use ( $star_class, $rating_input_id, $rating_field, $like_field, $dislike_field, $recommend_field, $find_field, $nonce_field_name, $submit_field, $nonce_action ) {
     135            function () use ( $star_class, $rating_input_id, $rating_field, $like_field, $dislike_field, $recommend_field, $find_field, $nonce_field_name, $submit_field, $nonce_action, $notice_classes ) {
    130136                ?>
    131                 <div class="notice notice-info is-dismissible">
     137                <div class="<?= esc_attr( $notice_classes ); ?>">
    132138                    <h3>We value your feedback!</h3>
    133139                    <h4>Thank you for using <?= esc_html( $this->plugin_title ); ?>!</h4>
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/MENFGF/gravityops/core/src/SuiteRegistry.php

    r3422687 r3444395  
    3838                'is_free'       => true,
    3939                'icon_html'     => '🗂️',
     40                'icon_filename' => 'f4g-icon.svg',
    4041            ],
    4142            [
     
    4950                'is_free'       => true,
    5051                'icon_html'     => '🔎',
     52                'icon_filename' => 'search-icon.svg',
    5153            ],
    5254            [
     
    6567                'is_free'       => false,
    6668                'icon_html'     => '🅰️',
     69                'icon_filename' => 'iawgf-icon.svg',
    6770            ],
    6871            [
     
    8184                'is_free'       => false,
    8285                'icon_html'     => '✉️',
     86                'icon_filename' => 'menfgf-icon.svg',
    8387            ],
    8488            [
     
    9296                'is_free'       => false,
    9397                'icon_html'     => '🗂️',
     98                'icon_filename' => 'kv4gv-icon.svg',
    9499            ],
    95100            [
     
    103108                'is_free'       => false,
    104109                'icon_html'     => '🔁',
     110                'icon_filename' => 'rfsfgf-icon.svg',
    105111            ],
    106112            [
     
    115121                'is_free'       => false,
    116122                'icon_html'     => '∑',
     123                'icon_filename' => 'gv4gm-icon.svg',
    117124            ],
    118125        ];
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/autoload.php

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

    r3422687 r3444395  
    22
    33// Functions and constants
     4
     5namespace {
     6
     7}
    48namespace GravityOps\Core\Admin {
    59    if(!function_exists('\\GravityOps\\Core\\Admin\\gravityops_shell')){
     
    913    }
    1014}
     15namespace TrustedLogin {
     16    if(!function_exists('\\TrustedLogin\\function_exists')){
     17        function function_exists(...$args) {
     18            return \MENFGF\TrustedLogin\function_exists(...func_get_args());
     19        }
     20    }
     21}
    1122
    1223
    1324namespace MENFGF {
    1425
     26    use BrianHenryIE\Strauss\Types\AutoloadAliasInterface;
     27
     28    /**
     29     * @see AutoloadAliasInterface
     30     *
     31     * @phpstan-type ClassAliasArray array{'type':'class',isabstract:bool,classname:string,namespace?:string,extends:string,implements:array<string>}
     32     * @phpstan-type InterfaceAliasArray array{'type':'interface',interfacename:string,namespace?:string,extends:array<string>}
     33     * @phpstan-type TraitAliasArray array{'type':'trait',traitname:string,namespace?:string,use:array<string>}
     34     * @phpstan-type AutoloadAliasArray array<string,ClassAliasArray|InterfaceAliasArray|TraitAliasArray>
     35     */
    1536    class AliasAutoloader
    1637    {
    1738        private string $includeFilePath;
    1839
     40        /**
     41         * @var AutoloadAliasArray
     42         */
    1943        private array $autoloadAliases = array (
    2044  'GravityOps\\Core\\Admin\\AdminShell' =>
     
    7397    ),
    7498  ),
     99  'GravityOps\\Core\\Admin\\TrustedLogin' =>
     100  array (
     101    'type' => 'class',
     102    'classname' => 'TrustedLogin',
     103    'isabstract' => false,
     104    'namespace' => 'GravityOps\\Core\\Admin',
     105    'extends' => 'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin',
     106    'implements' =>
     107    array (
     108    ),
     109  ),
    75110  'GravityOps\\Core\\SuiteRegistry' =>
    76111  array (
     
    91126    'namespace' => 'GravityOps\\Core\\Utils',
    92127    'extends' => 'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper',
     128    'implements' =>
     129    array (
     130    ),
     131  ),
     132  'TrustedLogin\\Admin' =>
     133  array (
     134    'type' => 'class',
     135    'classname' => 'Admin',
     136    'isabstract' => false,
     137    'namespace' => 'TrustedLogin',
     138    'extends' => 'MENFGF\\TrustedLogin\\Admin',
     139    'implements' =>
     140    array (
     141    ),
     142  ),
     143  'TrustedLogin\\Ajax' =>
     144  array (
     145    'type' => 'class',
     146    'classname' => 'Ajax',
     147    'isabstract' => false,
     148    'namespace' => 'TrustedLogin',
     149    'extends' => 'MENFGF\\TrustedLogin\\Ajax',
     150    'implements' =>
     151    array (
     152    ),
     153  ),
     154  'TrustedLogin\\Client' =>
     155  array (
     156    'type' => 'class',
     157    'classname' => 'Client',
     158    'isabstract' => false,
     159    'namespace' => 'TrustedLogin',
     160    'extends' => 'MENFGF\\TrustedLogin\\Client',
     161    'implements' =>
     162    array (
     163    ),
     164  ),
     165  'TrustedLogin\\Config' =>
     166  array (
     167    'type' => 'class',
     168    'classname' => 'Config',
     169    'isabstract' => false,
     170    'namespace' => 'TrustedLogin',
     171    'extends' => 'MENFGF\\TrustedLogin\\Config',
     172    'implements' =>
     173    array (
     174    ),
     175  ),
     176  'TrustedLogin\\Cron' =>
     177  array (
     178    'type' => 'class',
     179    'classname' => 'Cron',
     180    'isabstract' => false,
     181    'namespace' => 'TrustedLogin',
     182    'extends' => 'MENFGF\\TrustedLogin\\Cron',
     183    'implements' =>
     184    array (
     185    ),
     186  ),
     187  'TrustedLogin\\Encryption' =>
     188  array (
     189    'type' => 'class',
     190    'classname' => 'Encryption',
     191    'isabstract' => false,
     192    'namespace' => 'TrustedLogin',
     193    'extends' => 'MENFGF\\TrustedLogin\\Encryption',
     194    'implements' =>
     195    array (
     196    ),
     197  ),
     198  'TrustedLogin\\Endpoint' =>
     199  array (
     200    'type' => 'class',
     201    'classname' => 'Endpoint',
     202    'isabstract' => false,
     203    'namespace' => 'TrustedLogin',
     204    'extends' => 'MENFGF\\TrustedLogin\\Endpoint',
     205    'implements' =>
     206    array (
     207    ),
     208  ),
     209  'TrustedLogin\\Envelope' =>
     210  array (
     211    'type' => 'class',
     212    'classname' => 'Envelope',
     213    'isabstract' => false,
     214    'namespace' => 'TrustedLogin',
     215    'extends' => 'MENFGF\\TrustedLogin\\Envelope',
     216    'implements' =>
     217    array (
     218    ),
     219  ),
     220  'TrustedLogin\\Form' =>
     221  array (
     222    'type' => 'class',
     223    'classname' => 'Form',
     224    'isabstract' => false,
     225    'namespace' => 'TrustedLogin',
     226    'extends' => 'MENFGF\\TrustedLogin\\Form',
     227    'implements' =>
     228    array (
     229    ),
     230  ),
     231  'TrustedLogin\\Logger' =>
     232  array (
     233    'type' => 'class',
     234    'classname' => 'Logger',
     235    'isabstract' => false,
     236    'namespace' => 'TrustedLogin',
     237    'extends' => 'MENFGF\\TrustedLogin\\Logger',
     238    'implements' =>
     239    array (
     240    ),
     241  ),
     242  'TrustedLogin\\Logging' =>
     243  array (
     244    'type' => 'class',
     245    'classname' => 'Logging',
     246    'isabstract' => false,
     247    'namespace' => 'TrustedLogin',
     248    'extends' => 'MENFGF\\TrustedLogin\\Logging',
     249    'implements' =>
     250    array (
     251    ),
     252  ),
     253  'TrustedLogin\\Remote' =>
     254  array (
     255    'type' => 'class',
     256    'classname' => 'Remote',
     257    'isabstract' => false,
     258    'namespace' => 'TrustedLogin',
     259    'extends' => 'MENFGF\\TrustedLogin\\Remote',
     260    'implements' =>
     261    array (
     262    ),
     263  ),
     264  'TrustedLogin\\SecurityChecks' =>
     265  array (
     266    'type' => 'class',
     267    'classname' => 'SecurityChecks',
     268    'isabstract' => false,
     269    'namespace' => 'TrustedLogin',
     270    'extends' => 'MENFGF\\TrustedLogin\\SecurityChecks',
     271    'implements' =>
     272    array (
     273    ),
     274  ),
     275  'TrustedLogin\\SiteAccess' =>
     276  array (
     277    'type' => 'class',
     278    'classname' => 'SiteAccess',
     279    'isabstract' => false,
     280    'namespace' => 'TrustedLogin',
     281    'extends' => 'MENFGF\\TrustedLogin\\SiteAccess',
     282    'implements' =>
     283    array (
     284    ),
     285  ),
     286  'TrustedLogin\\SupportRole' =>
     287  array (
     288    'type' => 'class',
     289    'classname' => 'SupportRole',
     290    'isabstract' => false,
     291    'namespace' => 'TrustedLogin',
     292    'extends' => 'MENFGF\\TrustedLogin\\SupportRole',
     293    'implements' =>
     294    array (
     295    ),
     296  ),
     297  'TrustedLogin\\SupportUser' =>
     298  array (
     299    'type' => 'class',
     300    'classname' => 'SupportUser',
     301    'isabstract' => false,
     302    'namespace' => 'TrustedLogin',
     303    'extends' => 'MENFGF\\TrustedLogin\\SupportUser',
     304    'implements' =>
     305    array (
     306    ),
     307  ),
     308  'TrustedLogin\\Utils' =>
     309  array (
     310    'type' => 'class',
     311    'classname' => 'Utils',
     312    'isabstract' => false,
     313    'namespace' => 'TrustedLogin',
     314    'extends' => 'MENFGF\\TrustedLogin\\Utils',
     315    'implements' =>
     316    array (
     317    ),
     318  ),
     319  'TrustedLogin\\TrustedLoginClientTest' =>
     320  array (
     321    'type' => 'class',
     322    'classname' => 'TrustedLoginClientTest',
     323    'isabstract' => false,
     324    'namespace' => 'TrustedLogin',
     325    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginClientTest',
     326    'implements' =>
     327    array (
     328    ),
     329  ),
     330  'TrustedLogin\\TrustedLoginEncryptionTest' =>
     331  array (
     332    'type' => 'class',
     333    'classname' => 'TrustedLoginEncryptionTest',
     334    'isabstract' => false,
     335    'namespace' => 'TrustedLogin',
     336    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginEncryptionTest',
     337    'implements' =>
     338    array (
     339    ),
     340  ),
     341  'TrustedLogin\\TrustedLoginLoggingTest' =>
     342  array (
     343    'type' => 'class',
     344    'classname' => 'TrustedLoginLoggingTest',
     345    'isabstract' => false,
     346    'namespace' => 'TrustedLogin',
     347    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginLoggingTest',
     348    'implements' =>
     349    array (
     350    ),
     351  ),
     352  'TrustedLogin\\TrustedLoginRemoteTest' =>
     353  array (
     354    'type' => 'class',
     355    'classname' => 'TrustedLoginRemoteTest',
     356    'isabstract' => false,
     357    'namespace' => 'TrustedLogin',
     358    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginRemoteTest',
     359    'implements' =>
     360    array (
     361    ),
     362  ),
     363  'TrustedLogin\\TrustedLoginSiteAccessTest' =>
     364  array (
     365    'type' => 'class',
     366    'classname' => 'TrustedLoginSiteAccessTest',
     367    'isabstract' => false,
     368    'namespace' => 'TrustedLogin',
     369    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginSiteAccessTest',
    93370    'implements' =>
    94371    array (
     
    112389        }
    113390
    114         public function autoload($class)
     391        /**
     392         * @param string $class
     393         */
     394        public function autoload($class): void
    115395        {
    116396            if (!isset($this->autoloadAliases[$class])) {
     
    145425        }
    146426
    147         private function load(string $includeFile)
     427        private function load(string $includeFile): void
    148428        {
    149429            file_put_contents($this->includeFilePath, $includeFile);
     
    152432        }
    153433
     434        /**
     435         * @param ClassAliasArray $class
     436         */
    154437        private function classTemplate(array $class): string
    155438        {
     
    174457        }
    175458
     459        /**
     460         * @param InterfaceAliasArray $interface
     461         */
    176462        private function interfaceTemplate(array $interface): string
    177463        {
     
    188474                EOD;
    189475        }
     476
     477        /**
     478         * @param TraitAliasArray $trait
     479         */
    190480        private function traitTemplate(array $trait): string
    191481        {
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/composer/autoload_files.php

    r3422687 r3444395  
    88return array(
    99    '8d50dc88e56bace65e1e72f6017983ed' => $vendorDir . '/freemius/wordpress-sdk/start.php',
    10     '9387666eac3fc37c9ef87deb087980c6' => $vendorDir . '/MENFGF/autoload.php',
    11     '79fa1c9a31d9f4c8c1a536bd9e014492' => $vendorDir . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1210);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/composer/autoload_real.php

    r3422687 r3444395  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e
     5class ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::getInitializer($loader));
    3333
    3434        $loader->register(true);
    3535
    36         $filesToLoad = \Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$files;
     36        $filesToLoad = \Composer\Autoload\ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::$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.7/vendor/composer/autoload_static.php

    r3422687 r3444395  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e
     7class ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5
    88{
    99    public static $files = array (
    1010        '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php',
    11         '9387666eac3fc37c9ef87deb087980c6' => __DIR__ . '/..' . '/MENFGF/autoload.php',
    12         '79fa1c9a31d9f4c8c1a536bd9e014492' => __DIR__ . '/..' . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1311    );
    1412
     
    2018    {
    2119        return \Closure::bind(function () use ($loader) {
    22             $loader->classMap = ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$classMap;
     20            $loader->classMap = ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::$classMap;
    2321
    2422        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/composer/installed.json

    r3422687 r3444395  
    5959        {
    6060            "name": "gravityops/core",
    61             "version": "1.0.21",
    62             "version_normalized": "1.0.21.0",
     61            "version": "1.1.0",
     62            "version_normalized": "1.1.0.0",
    6363            "source": {
    6464                "type": "git",
    6565                "url": "[email protected]:Eitan-brightleaf/gravityops.git",
    66                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
     66                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e"
    6767            },
    6868            "dist": {
    6969                "type": "zip",
    70                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    71                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     70                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/cee27f55738670dc141b58af37d0feb74d4ce47e",
     71                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e",
    7272                "shasum": ""
    7373            },
    7474            "require": {
    75                 "php": ">=7.4"
     75                "php": ">=7.4",
     76                "trustedlogin/client": "^v1.9"
    7677            },
    77             "time": "2025-12-18T07:45:02+00:00",
     78            "time": "2026-01-21T19:42:14+00:00",
    7879            "type": "library",
    7980            "installation-source": "source",
     
    8485            "description": "Shared core library for GravityOps plugins",
    8586            "install-path": "../gravityops/core"
     87        },
     88        {
     89            "name": "trustedlogin/client",
     90            "version": "v1.9.0",
     91            "version_normalized": "1.9.0.0",
     92            "source": {
     93                "type": "git",
     94                "url": "https://github.com/trustedlogin/client.git",
     95                "reference": "b913058ae57b512a7766f449ab8d55952500fe72"
     96            },
     97            "dist": {
     98                "type": "zip",
     99                "url": "https://api.github.com/repos/trustedlogin/client/zipball/b913058ae57b512a7766f449ab8d55952500fe72",
     100                "reference": "b913058ae57b512a7766f449ab8d55952500fe72",
     101                "shasum": ""
     102            },
     103            "require-dev": {
     104                "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
     105                "ext-curl": "*",
     106                "ext-json": "*",
     107                "php": ">=5.3.0",
     108                "phpcompatibility/phpcompatibility-wp": "^2.1",
     109                "phpstan/extension-installer": "^1.3",
     110                "phpstan/phpstan": "^1.10",
     111                "szepeviktor/phpstan-wordpress": "^1.3",
     112                "wp-coding-standards/wpcs": "^3.0",
     113                "yoast/phpunit-polyfills": "^1.0.0"
     114            },
     115            "time": "2024-08-26T01:13:42+00:00",
     116            "bin": [
     117                "bin/build-sass"
     118            ],
     119            "type": "library",
     120            "installation-source": "dist",
     121            "autoload": [],
     122            "notification-url": "https://packagist.org/downloads/",
     123            "license": [
     124                "GPL-2.0-or-later"
     125            ],
     126            "authors": [
     127                {
     128                    "name": "TrustedLogin",
     129                    "email": "[email protected]",
     130                    "homepage": "https://www.trustedlogin.com"
     131                }
     132            ],
     133            "description": "Easily and securely log in to your customers sites when providing support.",
     134            "homepage": "https://www.trustedlogin.com",
     135            "keywords": [
     136                "login",
     137                "security",
     138                "support"
     139            ],
     140            "support": {
     141                "issues": "https://github.com/trustedlogin/client/issues",
     142                "source": "https://github.com/trustedlogin/client/tree/v1.9.0"
     143            },
     144            "install-path": "../trustedlogin/client"
    86145        }
    87146    ],
  • mass-email-notifications-for-gravity-forms/tags/1.3.7/vendor/composer/installed.php

    r3422687 r3444395  
    11<?php return array(
    22    'root' => array(
    3         'name' => '__root__',
     3        'name' => 'gravityops/mass-email',
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
     6        'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
     
    1111    ),
    1212    'versions' => array(
    13         '__root__' => array(
    14             'pretty_version' => 'dev-main',
    15             'version' => 'dev-main',
    16             'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    17             'type' => 'library',
    18             'install_path' => __DIR__ . '/../../',
    19             'aliases' => array(),
    20             'dev_requirement' => false,
    21         ),
    2213        'freemius/wordpress-sdk' => array(
    2314            'pretty_version' => '2.13.0',
     
    3021        ),
    3122        'gravityops/core' => array(
    32             'pretty_version' => '1.0.21',
    33             'version' => '1.0.21.0',
    34             'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
     23            'pretty_version' => '1.1.0',
     24            'version' => '1.1.0.0',
     25            'reference' => 'cee27f55738670dc141b58af37d0feb74d4ce47e',
    3526            'type' => 'library',
    3627            'install_path' => __DIR__ . '/../gravityops/core',
     
    3829            'dev_requirement' => false,
    3930        ),
     31        'gravityops/mass-email' => array(
     32            'pretty_version' => 'dev-main',
     33            'version' => 'dev-main',
     34            'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
     35            'type' => 'library',
     36            'install_path' => __DIR__ . '/../../',
     37            'aliases' => array(),
     38            'dev_requirement' => false,
     39        ),
     40        'trustedlogin/client' => array(
     41            'pretty_version' => 'v1.9.0',
     42            'version' => '1.9.0.0',
     43            'reference' => 'b913058ae57b512a7766f449ab8d55952500fe72',
     44            'type' => 'library',
     45            'install_path' => __DIR__ . '/../trustedlogin/client',
     46            'aliases' => array(),
     47            'dev_requirement' => false,
     48        ),
    4049    ),
    4150);
  • mass-email-notifications-for-gravity-forms/trunk/class-mass-email-notifications-for-gravity-forms.php

    r3422687 r3444395  
    241241                ],
    242242                // Freemius pages use the SDK menu slug (underscored) even if our AdminShell page uses a hyphenated slug.
    243                 AdminShell::freemius_tabs( $this->_slug )
     243                $this->get_freemius_tabs()
    244244             ),
    245245        ] );
    246246        // Admin actions to toggle feed activation and unsuppress emails from the GravityOps tabs.
    247247        add_action( 'admin_post_menfgf_toggle_feed', [$this, 'handle_toggle_feed'] );
     248        add_action( 'admin_post_menfgf_toggle_workflow_step', [$this, 'handle_toggle_workflow_step'] );
    248249        add_action( 'admin_post_menfgf_unsuppress', [$this, 'handle_unsuppress'] );
    249250        $param = 'https://wordpress.org/support/plugin/mass-email-notifications-for-gravity-forms/reviews/#new-post';
     
    315316            ];
    316317        }
     318        $workflow_steps = [];
     319        if ( class_exists( AdminShell::class ) ) {
     320            $workflow_steps = AdminShell::get_workflow_steps_by_type( 'menfgf_create_batch' );
     321        }
    317322        AdminShell::render_feeds_list(
    318323            $feeds_and_forms,
    319324            $this->_slug,
    320325            $this->_short_title,
    321             'menfgf_toggle_feed'
     326            'menfgf_toggle_feed',
     327            $workflow_steps
    322328        );
    323329    }
     
    402408
    403409    /**
     410     * Handle: Toggle workflow step activation from the Feeds tab (AdminShell)
     411     *
     412     * @return void
     413     */
     414    public function handle_toggle_workflow_step() {
     415        AdminShell::process_feed_toggle( 'menfgf_toggle_workflow_step', 'admin.php?page=mass_email_notifications_for_gf&tab=feeds' );
     416    }
     417
     418    /**
    404419     * Handle: Unsuppress an email from the Suppressions tab
    405420     *
     
    452467        $plan = menfgf_fs()->get_plan();
    453468        return ( is_object( $plan ) ? $plan->name : (( menfgf_fs()->is_free_plan() ? 'free' : 'unknown' )) );
     469    }
     470
     471    /**
     472     * Filter the AdminShell tabs to hide the Account tab if the user is not registered.
     473     *
     474     * @return array
     475     */
     476    private function get_freemius_tabs() {
     477        $tabs = AdminShell::freemius_tabs( $this->_slug );
     478        if ( !menfgf_fs()->is_registered() ) {
     479            unset($tabs['account']);
     480        }
     481        return $tabs;
    454482    }
    455483
     
    537565     */
    538566    public function get_menu_icon() {
    539         return $this->get_base_url() . '/includes/images/icon.svg';
     567        return ( SuiteMenu::get_plugin_icon_url( $this->_slug ) ?: $this->get_base_url() . '/includes/images/icon.svg' );
    540568    }
    541569
     
    549577     */
    550578    public function get_app_menu_icon() {
    551         return SuiteMenu::get_icon();
     579        return ( SuiteMenu::get_plugin_icon_url( $this->_slug ) ?: SuiteMenu::get_icon() );
    552580    }
    553581
  • mass-email-notifications-for-gravity-forms/trunk/mass-email-notifications-for-gf.php

    r3422687 r3444395  
    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.6
     8 * Version: 1.3.7
    99 * Author: BrightLeaf Digital
    1010 * License: GPL-2.0+
     
    1313 * @package MassEmailNotificationsForGravityForms
    1414 */
    15 use MENFGF\GravityOps\Core\Admin\AdminShell;
     15use function MENFGF\GravityOps\Core\Admin\gravityops_shell;
    1616if ( !defined( 'ABSPATH' ) ) {
    1717    exit;
     
    1919}
    2020require_once __DIR__ . '/vendor/autoload.php';
     21if ( file_exists( __DIR__ . '/vendor/MENFGF/autoload.php' ) ) {
     22    require_once __DIR__ . '/vendor/MENFGF/autoload.php';
     23}
    2124// Instantiate this plugin's copy of the AdminShell early so provider negotiation can happen on plugins_loaded.
    2225add_action( 'plugins_loaded', function () {
    23     AdminShell::instance();
     26    gravityops_shell();
    2427}, 1 );
    2528if ( function_exists( 'menfgf_fs' ) ) {
     
    7174    }
    7275    menfgf_fs()->add_filter( 'enable_cpt_advanced_menu_logic', '__return_true' );
    73     define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.6' );
     76    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_VERSION', '1.3.7' );
    7477    define( 'MASS_EMAIL_NOTIFICATIONS_FOR_GRAVITY_FORMS_BASENAME', plugin_basename( __FILE__ ) );
    7578    add_action( 'admin_notices', function () {
     
    100103    // Ensure GravityOps shared assets resolve when library is vendor-installed in this plugin.
    101104    add_filter( 'gravityops_assets_base_url', function ( $url ) {
    102         if ( !empty( $url ) && is_string( $url ) ) {
     105        if ( $url ) {
    103106            return $url;
    104107        }
    105         return plugins_url( 'vendor/MENFGF/gravityops/core/assets/', __FILE__ );
     108        if ( file_exists( __DIR__ . '/vendor/MENFGF/gravityops/core/assets/' ) ) {
     109            return plugins_url( 'vendor/MENFGF/gravityops/core/assets/', __FILE__ );
     110        }
     111        return plugins_url( 'vendor/gravityops/core/assets/', __FILE__ );
    106112    } );
    107113    add_action(
  • mass-email-notifications-for-gravity-forms/trunk/readme.txt

    r3422687 r3444395  
    22Tested up to: 6.9
    33Tags: GravityForms, notifications, email, task management, automation
    4 Stable tag: 1.3.6
     4Stable tag: 1.3.7
    55Requires PHP: 8.0
    66License: GPLv2 or later
     
    4444== Changelog ==
    4545
     46= 1.3.7 | Jan 21, 2026 =
     47* Bumped version of core GravityOps library to fix some bugs regarding the plugin admin menus and integrate [TrustedLogin](https://www.trustedlogin.com/about/easy-and-safe/)
     48
    4649= 1.3.6 | Dec 18, 2025 =
    4750* Fixed a bug in the new plugin menu where installed plugins would show as uninstalled
     
    6467* Added better support for viewing email content previews in the admin panel and strengthened CSV file handling for more accurate imports.
    6568* Tweaked permissions and review prompts to make the plugin even more user-friendly, plus a few behind-the-scenes updates for better performance.
    66 
    67 = 1.3.2 =
    68 * Added shortocde support for premium and agency plans.
    69 * Added a GravityFlow workflow step for premium and agency plans.
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/autoload.php

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

    r3420036 r3444395  
    1313    'MENFGF\\GravityOps\\Core\\Admin\\SuiteMenu' => $vendorDir . '/gravityops/core/src/Admin/SuiteMenu.php',
    1414    'MENFGF\\GravityOps\\Core\\Admin\\SurveyPrompter' => $vendorDir . '/gravityops/core/src/Admin/SurveyPrompter.php',
     15    'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin' => $vendorDir . '/gravityops/core/src/Admin/TrustedLogin.php',
    1516    'MENFGF\\GravityOps\\Core\\SuiteRegistry' => $vendorDir . '/gravityops/core/src/SuiteRegistry.php',
    1617    'MENFGF\\GravityOps\\Core\\Traits\\SingletonTrait' => $vendorDir . '/gravityops/core/src/Traits/SingletonTrait.php',
    1718    'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper' => $vendorDir . '/gravityops/core/src/Utils/AssetHelper.php',
     19    'MENFGF\\TrustedLogin\\Admin' => $vendorDir . '/trustedlogin/client/src/Admin.php',
     20    'MENFGF\\TrustedLogin\\Ajax' => $vendorDir . '/trustedlogin/client/src/Ajax.php',
     21    'MENFGF\\TrustedLogin\\Client' => $vendorDir . '/trustedlogin/client/src/Client.php',
     22    'MENFGF\\TrustedLogin\\Config' => $vendorDir . '/trustedlogin/client/src/Config.php',
     23    'MENFGF\\TrustedLogin\\Cron' => $vendorDir . '/trustedlogin/client/src/Cron.php',
     24    'MENFGF\\TrustedLogin\\Encryption' => $vendorDir . '/trustedlogin/client/src/Encryption.php',
     25    'MENFGF\\TrustedLogin\\Endpoint' => $vendorDir . '/trustedlogin/client/src/Endpoint.php',
     26    'MENFGF\\TrustedLogin\\Envelope' => $vendorDir . '/trustedlogin/client/src/Envelope.php',
     27    'MENFGF\\TrustedLogin\\Form' => $vendorDir . '/trustedlogin/client/src/Form.php',
     28    'MENFGF\\TrustedLogin\\Logger' => $vendorDir . '/trustedlogin/client/src/Logger.php',
     29    'MENFGF\\TrustedLogin\\Logging' => $vendorDir . '/trustedlogin/client/src/Logging.php',
     30    'MENFGF\\TrustedLogin\\Remote' => $vendorDir . '/trustedlogin/client/src/Remote.php',
     31    'MENFGF\\TrustedLogin\\SecurityChecks' => $vendorDir . '/trustedlogin/client/src/SecurityChecks.php',
     32    'MENFGF\\TrustedLogin\\SiteAccess' => $vendorDir . '/trustedlogin/client/src/SiteAccess.php',
     33    'MENFGF\\TrustedLogin\\SupportRole' => $vendorDir . '/trustedlogin/client/src/SupportRole.php',
     34    'MENFGF\\TrustedLogin\\SupportUser' => $vendorDir . '/trustedlogin/client/src/SupportUser.php',
     35    'MENFGF\\TrustedLogin\\Utils' => $vendorDir . '/trustedlogin/client/src/Utils.php',
    1836);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/autoload_psr4.php

    r3420036 r3444395  
    77
    88return array(
     9    'MENFGF\\TrustedLogin\\' => array($vendorDir . '/trustedlogin/client/src'),
    910    'MENFGF\\GravityOps\\Core\\' => array($vendorDir . '/gravityops/core/src'),
    1011);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/autoload_real.php

    r3422687 r3444395  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa
     5class ComposerAutoloaderInit576698bb6db496a6b33a55636c894704
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit576698bb6db496a6b33a55636c894704', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \MENFGF\Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitf3a8ee65c4639a42d5f2af71ff334aaa', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit576698bb6db496a6b33a55636c894704', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::getInitializer($loader));
     32        call_user_func(\MENFGF\Composer\Autoload\ComposerStaticInit576698bb6db496a6b33a55636c894704::getInitializer($loader));
    3333
    3434        $loader->setClassMapAuthoritative(true);
    3535        $loader->register(true);
    3636
     37        $filesToLoad = \MENFGF\Composer\Autoload\ComposerStaticInit576698bb6db496a6b33a55636c894704::$files;
     38        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
     39            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
     40                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
     41
     42                require $file;
     43            }
     44        }, null, null);
     45        foreach ($filesToLoad as $fileIdentifier => $file) {
     46            $requireFile($fileIdentifier, $file);
     47        }
     48
    3749        return $loader;
    3850    }
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/autoload_static.php

    r3422687 r3444395  
    55namespace MENFGF\Composer\Autoload;
    66
    7 class ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa
     7class ComposerStaticInit576698bb6db496a6b33a55636c894704
    88{
     9    public static $files = array (
     10        '6450a9b713c361c66ed3f0575f164e85' => __DIR__ . '/..' . '/gravityops/core/src/Admin/functions.php',
     11    );
     12
    913    public static $prefixLengthsPsr4 = array (
    1014        'M' =>
    1115        array (
     16            'MENFGF\\TrustedLogin\\' => 20,
    1217            'MENFGF\\GravityOps\\Core\\' => 23,
    1318        ),
     
    1520
    1621    public static $prefixDirsPsr4 = array (
     22        'MENFGF\\TrustedLogin\\' =>
     23        array (
     24            0 => __DIR__ . '/..' . '/trustedlogin/client/src',
     25        ),
    1726        'MENFGF\\GravityOps\\Core\\' =>
    1827        array (
     
    2837        'MENFGF\\GravityOps\\Core\\Admin\\SuiteMenu' => __DIR__ . '/..' . '/gravityops/core/src/Admin/SuiteMenu.php',
    2938        'MENFGF\\GravityOps\\Core\\Admin\\SurveyPrompter' => __DIR__ . '/..' . '/gravityops/core/src/Admin/SurveyPrompter.php',
     39        'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin' => __DIR__ . '/..' . '/gravityops/core/src/Admin/TrustedLogin.php',
    3040        'MENFGF\\GravityOps\\Core\\SuiteRegistry' => __DIR__ . '/..' . '/gravityops/core/src/SuiteRegistry.php',
    3141        'MENFGF\\GravityOps\\Core\\Traits\\SingletonTrait' => __DIR__ . '/..' . '/gravityops/core/src/Traits/SingletonTrait.php',
    3242        'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper' => __DIR__ . '/..' . '/gravityops/core/src/Utils/AssetHelper.php',
     43        'MENFGF\\TrustedLogin\\Admin' => __DIR__ . '/..' . '/trustedlogin/client/src/Admin.php',
     44        'MENFGF\\TrustedLogin\\Ajax' => __DIR__ . '/..' . '/trustedlogin/client/src/Ajax.php',
     45        'MENFGF\\TrustedLogin\\Client' => __DIR__ . '/..' . '/trustedlogin/client/src/Client.php',
     46        'MENFGF\\TrustedLogin\\Config' => __DIR__ . '/..' . '/trustedlogin/client/src/Config.php',
     47        'MENFGF\\TrustedLogin\\Cron' => __DIR__ . '/..' . '/trustedlogin/client/src/Cron.php',
     48        'MENFGF\\TrustedLogin\\Encryption' => __DIR__ . '/..' . '/trustedlogin/client/src/Encryption.php',
     49        'MENFGF\\TrustedLogin\\Endpoint' => __DIR__ . '/..' . '/trustedlogin/client/src/Endpoint.php',
     50        'MENFGF\\TrustedLogin\\Envelope' => __DIR__ . '/..' . '/trustedlogin/client/src/Envelope.php',
     51        'MENFGF\\TrustedLogin\\Form' => __DIR__ . '/..' . '/trustedlogin/client/src/Form.php',
     52        'MENFGF\\TrustedLogin\\Logger' => __DIR__ . '/..' . '/trustedlogin/client/src/Logger.php',
     53        'MENFGF\\TrustedLogin\\Logging' => __DIR__ . '/..' . '/trustedlogin/client/src/Logging.php',
     54        'MENFGF\\TrustedLogin\\Remote' => __DIR__ . '/..' . '/trustedlogin/client/src/Remote.php',
     55        'MENFGF\\TrustedLogin\\SecurityChecks' => __DIR__ . '/..' . '/trustedlogin/client/src/SecurityChecks.php',
     56        'MENFGF\\TrustedLogin\\SiteAccess' => __DIR__ . '/..' . '/trustedlogin/client/src/SiteAccess.php',
     57        'MENFGF\\TrustedLogin\\SupportRole' => __DIR__ . '/..' . '/trustedlogin/client/src/SupportRole.php',
     58        'MENFGF\\TrustedLogin\\SupportUser' => __DIR__ . '/..' . '/trustedlogin/client/src/SupportUser.php',
     59        'MENFGF\\TrustedLogin\\Utils' => __DIR__ . '/..' . '/trustedlogin/client/src/Utils.php',
    3360    );
    3461
     
    3663    {
    3764        return \Closure::bind(function () use ($loader) {
    38             $loader->prefixLengthsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixLengthsPsr4;
    39             $loader->prefixDirsPsr4 = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$prefixDirsPsr4;
    40             $loader->classMap = ComposerStaticInitf3a8ee65c4639a42d5f2af71ff334aaa::$classMap;
     65            $loader->prefixLengthsPsr4 = ComposerStaticInit576698bb6db496a6b33a55636c894704::$prefixLengthsPsr4;
     66            $loader->prefixDirsPsr4 = ComposerStaticInit576698bb6db496a6b33a55636c894704::$prefixDirsPsr4;
     67            $loader->classMap = ComposerStaticInit576698bb6db496a6b33a55636c894704::$classMap;
    4168
    4269        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/installed.json

    r3422687 r3444395  
    33        "1": {
    44            "name": "gravityops/core",
    5             "version": "1.0.21",
    6             "version_normalized": "1.0.21.0",
     5            "version": "1.1.0",
     6            "version_normalized": "1.1.0.0",
    77            "source": {
    88                "type": "git",
    99                "url": "[email protected]:Eitan-brightleaf/gravityops.git",
    10                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
     10                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e"
    1111            },
    1212            "dist": {
    1313                "type": "zip",
    14                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    15                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     14                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/cee27f55738670dc141b58af37d0feb74d4ce47e",
     15                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e",
    1616                "shasum": ""
    1717            },
    1818            "require": {
    19                 "php": ">=7.4"
     19                "php": ">=7.4",
     20                "trustedlogin/client": "^v1.9"
    2021            },
    21             "time": "2025-12-18T07:45:02+00:00",
     22            "time": "2026-01-21T19:42:14+00:00",
    2223            "type": "library",
    2324            "installation-source": "source",
     
    2526                "psr-4": {
    2627                    "MENFGF\\GravityOps\\Core\\": "src/"
    27                 }
     28                },
     29                "files": [
     30                    "src/Admin/functions.php"
     31                ]
    2832            },
    2933            "license": [
     
    3236            "description": "Shared core library for GravityOps plugins",
    3337            "install-path": "../gravityops/core"
     38        },
     39        "2": {
     40            "name": "trustedlogin/client",
     41            "version": "v1.9.0",
     42            "version_normalized": "1.9.0.0",
     43            "source": {
     44                "type": "git",
     45                "url": "https://github.com/trustedlogin/client.git",
     46                "reference": "b913058ae57b512a7766f449ab8d55952500fe72"
     47            },
     48            "dist": {
     49                "type": "zip",
     50                "url": "https://api.github.com/repos/trustedlogin/client/zipball/b913058ae57b512a7766f449ab8d55952500fe72",
     51                "reference": "b913058ae57b512a7766f449ab8d55952500fe72",
     52                "shasum": ""
     53            },
     54            "require-dev": {
     55                "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
     56                "ext-curl": "*",
     57                "ext-json": "*",
     58                "php": ">=5.3.0",
     59                "phpcompatibility/phpcompatibility-wp": "^2.1",
     60                "phpstan/extension-installer": "^1.3",
     61                "phpstan/phpstan": "^1.10",
     62                "szepeviktor/phpstan-wordpress": "^1.3",
     63                "wp-coding-standards/wpcs": "^3.0",
     64                "yoast/phpunit-polyfills": "^1.0.0"
     65            },
     66            "time": "2024-08-26T01:13:42+00:00",
     67            "bin": [
     68                "bin/build-sass"
     69            ],
     70            "type": "library",
     71            "installation-source": "dist",
     72            "autoload": {
     73                "psr-4": {
     74                    "MENFGF\\TrustedLogin\\": "src/"
     75                }
     76            },
     77            "notification-url": "https://packagist.org/downloads/",
     78            "license": [
     79                "GPL-2.0-or-later"
     80            ],
     81            "authors": [
     82                {
     83                    "name": "TrustedLogin",
     84                    "email": "[email protected]",
     85                    "homepage": "https://www.trustedlogin.com"
     86                }
     87            ],
     88            "description": "Easily and securely log in to your customers sites when providing support.",
     89            "homepage": "https://www.trustedlogin.com",
     90            "keywords": [
     91                "login",
     92                "security",
     93                "support"
     94            ],
     95            "support": {
     96                "issues": "https://github.com/trustedlogin/client/issues",
     97                "source": "https://github.com/trustedlogin/client/tree/v1.9.0"
     98            },
     99            "install-path": "../trustedlogin/client"
    34100        }
    35101    },
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/composer/installed.php

    r3422687 r3444395  
    22  'root' =>
    33  array (
    4     'name' => '__root__',
     4    'name' => 'gravityops/mass-email',
    55    'pretty_version' => 'dev-main',
    66    'version' => 'dev-main',
    7     'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
     7    'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
    88    'type' => 'library',
    99    'install_path' => __DIR__ . '/../',
     
    1717    'gravityops/core' =>
    1818    array (
    19       'pretty_version' => '1.0.21',
    20       'version' => '1.0.21.0',
    21       'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
     19      'pretty_version' => '1.1.0',
     20      'version' => '1.1.0.0',
     21      'reference' => 'cee27f55738670dc141b58af37d0feb74d4ce47e',
    2222      'type' => 'library',
    2323      'install_path' => __DIR__ . '/../gravityops/core',
     
    2727      'dev_requirement' => false,
    2828    ),
     29    'trustedlogin/client' =>
     30    array (
     31      'pretty_version' => 'v1.9.0',
     32      'version' => '1.9.0.0',
     33      'reference' => 'b913058ae57b512a7766f449ab8d55952500fe72',
     34      'type' => 'library',
     35      'install_path' => __DIR__ . '/../trustedlogin/client',
     36      'aliases' =>
     37      array (
     38      ),
     39      'dev_requirement' => false,
     40    ),
    2941  ),
    3042);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/composer.json

    r3420036 r3444395  
    55  "license": "GPL-2.0-or-later",
    66  "require": {
    7     "php": ">=7.4"
     7    "php": ">=7.4",
     8    "trustedlogin/client": "^v1.9"
    89  },
    910  "autoload": {
    1011    "psr-4": {
    1112      "GravityOps\\Core\\": "src/"
    12     }
     13    },
     14    "files": [
     15      "src/Admin/functions.php"
     16    ]
    1317  }
    1418}
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/AdminShell.php

    r3422687 r3444395  
    22
    33namespace MENFGF\GravityOps\Core\Admin;
     4
     5use GFAPI;
     6use MENFGF\GravityOps\Core\SuiteRegistry;
    47
    58if ( ! defined( 'ABSPATH' ) ) {
     
    1922     * The highest version across loaded copies should be selected as provider.
    2023     */
    21     public const CORE_VERSION = '1.0.21';
     24    public const CORE_VERSION = '1.1.0';
    2225
    2326    /**
     
    102105        // Each copy registers this, but only the selected provider will actually boot.
    103106        // If instantiated after plugins_loaded has already fired, boot immediately.
    104         if ( function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
     107        global $wp_filter;
     108        $has_run_already  = did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' );
     109        $is_past_priority = false;
     110
     111        if ( doing_action( 'plugins_loaded' ) && isset( $wp_filter['plugins_loaded'] ) ) {
     112            $is_past_priority = $wp_filter['plugins_loaded']->current_priority() > 20;
     113        }
     114
     115        if ( $has_run_already || $is_past_priority ) {
    105116            $this->maybe_boot();
    106117        } else {
     
    155166        // differs from the SDK menu slug (e.g., hyphenated vs underscored).
    156167        $fs_slug = $plugin_slug;
    157         // Built-in mapping for known cases.
    158         if ( 'mass-email-from-gf-notification' === $plugin_slug ) {
    159             $fs_slug = 'mass_email_notifications_for_gf';
    160         }
    161168        // External override if needed.
    162169        $fs_slug = apply_filters( 'gravityops_freemius_base_slug', $fs_slug, $plugin_slug );
     
    194201     * @param string $plugin_short_title Short plugin title used for the header, e.g., "Asana Integration".
    195202     * @param string $toggle_action     The admin_post action to handle toggle, used for form action and nonce prefix.
     203     * @param array  $workflow_steps    Optional array of workflow steps to display in the feed list.
    196204     *
    197205     * @return void
    198206     */
    199     public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action ) {
     207    public static function render_feeds_list( $feeds_and_forms, $gf_subview_slug, $plugin_short_title, $toggle_action, $workflow_steps = [] ) {
    200208        echo '<div class="gops-card">';
    201209        echo '<h2 class="gops-title" style="margin:0 0 10px;">' . esc_html( $plugin_short_title ) . ' Feeds</h2>';
     
    203211        if ( empty( $feeds_and_forms ) ) {
    204212            echo '<p>No feeds found. Create one from a form’s settings.</p>';
    205             echo '</div>';
    206             return;
    207         }
    208 
    209         echo '<ul style="margin:0; padding-left:18px;">';
    210         foreach ( $feeds_and_forms as $feed_and_form ) {
    211             $feed      = $feed_and_form['feed'];
    212             $form      = $feed_and_form['form'];
    213             $form_id   = $form['id'];
    214             $form_name = $form['title'];
    215             $feed_id   = $feed['id'];
    216             $is_active = (bool) $feed['is_active'];
    217             $name      = $feed['meta']['feedName'];
    218 
    219             $edit_form = admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id );
    220             $edit_feed = add_query_arg(
     213        } else {
     214            echo '<ul style="margin:0; padding-left:18px;">';
     215            foreach ( $feeds_and_forms as $feed_and_form ) {
     216                $feed      = $feed_and_form['feed'];
     217                $form      = $feed_and_form['form'];
     218                $form_id   = $form['id'];
     219                $form_name = $form['title'];
     220                $feed_id   = $feed['id'];
     221                $is_active = (bool) $feed['is_active'];
     222                $name      = $feed['meta']['feedName'];
     223
     224                $edit_form = admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id );
     225                $edit_feed = add_query_arg(
    221226                    [
    222                         'page'    => 'gf_edit_forms',
    223                         'view'    => 'settings',
    224                         'subview' => $gf_subview_slug,
    225                         'fid'     => $feed_id,
    226                         'id'      => $form_id,
     227                        'page'    => 'gf_edit_forms',
     228                        'view'    => 'settings',
     229                        'subview' => $gf_subview_slug,
     230                        'fid'     => $feed_id,
     231                        'id'      => $form_id,
    227232                    ],
    228233                    admin_url( 'admin.php' )
    229             );
    230 
    231             echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
    232             echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_feed ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
    233             echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
    234             echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_form ) . '">' . esc_html( $form_name ) . '</a>';
    235             // Toggle button
    236             echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
    237             echo '<input type="hidden" name="action" value="' . esc_attr( $toggle_action ) . '" />';
    238             echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $feed_id ) . '" />';
    239             echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $toggle_action . '_' . $feed_id ) ) . '" />';
    240             $label = $is_active ? 'Deactivate' : 'Activate';
    241             $cls   = $is_active ? 'button' : 'button button-primary';
    242             echo '<button class="' . esc_attr( $cls ) . '" type="submit">' . esc_html( $label ) . '</button>';
    243             echo '</form>';
    244             echo '</li>';
    245         }
    246         echo '</ul>';
     234                );
     235
     236                echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
     237                echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_feed ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
     238                echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
     239                echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_form ) . '">' . esc_html( $form_name ) . '</a>';
     240                // Toggle button
     241                echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
     242                echo '<input type="hidden" name="action" value="' . esc_attr( $toggle_action ) . '" />';
     243                echo '<input type="hidden" name="return_url" value="' . esc_attr( 'admin.php?page=' . $gf_subview_slug . '&tab=feeds' ) . '" />';
     244                echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $feed_id ) . '" />';
     245                echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $toggle_action . '_' . $feed_id ) ) . '" />';
     246                $label = $is_active ? 'Deactivate' : 'Activate';
     247                $cls   = $is_active ? 'button' : 'button button-primary';
     248                echo '<button class="' . esc_attr( $cls ) . '" type="submit">' . esc_html( $label ) . '</button>';
     249                echo '</form>';
     250                echo '</li>';
     251            }
     252            echo '</ul>';
     253        }
    247254        echo '</div>';
     255
     256        if ( ! empty( $workflow_steps ) ) {
     257            echo '<div class="gops-card" style="margin-top:20px;">';
     258            echo '<h2 class="gops-title" style="margin:0 0 10px;">Workflow Steps</h2>';
     259            echo '<ul style="margin:0; padding-left:18px;">';
     260            $workflow_toggle_action = str_replace( '_toggle_feed', '_toggle_workflow_step', $toggle_action );
     261            if ( $workflow_toggle_action === $toggle_action ) {
     262                $workflow_toggle_action = 'gravityops_toggle_workflow_step';
     263            }
     264
     265            foreach ( $workflow_steps as $item ) {
     266                $step      = $item['step'];
     267                $form      = $item['form'];
     268                $form_id   = $form['id'];
     269                $form_name = $form['title'];
     270                $step_id   = $step['id'];
     271                $is_active = (bool) ( $step['is_active'] ?? true );
     272                $name      = $step['step_label'] ?? ( 'Step #' . $step_id );
     273
     274                $edit_step = add_query_arg(
     275                    [
     276                        'page'    => 'gf_edit_forms',
     277                        'view'    => 'settings',
     278                        'subview' => 'gravityflow',
     279                        'fid'     => $step_id,
     280                        'id'      => $form_id,
     281                    ],
     282                    admin_url( 'admin.php' )
     283                );
     284
     285                echo '<li style="margin-bottom:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;">';
     286                echo '<a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( $edit_step ) . '"><strong>' . esc_html( (string) $name ) . '</strong></a>';
     287                echo ' — ' . ( $is_active ? '<span class="gops-badge gops-badge--ok">Active</span>' : '<span class="gops-badge gops-badge--warn">Inactive</span>' );
     288                echo ' &nbsp; <a class="gops-link" target="_blank" rel="noopener" href="' . esc_url( admin_url( 'admin.php?page=gf_edit_forms&id=' . $form_id ) ) . '">' . esc_html( $form_name ) . '</a>';
     289                // Toggle button for workflow step
     290                echo '<form method="post" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" style="display:inline-block; margin-left:8px;">';
     291                echo '<input type="hidden" name="action" value="' . esc_attr( $workflow_toggle_action ) . '" />';
     292                echo '<input type="hidden" name="feed_id" value="' . esc_attr( (string) $step_id ) . '" />';
     293                echo '<input type="hidden" name="_wpnonce" value="' . esc_attr( wp_create_nonce( $workflow_toggle_action . '_' . $step_id ) ) . '" />';
     294
     295                echo '<input type="hidden" name="return_url" value="' . esc_attr( 'admin.php?page=' . $gf_subview_slug . '&tab=feeds' ) . '" />';
     296                $step_label = $is_active ? 'Deactivate' : 'Activate';
     297                $step_cls   = $is_active ? 'button' : 'button button-primary';
     298                echo '<button class="' . esc_attr( $step_cls ) . '" type="submit">' . esc_html( $step_label ) . '</button>';
     299                echo '</form>';
     300
     301                echo '</li>';
     302            }
     303            echo '</ul>';
     304            echo '</div>';
     305        }
    248306    }
    249307
     
    263321        }
    264322
    265         $fid   = isset( $_POST['feed_id'] ) ? (int) $_POST['feed_id'] : 0; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
     323        $fid             = isset( $_POST['feed_id'] ) ? (int) $_POST['feed_id'] : 0; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
     324        $post_return_url = isset( $_POST['return_url'] ) ? sanitize_text_field( wp_unslash( $_POST['return_url'] ) ) : '';
     325        if ( ! empty( $post_return_url ) ) {
     326            $return_url = $post_return_url;
     327        }
     328
    266329        $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['_wpnonce'] ) ) : '';
    267330        if ( ! $fid || ! wp_verify_nonce( $nonce, $action_prefix . '_' . $fid ) ) {
     
    290353
    291354    /**
     355     * Helper to fetch workflow steps for specific types across all forms.
     356     *
     357     * @param string|array $step_types The step type(s) to filter by (e.g. 'iawgf_update_task' or ['type1', 'type2']).
     358     * @return array Array of items, each having 'step' (array) and 'form' (array).
     359     */
     360    public static function get_workflow_steps_by_type( $step_types ) {
     361        if ( ! function_exists( 'gravity_flow' ) || ! class_exists( 'GFAPI' ) ) {
     362            return [];
     363        }
     364
     365        $step_types = (array) $step_types;
     366
     367        global $wpdb;
     368        $table_name = $wpdb->prefix . 'gf_addon_feed';
     369
     370        // phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     371        // Check if table exists
     372        $has_table = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) === $table_name;
     373        if ( ! $has_table ) {
     374            return [];
     375        }
     376
     377        // Workflow steps in Gravity Flow are stored as feeds for the 'gravityflow' addon.
     378        $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table_name WHERE addon_slug = %s", 'gravityflow' ), ARRAY_A );
     379        // phpcs:enable WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     380
     381        if ( empty( $results ) ) {
     382            return [];
     383        }
     384
     385        $steps = [];
     386        foreach ( $results as $row ) {
     387            $meta = json_decode( (string) $row['meta'], true );
     388            if ( ! is_array( $meta ) ) {
     389                continue;
     390            }
     391
     392            $current_type = $meta['step_type'] ?? '';
     393            if ( in_array( $current_type, $step_types, true ) ) {
     394                $form_id = isset( $row['form_id'] ) ? (int) $row['form_id'] : 0;
     395                if ( ! $form_id ) {
     396                    continue;
     397                }
     398                $form = GFAPI::get_form( $form_id );
     399                if ( $form ) {
     400                    $steps[] = [
     401                        'step' => [
     402                            'id'         => $row['id'],
     403                            'form_id'    => $row['form_id'],
     404                            'is_active'  => $row['is_active'],
     405                            'step_label' => $meta['step_name'] ?? ( 'Step #' . $row['id'] ),
     406                        ],
     407                        'form' => $form,
     408                    ];
     409                }
     410            }
     411        }
     412
     413        return $steps;
     414    }
     415
     416    /**
    292417     * Render a standard Help tab card.
    293418     *
     
    306431        }
    307432        echo '</ul>';
     433        echo '<div style="margin-top: 20px;">';
     434        echo '<a class="button button-primary" href="' . esc_url( admin_url( 'admin.php?page=gravity_ops_support' ) ) . '">Grant Support Access</a>';
    308435        echo '</div>';
     436        echo '</div>';
     437    }
     438
     439    /**
     440     * Show coupons on the GravityOps dashboard for plugins that aren't installed as premium.
     441     *
     442     * @param string $content Existing content.
     443     * @param array  $item    Plugin registry item.
     444     * @return string
     445     */
     446    public function maybe_render_dashboard_coupon( $content, $item ) {
     447        // Folders and Search are free-only, no coupons.
     448        if ( ! empty( $item['is_free'] ) ) {
     449            return $content;
     450        }
     451
     452        // If premium version is installed, don't show coupon.
     453        if ( ! empty( $item['is_installed_prem'] ) ) {
     454            return $content;
     455        }
     456
     457        $coupons = [
     458            'integrate-asana-with-gravity-forms'          => 'GRAVITYASANA10GIFT',
     459            'mass_email_notifications_for_gf'             => 'MASSEMAIL10GIFT',
     460            'Recurring_Form_Submissions_For_Gravity_Form' => 'RECURSUB10GIFT',
     461            'gravity_ops_global_variables'                => 'GLOBVAR10GIFT',
     462            'kanban-view-for-gravity-view'                => 'KANBANVIEW10GIFT',
     463        ];
     464
     465        $slug   = $item['slug'] ?? '';
     466        $coupon = $coupons[ $slug ] ?? '';
     467
     468        if ( $coupon ) {
     469            $content .= '<div class="gops-tile-coupon" style="margin-top:10px; font-size: 0.7em; color: #2271b1; font-weight: 500;">';
     470            $content .= '<p><small>Special Gift: Get 10% Off Premium!</small></p>';
     471            $content .= '<p><small>Use coupon code <code><small>' . esc_html( $coupon ) . '</small></code> at checkout.</small></p>';
     472            $content .= '</div>';
     473        }
     474
     475        return $content;
    309476    }
    310477
     
    329496        }
    330497        $defaults             = [
     498            'slug'       => $slug,
    331499            'title'      => $slug,
    332500            'menu_title' => $slug,
     
    335503            'links'      => [],
    336504            'tabs'       => [], // array id => [ 'label' => '', 'type' => 'render|link', 'callback' => callable, 'url' => '' ]
     505            'render'     => null, // callable to render the whole page content (used if no tabs)
    337506        ];
    338507        $this->pages[ $slug ] = array_merge( $defaults, $args );
     
    362531            }
    363532
     533            $parent = 'gravity_ops';
     534            if ( 'gravity_ops_support' === $slug ) {
     535                $parent = null;
     536            }
     537
    364538            add_submenu_page(
    365                 'gravity_ops',
     539                $parent,
    366540                $args['title'] ?? $slug,
    367541                $args['menu_title'] ?? ( $args['title'] ?? $slug ),
     
    384558
    385559        $pages_lower_case = array_change_key_case( $this->pages );
    386         $is_shell_page    = isset( $pages_lower_case[ $page ] ) || ( false !== strpos( (string) $hook, 'gravity_ops' ) );
     560        $is_shell_page    = isset( $pages_lower_case[ $page ] ) || 'toplevel_page_gravity_ops' === $hook;
     561        $is_shell_page    = apply_filters( 'gravityops_is_shell_page', $is_shell_page, $page, $hook );
    387562
    388563        // Optionally style Freemius pages in-place.
     
    394569        }
    395570
    396         if ( ! $is_shell_page && ! $is_freemius ) {
     571        $is_gf_page = ( 0 === strpos( $page, 'gf_' ) ) || ( false !== strpos( (string) $hook, 'forms_page_gf' ) );
     572
     573        // Always load on our pages, Freemius pages, and GF pages.
     574        // Also load globally by default to ensure the sidebar menu icon is consistently styled.
     575        $load_globally = (bool) apply_filters( 'gravityops_load_admin_assets_globally', true );
     576
     577        if ( ! $is_shell_page && ! $is_freemius && ! $is_gf_page && ! $load_globally ) {
    397578            return;
    398579        }
    399580
    400581        $assets = self::resolve_assets_urls();
    401         if ( ! empty( $assets['css'] ) ) {
    402             wp_enqueue_style( 'gravityops-admin', $assets['css'], [], '1.0.0' );
    403         }
     582
     583        // Load minimal menu/icon CSS globally or on GF pages.
     584        if ( ! empty( $assets['menu_css'] ) ) {
     585            wp_enqueue_style( 'gravityops-menu', $assets['menu_css'], [], self::CORE_VERSION );
     586        }
     587
     588        // Load the full admin UI CSS only on our shell or Freemius pages.
     589        if ( ! empty( $assets['css'] ) && ( $is_shell_page || $is_freemius ) ) {
     590            wp_enqueue_style( 'gravityops-admin', $assets['css'], [ 'gravityops-menu' ], self::CORE_VERSION );
     591        }
     592
    404593        // On Freemius pages also load a small override stylesheet to hide native tabs safely.
    405594        if ( $is_freemius ) {
    406595            $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
    407             wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], '1.0.0' );
     596            wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], self::CORE_VERSION );
    408597        }
    409598        if ( ! empty( $assets['js'] ) ) {
    410             wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], '1.0.0', true );
     599            // We only need the JS on our shell pages or Freemius pages where we inject tabs.
     600            if ( ! $is_shell_page && ! $is_freemius ) {
     601                return;
     602            }
     603
     604            wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], self::CORE_VERSION, true );
     605
     606            // Identify the plugin and pass its config to JS
     607            $config       = null;
     608            $current_slug = '';
     609
     610            if ( $is_freemius ) {
     611                foreach ( $this->pages as $slug => $args ) {
     612                    $fs_slug = $slug;
     613                    $fs_slug = apply_filters( 'gravityops_freemius_base_slug', $fs_slug, $slug );
     614
     615                    $normalized_page = str_replace( '_', '-', $page );
     616                    $bases           = [
     617                        str_replace( '_', '-', strtolower( $fs_slug ) ),
     618                        str_replace( '_', '-', strtolower( $slug ) ),
     619                    ];
     620
     621                    $suffixes      = [ '-account', '-pricing', '-affiliation' ];
     622                    $valid_targets = array_merge(
     623                            ...array_map( fn( $b ) => array_map( fn( $s ) => $b . $s, $suffixes ), $bases )
     624                    );
     625
     626                    if ( in_array( $normalized_page, $valid_targets, true ) ) {
     627                        $current_slug = $slug;
     628                        break;
     629                    }
     630                }
     631            } elseif ( $is_shell_page && isset( $this->pages[ $page ] ) ) {
     632                $current_slug = $page;
     633            }
     634
     635            if ( $current_slug && isset( $this->pages[ $current_slug ] ) ) {
     636                $args     = $this->pages[ $current_slug ];
     637                $tabs     = [];
     638                $base_url = admin_url( 'admin.php?page=' . $current_slug );
     639
     640                foreach ( ( $args['tabs'] ?? [] ) as $id => $tab ) {
     641                    $tabs[] = [
     642                        'id'    => $id,
     643                        'label' => $tab['label'] ?? $id,
     644                        'url'   => ( ( $tab['type'] ?? 'render' ) === 'link' ) ? ( $tab['url'] ?? '#' ) : add_query_arg( 'tab', $id, $base_url ),
     645                    ];
     646                }
     647
     648                $config = apply_filters(
     649                    'gravityops_admin_config',
     650                    [
     651                        'slug'  => $current_slug,
     652                        'title' => $args['title'] ?? '',
     653                        'tabs'  => $tabs,
     654                    ],
     655                    $current_slug
     656                    );
     657            }
     658
     659            if ( $config ) {
     660                wp_localize_script( 'gravityops-admin', 'gops_admin_config', $config );
     661            }
    411662        }
    412663    }
     
    424675        add_action( 'admin_menu', [ $this, 'register_menus' ], 99 );
    425676        add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
     677        add_filter( 'gravityops_tile_after_description', [ $this, 'maybe_render_dashboard_coupon' ], 10, 2 );
     678
     679        // Initialize TrustedLogin on all page loads (for auth redirects and background tasks).
     680        if ( class_exists( __NAMESPACE__ . '\MENFGF\TrustedLogin' ) ) {
     681            TrustedLogin::get_instance();
     682        }
     683
     684        // Register the shared Support page.
     685        $this->register_support_page();
     686
    426687        self::$did_boot = true;
     688    }
     689
     690    /**
     691     * Register the shared Support page under the GravityOps menu.
     692     *
     693     * @return void
     694     */
     695    private function register_support_page() {
     696        $this->register_plugin_page(
     697            'gravity_ops_support',
     698            [
     699                'title'       => 'Grant Support Access',
     700                'menu_title'  => 'Support Access',
     701                'capability'  => class_exists( __NAMESPACE__ . '\SuiteMenu' ) ? SuiteMenu::get_parent_capability() : 'manage_options',
     702                'hide_header' => true,
     703                'render'      => [ TrustedLogin::get_instance(), 'render_support_screen' ],
     704            ]
     705        );
    427706    }
    428707
     
    470749        }
    471750
    472         $base_url = menu_page_url( $slug, false );
     751        $base_url    = menu_page_url( $slug, false );
     752        $hide_header = ! empty( $args['hide_header'] );
     753
    473754        // Always render full wrapper + header here; notices will be relocated via JS beneath the header.
    474         echo '<div class="wrap gops-admin">';
    475         $this->render_header_only( $args );
     755        echo '<div class="wrap gops-admin' . ( $hide_header ? ' gops-hide-header' : '' ) . '">';
     756        if ( ! $hide_header ) {
     757            $this->render_header_only( $args );
     758        }
    476759        // Dedicated notices container prevents margin-collapsing into the header
    477760        echo '<div class="gops-notices" aria-live="polite"></div>';
     
    495778
    496779        echo '<section class="gops-content">';
    497         if ( isset( $tabs[ $active ] ) ) {
     780        if ( ! empty( $tabs ) && isset( $tabs[ $active ] ) ) {
    498781            $tab  = $tabs[ $active ];
    499782            $type = $tab['type'] ?? 'render';
     
    501784                call_user_func( $tab['callback'] );
    502785            }
     786        } elseif ( isset( $args['render'] ) && is_callable( $args['render'] ) ) {
     787            call_user_func( $args['render'] );
    503788        }
    504789        echo '</section>';
     
    514799     * @return void
    515800     */
    516     private function render_header_only( $args ) {
     801    public function render_header_only( $args ) {
     802        $icon_url = '';
     803        if ( ! empty( $args['slug'] ) && class_exists( __NAMESPACE__ . '\SuiteMenu' ) ) {
     804            $registry = SuiteRegistry::all();
     805            $item     = null;
     806            foreach ( $registry as $r ) {
     807                if ( ( $r['slug'] ?? '' ) === $args['slug'] ) {
     808                    $item = $r;
     809                    break;
     810                }
     811            }
     812            if ( $item ) {
     813                $icon_url = SuiteMenu::resolve_plugin_icon_url( $item );
     814            }
     815        }
    517816        ?>
    518         <header class="gops-header">
    519             <div class="gops-header__left">
    520                 <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
    521                 <div class="gops-headings">
    522                     <h1 class="gops-title"><?php echo esc_html( $args['title'] ?? '' ); ?></h1>
    523                     <?php if ( ! empty( $args['subtitle'] ) ) : ?>
    524                         <p class="gops-subtitle"><?php echo esc_html( $args['subtitle'] ); ?></p>
    525                     <?php endif; ?>
     817        <div class="gops-header-wrapper">
     818            <?php if ( $icon_url ) : ?>
     819                <img class="gops-header-icon" src="<?php echo esc_url( $icon_url ); ?>" alt="" width="80" height="80" />
     820            <?php endif; ?>
     821            <header class="gops-header">
     822                <div class="gops-header__left">
     823                    <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
     824                    <div class="gops-headings">
     825                        <h1 class="gops-title"><?php echo esc_html( $args['title'] ?? '' ); ?></h1>
     826                        <?php if ( ! empty( $args['subtitle'] ) ) : ?>
     827                            <p class="gops-subtitle"><?php echo esc_html( $args['subtitle'] ); ?></p>
     828                        <?php endif; ?>
     829                    </div>
    526830                </div>
    527             </div>
    528             <?php if ( ! empty( $args['links'] ) && is_array( $args['links'] ) ) : ?>
    529                 <div class="gops-header__right">
    530                     <?php foreach ( $args['links'] as $label => $url ) : ?>
    531                         <a class="gops-link" target="_blank" href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $label ); ?></a>
    532                     <?php endforeach; ?>
    533                 </div>
    534             <?php endif; ?>
    535         </header>
     831                <?php if ( ! empty( $args['links'] ) && is_array( $args['links'] ) ) : ?>
     832                    <div class="gops-header__right">
     833                        <?php foreach ( $args['links'] as $label => $url ) : ?>
     834                            <a class="gops-link" target="_blank" href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $label ); ?></a>
     835                        <?php endforeach; ?>
     836                    </div>
     837                <?php endif; ?>
     838            </header>
     839        </div>
    536840        <?php
    537841    }
     
    548852     *  - Fallback to site_url('gravityops/assets/') if present
    549853     *
    550      * @return array{css:string,js:string}
     854     * @return array{css:string,menu_css:string,js:string,base_url:string}
    551855     */
    552856    public static function resolve_assets_urls() {
    553857        $base_url = apply_filters( 'gravityops_assets_base_url', '' );
    554858        $css      = '';
     859        $menu_css = '';
    555860        $js       = '';
    556861
    557862        if ( is_string( $base_url ) && '' !== $base_url ) {
    558863            $base_url = trailingslashit( $base_url );
    559             $css      = $base_url . 'admin.css';
    560             $js       = $base_url . 'admin.js';
     864            $css      = $base_url . 'css/admin.css';
     865            $menu_css = $base_url . 'css/menu.css';
     866            $js       = $base_url . 'js/admin.js';
    561867            return [
    562                 'css' => $css,
    563                 'js'  => $js,
     868                'css'      => $css,
     869                'menu_css' => $menu_css,
     870                'js'       => $js,
     871                'base_url' => $base_url,
    564872            ];
    565873        }
     
    567875        // Try resolving relative to this class file (../../assets)
    568876        $assets_path = wp_normalize_path( dirname( __DIR__, 2 ) . '/assets' );
    569         $css_path    = $assets_path . '/admin.css';
    570         $js_path     = $assets_path . '/admin.js';
    571 
    572         if ( file_exists( $css_path ) || file_exists( $js_path ) ) {
     877        $css_path    = $assets_path . '/css/admin.css';
     878        $menu_path   = $assets_path . '/css/menu.css';
     879        $js_path     = $assets_path . '/js/admin.js';
     880
     881        if ( file_exists( $css_path ) || file_exists( $js_path ) || file_exists( $menu_path ) ) {
    573882            $content_dir = wp_normalize_path( WP_CONTENT_DIR );
    574883            if ( 0 === strpos( $assets_path, $content_dir ) ) {
     
    583892            }
    584893            if ( $base_url ) {
    585                 $css = file_exists( $css_path ) ? $base_url . 'admin.css' : '';
    586                 $js  = file_exists( $js_path ) ? $base_url . 'admin.js' : '';
     894                $css      = file_exists( $css_path ) ? $base_url . 'css/admin.css' : '';
     895                $menu_css = file_exists( $menu_path ) ? $base_url . 'css/menu.css' : '';
     896                $js       = file_exists( $js_path ) ? $base_url . 'js/admin.js' : '';
    587897                return [
    588                     'css' => $css,
    589                     'js'  => $js,
     898                    'css'      => $css,
     899                    'menu_css' => $menu_css,
     900                    'js'       => $js,
     901                    'base_url' => $base_url,
    590902                ];
    591903            }
     
    594906        // Fallback to root-level gravityops/assets
    595907        $root_assets = 'gravityops/assets/';
    596         if ( file_exists( ABSPATH . $root_assets . 'admin.css' ) ) {
    597             $css = site_url( $root_assets . 'admin.css' );
    598         }
    599         if ( file_exists( ABSPATH . $root_assets . 'admin.js' ) ) {
    600             $js = site_url( $root_assets . 'admin.js' );
     908        $base_url    = trailingslashit( site_url( $root_assets ) );
     909        if ( file_exists( ABSPATH . $root_assets . 'css/admin.css' ) ) {
     910            $css = $base_url . 'css/admin.css';
     911        }
     912        if ( file_exists( ABSPATH . $root_assets . 'css/menu.css' ) ) {
     913            $menu_css = $base_url . 'css/menu.css';
     914        }
     915        if ( file_exists( ABSPATH . $root_assets . 'js/admin.js' ) ) {
     916            $js = $base_url . 'js/admin.js';
    601917        }
    602918        return [
    603             'css' => $css,
    604             'js'  => $js,
     919            'css'      => $css,
     920            'menu_css' => $menu_css,
     921            'js'       => $js,
     922            'base_url' => $base_url,
    605923        ];
    606924    }
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/ReviewPrompter.php

    r3420036 r3444395  
    7777
    7878        if ( $current_count > $threshold ) {
    79             add_action( 'admin_notices', [ $this, 'render_notice' ] );
     79            $this->render_notice();
    8080        }
    8181    }
     
    120120        }
    121121
    122         $nonce = wp_create_nonce( $this->prefix . 'rating_asked' );
    123         ?>
    124         <div class="notice notice-success is-dismissible">
    125             <h3>Thank you for using <?php echo esc_html( $this->plugin_title ); ?>! I noticed you've used it a lot!</h3>
    126             <h4>
    127                 If you like the plugin and find it helpful, can you do us a big favor and <a
    128                         href="<?php echo esc_url( $url ); ?>"
    129                         target="_blank" rel="noreferrer">rate it</a> with ⭐⭐⭐⭐⭐?
    130                 It helps us spread the word and boost our motivation.
    131             </h4>
    132             <form method="post" action="">
    133                 <input type="hidden" name="<?php echo esc_attr( $this->prefix . 'rating_nonce' ); ?>" value="<?php echo esc_attr( $nonce ); ?>">
    134                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="remind">Remind me later</button>
    135                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="done">Done!</button>
    136                 <button class="button" type="submit" name="<?php echo esc_attr( $this->prefix . 'rating_action' ); ?>" value="done">Not Interested</button>
    137             </form>
    138         </div>
    139         <?php
     122        $nonce_field  = $this->prefix . 'rating_nonce';
     123        $action_field = $this->prefix . 'rating_action';
     124        $nonce_action = $this->prefix . 'rating_asked';
     125        $plugin_title = $this->plugin_title;
     126
     127        $nonce = wp_create_nonce( $nonce_action );
     128
     129        $current_page   = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     130        $is_gops_page   = ( 'gravity_ops' === $current_page || AdminShell::has_page( $current_page ) );
     131        $notice_classes = 'notice notice-success is-dismissible';
     132        if ( $is_gops_page ) {
     133            $notice_classes .= ' inline';
     134        }
     135        add_action(
     136            'admin_notices',
     137            function () use ( $nonce, $action_field, $nonce_field, $plugin_title, $url, $notice_classes ) {
     138                ?>
     139            <div class="<?= esc_attr( $notice_classes ); ?>">
     140                <h3>Thank you for using <?php echo esc_html( $plugin_title ); ?>! I noticed you've used it a lot!</h3>
     141                <h4>
     142                    If you like the plugin and find it helpful, can you do us a big favor and <a
     143                            href="<?php echo esc_url( $url ); ?>"
     144                            target="_blank" rel="noreferrer">rate it</a> with ⭐⭐⭐⭐⭐?
     145                    It helps us spread the word and boost our motivation.
     146                </h4>
     147                <form method="post" action="">
     148                    <input type="hidden" name="<?php echo esc_attr( $nonce_field ); ?>" value="<?php echo esc_attr( $nonce ); ?>">
     149                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="remind">Remind me later</button>
     150                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="done">Done!</button>
     151                    <button class="button" type="submit" name="<?php echo esc_attr( $action_field ); ?>" value="done">Not Interested</button>
     152                </form>
     153            </div>
     154                <?php
     155            }
     156            );
    140157    }
    141158
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/SuiteMenu.php

    r3422687 r3444395  
    216216                }
    217217                $registry[ $key ]['is_installed']       = $is_installed;
     218                $registry[ $key ]['is_installed_prem']  = ! empty( $item['is_free'] ) ? false : $is_installed;
     219                $registry[ $key ]['is_installed_free']  = ! empty( $item['is_free'] ) ? $is_installed : false;
    218220                $registry[ $key ]['is_active']          = $is_active;
    219221                $registry[ $key ]['version']            = $version;
     
    270272            // Updates: consider whichever is installed; prefer premium if both
    271273            if ( $upd_prem || $upd_free ) {
    272                 $has_update  = $upd_prem || $upd_free;
    273                 $new_version = $upd_prem ? $new_prem : $new_free;
    274                 ++$updates_count;
     274                $has_update  = $upd_prem || ( $upd_free && ! $is_installed_prem );
     275                $new_version = $upd_prem ? $new_prem : ( $is_installed_prem ? '' : $new_free );
     276                if ( $has_update ) {
     277                    ++$updates_count;
     278                }
    275279            }
    276280
     
    284288
    285289            $registry[ $key ]['is_installed']       = $is_installed;
     290            $registry[ $key ]['is_installed_prem']  = $is_installed_prem;
     291            $registry[ $key ]['is_installed_free']  = $is_installed_free;
    286292            $registry[ $key ]['is_active']          = $is_active;
    287293            $registry[ $key ]['version']            = $version;
     
    328334        ?>
    329335        <div class="wrap gops-admin">
    330             <header class="gops-header">
    331                 <div class="gops-header__left">
    332                     <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
    333                     <div class="gops-headings">
    334                         <h1 class="gops-title">Run Your Business on WordPress</h1>
    335                         <p class="gops-subtitle">All your GravityOps tools in one place.</p>
     336            <div class="gops-header-wrapper">
     337                <img class="gops-header-icon" src="<?php echo esc_url( self::get_icon() ); ?>" alt="" width="80" height="80" />
     338                <header class="gops-header">
     339                    <div class="gops-header__left">
     340                        <a class="gops-logo-chip" href="<?php echo esc_url( admin_url( 'admin.php?page=gravity_ops' ) ); ?>">GravityOps</a>
     341                        <div class="gops-headings">
     342                            <h1 class="gops-title">Run Your Business on WordPress</h1>
     343                            <p class="gops-subtitle">All your GravityOps tools in one place.</p>
     344                        </div>
    336345                    </div>
    337                 </div>
    338                 <div class="gops-header__right">
    339                     <a class="button button-primary" target="_blank" rel="noopener" href="https://brightleafdigital.io/plugintomember">Join Community</a>
    340                 </div>
    341             </header>
     346                    <div class="gops-header__right">
     347                        <a class="button button-primary" target="_blank" rel="noopener" href="https://brightleafdigital.io/plugintomember">Join Community</a>
     348                    </div>
     349                </header>
     350            </div>
    342351            <div class="gops-notices" aria-live="polite"></div>
    343352
     
    404413                            if ( $icon_url ) :
    405414                                ?>
    406                                 <img class="gops-tile__iconimg" width="22" height="22" src="<?php echo esc_url( $icon_url ); ?>" alt=""/>
     415                                <img class="gops-tile__iconimg" width="48" height="48" src="<?php echo esc_url( $icon_url ); ?>" alt=""/>
    407416                            <?php else : ?>
    408417                                <div class="gops-tile__icon" aria-hidden="true"><?php echo isset( $item['icon_html'] ) ? wp_kses_post( $item['icon_html'] ) : '🔧'; ?></div>
     
    411420                        </div>
    412421                        <p class="gops-tile__desc"><?php echo esc_html( $item['description'] ); ?></p>
     422                        <?php echo wp_kses_post( apply_filters( 'gravityops_tile_after_description', '', $item ) ); ?>
    413423                        <div class="gops-tile__meta">
    414                             <span class="gops-badge<?php echo $is_active ? ' gops-badge--ok' : ' gops-badge--warn'; ?>">
    415                                 <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
    416                             </span>
    417424                            <?php if ( ! empty( $item['uses_free'] ) ) : ?>
    418425                                <span class="gops-badge">Free</span>
    419                             <?php endif; ?>
    420                             <?php if ( $version ) : ?>
    421                                 <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
    422426                            <?php endif; ?>
    423427                            <?php if ( $has_update ) : ?>
     
    427431
    428432                        <div class="gops-tile__actions">
    429                             <?php if ( $is_installed ) : ?>
    430                                 <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
    431                                     <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
    432                                         <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
    433                                         <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
    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'] ) ); ?>" />
    435                                         <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
    436                                     </form>
     433                            <div class="gops-tile__action-group">
     434                                <?php if ( $version ) : ?>
     435                                    <span class="gops-tile__version">v<?php echo esc_html( $version ); ?></span>
    437436                                <?php endif; ?>
    438                             <?php else : ?>
    439                                 <a class="button button-primary" target="_blank" href="<?php echo esc_url( ( $item['marketing_url'] ?? '' ) . '#pricing' ); ?>">Buy</a>
    440                             <?php endif; ?>
    441 
    442                             <a class="gops-link" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Learn More →</a>
     437                                <span class="gops-badge<?php echo $is_active ? ' gops-badge--ok' : ' gops-badge--warn'; ?>">
     438                                    <?php echo $is_active ? 'Active' : ( $is_installed ? 'Inactive' : 'Not Installed' ); ?>
     439                                </span>
     440
     441                                <?php if ( $is_installed ) : ?>
     442                                    <?php
     443                                    if ( $has_update && current_user_can( 'update_plugins' ) ) :
     444                                        // Use the file that actually has the update (prefer premium if both, though Issue 3 might have simplified this).
     445                                        $update_file = ( isset( $upd_prem ) && $upd_prem ) ? $premium_file : ( ( isset( $upd_free ) && $upd_free ) ? $free_file : $item['plugin_file_action'] );
     446                                        $update_url  = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . rawurlencode( $update_file ) ), 'upgrade-plugin_' . $update_file );
     447                                        ?>
     448                                        <a class="button button-primary" href="<?php echo esc_url( $update_url ); ?>">Update Now</a>
     449                                    <?php endif; ?>
     450
     451                                    <?php if ( current_user_can( 'activate_plugins' ) ) : ?>
     452                                        <form class="gops-action" method="post" action="<?php echo esc_url( $base_url ); ?>">
     453                                            <?php wp_nonce_field( 'gops_toggle_' . ( $item['plugin_file_action'] ?? $item['plugin_file'] ), 'gops_nonce' ); ?>
     454                                            <input type="hidden" name="gops-action" value="<?php echo $is_active ? 'deactivate' : 'activate'; ?>" />
     455                                            <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'] ) ); ?>" />
     456                                            <button class="button<?php echo $is_active ? '' : ' button-primary'; ?>" type="submit"><?php echo $is_active ? 'Deactivate' : 'Activate'; ?></button>
     457                                        </form>
     458                                    <?php endif; ?>
     459                                <?php else : ?>
     460                                    <?php if ( ! empty( $item['is_free'] ) ) : ?>
     461                                        <a class="button button-primary" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Download Now</a>
     462                                    <?php else : ?>
     463                                        <a class="button button-primary" target="_blank" href="<?php echo esc_url( ( $item['marketing_url'] ?? '' ) . '#pricing' ); ?>">Buy</a>
     464                                    <?php endif; ?>
     465                                <?php endif; ?>
     466                            </div>
     467
     468                            <a class="gops-link gops-tile__learn-more" target="_blank" href="<?php echo esc_url( $item['marketing_url'] ); ?>">Learn More →</a>
    443469                        </div>
    444470                    </div>
     
    452478
    453479    /**
     480     * Helper to get a plugin's icon URL by its slug.
     481     *
     482     * @param string $slug Plugin slug as defined in SuiteRegistry.
     483     * @return string Icon URL or empty string.
     484     */
     485    public static function get_plugin_icon_url( $slug ) {
     486        $registry = SuiteRegistry::all();
     487        foreach ( $registry as $item ) {
     488            if ( ( $item['slug'] ?? '' ) === $slug ) {
     489                return self::resolve_plugin_icon_url( $item );
     490            }
     491        }
     492        return '';
     493    }
     494
     495    /**
    454496     * Resolve a plugin icon URL from common asset locations, with filter override.
    455497     *
     
    457499     * @return string Icon URL or empty string if none found.
    458500     */
    459     private static function resolve_plugin_icon_url( $item ) {
     501    public static function resolve_plugin_icon_url( $item ) {
    460502        $url = apply_filters( 'gravityops_plugin_icon_url', '', $item );
    461503        if ( ! empty( $url ) ) {
     
    463505        }
    464506
    465         if ( empty( $item['plugin_file'] ) ) {
    466             return '';
    467         }
    468 
    469         $plugin_main = WP_PLUGIN_DIR . '/' . $item['plugin_file'];
    470         if ( ! file_exists( $plugin_main ) ) {
    471             return '';
    472         }
    473 
    474         // Base plugin URL for building asset URLs.
    475         $base_url = plugins_url( '', $plugin_main );
    476         $base_dir = dirname( $plugin_main );
    477 
    478         $candidates = [
    479             'assets/icon.svg',
    480             'assets/icon.png',
    481             'assets/images/icon.svg',
    482             'assets/images/icon.png',
    483             'includes/images/icon.svg',
    484             'includes/images/icon.png',
    485             'assets/img/icon.svg',
    486             'assets/img/icon.png',
    487         ];
    488         foreach ( $candidates as $rel ) {
    489             $path = $base_dir . '/' . $rel;
    490             if ( file_exists( $path ) ) {
    491                 return $base_url . '/' . $rel;
    492             }
    493         }
    494 
    495         // Wildcard: first match like assets/img/*-icon.svg|png
    496         $wild_dirs = [ 'assets/img' ];
    497         foreach ( $wild_dirs as $wd ) {
    498             $dir = $base_dir . '/' . $wd;
    499             if ( is_dir( $dir ) ) {
    500                 $matches = array_merge( glob( $dir . '/*-icon.svg' ) ?: [], glob( $dir . '/*-icon.png' ) ?: [] );
    501                 if ( ! empty( $matches ) ) {
    502                     // Return the first match
    503                     $first = $matches[0];
    504                     return $base_url . '/' . $wd . '/' . basename( $first );
     507        if ( ! empty( $item['icon_filename'] ) ) {
     508            $assets = class_exists( __NAMESPACE__ . '\AdminShell' ) ? AdminShell::resolve_assets_urls() : [];
     509            $base   = ! empty( $assets['base_url'] ) ? $assets['base_url'] : ( ! empty( $assets['css'] ) ? trailingslashit( dirname( $assets['css'], 2 ) ) : '' );
     510            if ( $base ) {
     511                return $base . 'images/' . $item['icon_filename'];
     512            }
     513        }
     514
     515        $files_to_check = [];
     516        if ( ! empty( $item['plugin_files'] ) ) {
     517            if ( isset( $item['plugin_files']['premium'] ) ) {
     518                $files_to_check[] = $item['plugin_files']['premium'];
     519            }
     520            if ( isset( $item['plugin_files']['free'] ) ) {
     521                $files_to_check[] = $item['plugin_files']['free'];
     522            }
     523        }
     524        if ( ! empty( $item['plugin_file'] ) ) {
     525            $files_to_check[] = (string) $item['plugin_file'];
     526        }
     527
     528        $files_to_check = array_unique( $files_to_check );
     529
     530        foreach ( $files_to_check as $plugin_rel_file ) {
     531            $plugin_main = WP_PLUGIN_DIR . '/' . $plugin_rel_file;
     532            if ( ! file_exists( $plugin_main ) ) {
     533                continue;
     534            }
     535
     536            // Base plugin URL for building asset URLs.
     537            $base_url = plugins_url( '', $plugin_main );
     538            $base_dir = dirname( $plugin_main );
     539
     540            $candidates = [
     541                'assets/icon.svg',
     542                'assets/icon.png',
     543                'assets/images/icon.svg',
     544                'assets/images/icon.png',
     545                'includes/images/icon.svg',
     546                'includes/images/icon.png',
     547                'assets/img/icon.svg',
     548                'assets/img/icon.png',
     549            ];
     550            foreach ( $candidates as $rel ) {
     551                $path = $base_dir . '/' . $rel;
     552                if ( file_exists( $path ) ) {
     553                    return $base_url . '/' . $rel;
    505554                }
    506555            }
    507         }
     556
     557            // Wildcard: first match like assets/img/*-icon.svg|png
     558            $wild_dirs = [ 'assets/img', 'assets/images' ];
     559            foreach ( $wild_dirs as $wd ) {
     560                $dir = $base_dir . '/' . $wd;
     561                if ( is_dir( $dir ) ) {
     562                    $matches = array_merge( glob( $dir . '/*-icon.svg' ) ?: [], glob( $dir . '/*-icon.png' ) ?: [] );
     563                    if ( ! empty( $matches ) ) {
     564                        // Return the first match
     565                        $first = $matches[0];
     566                        return $base_url . '/' . $wd . '/' . basename( $first );
     567                    }
     568                }
     569            }
     570        }
     571
    508572        return '';
    509573    }
     
    525589        $is_gravityops_screen = ( false !== strpos( (string) $hook, 'gravity_ops' ) ) || ( 'gravity_ops' === $page );
    526590        $is_freemius          = (bool) preg_match( '/\-(account|pricing|affiliation)$/', $page );
    527         if ( ! $is_gravityops_screen && ! $is_freemius ) {
     591        $is_gf_page           = ( 0 === strpos( $page, 'gf_' ) ) || ( false !== strpos( (string) $hook, 'forms_page_gf' ) );
     592
     593        // Always load on our pages, Freemius pages, and GF pages.
     594        // Also load globally by default to ensure the sidebar menu icon is consistently styled.
     595        $load_globally = (bool) apply_filters( 'gravityops_load_admin_assets_globally', true );
     596
     597        if ( ! $is_gravityops_screen && ! $is_freemius && ! $is_gf_page && ! $load_globally ) {
    528598            return;
    529599        }
     
    531601        // Reuse AdminShell asset resolution to support both root and vendor installs.
    532602        if ( class_exists( __NAMESPACE__ . '\\AdminShell' ) ) {
    533             $assets = AdminShell::resolve_assets_urls();
    534             if ( ! empty( $assets['css'] ) ) {
    535                 wp_enqueue_style( 'gravityops-admin', $assets['css'], [], '1.0.0' );
    536             }
    537             if ( ! empty( $assets['js'] ) ) {
    538                 wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], '1.0.0', true );
    539             }
    540             // If this is a Freemius page, also enqueue the freemius.css override to hide native tabs.
    541             if ( $is_freemius ) {
    542                 $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
    543                 wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], '1.0.0' );
     603            $assets  = AdminShell::resolve_assets_urls();
     604            $version = defined( AdminShell::class . '::CORE_VERSION' ) ? AdminShell::CORE_VERSION : '1.0.0';
     605
     606            // Load minimal menu/icon CSS globally or on GF pages.
     607            if ( ! empty( $assets['menu_css'] ) ) {
     608                wp_enqueue_style( 'gravityops-menu', $assets['menu_css'], [], $version );
     609            }
     610
     611            // Load the full admin UI CSS only on our screens or Freemius screens.
     612            if ( ! empty( $assets['css'] ) && ( $is_gravityops_screen || $is_freemius ) ) {
     613                wp_enqueue_style( 'gravityops-admin', $assets['css'], [ 'gravityops-menu' ], $version );
     614            }
     615
     616            // We only need the JS on our screens or Freemius screens.
     617            if ( $is_gravityops_screen || $is_freemius ) {
     618                if ( ! empty( $assets['js'] ) ) {
     619                    wp_enqueue_script( 'gravityops-admin', $assets['js'], [ 'jquery' ], $version, true );
     620                }
     621                // If this is a Freemius page, also enqueue the freemius.css override to hide native tabs.
     622                if ( $is_freemius ) {
     623                    $fs_css = trailingslashit( dirname( $assets['css'] ) ) . 'freemius.css';
     624                    wp_enqueue_style( 'gravityops-freemius', $fs_css, [ 'gravityops-admin' ], $version );
     625                }
    544626            }
    545627        }
     
    637719    public static function get_icon() {
    638720        $assets    = class_exists( __NAMESPACE__ . '\AdminShell' ) ? AdminShell::resolve_assets_urls() : [
    639             'css' => '',
    640             'js'  => '',
     721            'css'      => '',
     722            'js'       => '',
     723            'base_url' => '',
    641724        ];
    642         $base      = ! empty( $assets['css'] ) ? trailingslashit( dirname( $assets['css'] ) ) : '';
    643         $candidate = 'images/icon.png';
     725        $base      = ! empty( $assets['base_url'] ) ? $assets['base_url'] : ( ! empty( $assets['css'] ) ? trailingslashit( dirname( dirname( $assets['css'] ) ) ) : '' );
     726        $candidate = 'images/ops-icon.svg';
    644727        $url       = $base ? $base . $candidate : '';
    645728        return apply_filters( 'gravityops_menu_icon_url', $url );
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/Admin/SurveyPrompter.php

    r3420036 r3444395  
    125125        $nonce_action     = "{$this->prefix}do_survey";
    126126
     127        $current_page   = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     128        $is_gops_page   = ( 'gravity_ops' === $current_page || AdminShell::has_page( $current_page ) );
     129        $notice_classes = 'notice notice-info is-dismissible';
     130        if ( $is_gops_page ) {
     131            $notice_classes .= ' inline';
     132        }
    127133        add_action(
    128134            'admin_notices',
    129             function () use ( $star_class, $rating_input_id, $rating_field, $like_field, $dislike_field, $recommend_field, $find_field, $nonce_field_name, $submit_field, $nonce_action ) {
     135            function () use ( $star_class, $rating_input_id, $rating_field, $like_field, $dislike_field, $recommend_field, $find_field, $nonce_field_name, $submit_field, $nonce_action, $notice_classes ) {
    130136                ?>
    131                 <div class="notice notice-info is-dismissible">
     137                <div class="<?= esc_attr( $notice_classes ); ?>">
    132138                    <h3>We value your feedback!</h3>
    133139                    <h4>Thank you for using <?= esc_html( $this->plugin_title ); ?>!</h4>
  • mass-email-notifications-for-gravity-forms/trunk/vendor/MENFGF/gravityops/core/src/SuiteRegistry.php

    r3422687 r3444395  
    3838                'is_free'       => true,
    3939                'icon_html'     => '🗂️',
     40                'icon_filename' => 'f4g-icon.svg',
    4041            ],
    4142            [
     
    4950                'is_free'       => true,
    5051                'icon_html'     => '🔎',
     52                'icon_filename' => 'search-icon.svg',
    5153            ],
    5254            [
     
    6567                'is_free'       => false,
    6668                'icon_html'     => '🅰️',
     69                'icon_filename' => 'iawgf-icon.svg',
    6770            ],
    6871            [
     
    8184                'is_free'       => false,
    8285                'icon_html'     => '✉️',
     86                'icon_filename' => 'menfgf-icon.svg',
    8387            ],
    8488            [
     
    9296                'is_free'       => false,
    9397                'icon_html'     => '🗂️',
     98                'icon_filename' => 'kv4gv-icon.svg',
    9499            ],
    95100            [
     
    103108                'is_free'       => false,
    104109                'icon_html'     => '🔁',
     110                'icon_filename' => 'rfsfgf-icon.svg',
    105111            ],
    106112            [
     
    115121                'is_free'       => false,
    116122                'icon_html'     => '∑',
     123                'icon_filename' => 'gv4gm-icon.svg',
    117124            ],
    118125        ];
  • mass-email-notifications-for-gravity-forms/trunk/vendor/autoload.php

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

    r3422687 r3444395  
    22
    33// Functions and constants
     4
     5namespace {
     6
     7}
    48namespace GravityOps\Core\Admin {
    59    if(!function_exists('\\GravityOps\\Core\\Admin\\gravityops_shell')){
     
    913    }
    1014}
     15namespace TrustedLogin {
     16    if(!function_exists('\\TrustedLogin\\function_exists')){
     17        function function_exists(...$args) {
     18            return \MENFGF\TrustedLogin\function_exists(...func_get_args());
     19        }
     20    }
     21}
    1122
    1223
    1324namespace MENFGF {
    1425
     26    use BrianHenryIE\Strauss\Types\AutoloadAliasInterface;
     27
     28    /**
     29     * @see AutoloadAliasInterface
     30     *
     31     * @phpstan-type ClassAliasArray array{'type':'class',isabstract:bool,classname:string,namespace?:string,extends:string,implements:array<string>}
     32     * @phpstan-type InterfaceAliasArray array{'type':'interface',interfacename:string,namespace?:string,extends:array<string>}
     33     * @phpstan-type TraitAliasArray array{'type':'trait',traitname:string,namespace?:string,use:array<string>}
     34     * @phpstan-type AutoloadAliasArray array<string,ClassAliasArray|InterfaceAliasArray|TraitAliasArray>
     35     */
    1536    class AliasAutoloader
    1637    {
    1738        private string $includeFilePath;
    1839
     40        /**
     41         * @var AutoloadAliasArray
     42         */
    1943        private array $autoloadAliases = array (
    2044  'GravityOps\\Core\\Admin\\AdminShell' =>
     
    7397    ),
    7498  ),
     99  'GravityOps\\Core\\Admin\\TrustedLogin' =>
     100  array (
     101    'type' => 'class',
     102    'classname' => 'TrustedLogin',
     103    'isabstract' => false,
     104    'namespace' => 'GravityOps\\Core\\Admin',
     105    'extends' => 'MENFGF\\GravityOps\\Core\\Admin\\TrustedLogin',
     106    'implements' =>
     107    array (
     108    ),
     109  ),
    75110  'GravityOps\\Core\\SuiteRegistry' =>
    76111  array (
     
    91126    'namespace' => 'GravityOps\\Core\\Utils',
    92127    'extends' => 'MENFGF\\GravityOps\\Core\\Utils\\AssetHelper',
     128    'implements' =>
     129    array (
     130    ),
     131  ),
     132  'TrustedLogin\\Admin' =>
     133  array (
     134    'type' => 'class',
     135    'classname' => 'Admin',
     136    'isabstract' => false,
     137    'namespace' => 'TrustedLogin',
     138    'extends' => 'MENFGF\\TrustedLogin\\Admin',
     139    'implements' =>
     140    array (
     141    ),
     142  ),
     143  'TrustedLogin\\Ajax' =>
     144  array (
     145    'type' => 'class',
     146    'classname' => 'Ajax',
     147    'isabstract' => false,
     148    'namespace' => 'TrustedLogin',
     149    'extends' => 'MENFGF\\TrustedLogin\\Ajax',
     150    'implements' =>
     151    array (
     152    ),
     153  ),
     154  'TrustedLogin\\Client' =>
     155  array (
     156    'type' => 'class',
     157    'classname' => 'Client',
     158    'isabstract' => false,
     159    'namespace' => 'TrustedLogin',
     160    'extends' => 'MENFGF\\TrustedLogin\\Client',
     161    'implements' =>
     162    array (
     163    ),
     164  ),
     165  'TrustedLogin\\Config' =>
     166  array (
     167    'type' => 'class',
     168    'classname' => 'Config',
     169    'isabstract' => false,
     170    'namespace' => 'TrustedLogin',
     171    'extends' => 'MENFGF\\TrustedLogin\\Config',
     172    'implements' =>
     173    array (
     174    ),
     175  ),
     176  'TrustedLogin\\Cron' =>
     177  array (
     178    'type' => 'class',
     179    'classname' => 'Cron',
     180    'isabstract' => false,
     181    'namespace' => 'TrustedLogin',
     182    'extends' => 'MENFGF\\TrustedLogin\\Cron',
     183    'implements' =>
     184    array (
     185    ),
     186  ),
     187  'TrustedLogin\\Encryption' =>
     188  array (
     189    'type' => 'class',
     190    'classname' => 'Encryption',
     191    'isabstract' => false,
     192    'namespace' => 'TrustedLogin',
     193    'extends' => 'MENFGF\\TrustedLogin\\Encryption',
     194    'implements' =>
     195    array (
     196    ),
     197  ),
     198  'TrustedLogin\\Endpoint' =>
     199  array (
     200    'type' => 'class',
     201    'classname' => 'Endpoint',
     202    'isabstract' => false,
     203    'namespace' => 'TrustedLogin',
     204    'extends' => 'MENFGF\\TrustedLogin\\Endpoint',
     205    'implements' =>
     206    array (
     207    ),
     208  ),
     209  'TrustedLogin\\Envelope' =>
     210  array (
     211    'type' => 'class',
     212    'classname' => 'Envelope',
     213    'isabstract' => false,
     214    'namespace' => 'TrustedLogin',
     215    'extends' => 'MENFGF\\TrustedLogin\\Envelope',
     216    'implements' =>
     217    array (
     218    ),
     219  ),
     220  'TrustedLogin\\Form' =>
     221  array (
     222    'type' => 'class',
     223    'classname' => 'Form',
     224    'isabstract' => false,
     225    'namespace' => 'TrustedLogin',
     226    'extends' => 'MENFGF\\TrustedLogin\\Form',
     227    'implements' =>
     228    array (
     229    ),
     230  ),
     231  'TrustedLogin\\Logger' =>
     232  array (
     233    'type' => 'class',
     234    'classname' => 'Logger',
     235    'isabstract' => false,
     236    'namespace' => 'TrustedLogin',
     237    'extends' => 'MENFGF\\TrustedLogin\\Logger',
     238    'implements' =>
     239    array (
     240    ),
     241  ),
     242  'TrustedLogin\\Logging' =>
     243  array (
     244    'type' => 'class',
     245    'classname' => 'Logging',
     246    'isabstract' => false,
     247    'namespace' => 'TrustedLogin',
     248    'extends' => 'MENFGF\\TrustedLogin\\Logging',
     249    'implements' =>
     250    array (
     251    ),
     252  ),
     253  'TrustedLogin\\Remote' =>
     254  array (
     255    'type' => 'class',
     256    'classname' => 'Remote',
     257    'isabstract' => false,
     258    'namespace' => 'TrustedLogin',
     259    'extends' => 'MENFGF\\TrustedLogin\\Remote',
     260    'implements' =>
     261    array (
     262    ),
     263  ),
     264  'TrustedLogin\\SecurityChecks' =>
     265  array (
     266    'type' => 'class',
     267    'classname' => 'SecurityChecks',
     268    'isabstract' => false,
     269    'namespace' => 'TrustedLogin',
     270    'extends' => 'MENFGF\\TrustedLogin\\SecurityChecks',
     271    'implements' =>
     272    array (
     273    ),
     274  ),
     275  'TrustedLogin\\SiteAccess' =>
     276  array (
     277    'type' => 'class',
     278    'classname' => 'SiteAccess',
     279    'isabstract' => false,
     280    'namespace' => 'TrustedLogin',
     281    'extends' => 'MENFGF\\TrustedLogin\\SiteAccess',
     282    'implements' =>
     283    array (
     284    ),
     285  ),
     286  'TrustedLogin\\SupportRole' =>
     287  array (
     288    'type' => 'class',
     289    'classname' => 'SupportRole',
     290    'isabstract' => false,
     291    'namespace' => 'TrustedLogin',
     292    'extends' => 'MENFGF\\TrustedLogin\\SupportRole',
     293    'implements' =>
     294    array (
     295    ),
     296  ),
     297  'TrustedLogin\\SupportUser' =>
     298  array (
     299    'type' => 'class',
     300    'classname' => 'SupportUser',
     301    'isabstract' => false,
     302    'namespace' => 'TrustedLogin',
     303    'extends' => 'MENFGF\\TrustedLogin\\SupportUser',
     304    'implements' =>
     305    array (
     306    ),
     307  ),
     308  'TrustedLogin\\Utils' =>
     309  array (
     310    'type' => 'class',
     311    'classname' => 'Utils',
     312    'isabstract' => false,
     313    'namespace' => 'TrustedLogin',
     314    'extends' => 'MENFGF\\TrustedLogin\\Utils',
     315    'implements' =>
     316    array (
     317    ),
     318  ),
     319  'TrustedLogin\\TrustedLoginClientTest' =>
     320  array (
     321    'type' => 'class',
     322    'classname' => 'TrustedLoginClientTest',
     323    'isabstract' => false,
     324    'namespace' => 'TrustedLogin',
     325    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginClientTest',
     326    'implements' =>
     327    array (
     328    ),
     329  ),
     330  'TrustedLogin\\TrustedLoginEncryptionTest' =>
     331  array (
     332    'type' => 'class',
     333    'classname' => 'TrustedLoginEncryptionTest',
     334    'isabstract' => false,
     335    'namespace' => 'TrustedLogin',
     336    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginEncryptionTest',
     337    'implements' =>
     338    array (
     339    ),
     340  ),
     341  'TrustedLogin\\TrustedLoginLoggingTest' =>
     342  array (
     343    'type' => 'class',
     344    'classname' => 'TrustedLoginLoggingTest',
     345    'isabstract' => false,
     346    'namespace' => 'TrustedLogin',
     347    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginLoggingTest',
     348    'implements' =>
     349    array (
     350    ),
     351  ),
     352  'TrustedLogin\\TrustedLoginRemoteTest' =>
     353  array (
     354    'type' => 'class',
     355    'classname' => 'TrustedLoginRemoteTest',
     356    'isabstract' => false,
     357    'namespace' => 'TrustedLogin',
     358    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginRemoteTest',
     359    'implements' =>
     360    array (
     361    ),
     362  ),
     363  'TrustedLogin\\TrustedLoginSiteAccessTest' =>
     364  array (
     365    'type' => 'class',
     366    'classname' => 'TrustedLoginSiteAccessTest',
     367    'isabstract' => false,
     368    'namespace' => 'TrustedLogin',
     369    'extends' => 'MENFGF\\TrustedLogin\\TrustedLoginSiteAccessTest',
    93370    'implements' =>
    94371    array (
     
    112389        }
    113390
    114         public function autoload($class)
     391        /**
     392         * @param string $class
     393         */
     394        public function autoload($class): void
    115395        {
    116396            if (!isset($this->autoloadAliases[$class])) {
     
    145425        }
    146426
    147         private function load(string $includeFile)
     427        private function load(string $includeFile): void
    148428        {
    149429            file_put_contents($this->includeFilePath, $includeFile);
     
    152432        }
    153433
     434        /**
     435         * @param ClassAliasArray $class
     436         */
    154437        private function classTemplate(array $class): string
    155438        {
     
    174457        }
    175458
     459        /**
     460         * @param InterfaceAliasArray $interface
     461         */
    176462        private function interfaceTemplate(array $interface): string
    177463        {
     
    188474                EOD;
    189475        }
     476
     477        /**
     478         * @param TraitAliasArray $trait
     479         */
    190480        private function traitTemplate(array $trait): string
    191481        {
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/autoload_files.php

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

    r3422687 r3444395  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e
     5class ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit7bc26ac187e3e5b59cfcfcf02aeed97e', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit0e8b87e452507fa901dfbb37bbc8b6c5', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::getInitializer($loader));
    3333
    3434        $loader->register(true);
    3535
    36         $filesToLoad = \Composer\Autoload\ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$files;
     36        $filesToLoad = \Composer\Autoload\ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::$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

    r3422687 r3444395  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e
     7class ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5
    88{
    99    public static $files = array (
    1010        '8d50dc88e56bace65e1e72f6017983ed' => __DIR__ . '/..' . '/freemius/wordpress-sdk/start.php',
    11         '9387666eac3fc37c9ef87deb087980c6' => __DIR__ . '/..' . '/MENFGF/autoload.php',
    12         '79fa1c9a31d9f4c8c1a536bd9e014492' => __DIR__ . '/..' . '/MENFGF/gravityops/core/src/Admin/functions.php',
    1311    );
    1412
     
    2018    {
    2119        return \Closure::bind(function () use ($loader) {
    22             $loader->classMap = ComposerStaticInit7bc26ac187e3e5b59cfcfcf02aeed97e::$classMap;
     20            $loader->classMap = ComposerStaticInit0e8b87e452507fa901dfbb37bbc8b6c5::$classMap;
    2321
    2422        }, null, ClassLoader::class);
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/installed.json

    r3422687 r3444395  
    5959        {
    6060            "name": "gravityops/core",
    61             "version": "1.0.21",
    62             "version_normalized": "1.0.21.0",
     61            "version": "1.1.0",
     62            "version_normalized": "1.1.0.0",
    6363            "source": {
    6464                "type": "git",
    6565                "url": "[email protected]:Eitan-brightleaf/gravityops.git",
    66                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522"
     66                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e"
    6767            },
    6868            "dist": {
    6969                "type": "zip",
    70                 "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
    71                 "reference": "5d859a7cca5cf8c1e469c80a88e755fb1be7c522",
     70                "url": "https://api.github.com/repos/Eitan-brightleaf/gravityops/zipball/cee27f55738670dc141b58af37d0feb74d4ce47e",
     71                "reference": "cee27f55738670dc141b58af37d0feb74d4ce47e",
    7272                "shasum": ""
    7373            },
    7474            "require": {
    75                 "php": ">=7.4"
     75                "php": ">=7.4",
     76                "trustedlogin/client": "^v1.9"
    7677            },
    77             "time": "2025-12-18T07:45:02+00:00",
     78            "time": "2026-01-21T19:42:14+00:00",
    7879            "type": "library",
    7980            "installation-source": "source",
     
    8485            "description": "Shared core library for GravityOps plugins",
    8586            "install-path": "../gravityops/core"
     87        },
     88        {
     89            "name": "trustedlogin/client",
     90            "version": "v1.9.0",
     91            "version_normalized": "1.9.0.0",
     92            "source": {
     93                "type": "git",
     94                "url": "https://github.com/trustedlogin/client.git",
     95                "reference": "b913058ae57b512a7766f449ab8d55952500fe72"
     96            },
     97            "dist": {
     98                "type": "zip",
     99                "url": "https://api.github.com/repos/trustedlogin/client/zipball/b913058ae57b512a7766f449ab8d55952500fe72",
     100                "reference": "b913058ae57b512a7766f449ab8d55952500fe72",
     101                "shasum": ""
     102            },
     103            "require-dev": {
     104                "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
     105                "ext-curl": "*",
     106                "ext-json": "*",
     107                "php": ">=5.3.0",
     108                "phpcompatibility/phpcompatibility-wp": "^2.1",
     109                "phpstan/extension-installer": "^1.3",
     110                "phpstan/phpstan": "^1.10",
     111                "szepeviktor/phpstan-wordpress": "^1.3",
     112                "wp-coding-standards/wpcs": "^3.0",
     113                "yoast/phpunit-polyfills": "^1.0.0"
     114            },
     115            "time": "2024-08-26T01:13:42+00:00",
     116            "bin": [
     117                "bin/build-sass"
     118            ],
     119            "type": "library",
     120            "installation-source": "dist",
     121            "autoload": [],
     122            "notification-url": "https://packagist.org/downloads/",
     123            "license": [
     124                "GPL-2.0-or-later"
     125            ],
     126            "authors": [
     127                {
     128                    "name": "TrustedLogin",
     129                    "email": "[email protected]",
     130                    "homepage": "https://www.trustedlogin.com"
     131                }
     132            ],
     133            "description": "Easily and securely log in to your customers sites when providing support.",
     134            "homepage": "https://www.trustedlogin.com",
     135            "keywords": [
     136                "login",
     137                "security",
     138                "support"
     139            ],
     140            "support": {
     141                "issues": "https://github.com/trustedlogin/client/issues",
     142                "source": "https://github.com/trustedlogin/client/tree/v1.9.0"
     143            },
     144            "install-path": "../trustedlogin/client"
    86145        }
    87146    ],
  • mass-email-notifications-for-gravity-forms/trunk/vendor/composer/installed.php

    r3422687 r3444395  
    11<?php return array(
    22    'root' => array(
    3         'name' => '__root__',
     3        'name' => 'gravityops/mass-email',
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
     6        'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
     
    1111    ),
    1212    'versions' => array(
    13         '__root__' => array(
    14             'pretty_version' => 'dev-main',
    15             'version' => 'dev-main',
    16             'reference' => '4b921b3009464563093dfd512b32f402b1533e6b',
    17             'type' => 'library',
    18             'install_path' => __DIR__ . '/../../',
    19             'aliases' => array(),
    20             'dev_requirement' => false,
    21         ),
    2213        'freemius/wordpress-sdk' => array(
    2314            'pretty_version' => '2.13.0',
     
    3021        ),
    3122        'gravityops/core' => array(
    32             'pretty_version' => '1.0.21',
    33             'version' => '1.0.21.0',
    34             'reference' => '5d859a7cca5cf8c1e469c80a88e755fb1be7c522',
     23            'pretty_version' => '1.1.0',
     24            'version' => '1.1.0.0',
     25            'reference' => 'cee27f55738670dc141b58af37d0feb74d4ce47e',
    3526            'type' => 'library',
    3627            'install_path' => __DIR__ . '/../gravityops/core',
     
    3829            'dev_requirement' => false,
    3930        ),
     31        'gravityops/mass-email' => array(
     32            'pretty_version' => 'dev-main',
     33            'version' => 'dev-main',
     34            'reference' => '844dcc46ed2d370fadaccebd03c6dae5521ea1ba',
     35            'type' => 'library',
     36            'install_path' => __DIR__ . '/../../',
     37            'aliases' => array(),
     38            'dev_requirement' => false,
     39        ),
     40        'trustedlogin/client' => array(
     41            'pretty_version' => 'v1.9.0',
     42            'version' => '1.9.0.0',
     43            'reference' => 'b913058ae57b512a7766f449ab8d55952500fe72',
     44            'type' => 'library',
     45            'install_path' => __DIR__ . '/../trustedlogin/client',
     46            'aliases' => array(),
     47            'dev_requirement' => false,
     48        ),
    4049    ),
    4150);
Note: See TracChangeset for help on using the changeset viewer.