예제 #1
0
파일: cron.php 프로젝트: hungnv0789/vhtm
 /**
  * _ProcessJob
  * This method does the "setup work" for a split test campaign.
  *
  * If a job is passed in that hasn't been started before, it will set everything up:
  * - create a "queue" of recipients
  * - clean the queue (remove banned/duplicate recipients etc)
  * - set up stats for each newsletter in the split test campaign
  * - save stats for the user sending the campaign to take off credits etc
  *
  * If a job is passed in that has been set up before, it just loads the data up.
  *
  * Once it has done either of those, it gives the details to the Splittest_Send_API class
  * and then calls _ActionJob.
  * Based on what that returns, it will either mark the job as complete or not.
  *
  * If the job is a percentage split test send (send to first X % of a list/segment), then
  * it sets the appropriate flags etc to make sure we only send to that first X%.
  * If the job hasn't been set up before, it works out the limit and sets the details in the jobdetails
  * which are then saved in the database in case the job dies or is paused etc.
  *
  * If the job is a percentage split test send and it's time to send to the rest of the list/segment,
  * then it works out the "best" one to send and sets the appropriate variables for that to happen.
  *
  * @param Int $jobid The specific job id we're going to process.
  *
  * @uses _jobid
  * @uses StartJob
  * @uses PauseJob
  * @uses LoadJob
  * @uses GetUser
  * @uses GetJobQueue
  * @uses CreateQueue
  * @uses JobQueue
  * @uses GetSubscribersFromSegment
  * @uses GetSubscribers
  * @uses RemoveDuplicatesInQueue
  * @uses RemoveBannedEmails
  * @uses RemoveUnsubscribedEmails
  * @uses QueueSize
  * @uses _CalculateBestNewsletter
  * @uses _FinishJob
  * @uses _ActionJob
  * @uses _CalculateBestNewsletter
  *
  * @return Boolean Returns whether the job was processed or not. If a job could not be processed, it returns false. Otherwise it returns true.
  */
 private function _ProcessJob($jobid = 0)
 {
     if ($jobid <= 0) {
         return false;
     }
     $this->_jobid = $jobid;
     /**
      * Load the job, then start it.
      * We need to do this so when we call "StartJob" we can give it the splitid to "start" as well.
      */
     $jobinfo = $this->LoadJob($jobid);
     $jobdetails = $jobinfo['jobdetails'];
     /**
      * Need to load the split campaign
      * before starting the job
      * so if we're in "t"imeout mode,
      * we can look at the stats
      * We also need the weighting's from the split campaign
      * to work it out.
      */
     $this->splitcampaign_details = $this->_splittest_api->Load($jobdetails['splitid']);
     /**
      * If it's a "t"imeout, work out the best stat.
      */
     if ($jobinfo['jobstatus'] == 't') {
         $jobdetails['newsletters'] = $this->_CalculateBestNewsletter($jobdetails['Stats']);
         /**
          * Also need to kill off the "percentage_send_maximum" element
          * as this would cause the job to go into "timeout" mode again.
          */
         unset($jobdetails['percentage_send_maximum']);
     }
     if (!$this->StartJob($jobid, $jobdetails['splitid'])) {
         $this->PauseJob($jobid);
         return false;
     }
     // ----- "Login" to the system as the job's owner.
     $user = GetUser($jobinfo['ownerid']);
     IEM::userLogin($jobinfo['ownerid'], false);
     // -----
     $queueid = false;
     // if there's no queue, start one up.
     if (!($queueid = $this->GetJobQueue($jobid))) {
         /**
          * Randomize the newsletters
          * It's probably already been done but can't hurt to do it again.
          */
         shuffle($jobdetails['newsletters']);
         $sendqueue = $this->CreateQueue('splittest');
         $queueok = $this->JobQueue($jobid, $sendqueue);
         $send_criteria = $jobdetails['SendCriteria'];
         $queueinfo = array('queueid' => $sendqueue, 'queuetype' => 'splittest', 'ownerid' => $jobinfo['ownerid']);
         if (isset($jobdetails['Segments']) && is_array($jobdetails['Segments'])) {
             $this->_subscribers_api->GetSubscribersFromSegment($jobdetails['Segments'], false, $queueinfo, 'nosort');
         } else {
             $this->_subscribers_api->GetSubscribers($send_criteria, array(), false, $queueinfo, $sendqueue);
         }
         if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
             $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
         }
         $this->_subscribers_api->RemoveDuplicatesInQueue($sendqueue, 'splittest', $jobdetails['Lists']);
         $this->_subscribers_api->RemoveBannedEmails($jobdetails['Lists'], $sendqueue, 'splittest');
         $this->_subscribers_api->RemoveUnsubscribedEmails($jobdetails['Lists'], $sendqueue, 'splittest');
         if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
             $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
         }
         $jobdetails['SendSize'] = $this->_subscribers_api->QueueSize($sendqueue, 'splittest');
         $jobdetails['Stats'] = array();
         $jobdetails['SendQueue'] = $sendqueue;
         /**
          * Delete the old user stats allocations.
          * They were all allocated under one stat/job before so the user recorded their send info
          * so they couldn't set up split test sends and go over their send quota.
          *
          * Now, we need to re-allocate them per newsletter being sent.
          */
         $this->_stats_api->DeleteUserStats($jobinfo['ownerid'], $this->_jobid);
         $statids = array();
         foreach ($jobdetails['newsletters'] as $newsletterid) {
             $newsletterstats = $jobdetails;
             $newsletterstats['Job'] = $jobid;
             $newsletterstats['Queue'] = $sendqueue;
             $newsletterstats['SentBy'] = $queueinfo['ownerid'];
             $newsletterstats['SendType'] = 'splittest';
             $newsletterstats['Newsletter'] = $newsletterid;
             $newsletterstats['Lists'] = $jobdetails['sendingto']['Lists'];
             $newsletterstats['SendCriteria'] = $jobdetails['SendCriteria'];
             $statid = $this->_stats_api->SaveNewsletterStats($newsletterstats);
             $statids[] = $statid;
             $jobdetails['Stats'][$newsletterid] = $statid;
             $this->_stats_api->RecordUserStats($jobinfo['ownerid'], $this->_jobid, $jobdetails['SendSize'], $jobdetails['SendStartTime'], $statid);
         }
         $this->SaveSplitStats($jobdetails['splitid'], $this->_jobid, $statids);
         /**
          * If it's a percentage send,
          * work out the number of emails to send for the first percentage
          * It gets stored in the jobdetails array so it can be saved in the database.
          */
         if ($this->splitcampaign_details['splittype'] == 'percentage') {
             $max_to_email = ceil($this->splitcampaign_details['splitdetails']['percentage'] / 100 * $jobdetails['SendSize']);
             $jobdetails['percentage_send_maximum'] = $max_to_email;
         }
         /**
          * Save the job stat details.
          * Otherwise we could potentially end up with a 'start'ed queue but no stats.
          */
         $this->Set('jobdetails', $jobdetails);
         $this->UpdateJobDetails();
         /**
          * This is to process the 'queueid' later in the code.
          */
         $queueid = $sendqueue;
         // This will make sure that the credit warning emails are also being send out from splittest
         API_USERS::creditEvaluateWarnings($user->GetNewAPI());
     }
     $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
     $queuesize = $this->_subscribers_api->QueueSize($queueid, 'splittest');
     $this->_queueid = $queueid;
     /**
      * If there is a "percentage_send_maximum" variable in the jobdetails array,
      * we are sending to the first part of a 'percentage' split test.
      *
      * We have to send to the rest of the percentage maximum before we pause the job,
      * work out the "best" performing campaign and send to that.
      */
     if (isset($jobdetails['percentage_send_maximum'])) {
         $this->_percentage_send_maximum = (int) $jobdetails['percentage_send_maximum'];
     }
     /**
      * If the _percentage_send_maximum is 0, then "timeout" the job.
      * We must have hit "pause" right at the end of the initial send process or something.
      */
     if ($this->_percentage_send_maximum !== null && $this->_percentage_send_maximum <= 0) {
         $this->TimeoutJob($jobid, $this->splitcampaign_details['splitid'], $this->splitcampaign_details['splitdetails']['hoursafter']);
         IEM::userLogout();
         return true;
     }
     $this->Set('statids', $jobdetails['Stats']);
     $this->Set('jobdetails', $jobdetails);
     $this->Set('jobowner', $jobinfo['ownerid']);
     /**
      * There's nothing left? Just mark it as done.
      */
     if ($queuesize == 0) {
         $this->_FinishJob();
         IEM::userLogout();
         return true;
     }
     $finished = $this->_ActionJob($jobid, $queueid);
     if ($finished) {
         $this->_FinishJob();
     }
     IEM::userLogout();
     return true;
 }
예제 #2
0
 /**
  * DeleteSchedules
  * If scheduled items are going to be deleted, this processes the jobs it needs to.
  *
  * The data passed in contains lots of data:
  * jobids - the job id's that need to be processed
  * message - the current success/failure message
  * success - the current success counter (how many jobs have successfully been deleted previous to getting here)
  * failure - the current failure counter (how many jobs have not successfully been deleted previous to getting here)
  *
  * Any non-"splittest" job types are skipped
  * Any "in progress" splittest jobs are skipped and the failure counter is incremented
  * Any jobs that can be deleted are - as well as figuring out whether a job needs to give back any email credits.
  *
  * Any appropriate messages are added to the "message" item in the passed in array.
  *
  * @param EventData_IEM_SCHEDULE_DELETEJOBS $data The data array containing the jobs to process, the current message, success and failure counts.
  *
  * @uses Jobs_API::LoadJob()
  * @uses Stats_API::DeleteUserStats()
  * @uses Stats_API::MarkNewsletterFinished()
  * @uses Splittest_Send_API::DeleteJob()
  * @uses User_API::ReduceEmails()
  * @uses EventData_IEM_SCHEDULE_DELETEJOBS
  */
 public static function DeleteSchedules(EventData_IEM_SCHEDULE_DELETEJOBS $data)
 {
     $jobids =& $data->jobids;
     $message =& $data->Message;
     $success =& $data->success;
     $failure =& $data->failure;
     $user = GetUser();
     require_once SENDSTUDIO_API_DIRECTORY . '/jobs.php';
     require_once SENDSTUDIO_API_DIRECTORY . '/stats.php';
     require_once dirname(__FILE__) . '/api/splittest_send.php';
     $jobapi = new Jobs_API();
     $stats_api = new Stats_API();
     $send_api = new Splittest_Send_API();
     foreach ($jobids as $p => $jobid) {
         $jobinfo = $jobapi->LoadJob($jobid);
         if (empty($jobinfo)) {
             continue;
         }
         if ($jobinfo['jobtype'] !== 'splittest') {
             continue;
         }
         if ($jobinfo['jobstatus'] == 'i') {
             $failure++;
             unset($jobids[$p]);
             continue;
         }
         $statids = array();
         if (isset($jobinfo['jobdetails']['Stats'])) {
             $statids = array_values($jobinfo['jobdetails']['Stats']);
         }
         /**
          * If there are no stats, then the send hasn't started yet.
          * So just credit the user back with the number of emails they were trying to send.
          * Use 'ReduceEmails' to re-add the credits by using a double negative :)
          */
         if (empty($statids) && $jobinfo['jobstatus'] == 'w') {
             $stats_api->DeleteUserStats($jobinfo['ownerid'], $jobid);
             $user->ReduceEmails(-(int) $jobinfo['jobdetails']['SendSize']);
         }
         /**
          * If a send is started (ie it has stats),
          * but is not completed,
          * We need to mark it as complete.
          *
          * This also credits a user back if they have any limits in place.
          *
          * This needs to happen before we delete the 'job' from the database
          * as deleting the job cleans up the queues/unsent items.
          */
         if (!empty($statids) && $jobinfo['jobstatus'] != 'c') {
             $stats_api->MarkNewsletterFinished($statids, $jobinfo['jobdetails']['SendSize']);
             // Credits needs to be returned too whenever the job is canceled AFTER it has been scheduled, but before it was sent
         } elseif ($jobinfo['jobstatus'] != 'c') {
             $stats_api->RefundFixedCredit($jobid);
         }
         $result = $send_api->DeleteJob($jobid);
         if ($result) {
             $success++;
         } else {
             $failure++;
         }
         unset($jobids[$p]);
     }
     /**
      * Only failure messages get added to the message stack.
      * Successful deletes are handled in the calling code
      * in case:
      * - a non-addon deletes an item
      * - other addons delete their own items
      */
     if ($failure > 0) {
         if ($failure == 1) {
             FlashMessage(GetLang('Addon_splittest_Schedule_JobDeleteFail'), SS_FLASH_MSG_ERROR);
         } else {
             FlashMessage(sprintf(GetLang('Addon_splittest_Schedule_JobsDeleteFail'), self::PrintNumber($failure)), SS_FLASH_MSG_SUCCESS);
         }
     }
     $message .= GetFlashMessages();
 }