<?php
/**
 * Plugin Name:       GriffinForms – Form Builder
 * Plugin URI:        https://griffinforms.com/
 * Description:       A powerful and flexible form builder for WordPress. Create multi-page forms with drag-and-drop ease, custom validations, and full submission management.
 * Version:           3.2.3.0
 * Requires at least: 6.6
 * Requires PHP:      8.2
 * Author:            GriffinForms
 * Author URI:        https://profiles.wordpress.org/griffinforms/
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       griffinforms-form-builder
 * Domain Path:       /languages
 GriffinForms is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.
 
GriffinForms is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with GriffinForms. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
 */

//All plugin code exists inside namespace GriffinForms
namespace GriffinForms;

//exit if the file is accessed directly.
if (!defined('WPINC')) die;

require_once(ABSPATH . 'wp-admin/includes/plugin.php');

function fileNotFound($file) {
    \deactivate_plugins(plugin_basename(__FILE__));

    wp_die(
        wp_kses_post(sprintf(
            // Translators: %1$s is the missing file path, %2$s is the URL to the dashboard.
            __('A required file <br><pre>%1$s</pre><br>was not found. Plugin GriffinForms has been deactivated. <a href="%2$s">Click here</a> to return to the dashboard.', 'griffinforms-form-builder'),
            esc_html($file),
            esc_url(get_dashboard_url())
        ))
    );
}

//Class autoloader to include class files based on object creation. 

if (is_readable(plugin_dir_path(__FILE__) . 'loader.php')) {
    require_once plugin_dir_path(__FILE__) . 'loader.php';
} else {
    fileNotFound(plugin_dir_path(__FILE__) . 'loader.php');
}

spl_autoload_register(array(__NAMESPACE__ . '\Loader', 'loadClass'));
require_once __DIR__ . '/vendor/autoload.php';

add_filter('cron_schedules', function (array $schedules): array {
    if (!isset($schedules['griffinforms_every_minute'])) {
        $schedules['griffinforms_every_minute'] = [
            'interval' => 60,
            'display'  => __('Every Minute (GriffinForms)', 'griffinforms-form-builder'),
        ];
    }

    return $schedules;
}, 1);

Includes\Packages\PackageBootstrap::getInstance()->registerHooks();

register_activation_hook(__FILE__, function () {
    (new Install())->install();
    Includes\Packages\PackageStateStore::getInstance()->markActivated('core', get_current_user_id());
    Includes\Packages\PackageBootstrap::getInstance()->refreshCurrentState();
});

add_action('admin_init', function () {
    (new Install())->redirectOnActivation();
});

add_action('init', function () {
    $bootstrap_frontend_ajax = !is_admin() || wp_doing_ajax();

    // Lightweight migrations (safe + idempotent).
    (new Db())->maybeRunMigrations();

    if ($bootstrap_frontend_ajax) {
        new Frontend\Ajax\Validations();
        new Frontend\Ajax\Submission();
        new Frontend\Ajax\Terms();
        new Frontend\Ajax\Payments();
    }

    if (is_admin()) {
        new Admin\Menu();
        new Admin\StyleSheets();
        new Admin\DeactivationWarning();
        new Admin\UninstallFeedback();
        new Includes\Privacy\PersonalData();

        new Admin\Ajax\Lists();
        new Admin\Ajax\ListPrefs();
        new Admin\Ajax\Field();
        new Admin\Ajax\Form();
        new Admin\Ajax\Forms();
        new Admin\Ajax\Single();
        new Admin\Ajax\FormTheme();
        new Admin\Ajax\Settings();
        new Admin\Ajax\Submission();
        new Admin\Ajax\UninstallFeedback();
        Admin\App\Html\LandingPage::getInstance();
        if (wp_doing_ajax()) {
            new Admin\App\Html\Widgets\PresentationArea\FormLayout();
        }
        Admin\Actions\ProcessActions::getInstance()->register();
    } else {
        new Frontend\ShortCodes();
    }

    // Register Block Editor integrations (Gutenberg block + REST)
    Editors\Gutenberg\Registrar::register();
    Includes\Publication\PostSaveTracker::getInstance()->registerHooks();
}, 9);

add_action('init', function () {
    Includes\Onboarding\PreviewPage::getInstance()->registerHooks();
}, 1);

// Register all background process schedulers, such as async email handlers.
Includes\Schedulers\ProcessScheduler::register();
Includes\Security\Capabilities::registerHooks();
new Includes\Api\SubmissionsRest();
new Includes\Api\MigrationRest();
new Includes\CommandPalette\PaletteRest();
add_action('rest_api_init', function () {
    Admin\App\Html\Modals\FormOptions::getInstance()->registerRestRoutes();
    Admin\App\Html\Modals\FormNotifications::getInstance()->registerRestRoutes();
});

// Bootstrap command palette: keyword map, provider registry.
$gf_keyword_map = new Includes\CommandPalette\KeywordMap();

$gf_keyword_map->register('conditional logic',  'open_modal', ['modal_id' => 'griffinforms-builder-modal-conditionallogic'], 'Conditional Logic', 'Add rules to show or hide fields based on user input', 'conditional_logic');
$gf_keyword_map->register('rules',              'open_modal', ['modal_id' => 'griffinforms-builder-modal-conditionallogic'], 'Conditional Logic', 'Add rules to show or hide fields based on user input', 'conditional_logic');
$gf_keyword_map->register('conditions',         'open_modal', ['modal_id' => 'griffinforms-builder-modal-conditionallogic'], 'Conditional Logic', 'Add rules to show or hide fields based on user input', 'conditional_logic');
$gf_keyword_map->register('if then',            'open_modal', ['modal_id' => 'griffinforms-builder-modal-conditionallogic'], 'Conditional Logic', 'Add rules to show or hide fields based on user input', 'conditional_logic');
$gf_keyword_map->register('logic',              'open_modal', ['modal_id' => 'griffinforms-builder-modal-conditionallogic'], 'Conditional Logic', 'Add rules to show or hide fields based on user input', 'conditional_logic');

$gf_keyword_map->register('user registration',  'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');
$gf_keyword_map->register('accounts',           'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');
$gf_keyword_map->register('sign up',            'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');
$gf_keyword_map->register('register',           'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');
$gf_keyword_map->register('create user',        'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');
$gf_keyword_map->register('wordpress user',     'open_modal', ['modal_id' => 'griffinforms-builder-modal-accounts'], 'User Registration', 'Automatically create WordPress accounts on form submission', 'accounts');

$gf_keyword_map->register('notifications',      'open_modal', ['modal_id' => 'griffinforms-builder-modal-formnotifications'], 'Notifications', 'Set up autoresponder and admin alert emails', 'notification');
$gf_keyword_map->register('autoresponder',      'open_modal', ['modal_id' => 'griffinforms-builder-modal-formnotifications'], 'Notifications', 'Set up autoresponder and admin alert emails', 'notification');
$gf_keyword_map->register('alert',              'open_modal', ['modal_id' => 'griffinforms-builder-modal-formnotifications'], 'Notifications', 'Set up autoresponder and admin alert emails', 'notification');
$gf_keyword_map->register('email notification', 'open_modal', ['modal_id' => 'griffinforms-builder-modal-formnotifications'], 'Notifications', 'Set up autoresponder and admin alert emails', 'notification');
$gf_keyword_map->register('admin email',        'open_modal', ['modal_id' => 'griffinforms-builder-modal-formnotifications'], 'Notifications', 'Set up autoresponder and admin alert emails', 'notification');

$gf_keyword_map->register('theme',              'open_modal', ['modal_id' => 'griffinforms-builder-modal-formthemes'], 'Form Theme', 'Apply or change the visual theme for this form', 'theme');
$gf_keyword_map->register('style',              'open_modal', ['modal_id' => 'griffinforms-builder-modal-formthemes'], 'Form Theme', 'Apply or change the visual theme for this form', 'theme');
$gf_keyword_map->register('design',             'open_modal', ['modal_id' => 'griffinforms-builder-modal-formthemes'], 'Form Theme', 'Apply or change the visual theme for this form', 'theme');
$gf_keyword_map->register('colors',             'open_modal', ['modal_id' => 'griffinforms-builder-modal-formthemes'], 'Form Theme', 'Apply or change the visual theme for this form', 'theme');
$gf_keyword_map->register('appearance',         'open_modal', ['modal_id' => 'griffinforms-builder-modal-formthemes'], 'Form Theme', 'Apply or change the visual theme for this form', 'theme');

$gf_keyword_map->register('integrations',       'open_modal', ['modal_id' => 'griffinforms-builder-modal-integrations'], 'Integrations', 'Connect third-party services to this form', 'keyword');
$gf_keyword_map->register('connect',            'open_modal', ['modal_id' => 'griffinforms-builder-modal-integrations'], 'Integrations', 'Connect third-party services to this form', 'keyword');
$gf_keyword_map->register('mailchimp',          'open_modal', ['modal_id' => 'griffinforms-builder-modal-integrations'], 'Integrations', 'Connect third-party services to this form', 'keyword');
$gf_keyword_map->register('stripe',             'open_modal', ['modal_id' => 'griffinforms-builder-modal-integrations'], 'Integrations', 'Connect third-party services to this form', 'keyword');
$gf_keyword_map->register('paypal',             'open_modal', ['modal_id' => 'griffinforms-builder-modal-integrations'], 'Integrations', 'Connect third-party services to this form', 'keyword');

$gf_palette_registry = Includes\CommandPalette\SearchProviderRegistry::getInstance();
$gf_palette_registry->register(new Includes\CommandPalette\Providers\RecentFormsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\CreateActionsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\NavigationProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\BuilderKeywordsProvider($gf_keyword_map));
$gf_palette_registry->register(new Includes\CommandPalette\Providers\IntegrationsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\ThemesProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\ThemeTabsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\ThemeActionsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\FormOptionsProvider());
$gf_palette_registry->register(new Includes\CommandPalette\Providers\PluginSettingsProvider());

unset($gf_keyword_map, $gf_palette_registry);

// Bootstrap notification registries.
// EmailChannel is always available (no integration dependency).
Includes\Notifications\NotificationChannelRegistry::getInstance()->register(
    new Includes\Notifications\Channels\EmailChannel()
);

// Register integration-owned channels: iterate active integrations after they are loaded.
add_action('init', function () {
    $providers   = Includes\Integrations\Providers::getInstance();
    $channel_reg = Includes\Notifications\NotificationChannelRegistry::getInstance();
    foreach ($providers->getAll() as $provider_meta) {
        $integration = $providers->getIntegration($provider_meta['id'] ?? '');
        if ($integration instanceof Includes\Integrations\Format) {
            $channel = $integration->getNotificationChannel();
            if ($channel instanceof Includes\Notifications\NotificationChannelInterface) {
                $channel_reg->register($channel);
            }
        }
    }
}, 11); // priority 11 — after integrations register at ≤10

// Bootstrap notification event registry.
add_action('init', function () {
    $event_reg = Includes\Notifications\NotificationEventRegistry::getInstance();
    $event_reg->register(new Includes\Notifications\Events\FormSubmissionEvent());
    $event_reg->register(new Includes\Notifications\Events\PaymentReceivedEvent());
}, 10);
Includes\Api\WebhookDelivery::registerHooks();
add_action('griffinforms_pro_shell_activation_success', ['GriffinForms\\Admin\\Menu', 'storeProActivationSuccessRecord']);

add_action('plugins_loaded', function () {
    $pipeline = Includes\Pipelines\PostSubmissionPipeline::getInstance();
    do_action('griffinforms_register_post_submission_handlers', $pipeline);
});

add_action('plugins_loaded', function () {
    Includes\Migration\MigrationRegistry::getInstance();
    Includes\Migration\MigrationNotice::getInstance();
}, 10);

add_action('griffinforms_register_post_submission_handlers', function ($pipeline) {
    if (!$pipeline instanceof Includes\Pipelines\PostSubmissionPipeline) {
        return;
    }

    $pipeline->registerHandler(new Includes\Pipelines\Handlers\MailQueueHandler());
    $pipeline->registerHandler(new Includes\Pipelines\Handlers\NotificationDispatchHandler());
    $pipeline->registerHandler(new Includes\Pipelines\Handlers\AccountRegistrationHandler());

    if (class_exists('GriffinForms\\Includes\\Integrations\\Mailchimp\\Main')) {
        $pipeline->registerHandler(new Includes\Pipelines\Handlers\MailchimpSyncHandler());
    }
});
