| @@ -11,14 +11,14 @@ | ||
| 11 | 11 | register_activation_hook($file, function () use ($app) { |
| 12 | 12 | ($app->make(ActivationHandler::class))->handle(); |
| 13 | 13 | |
| 14 | 14 | if (function_exists('\as_next_scheduled_action')) { |
| 15 | - if (!as_next_scheduled_action('fluent_community_scheduled_hour_jobs')) { | |
| 16 | - as_schedule_recurring_action(time(), 3600, 'fluent_community_scheduled_hour_jobs', [], 'fluent-community'); | |
| 15 | + if (!\as_next_scheduled_action('fluent_community_scheduled_hour_jobs')) { | |
| 16 | + \as_schedule_recurring_action(time(), 3600, 'fluent_community_scheduled_hour_jobs', [], 'fluent-community', true); | |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | - if (!as_next_scheduled_action('fluent_community_daily_jobs')) { | |
| 20 | - as_schedule_recurring_action(time(), 86400, 'fluent_community_daily_jobs', [], 'fluent-community'); | |
| 19 | + if (!\as_next_scheduled_action('fluent_community_daily_jobs')) { | |
| 20 | + \as_schedule_recurring_action(time(), 86400, 'fluent_community_daily_jobs', [], 'fluent-community', true); | |
| 21 | 21 | } |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | }); |
| @@ -35,29 +35,108 @@ | ||
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | add_action('plugins_loaded', function () use ($app) { |
| 38 | 38 | do_action('fluent_community/portal_loaded', $app); |
| 39 | + | |
| 40 | + add_action('init', function () use ($app) { | |
| 41 | + /* | |
| 42 | + * Transitional: repair a stale schema on ANY request, not only on the | |
| 43 | + * ones a privileged user makes. | |
| 44 | + * | |
| 45 | + * Both entry points below are gated on a capability, so on an | |
| 46 | + * upgrading site a newly added table does not exist until someone who | |
| 47 | + * can activate plugins loads wp-admin. Cron, REST and ordinary member | |
| 48 | + * requests all reach the plugin before that and read a table that is | |
| 49 | + * not there yet. Multisite is worse: activate_plugins maps to | |
| 50 | + * manage_network_plugins there, so only a super admin, visiting each | |
| 51 | + * subsite in turn, ever migrates it. | |
| 52 | + * | |
| 53 | + * Ahead of on_wp_init deliberately, so the request that performs the | |
| 54 | + * migration is also the first to benefit from it. | |
| 55 | + * | |
| 56 | + * Safe under the concurrency this exposes it to: dbDelta sits behind a | |
| 57 | + * table-exists check, and the preference backfill replays as a no-op | |
| 58 | + * (its INSERT is ON DUPLICATE KEY UPDATE with a self-assignment), so a | |
| 59 | + * burst of traffic straight after an update duplicates work rather | |
| 60 | + * than corrupting anything. | |
| 61 | + * | |
| 62 | + * Remove once 2.9.x is broadly adopted; the capability-gated entry | |
| 63 | + * points are enough on a site that is already current. | |
| 64 | + */ | |
| 65 | + fluent_community_maybe_migrate_db(); | |
| 66 | + | |
| 67 | + do_action('fluent_community/on_wp_init', $app); | |
| 68 | + }); | |
| 39 | 69 | }); |
| 40 | 70 | |
| 71 | + /* | |
| 72 | + * A stale schema is repaired from three places. The init hook above is the one | |
| 73 | + * that actually closes the gap, because it needs no privileged user; the two | |
| 74 | + * below predate it and are kept as belt and braces. Portal render catches | |
| 75 | + * sites where an admin browses the community; admin_init catches the | |
| 76 | + * plugin-update case, where the first request after the new code lands is a | |
| 77 | + * wp-admin page. A missing index only slows things down, but a missing table | |
| 78 | + * is fatal, so more than one entry point matters. | |
| 79 | + * | |
| 80 | + * The version option is autoloaded so the check below costs nothing on the | |
| 81 | + * requests where there is nothing to do - which, after the first one, is all | |
| 82 | + * of them. Note that update_option() returns early when the value is | |
| 83 | + * unchanged, so the autoload flag only flips on a site whose version string | |
| 84 | + * actually moves; one already stamped at the current version keeps the old | |
| 85 | + * flag until the next DB version bump. | |
| 86 | + */ | |
| 87 | + if (!function_exists('fluent_community_maybe_migrate_db')) { | |
| 88 | + function fluent_community_maybe_migrate_db() | |
| 89 | + { | |
| 90 | + $currentDBVersion = get_option('fluent_community_db_version'); | |
| 91 | + | |
| 92 | + if ($currentDBVersion && version_compare($currentDBVersion, FLUENT_COMMUNITY_DB_VERSION, '>=')) { | |
| 93 | + return; | |
| 94 | + } | |
| 95 | + | |
| 96 | + if (get_transient('fluent_community_db_migration_lock')) { | |
| 97 | + return; | |
| 98 | + } | |
| 99 | + | |
| 100 | + set_transient('fluent_community_db_migration_lock', 1, 5 * MINUTE_IN_SECONDS); | |
| 101 | + \FluentCommunity\Database\DBMigrator::run(); | |
| 102 | + update_option('fluent_community_db_version', FLUENT_COMMUNITY_DB_VERSION, true); | |
| 103 | + delete_transient('fluent_community_db_migration_lock'); | |
| 104 | + } | |
| 105 | + } | |
| 106 | + | |
| 107 | + add_action('admin_init', function () { | |
| 108 | + if (current_user_can('activate_plugins')) { | |
| 109 | + fluent_community_maybe_migrate_db(); | |
| 110 | + } | |
| 111 | + }); | |
| 112 | + | |
| 41 | 113 | add_action('fluent_community/portal_render_for_user', function () { |
| 42 | 114 | if (!\FluentCommunity\App\Services\Helper::isSiteAdmin()) { |
| 43 | 115 | return; |
| 44 | 116 | } |
| 45 | 117 | |
| 46 | - if (!as_next_scheduled_action('fluent_community_scheduled_hour_jobs')) { | |
| 118 | + if (!\as_next_scheduled_action('fluent_community_scheduled_hour_jobs')) { | |
| 47 | 119 | as_schedule_recurring_action(time(), 3600, 'fluent_community_scheduled_hour_jobs', [], 'fluent-community'); |
| 48 | 120 | } |
| 49 | 121 | |
| 50 | - if (!as_next_scheduled_action('fluent_community_daily_jobs')) { | |
| 51 | - as_schedule_recurring_action(time(), 86400, 'fluent_community_daily_jobs', [], 'fluent-community'); | |
| 122 | + if (!\as_next_scheduled_action('fluent_community_daily_jobs')) { | |
| 123 | + \as_schedule_recurring_action(time(), 86400, 'fluent_community_daily_jobs', [], 'fluent-community'); | |
| 52 | 124 | } |
| 53 | - | |
| 54 | 125 | /* |
| 55 | 126 | * We will remove this after final release |
| 56 | 127 | */ |
| 57 | - $currentDBVersion = get_option('fluent_community_db_version'); | |
| 58 | - if (!$currentDBVersion || version_compare($currentDBVersion, FLUENT_COMMUNITY_DB_VERSION, '<')) { | |
| 59 | - update_option('fluent_community_db_version', FLUENT_COMMUNITY_DB_VERSION, 'no'); | |
| 60 | - \FluentCommunity\Database\DBMigrator::run(); | |
| 128 | + fluent_community_maybe_migrate_db(); | |
| 129 | + | |
| 130 | + | |
| 131 | + if (defined('FLUENT_COMMUNITY_PRO_VERSION')) { | |
| 132 | + add_filter('fluent_community/portal_notices', function ($notices) { | |
| 133 | + if (FLUENT_COMMUNITY_MIN_PRO_VERSION !== FLUENT_COMMUNITY_PRO_VERSION && version_compare(FLUENT_COMMUNITY_MIN_PRO_VERSION, FLUENT_COMMUNITY_PRO_VERSION, '>')) { | |
| 134 | + $updateUrl = admin_url('plugins.php?s=fluent-community&plugin_status=all&fluent-fluent-community-pro-check-update=' . time()); | |
| 135 | + $notices[] = '<div style="padding: 10px; background-color: var(--fcom-primary-bg, white);" class="error"><b>' . esc_html__('Heads UP:', 'fluent-community') . ' </b> ' . esc_html__('FluentCommunityPro Plugin needs to be updated to the latest version.', 'fluent-community') . ' <a href="' . esc_url($updateUrl) . '">' . esc_html__('Click here to update', 'fluent-community') . '</a></div>'; | |
| 136 | + } | |
| 137 | + return $notices; | |
| 138 | + }); | |
| 61 | 139 | } |
| 140 | + | |
| 62 | 141 | }); |
| 63 | 142 | }; |