Нет описания

WordPress.php 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <?php
  2. namespace MailPoet\Cron\Triggers;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\Cron\CronHelper;
  5. use MailPoet\Cron\Workers\AuthorizedSendingEmailsCheck;
  6. use MailPoet\Cron\Workers\Beamer as BeamerWorker;
  7. use MailPoet\Cron\Workers\Bounce as BounceWorker;
  8. use MailPoet\Cron\Workers\InactiveSubscribers;
  9. use MailPoet\Cron\Workers\KeyCheck\PremiumKeyCheck as PremiumKeyCheckWorker;
  10. use MailPoet\Cron\Workers\KeyCheck\SendingServiceKeyCheck as SendingServiceKeyCheckWorker;
  11. use MailPoet\Cron\Workers\Scheduler as SchedulerWorker;
  12. use MailPoet\Cron\Workers\SendingQueue\Migration as MigrationWorker;
  13. use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
  14. use MailPoet\Cron\Workers\StatsNotifications\AutomatedEmails;
  15. use MailPoet\Cron\Workers\StatsNotifications\Worker as StatsNotificationsWorker;
  16. use MailPoet\Cron\Workers\SubscriberLinkTokens;
  17. use MailPoet\Cron\Workers\SubscribersCountCacheRecalculation;
  18. use MailPoet\Cron\Workers\SubscribersEngagementScore;
  19. use MailPoet\Cron\Workers\SubscribersLastEngagement;
  20. use MailPoet\Cron\Workers\UnsubscribeTokens;
  21. use MailPoet\Cron\Workers\WooCommercePastOrders;
  22. use MailPoet\Cron\Workers\WooCommerceSync as WooCommerceSyncWorker;
  23. use MailPoet\Mailer\MailerLog;
  24. use MailPoet\Models\ScheduledTask;
  25. use MailPoet\Services\Bridge;
  26. use MailPoet\Settings\SettingsController;
  27. use MailPoet\WP\Functions as WPFunctions;
  28. class WordPress {
  29. const SCHEDULED_IN_THE_PAST = 'past';
  30. const SCHEDULED_IN_THE_FUTURE = 'future';
  31. const RUN_INTERVAL = -1; // seconds
  32. const LAST_RUN_AT_SETTING = 'cron_trigger_wordpress.last_run_at';
  33. private $tasksCounts;
  34. /** @var CronHelper */
  35. private $cronHelper;
  36. /** @var MailPoet */
  37. private $mailpoetTrigger;
  38. /** @var SettingsController */
  39. private $settings;
  40. /** @var WPFunctions */
  41. private $wp;
  42. public function __construct(
  43. CronHelper $cronHelper,
  44. MailPoet $mailpoetTrigger,
  45. SettingsController $settings,
  46. WPFunctions $wp
  47. ) {
  48. $this->mailpoetTrigger = $mailpoetTrigger;
  49. $this->settings = $settings;
  50. $this->wp = $wp;
  51. $this->cronHelper = $cronHelper;
  52. }
  53. public function run() {
  54. if (!$this->checkRunInterval()) {
  55. return false;
  56. }
  57. return ($this->checkExecutionRequirements()) ?
  58. $this->mailpoetTrigger->run() :
  59. self::stop();
  60. }
  61. private function checkRunInterval() {
  62. $lastRunAt = (int)$this->settings->get(self::LAST_RUN_AT_SETTING, 0);
  63. $runInterval = $this->wp->applyFilters('mailpoet_cron_trigger_wordpress_run_interval', self::RUN_INTERVAL);
  64. $runIntervalElapsed = (time() - $lastRunAt) >= $runInterval;
  65. if ($runIntervalElapsed) {
  66. $this->settings->set(self::LAST_RUN_AT_SETTING, time());
  67. return true;
  68. }
  69. return false;
  70. }
  71. public static function resetRunInterval() {
  72. $settings = SettingsController::getInstance();
  73. $settings->set(self::LAST_RUN_AT_SETTING, 0);
  74. }
  75. public function checkExecutionRequirements() {
  76. $this->loadTasksCounts();
  77. // migration
  78. $migrationDisabled = $this->settings->get('cron_trigger.method') === 'none';
  79. $migrationDueTasks = $this->getTasksCount([
  80. 'type' => MigrationWorker::TASK_TYPE,
  81. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  82. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  83. ]);
  84. $migrationCompletedTasks = $this->getTasksCount([
  85. 'type' => MigrationWorker::TASK_TYPE,
  86. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST, self::SCHEDULED_IN_THE_FUTURE],
  87. 'status' => [ScheduledTask::STATUS_COMPLETED],
  88. ]);
  89. $migrationFutureTasks = $this->getTasksCount([
  90. 'type' => MigrationWorker::TASK_TYPE,
  91. 'scheduled_in' => [self::SCHEDULED_IN_THE_FUTURE],
  92. 'status' => [ScheduledTask::STATUS_SCHEDULED],
  93. ]);
  94. // sending queue
  95. $scheduledQueues = SchedulerWorker::getScheduledQueues();
  96. $runningQueues = SendingQueueWorker::getRunningQueues();
  97. $sendingLimitReached = MailerLog::isSendingLimitReached();
  98. $sendingIsPaused = MailerLog::isSendingPaused();
  99. // sending service
  100. $mpSendingEnabled = Bridge::isMPSendingServiceEnabled();
  101. // bounce sync
  102. $bounceDueTasks = $this->getTasksCount([
  103. 'type' => BounceWorker::TASK_TYPE,
  104. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  105. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  106. ]);
  107. $bounceFutureTasks = $this->getTasksCount([
  108. 'type' => BounceWorker::TASK_TYPE,
  109. 'scheduled_in' => [self::SCHEDULED_IN_THE_FUTURE],
  110. 'status' => [ScheduledTask::STATUS_SCHEDULED],
  111. ]);
  112. // sending service key check
  113. $msskeycheckDueTasks = $this->getTasksCount([
  114. 'type' => SendingServiceKeyCheckWorker::TASK_TYPE,
  115. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  116. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  117. ]);
  118. $msskeycheckFutureTasks = $this->getTasksCount([
  119. 'type' => SendingServiceKeyCheckWorker::TASK_TYPE,
  120. 'scheduled_in' => [self::SCHEDULED_IN_THE_FUTURE],
  121. 'status' => [ScheduledTask::STATUS_SCHEDULED],
  122. ]);
  123. // premium key check
  124. $premiumKeySpecified = Bridge::isPremiumKeySpecified();
  125. $premiumKeycheckDueTasks = $this->getTasksCount([
  126. 'type' => PremiumKeyCheckWorker::TASK_TYPE,
  127. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  128. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  129. ]);
  130. $premiumKeycheckFutureTasks = $this->getTasksCount([
  131. 'type' => PremiumKeyCheckWorker::TASK_TYPE,
  132. 'scheduled_in' => [self::SCHEDULED_IN_THE_FUTURE],
  133. 'status' => [ScheduledTask::STATUS_SCHEDULED],
  134. ]);
  135. // stats notifications
  136. $statsNotificationsTasks = $this->getTasksCount([
  137. 'type' => StatsNotificationsWorker::TASK_TYPE,
  138. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  139. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  140. ]);
  141. // stats notifications for auto emails
  142. $autoStatsNotificationsTasks = $this->getTasksCount([
  143. 'type' => AutomatedEmails::TASK_TYPE,
  144. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  145. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  146. ]);
  147. // inactive subscribers check
  148. $inactiveSubscribersTasks = $this->getTasksCount([
  149. 'type' => InactiveSubscribers::TASK_TYPE,
  150. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  151. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  152. ]);
  153. // unsubscribe tokens check
  154. $unsubscribeTokensTasks = $this->getTasksCount([
  155. 'type' => UnsubscribeTokens::TASK_TYPE,
  156. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  157. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  158. ]);
  159. // subscriber link tokens check
  160. $subscriberLinkTokensTasks = $this->getTasksCount([
  161. 'type' => SubscriberLinkTokens::TASK_TYPE,
  162. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  163. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  164. ]);
  165. // WooCommerce sync
  166. $wooCommerceSyncTasks = $this->getTasksCount([
  167. 'type' => WooCommerceSyncWorker::TASK_TYPE,
  168. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  169. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  170. ]);
  171. // Beamer
  172. $beamerDueChecks = $this->getTasksCount([
  173. 'type' => BeamerWorker::TASK_TYPE,
  174. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  175. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  176. ]);
  177. $beamerFutureChecks = $this->getTasksCount([
  178. 'type' => BeamerWorker::TASK_TYPE,
  179. 'scheduled_in' => [self::SCHEDULED_IN_THE_FUTURE],
  180. 'status' => [ScheduledTask::STATUS_SCHEDULED],
  181. ]);
  182. // Authorized email addresses check
  183. $authorizedEmailAddressesTasks = $this->getTasksCount([
  184. 'type' => AuthorizedSendingEmailsCheck::TASK_TYPE,
  185. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  186. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  187. ]);
  188. // WooCommerce past orders revenues sync
  189. $wooCommercePastOrdersTasks = $this->getTasksCount([
  190. 'type' => WooCommercePastOrders::TASK_TYPE,
  191. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  192. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  193. ]);
  194. // subscriber engagement score
  195. $subscriberEngagementScoreTasks = $this->getTasksCount([
  196. 'type' => SubscribersEngagementScore::TASK_TYPE,
  197. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  198. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  199. ]);
  200. // subscriber counts cache recalculation
  201. $subscribersCountCacheRecalculationTasks = $this->getTasksCount([
  202. 'type' => SubscribersCountCacheRecalculation::TASK_TYPE,
  203. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  204. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  205. ]);
  206. // subscriber last engagement
  207. $subscribersLastEngagementTasks = $this->getTasksCount([
  208. 'type' => SubscribersLastEngagement::TASK_TYPE,
  209. 'scheduled_in' => [self::SCHEDULED_IN_THE_PAST],
  210. 'status' => ['null', ScheduledTask::STATUS_SCHEDULED],
  211. ]);
  212. // check requirements for each worker
  213. $sendingQueueActive = (($scheduledQueues || $runningQueues) && !$sendingLimitReached && !$sendingIsPaused);
  214. $bounceSyncActive = ($mpSendingEnabled && ($bounceDueTasks || !$bounceFutureTasks));
  215. $sendingServiceKeyCheckActive = ($mpSendingEnabled && ($msskeycheckDueTasks || !$msskeycheckFutureTasks));
  216. $premiumKeyCheckActive = ($premiumKeySpecified && ($premiumKeycheckDueTasks || !$premiumKeycheckFutureTasks));
  217. $migrationActive = !$migrationDisabled && ($migrationDueTasks || (!$migrationCompletedTasks && !$migrationFutureTasks));
  218. $beamerActive = $beamerDueChecks || !$beamerFutureChecks;
  219. return (
  220. $migrationActive
  221. || $sendingQueueActive
  222. || $bounceSyncActive
  223. || $sendingServiceKeyCheckActive
  224. || $premiumKeyCheckActive
  225. || $statsNotificationsTasks
  226. || $autoStatsNotificationsTasks
  227. || $inactiveSubscribersTasks
  228. || $wooCommerceSyncTasks
  229. || $authorizedEmailAddressesTasks
  230. || $beamerActive
  231. || $wooCommercePastOrdersTasks
  232. || $unsubscribeTokensTasks
  233. || $subscriberLinkTokensTasks
  234. || $subscriberEngagementScoreTasks
  235. || $subscribersCountCacheRecalculationTasks
  236. || $subscribersLastEngagementTasks
  237. );
  238. }
  239. public function stop() {
  240. $cronDaemon = $this->cronHelper->getDaemon();
  241. if ($cronDaemon) {
  242. $this->cronHelper->deactivateDaemon($cronDaemon);
  243. }
  244. }
  245. private function loadTasksCounts() {
  246. $query = sprintf(
  247. "select
  248. type,
  249. status,
  250. count(*) as count,
  251. case when scheduled_at <= '%s' then '%s' else '%s' end as scheduled_in
  252. from %s
  253. where deleted_at is null
  254. group by type, status, scheduled_in
  255. ",
  256. date('Y-m-d H:i:s', $this->wp->currentTime('timestamp')),
  257. self::SCHEDULED_IN_THE_PAST,
  258. self::SCHEDULED_IN_THE_FUTURE,
  259. ScheduledTask::$_table
  260. );
  261. $rows = ScheduledTask::rawQuery($query)->findMany();
  262. $this->tasksCounts = [];
  263. foreach ($rows as $r) {
  264. if (empty($this->tasksCounts[$r->type])) {
  265. $this->tasksCounts[$r->type] = [];
  266. }
  267. if (empty($this->tasksCounts[$r->type][$r->scheduledIn])) {
  268. $this->tasksCounts[$r->type][$r->scheduledIn] = [];
  269. }
  270. $this->tasksCounts[$r->type][$r->scheduledIn][$r->status ?: 'null'] = $r->count;
  271. }
  272. }
  273. private function getTasksCount(array $options) {
  274. $count = 0;
  275. $type = $options['type'];
  276. foreach ($options['scheduled_in'] as $scheduledIn) {
  277. foreach ($options['status'] as $status) {
  278. if (! empty($this->tasksCounts[$type][$scheduledIn][$status])) {
  279. $count += $this->tasksCounts[$type][$scheduledIn][$status];
  280. }
  281. }
  282. }
  283. return $count;
  284. }
  285. }