%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /var/www/pn/beta/64801_wp-content/plugins/mailpoet/lib/Cron/Workers/SendingQueue/
Upload File :
Create Path :
Current File : //var/www/pn/beta/64801_wp-content/plugins/mailpoet/lib/Cron/Workers/SendingQueue/Migration.php

<?php
namespace MailPoet\Cron\Workers\SendingQueue;

use Carbon\Carbon;
use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Workers\SimpleWorker;
use MailPoet\Mailer\MailerLog;
use MailPoet\Models\ScheduledTask;
use MailPoet\Models\ScheduledTaskSubscriber;
use MailPoet\Models\SendingQueue;
use MailPoet\WP\Functions as WPFunctions;

if(!defined('ABSPATH')) exit;

class Migration extends SimpleWorker {
  const TASK_TYPE = 'migration';
  const BATCH_SIZE = 20;

  function checkProcessingRequirements() {
    // if migration was completed, don't run it again
    $completed_tasks = self::getCompletedTasks();
    return empty($completed_tasks);
  }

  function prepareTask(ScheduledTask $task) {
    $unmigrated_columns = self::checkUnmigratedColumnsExist();
    if($unmigrated_columns) {
      $unmigrated_queues_count = $this->getUnmigratedQueues()->count();
      $unmigrated_queue_subscribers = $this->getTaskIdsForUnmigratedSubscribers();
    }

    if(!$unmigrated_columns ||
      ($unmigrated_queues_count == 0
      && count($unmigrated_queue_subscribers) == 0)
    ) {
      // nothing to migrate
      $this->complete($task);
      $this->resumeSending();
      return false;
    }

    // pause sending while the migration is in process
    $this->pauseSending();

    return parent::prepareTask($task);
  }

  function pauseSending() {
    $mailer_log = MailerLog::getMailerLog();
    if(MailerLog::isSendingPaused($mailer_log)) {
      // sending is already paused
      return false;
    }
    $mailer_log = MailerLog::setError(
      $mailer_log,
      'migration',
      __('Your sending queue data is being migrated to allow better performance, sending is paused while the migration is in progress and will resume automatically upon completion. This may take a few minutes.')
    );
    return MailerLog::pauseSending($mailer_log);
  }

  function resumeSending() {
    $mailer_log = MailerLog::getMailerLog();
    if(!MailerLog::isSendingPaused($mailer_log)) {
      // sending is not paused
      return false;
    }
    $error = MailerLog::getError($mailer_log);
    // only resume sending if it was paused by migration
    if(isset($error['operation']) && $error['operation'] === 'migration') {
      return MailerLog::resumeSending();
    }
  }

  function processTask(ScheduledTask $task) {
    $this->migrateSendingQueues();
    $this->migrateSubscribers();

    $this->complete($task);
    $this->resumeSending();

    return true;
  }

  static function checkUnmigratedColumnsExist() {
    global $wpdb;
    $existing_columns = $wpdb->get_col('DESC ' . SendingQueue::$_table);
    return in_array('type', $existing_columns);
  }

  function getUnmigratedQueues() {
    return SendingQueue::where('task_id', 0)
      ->whereNull('type');
  }

  function getTaskIdsForUnmigratedSubscribers() {
    global $wpdb;
    $query = sprintf(
      'SELECT queues.`task_id` FROM %1$s queues INNER JOIN %2$s tasks ON queues.`task_id` = tasks.`id` ' .
      'WHERE tasks.`type` = "sending" AND (tasks.`status` IS NULL OR tasks.`status` = "paused") ' .
      'AND queues.`subscribers` != "" AND queues.`subscribers` != "N;"' .
      'AND queues.`count_total` > (SELECT COUNT(*) FROM %3$s subs WHERE subs.`task_id` = queues.`task_id`)',
      MP_SENDING_QUEUES_TABLE,
      MP_SCHEDULED_TASKS_TABLE,
      MP_SCHEDULED_TASK_SUBSCRIBERS_TABLE
    );
    return $wpdb->get_col($query);
  }

  /*
   * Migrate all sending queues without converting subscriber data
   */
  function migrateSendingQueues() {
    global $wpdb;

    $queues = $this->getUnmigratedQueues()
      ->select('id')
      ->findArray();

    $column_list = array(
      'status',
      'priority',
      'scheduled_at',
      'processed_at',
      'created_at',
      'updated_at',
      'deleted_at'
    );

    if(!empty($queues)) {
      foreach(array_chunk($queues, self::BATCH_SIZE) as $queue_batch) {
        // abort if execution limit is reached
        CronHelper::enforceExecutionLimit($this->timer);

        foreach($queue_batch as $queue) {
          // create a new scheduled task of type "sending"
          $wpdb->query(sprintf(
            'INSERT IGNORE INTO %1$s (`type`, %2$s) ' .
            'SELECT "sending", %2$s FROM %3$s WHERE `id` = %4$s',
            MP_SCHEDULED_TASKS_TABLE,
            '`' . join('`, `', $column_list) . '`',
            MP_SENDING_QUEUES_TABLE,
            $queue['id']
          ));
          // link the queue with the task via task_id
          $new_task_id = $wpdb->insert_id;
          $wpdb->query(sprintf(
            'UPDATE %1$s SET `task_id` = %2$s WHERE `id` = %3$s',
            MP_SENDING_QUEUES_TABLE,
            $new_task_id,
            $queue['id']
          ));
        }
      }
    }

    return true;
  }

  /*
   * Migrate subscribers for in-progress sending tasks from the `subscribers` field to a separate table
   */
  function migrateSubscribers() {
    global $wpdb;

    // find in-progress queues that have serialized subscribers
    $task_ids = $this->getTaskIdsForUnmigratedSubscribers();

    // check if subscribers for each one were already migrated
    if(!empty($task_ids)) {
      $task_ids = $wpdb->get_col(sprintf(
        'SELECT queues.`task_id` FROM %1$s queues WHERE queues.`task_id` IN(' . join(',', array_map('intval', $task_ids)) . ') ' .
        'AND queues.`count_total` > (SELECT COUNT(*) FROM %2$s subs WHERE subs.`task_id` = queues.`task_id`)',
        MP_SENDING_QUEUES_TABLE,
        MP_SCHEDULED_TASK_SUBSCRIBERS_TABLE
      ));
    }

    if(!empty($task_ids)) {
      foreach($task_ids as $task_id) {
        // abort if execution limit is reached
        CronHelper::enforceExecutionLimit($this->timer);

        $this->migrateTaskSubscribers($task_id);
      }
    }

    return true;
  }

  function migrateTaskSubscribers($task_id) {
    global $wpdb;

    $migrated_unprocessed_count = ScheduledTaskSubscriber::getUnprocessedCount($task_id);
    $migrated_processed_count = ScheduledTaskSubscriber::getProcessedCount($task_id);

    $subscribers = $wpdb->get_var(sprintf(
      'SELECT `subscribers` FROM %1$s WHERE `task_id` = %2$d ' .
      'AND (`count_processed` > %3$d OR `count_to_process` > %4$d)',
      MP_SENDING_QUEUES_TABLE,
      $task_id,
      $migrated_unprocessed_count,
      $migrated_processed_count
    ));

    // sanity check
    if(empty($subscribers)) {
      return false;
    }

    $subscribers = unserialize($subscribers);

    if(!empty($subscribers['to_process'])) {
      $subscribers_to_migrate = array_slice($subscribers['to_process'], $migrated_unprocessed_count);
      foreach($subscribers_to_migrate as $sub_id) {
        // abort if execution limit is reached
        CronHelper::enforceExecutionLimit($this->timer);

        ScheduledTaskSubscriber::createOrUpdate(array(
          'task_id' => $task_id,
          'subscriber_id' => $sub_id,
          'processed' => ScheduledTaskSubscriber::STATUS_UNPROCESSED
        ));
      }
    }

    if(!empty($subscribers['processed'])) {
      $subscribers_to_migrate = array_slice($subscribers['processed'], $migrated_processed_count);
      foreach($subscribers_to_migrate as $sub_id) {
        // abort if execution limit is reached
        CronHelper::enforceExecutionLimit($this->timer);

        ScheduledTaskSubscriber::createOrUpdate(array(
          'task_id' => $task_id,
          'subscriber_id' => $sub_id,
          'processed' => ScheduledTaskSubscriber::STATUS_PROCESSED
        ));
      }
    }

    return true;
  }

  static function getNextRunDate() {
    // run migration immediately
    return Carbon::createFromTimestamp(WPFunctions::currentTime('timestamp'));
  }
}

Zerion Mini Shell 1.0