Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
state.php
1<?php
9
23
24Loc::loadMessages(__FILE__);
25
30class State
31{
32 const NEWISH = 'N';
33 const INIT = 'I';
34 const READY = 'R';
35 const SENDING = 'S';
36 const WAITING = 'W';
37 const PLANNED = 'T';
38 const PAUSED = 'P';
39 const SENT = 'Y';
40 const STOPPED = 'X';
41 const HALTED = 'H';
42
44 private $letter;
45
47 protected $dateTime;
48
54 public function __construct(Entity\Letter $letter)
55 {
56 $this->letter = $letter;
57 }
58
64 public function isReady()
65 {
66 return in_array($this->getCode(), array(self::NEWISH, self::INIT, self::READY));
67 }
68
74 public function isSent()
75 {
76 return in_array($this->getCode(), array(self::SENT));
77 }
78
84 public function isFinished()
85 {
86 return in_array($this->getCode(), Semantics::getFinishStates());
87 }
88
94 public function isStopped()
95 {
96 return in_array($this->getCode(), array(self::STOPPED));
97 }
98
104 public function isWaiting()
105 {
106 return in_array($this->getCode(), [self::WAITING]);
107 }
108
114 public function isHalted()
115 {
116 return in_array($this->getCode(), [self::HALTED]);
117 }
118
124 public function isSending()
125 {
126 return in_array($this->getCode(), [self::SENDING]);
127 }
128
134 public function isPlanned()
135 {
136 return in_array($this->getCode(), array(self::PLANNED));
137 }
138
144 public function isPaused()
145 {
146 return in_array($this->getCode(), [self::PAUSED]);
147 }
148
154 public function wasStartedSending()
155 {
156 return in_array(
157 $this->getCode(),
158 array(
159 self::SENDING,
160 self::WAITING,
161 self::PAUSED,
162 self::SENT,
163 self::STOPPED,
164 self::HALTED,
165 ));
166 }
167
173 public function wasPostingBuilt()
174 {
175 return in_array(
176 $this->getCode(),
177 array(
178 self::PLANNED,
179 self::SENDING,
180 self::PAUSED,
181 self::SENT,
182 self::STOPPED,
183 ));
184 }
185
191 public function isSendingLimitExceeded()
192 {
193 if (!$this->isSending())
194 {
195 return false;
196 }
197
198 $message = $this->letter->getMessage();
199 return $message->getTransport()->isLimitsExceeded($message);
200 }
201
207 public function isSendingLimitTemporary()
208 {
209 if (!$this->isSending())
210 {
211 return false;
212 }
213
214 $message = $this->letter->getMessage();
215 $limiter = $message->getTransport()->getExceededLimiter($message);
216
217 if (!$limiter)
218 {
219 return false;
220 }
221
222 return $limiter->getParameter('temporaryLimit') === true;
223 }
224
230 public function isSendingLimitWaiting()
231 {
232 if (!$this->isSending())
233 {
234 return false;
235 }
236
237 $message = $this->letter->getMessage();
238 return $message->getTransport()->getExceededLimiter($message) instanceof TimeLimiter;
239 }
240
247 public function isSendingPlanned()
248 {
249 if (!$this->isSending())
250 {
251 return false;
252 }
253
254 $plannedDateSend = $this->getPlannedDateSend();
255 if (!$plannedDateSend)
256 {
257 return false;
258 }
259 $dateNow = new DateTime();
260
261 return $plannedDateSend->getTimestamp() > $dateNow->getTimestamp();
262 }
263
269 public function getDateSend()
270 {
271 return $this->letter->get('DATE_SEND');
272 }
273
279 public function getDatePause()
280 {
281 return $this->letter->get('DATE_PAUSE');
282 }
283
289 public function getDateSent()
290 {
291 return $this->letter->get('DATE_SENT');
292 }
293
299 public function getDateCreate()
300 {
301 return $this->letter->get('DATE_INSERT');
302 }
303
309 public function getPlannedDateSend()
310 {
311 return $this->letter->get('AUTO_SEND_TIME');
312 }
313
319 public function getLastExecutedDate()
320 {
321 return $this->letter->get('LAST_EXECUTED');
322 }
323
330 public function updatePlannedDateSend(Date $date)
331 {
332 \CTimeZone::disable();
333 $result = Model\LetterTable::update($this->letter->getId(), array('AUTO_SEND_TIME' => $date));
334 \CTimeZone::enable();
335 if ($result->isSuccess())
336 {
337 $this->letter->set('AUTO_SEND_TIME', $date);
338 }
339
340 return $result->isSuccess();
341 }
342
348 protected function updateDateSend()
349 {
350 return $this->updateDate('DATE_SEND');
351 }
352
358 protected function updateDatePause()
359 {
360 return $this->updateDate('DATE_PAUSE');
361 }
362
368 protected function updateDateSent()
369 {
370 return $this->updateDate('DATE_SENT');
371 }
372
380 protected function updateDate($name, $date = null)
381 {
382 if (!$this->letter->get('POSTING_ID'))
383 {
384 return false;
385 }
386 \CTimeZone::disable();
387 $result = Model\PostingTable::update(
388 $this->letter->get('POSTING_ID'),
389 array(
390 $name => ($date ?: new DateTime())
391 )
392 );
393 \CTimeZone::enable();
394
395 return $result->isSuccess();
396 }
397
403 public function getCode()
404 {
405 $map = self::getStatusMap();
406 $status = $this->letter->get('STATUS');
407
408 if (($status && isset($map[$status])))
409 {
410 return $map[$status];
411 }
412
413 return self::NEWISH;
414 }
415
421 public function getName()
422 {
423 /*
424 if ($this->isSendingPlanned())
425 {
426 return Loc::getMessage('SENDER_DISPATCH_STATE_T');
427 }
428 */
429
430 return self::getStateName($this->getCode());
431 }
432
433 protected static function getStateName($code)
434 {
435// $code = $code === self::NEWISH ? self::READY : $code;
436 return Loc::getMessage('SENDER_DISPATCH_STATE1_' . $code) ?: Loc::getMessage('SENDER_DISPATCH_STATE_' . $code);
437 }
438
444 public static function getList()
445 {
446 $class = new \ReflectionClass(__CLASS__);
447 $constants = $class->getConstants();
448
449 $list = array();
450 foreach ($constants as $id => $value)
451 {
452 if (in_array($value, array(self::INIT)))
453 {
454 continue;
455 }
456
457 $list[$value] = self::getStateName($value);
458 }
459
460 return $list;
461 }
462
470 public function plan(Date $sendDate)
471 {
472 return $this->changeState(self::PLANNED, $sendDate);
473 }
474
481 public function ready()
482 {
483 return $this->changeState(self::READY);
484 }
485
492 public function send()
493 {
494 return $this->changeState(self::SENDING);
495 }
496
503 public function sendErrors()
504 {
505 if (!$this->canSendErrors())
506 {
507 throw new InvalidOperationException('Can not resend error letters.');
508 }
509
510 $postingId = $this->letter->get('POSTING_ID');
511 $updateSql = 'UPDATE ' . PostingRecipientTable::getTableName() .
512 " SET STATUS='" . PostingRecipientTable::SEND_RESULT_NONE . "'" .
513 " WHERE POSTING_ID=" . intval($postingId) .
514 " AND STATUS='" . PostingRecipientTable::SEND_RESULT_ERROR . "'";
515 Application::getConnection()->query($updateSql);
516 Posting\Sender::updateActualStatus($this->letter->get('POSTING_ID'));
517
518 return $this->updateStatus(Model\LetterTable::STATUS_SEND, self::SENDING);
519 }
520
527 public function pause()
528 {
529 if ($this->changeState(self::PAUSED))
530 {
531 $this->updateDatePause(); //TODO: move to tablet!
532 return true;
533 }
534
535 return false;
536 }
537
544 public function halt()
545 {
546 if ($this->changeState(self::HALTED))
547 {
548 $this->updateDatePause(); //TODO: move to tablet!
549 return true;
550 }
551
552 return false;
553 }
554
561 public function resume()
562 {
563 if ($this->changeState(self::SENDING))
564 {
565 $this->updateDateSend(); //TODO: move to tablet!
566 return true;
567 }
568
569 return false;
570 }
571
578 public function stop()
579 {
580 if ($this->changeState(self::STOPPED))
581 {
582 $this->updateDateSent(); //TODO: move to tablet!
583 return true;
584 }
585
586 return false;
587 }
588
595 public function init()
596 {
597 return $this->changeState(self::INIT);
598 }
599
607 public function reset()
608 {
609 throw new NotImplementedException('init reset not implemented.');
610 }
611
619 public function wait(Dispatch\MethodSchedule $method = null)
620 {
621 return $this->changeState(self::WAITING, $method ? $method->getNextDate() : null);
622 }
623
629 public function canReady()
630 {
631 return $this->canChangeState(self::READY);
632 }
633
639 public function canSend()
640 {
641 if ($this->getCode() === self::PAUSED)
642 {
643 return false;
644 }
645
646 return $this->canChangeState(self::SENDING);
647 }
648
654 public function canSendErrors()
655 {
656 if (Integration\Bitrix24\Service::isCloud())
657 {
658 return false;
659 }
660
661 if ($this->letter->isTrigger() || $this->letter->isReiterate())
662 {
663 return false;
664 }
665
666 if (!$this->letter->isSupportHeatMap() || !$this->letter->get('POSTING_ID'))
667 {
668 return false;
669 }
670
671 if (!$this->isSent())
672 {
673 return false;
674 }
675
676 $postingData = $this->letter->getLastPostingData();
677 return !empty($postingData['COUNT_SEND_ERROR']);
678 }
679
685 public function canPlan()
686 {
687 return $this->canChangeState(self::SENDING);
688 }
689
695 public function canPause()
696 {
697 return $this->canChangeState(self::PAUSED);
698 }
699
705 public function canStop()
706 {
707 return $this->canChangeState(self::STOPPED);
708 }
709
715 public function canResume()
716 {
717 if ($this->getCode() !== self::PAUSED)
718 {
719 return false;
720 }
721
722 return $this->canChangeState(self::SENDING);
723 }
724
730 public function canReset()
731 {
732 return $this->canChangeState(self::NEWISH);
733 }
734
740 public function canInit()
741 {
742 return $this->canChangeState(self::INIT);
743 }
744
750 public function canWait()
751 {
752 return $this->canChangeState(self::WAITING);
753 }
754
760 public function canHalt()
761 {
762 return $this->canChangeState(self::HALTED);
763 }
764
770 protected function getPossibleStates()
771 {
772 switch ($this->getCode())
773 {
774 case self::NEWISH:
775 return array(
776 self::INIT,
777 self::SENDING,
778 self::PLANNED,
779 self::WAITING,
780 );
781 case self::INIT:
782 return array(
783 self::READY,
784 );
785 case self::READY:
786 return array(
787 self::SENDING,
788 self::PLANNED,
789 self::WAITING,
790 );
791 case self::PLANNED:
792 return array(
793 self::READY,
794 self::PLANNED,
795 self::SENDING,
796 self::SENT,
797 self::STOPPED,
798 );
799 case self::SENDING:
800 return array(
801 self::PAUSED,
802 self::SENT,
803 self::STOPPED,
804 self::WAITING,
805 );
806 case self::PAUSED:
807 return array(
808 self::SENDING,
809 self::SENT,
810 self::STOPPED,
811 self::WAITING,
812 );
813 case self::WAITING:
814 return array(
815 self::SENT,
816 self::WAITING,
817 self::HALTED,
818 self::STOPPED,
819 self::READY,
820 );
821 case self::HALTED:
822 return [
823 self::WAITING,
824 self::STOPPED,
825 ];
826 case self::STOPPED:
827 case self::SENT:
828 default:
829 return [];
830 }
831 }
832
839 private function canChangeState($state)
840 {
841 if (!$this->letter->getId())
842 {
843 return false;
844 }
845
846 return $this->isPossibleState($state);
847 }
848
857 private function changeState($state, Date $sendDate = null)
858 {
859 if (!$this->isCampaignActive() && in_array($state, [self::SENDING, self::PLANNED]))
860 {
861 throw new InvalidOperationException(Loc::getMessage('SENDER_DISPATCH_STATE_ERROR_CAMPAIGN_INACTIVE'));
862 }
863
864 if (!$this->canChangeState($state))
865 {
866 $messageText = Loc::getMessage('SENDER_DISPATCH_STATE_ERROR_CHANGE', array(
867 '%old%' => $this->getName(),
868 '%new%' => self::getStateName($state)
869 ));
870
871 throw new InvalidOperationException($messageText);
872 }
873
874 $map = self::getStateMap();
875 if ($map[$state])
876 {
877 return $this->updateStatus($map[$state], $state, $sendDate);
878 }
879
880 return false;
881 }
882
889 private function isPossibleState($state)
890 {
891 $possibleStates = $this->getPossibleStates();
892
893 //TODO: remove
894 if (!$this->letter->isSupportReiterate() && !$this->letter->isTrigger())
895 {
896 $possibleStates = array_filter($possibleStates, function ($value)
897 {
898 return !in_array($value, [self::WAITING, self::HALTED]);
899 });
900 }
901
902 return in_array($state, $possibleStates);
903 }
904
913 private function updateStatus($status, $state, Date $sendDate = null)
914 {
915 $fields = array('STATUS' => $status);
916 if ($state === self::READY && $this->letter->get('AUTO_SEND_TIME'))
917 {
918 $fields['AUTO_SEND_TIME'] = null;
919 }
920 if ($state === self::SENDING)
921 {
922 $fields['AUTO_SEND_TIME'] = $sendDate ?: new DateTime();
923 }
924 if ($state === self::PLANNED)
925 {
926 $fields['AUTO_SEND_TIME'] = $sendDate ?: new DateTime();
927 }
928 if ($state === self::WAITING && $sendDate)
929 {
930 $fields['AUTO_SEND_TIME'] = $sendDate;
931 }
932 if ($updatedBy = $this->letter->get('UPDATED_BY'))
933 {
934 $fields['UPDATED_BY'] = $updatedBy;
935 }
936 \CTimeZone::disable();
937 $result = Model\LetterTable::update($this->letter->getId(), $fields);
938 \CTimeZone::enable();
939
940 if ($result->isSuccess())
941 {
942 $this->letter->set('STATUS', $status);
943 if (isset($fields['AUTO_SEND_TIME']))
944 {
945 $this->letter->set('AUTO_SEND_TIME', $fields['AUTO_SEND_TIME']);
946 }
947 }
948 else
949 {
950 $this->letter->getErrorCollection()->add($result->getErrors());
951 }
952
953 return $result->isSuccess();
954 }
955
961 private static function getStateMap()
962 {
963 $map = array_flip(self::getStatusMap());
964 $map[self::INIT] = Model\LetterTable::STATUS_NEW; // for init-operation
965
966 return $map;
967 }
968
974 private static function getStatusMap()
975 {
976 return array(
977 Model\LetterTable::STATUS_NEW => self::NEWISH,
978 Model\LetterTable::STATUS_PLAN => self::PLANNED,
979 Model\LetterTable::STATUS_READY => self::READY,
980 Model\LetterTable::STATUS_SEND => self::SENDING,
981 Model\LetterTable::STATUS_WAIT => self::WAITING,
982 Model\LetterTable::STATUS_HALT => self::HALTED,
983 Model\LetterTable::STATUS_PAUSE => self::PAUSED,
984 Model\LetterTable::STATUS_END => self::SENT,
985 Model\LetterTable::STATUS_CANCEL => self::STOPPED,
986 );
987 }
988
989 private function isCampaignActive()
990 {
991 return $this->letter->get('CAMPAIGN_ACTIVE', 'Y') === 'Y';
992 }
993}
static getConnection($name="")
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static getStateName($code)
Definition state.php:433
updateDate($name, $date=null)
Definition state.php:380
plan(Date $sendDate)
Definition state.php:470
updatePlannedDateSend(Date $date)
Definition state.php:330
__construct(Entity\Letter $letter)
Definition state.php:54
wait(Dispatch\MethodSchedule $method=null)
Definition state.php:619