PopulatorData
2 months ago
AccessControl.php
2 years ago
Activator.php
2 months ago
AssetsLoader.php
2 weeks ago
Capabilities.php
2 months ago
Changelog.php
2 months ago
DeactivationPoll.php
3 years ago
DeferredAdminNotices.php
2 months ago
Env.php
6 months ago
Hooks.php
1 month ago
HooksWooCommerce.php
1 month ago
Initializer.php
1 month ago
Installer.php
10 months ago
Localizer.php
3 years ago
Menu.php
1 month ago
PersonalDataErasers.php
1 month ago
PersonalDataExporters.php
1 month ago
PluginActivatedHook.php
3 years ago
Populator.php
2 weeks ago
PrivacyPolicy.php
1 month ago
Renderer.php
1 year ago
RendererFactory.php
3 years ago
RequirementsChecker.php
2 months ago
Router.php
2 months ago
ServicesChecker.php
3 years ago
Shortcodes.php
1 month ago
SilentUpgraderSkin.php
3 years ago
SubscriberChangesNotifier.php
2 months ago
TranslationUpdater.php
3 months ago
TwigEnvironment.php
1 year ago
TwigFileSystemCache.php
3 years ago
Updater.php
4 days ago
index.php
3 years ago
Activator.php
211 lines
| 1 | <?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing |
| 2 | |
| 3 | namespace MailPoet\Config; |
| 4 | |
| 5 | if (!defined('ABSPATH')) exit; |
| 6 | |
| 7 | |
| 8 | use MailPoet\Cron\ActionScheduler\Actions\DaemonTrigger; |
| 9 | use MailPoet\Cron\ActionScheduler\ActionScheduler as CronActionScheduler; |
| 10 | use MailPoet\Cron\CronTrigger; |
| 11 | use MailPoet\Cron\DaemonActionSchedulerRunner; |
| 12 | use MailPoet\InvalidStateException; |
| 13 | use MailPoet\Migrator\Migrator; |
| 14 | use MailPoet\Settings\SettingsController; |
| 15 | use MailPoet\Util\Notices\DisabledMailFunctionNotice; |
| 16 | use MailPoet\WP\Functions as WPFunctions; |
| 17 | use MailPoetVendor\Doctrine\DBAL\Connection; |
| 18 | |
| 19 | class Activator { |
| 20 | public const TRANSIENT_ACTIVATE_KEY = 'mailpoet_activator_activate'; |
| 21 | private const TRANSIENT_EXPIRATION = 120; // seconds |
| 22 | |
| 23 | /** @var Connection */ |
| 24 | private $connection; |
| 25 | |
| 26 | /** @var SettingsController */ |
| 27 | private $settings; |
| 28 | |
| 29 | /** @var Populator */ |
| 30 | private $populator; |
| 31 | |
| 32 | /** @var WPFunctions */ |
| 33 | private $wp; |
| 34 | |
| 35 | /** @var Migrator */ |
| 36 | private $migrator; |
| 37 | |
| 38 | /** @var CronActionScheduler */ |
| 39 | private $cronActionSchedulerRunner; |
| 40 | |
| 41 | /** @var DaemonActionSchedulerRunner */ |
| 42 | private $daemonActionSchedulerRunner; |
| 43 | |
| 44 | public function __construct( |
| 45 | Connection $connection, |
| 46 | SettingsController $settings, |
| 47 | Populator $populator, |
| 48 | WPFunctions $wp, |
| 49 | Migrator $migrator, |
| 50 | CronActionScheduler $cronActionSchedulerRunner, |
| 51 | DaemonActionSchedulerRunner $daemonActionSchedulerRunner |
| 52 | ) { |
| 53 | $this->connection = $connection; |
| 54 | $this->settings = $settings; |
| 55 | $this->populator = $populator; |
| 56 | $this->wp = $wp; |
| 57 | $this->migrator = $migrator; |
| 58 | $this->cronActionSchedulerRunner = $cronActionSchedulerRunner; |
| 59 | $this->daemonActionSchedulerRunner = $daemonActionSchedulerRunner; |
| 60 | } |
| 61 | |
| 62 | public function activate() { |
| 63 | $isRunning = $this->wp->getTransient(self::TRANSIENT_ACTIVATE_KEY); |
| 64 | if ($isRunning === false) { |
| 65 | $this->lockActivation(); |
| 66 | try { |
| 67 | $this->processActivate(); |
| 68 | } finally { |
| 69 | $this->unlockActivation(); |
| 70 | } |
| 71 | } else { |
| 72 | throw new InvalidStateException(__('MailPoet version update is in progress, please refresh the page in a minute.', 'mailpoet')); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | private function lockActivation(): void { |
| 77 | $this->wp->setTransient(self::TRANSIENT_ACTIVATE_KEY, '1', self::TRANSIENT_EXPIRATION); |
| 78 | } |
| 79 | |
| 80 | private function unlockActivation(): void { |
| 81 | $this->wp->deleteTransient(self::TRANSIENT_ACTIVATE_KEY); |
| 82 | } |
| 83 | |
| 84 | private function processActivate(): void { |
| 85 | $this->migrator->run(); |
| 86 | $this->refreshCronActions(); |
| 87 | $this->populator->up(); |
| 88 | $this->updateDbVersion(); |
| 89 | |
| 90 | $caps = new Capabilities(); |
| 91 | $caps->setupWPCapabilities(); |
| 92 | |
| 93 | $localizer = new Localizer(); |
| 94 | $localizer->forceInstallLanguagePacks($this->wp); |
| 95 | |
| 96 | $this->checkForDisabledMailFunction(); |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * Public because it can be deferred until Action Scheduler is initialized. |
| 101 | */ |
| 102 | public function refreshCronActions(): void { |
| 103 | $currentMethod = $this->settings->get(CronTrigger::SETTING_NAME . '.method'); |
| 104 | if ($currentMethod !== CronTrigger::METHOD_ACTION_SCHEDULER) { |
| 105 | $this->daemonActionSchedulerRunner->clearDeactivationFlag(); |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | if (!$this->cronActionSchedulerRunner->isInitialized()) { |
| 110 | $this->cronActionSchedulerRunner->runAfterInitialized([$this, 'refreshCronActions']); |
| 111 | return; |
| 112 | } |
| 113 | |
| 114 | $this->deactivateCronActions(); |
| 115 | $this->reactivateCronActions(); |
| 116 | } |
| 117 | |
| 118 | public function deactivate() { |
| 119 | $this->lockActivation(); |
| 120 | $this->deleteAllMailPoetTablesAndData(); |
| 121 | |
| 122 | $caps = new Capabilities(); |
| 123 | $caps->removeWPCapabilities(); |
| 124 | $this->unlockActivation(); |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Deactivate action scheduler cron actions when the migration run. |
| 129 | * This should prevent processing actions during migrations. |
| 130 | * They are later re-activated in CronTrigger |
| 131 | * |
| 132 | * @return void |
| 133 | */ |
| 134 | private function deactivateCronActions(): void { |
| 135 | $currentMethod = $this->settings->get(CronTrigger::SETTING_NAME . '.method'); |
| 136 | if ($currentMethod !== CronTrigger::METHOD_ACTION_SCHEDULER) { |
| 137 | return; |
| 138 | } |
| 139 | $this->cronActionSchedulerRunner->unscheduleAllCronActions(); |
| 140 | } |
| 141 | |
| 142 | private function reactivateCronActions(): void { |
| 143 | $this->daemonActionSchedulerRunner->clearDeactivationFlag(); |
| 144 | $currentMethod = $this->settings->get(CronTrigger::SETTING_NAME . '.method'); |
| 145 | if ($currentMethod !== CronTrigger::METHOD_ACTION_SCHEDULER) { |
| 146 | return; |
| 147 | } |
| 148 | if (!$this->cronActionSchedulerRunner->hasScheduledAction(DaemonTrigger::NAME)) { |
| 149 | $this->cronActionSchedulerRunner->scheduleRecurringAction( |
| 150 | $this->wp->currentTime('timestamp', true), |
| 151 | DaemonTrigger::TRIGGER_RUN_INTERVAL, |
| 152 | DaemonTrigger::NAME |
| 153 | ); |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | public function updateDbVersion() { |
| 158 | try { |
| 159 | $currentDbVersion = $this->settings->get('db_version'); |
| 160 | } catch (\Exception $e) { |
| 161 | $currentDbVersion = null; |
| 162 | } |
| 163 | |
| 164 | $this->settings->set('db_version', Env::$version); |
| 165 | |
| 166 | // if current db version and plugin version differ, log an update |
| 167 | if (version_compare((string)$currentDbVersion, Env::$version) !== 0) { |
| 168 | $updatesLog = (array)$this->settings->get('updates_log', []); |
| 169 | $updatesLog[] = [ |
| 170 | 'previous_version' => $currentDbVersion, |
| 171 | 'new_version' => Env::$version, |
| 172 | 'date' => date('Y-m-d H:i:s'), |
| 173 | ]; |
| 174 | $this->settings->set('updates_log', $updatesLog); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | private function checkForDisabledMailFunction() { |
| 179 | $version = $this->settings->get('version'); |
| 180 | |
| 181 | if (!is_null($version)) return; // not a new user |
| 182 | |
| 183 | // check for valid mail function on new installs |
| 184 | $this->settings->set(DisabledMailFunctionNotice::QUEUE_DISABLED_MAIL_FUNCTION_CHECK, true); |
| 185 | } |
| 186 | |
| 187 | private function deleteAllMailPoetTablesAndData(): void { |
| 188 | $prefix = Env::$dbPrefix; |
| 189 | if (!$prefix) { |
| 190 | throw InvalidStateException::create()->withMessage('No database table prefix was set.'); |
| 191 | } |
| 192 | |
| 193 | // list all MailPoet tables by prefix |
| 194 | $prefixSql = $this->wp->escSql($prefix); |
| 195 | $tables = $this->connection->executeQuery("SHOW TABLES LIKE '$prefixSql%'")->fetchFirstColumn(); |
| 196 | |
| 197 | // drop all MailPoet tables in a single query |
| 198 | $tablesSql = implode( |
| 199 | ',', |
| 200 | array_map(function ($table): string { |
| 201 | /** @var string $table */ |
| 202 | return $this->wp->escSql(strval($table)); |
| 203 | }, $tables) |
| 204 | ); |
| 205 | |
| 206 | $this->connection->executeStatement('SET foreign_key_checks = 0'); |
| 207 | $this->connection->executeStatement("DROP TABLE IF EXISTS $tablesSql"); |
| 208 | $this->connection->executeStatement('SET foreign_key_checks = 1'); |
| 209 | } |
| 210 | } |
| 211 |