at the end of the day, it was inevitable

This commit is contained in:
Mo Elzubeir
2022-12-09 08:36:26 -06:00
commit 1218570914
1768 changed files with 887087 additions and 0 deletions
@@ -0,0 +1,140 @@
<?php
namespace UserBundle\Entity\Notification\Schedule;
use ApiBundle\Entity\NormalizableEntityInterface;
use AppBundle\Entity\BaseEntityTrait;
use AppBundle\Entity\EntityInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use UserBundle\Entity\Notification\Notification;
use UserBundle\Entity\Notification\NotificationSendHistory;
/**
* Class AbstractNotificationSchedule
*
* @ORM\Table(name="notification_schedule")
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({
* "daily"="DailyNotificationSchedule",
* "weekly"="WeeklyNotificationSchedule",
* "monthly"="MonthlyNotificationSchedule"
* })
*/
abstract class AbstractNotificationSchedule implements
EntityInterface,
NormalizableEntityInterface
{
use BaseEntityTrait;
/**
* @var Notification
*
* @ORM\ManyToOne(
* targetEntity="UserBundle\Entity\Notification\Notification",
* inversedBy="schedules"
* )
*/
private $notification;
/**
* @var NotificationSendHistory
*
* @ORM\ManyToOne(
* targetEntity="UserBundle\Entity\Notification\NotificationSendHistory",
* inversedBy="schedules"
* )
*/
private $history;
/**
* Set notification
*
* @param Notification $notification A Notification instance.
*
* @return static
*/
public function setNotification(Notification $notification = null)
{
$this->notification = $notification;
return $this;
}
/**
* Get notification
*
* @return Notification
*/
public function getNotification()
{
return $this->notification;
}
/**
* Set history
*
* @param NotificationSendHistory $history A NotificationSendHistory instance.
*
* @return AbstractNotificationSchedule
*/
public function setHistory(NotificationSendHistory $history = null)
{
$this->history = $history;
return $this;
}
/**
* Get history
*
* @return NotificationSendHistory
*/
public function getHistory()
{
return $this->history;
}
/**
* Compute all date's for this schedule in specified period.
*
* @param \DateTime $start Start of computing period.
* @param \DateTime $end End of computing period.
*
* @return \DateTime[]
*/
public function computeDates(\DateTime $start, \DateTime $end)
{
$modifiedStart = clone $start;
$modifiedEnd = clone $end;
$modifiedStart
->setTime($modifiedStart->format('H'), $modifiedStart->format('i'), 0);
// Add 1 seconds in order to catch end date if it should exists in result's.
$modifiedEnd
->setTime($modifiedEnd->format('H'), $modifiedEnd->format('i'), 1);
return $this->doComputeDates($modifiedStart, $modifiedEnd);
}
/**
* Return key identifier for current schedule.
*
* @return string
*/
abstract public function getKey();
/**
* Compute all date's for this schedule in specified period.
*
* @param \DateTime $start Start of computing period.
* @param \DateTime $end End of computing period.
*
* @return \DateTime[]
*/
abstract protected function doComputeDates(\DateTime $start, \DateTime $end);
}
@@ -0,0 +1,251 @@
<?php
namespace UserBundle\Entity\Notification\Schedule;
use ApiBundle\Serializer\Metadata\Metadata;
use ApiBundle\Serializer\Metadata\PropertyMetadata;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class DailyNotificationSchedule
*
* @ORM\Entity
*/
class DailyNotificationSchedule extends AbstractNotificationSchedule
{
const TIME_15_M = '15m';
const TIME_30_M = '30m';
const TIME_1_H = '1h';
const TIME_2_H = '2h';
const TIME_3_H = '3h';
const TIME_4_H = '4h';
const TIME_6_H = '6h';
const TIME_12_H = '12h';
const TIME_ONCE = 'once';
const DAYS_ALL = 'all';
const DAYS_WEEKDAYS = 'weekdays';
const DAYS_WEEKENDS = 'weekends';
/**
* @var string
*
* @ORM\Column(length=5)
* @Assert\Choice(callback="getAvailableTime")
*/
private $time;
/**
* @var string
*
* @ORM\Column(length=9)
* @Assert\Choice(callback="getAvailableDays")
*/
private $days;
/**
* Map between available time values and crontab schedule string.
*
* @var string[]
*/
private static $timeMap = [
self::TIME_15_M => 'T15M',
self::TIME_30_M => 'T30M',
self::TIME_1_H => 'T1H',
self::TIME_2_H => 'T2H',
self::TIME_3_H => 'T3H',
self::TIME_4_H => 'T4H',
self::TIME_6_H => 'T6H',
self::TIME_12_H => 'T12H',
self::TIME_ONCE => '1D',
];
/**
* Get available time values.
*
* @return string[]
*/
public static function getAvailableTime()
{
return [
self::TIME_15_M,
self::TIME_30_M,
self::TIME_1_H,
self::TIME_2_H,
self::TIME_3_H,
self::TIME_4_H,
self::TIME_6_H,
self::TIME_12_H,
self::TIME_ONCE,
];
}
/**
* Get available days values.
*
* @return string[]
*/
public static function getAvailableDays()
{
return [
self::DAYS_ALL,
self::DAYS_WEEKDAYS,
self::DAYS_WEEKENDS,
];
}
/**
* Set time
*
* @param string $time One of TIME_ constant's.
*
* @return DailyNotificationSchedule
*/
public function setTime($time)
{
$this->time = $time;
return $this;
}
/**
* Get time
*
* @return string
*/
public function getTime()
{
return $this->time;
}
/**
* Set days
*
* @param string $days One of DAYS_ constant's.
*
* @return DailyNotificationSchedule
*/
public function setDays($days)
{
$this->days = $days;
return $this;
}
/**
* Get days
*
* @return string
*/
public function getDays()
{
return $this->days;
}
/**
* Get entity type
*
* @return string
*/
public function getEntityType()
{
return 'daily';
}
/**
* Return metadata for current entity.
*
* @return \ApiBundle\Serializer\Metadata\Metadata
*/
public function getMetadata()
{
return new Metadata(static::class, [
PropertyMetadata::createString('time', [ 'schedule' ]),
PropertyMetadata::createString('days', [ 'schedule' ]),
]);
}
/**
* Return default normalization groups.
*
* @return array
*/
public function defaultGroups()
{
return [ 'schedule' ];
}
/**
* @param array $data Normalized DailyNotificationSchedule.
*
* @return DailyNotificationSchedule
*/
public static function denormalize(array $data)
{
if (! isset($data['time'], $data['days'])) {
throw new \LogicException('Normalized DailyNotificationSchedule data must have \'time\' and \'days\' fields.');
}
return DailyNotificationSchedule::create()
->setTime($data['time'])
->setDays($data['days']);
}
/**
* Return key identifier for current schedule.
*
* @return string
*/
public function getKey()
{
return sprintf('daily_%s_%s', $this->time, $this->days);
}
/**
* Compute all date's for this schedule in specified period.
*
* @param \DateTime $start Start of computing period.
* @param \DateTime $end End of computing period.
*
* @return \DateTime[]
*/
protected function doComputeDates(\DateTime $start, \DateTime $end)
{
$period = new \DatePeriod(
$start,
new \DateInterval('P'. self::$timeMap[$this->time]),
$end,
\DatePeriod::EXCLUDE_START_DATE
);
$results = [];
switch ($this->days) {
case self::DAYS_ALL:
$results = iterator_to_array($period);
break;
case self::DAYS_WEEKDAYS:
/** @var \DateTime $date */
foreach ($period as $date) {
if ($date->format('N') <= 5) {
$results[] = $date;
}
}
break;
case self::DAYS_WEEKENDS:
/** @var \DateTime $date */
foreach ($period as $date) {
if ($date->format('N') > 5) {
$results[] = $date;
}
}
break;
}
return $results;
}
}
@@ -0,0 +1,235 @@
<?php
namespace UserBundle\Entity\Notification\Schedule;
use ApiBundle\Serializer\Metadata\Metadata;
use ApiBundle\Serializer\Metadata\PropertyMetadata;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class MonthlyNotificationSchedule
*
* @ORM\Entity
*/
class MonthlyNotificationSchedule extends AbstractNotificationSchedule
{
const DAY_LAST = 'last';
/**
* @var string
*
* @ORM\Column(length=10)
* @Assert\Choice(callback="getAvailableDay")
*/
private $day;
/**
* @var integer
*
* @ORM\Column(type="smallint")
*/
private $hour;
/**
* @var integer
*
* @ORM\Column(type="smallint")
*/
private $minute;
/**
* Get available day's.
*
* @return string[]
*/
public static function getAvailableDay()
{
$days = range(1, 31);
$days[] = self::DAY_LAST;
return $days;
}
/**
* Set day
*
* @param string $day One of DAY_ const's.
*
* @return MonthlyNotificationSchedule
*/
public function setDay($day)
{
$this->day = $day;
return $this;
}
/**
* Get day
*
* @return string
*/
public function getDay()
{
return $this->day;
}
/**
* Set hour
*
* @param integer $hour Schedule hours.
*
* @return MonthlyNotificationSchedule
*/
public function setHour($hour)
{
$this->hour = $hour;
return $this;
}
/**
* Get hour
*
* @return integer
*/
public function getHour()
{
return $this->hour;
}
/**
* Set minutes
*
* @param integer $minute Schedule minutes.
*
* @return MonthlyNotificationSchedule
*/
public function setMinute($minute)
{
$this->minute = $minute;
return $this;
}
/**
* Get minute
*
* @return integer
*/
public function getMinute()
{
return $this->minute;
}
/**
* Get entity type
*
* @return string
*/
public function getEntityType()
{
return 'monthly';
}
/**
* Return metadata for current entity.
*
* @return \ApiBundle\Serializer\Metadata\Metadata
*/
public function getMetadata()
{
return new Metadata(static::class, [
PropertyMetadata::createString('day', [ 'schedule' ]),
PropertyMetadata::createString('hour', [ 'schedule' ]),
PropertyMetadata::createString('minute', [ 'schedule' ]),
]);
}
/**
* Return default normalization groups.
*
* @return array
*/
public function defaultGroups()
{
return [ 'schedule' ];
}
/**
* @param array $data Normalized MonthlyNotificationSchedule.
*
* @return MonthlyNotificationSchedule
*/
public static function denormalize(array $data)
{
if (! isset($data['day'], $data['hour'], $data['minute'])) {
throw new \LogicException('Normalized MonthlyNotificationSchedule data must have \'day\', \'hour\' and \'minute\' fields.');
}
return MonthlyNotificationSchedule::create()
->setDay($data['day'])
->setHour($data['hour'])
->setMinute($data['minute']);
}
/**
* Return key identifier for current schedule.
*
* @return string
*/
public function getKey()
{
return sprintf(
'monthly_%s_%s_%s',
$this->day,
$this->hour,
$this->minute
);
}
/**
* Compute all date's for this schedule in specified period.
*
* @param \DateTime $start Start of computing period.
* @param \DateTime $end End of computing period.
*
* @return \DateTime[]
*/
protected function doComputeDates(\DateTime $start, \DateTime $end)
{
$dates = [];
$date = clone $start;
if ($this->day === self::DAY_LAST) {
$date->modify('last day of this month');
while ($date <= $end) {
$tmp = clone $date;
$dates[] = $tmp->setTime($this->hour, $this->minute);
$date->modify('last day of next month');
}
} else {
$currentNum = $date->format('j');
if ($currentNum > $this->day) {
$date
->modify('first day of next month')
->modify(sprintf('%d day', $this->day - 1));
} elseif ($currentNum < $this->day) {
$date->modify(sprintf('%d day', $this->day - $currentNum));
}
while ($date <= $end) {
$tmp = clone $date;
$dates[] = $tmp->setTime($this->hour, $this->minute);
$date
->modify('first day of next month')
->modify(sprintf('%d day', $this->day - 1));
}
}
return $dates;
}
}
@@ -0,0 +1,331 @@
<?php
namespace UserBundle\Entity\Notification\Schedule;
use ApiBundle\Serializer\Metadata\Metadata;
use ApiBundle\Serializer\Metadata\PropertyMetadata;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class WeeklyNotificationSchedule
*
* @ORM\Entity
*/
class WeeklyNotificationSchedule extends AbstractNotificationSchedule
{
const PERIOD_EVERY = 'every';
const PERIOD_FIRST = 'first';
const PERIOD_SECOND = 'second';
const PERIOD_THIRD = 'third';
const PERIOD_FOURTH = 'fourth';
const PERIOD_LAST = 'last';
const DAY_MONDAY = 'monday';
const DAY_TUESDAY = 'tuesday';
const DAY_WEDNESDAY = 'wednesday';
const DAY_THURSDAY = 'thursday';
const DAY_FRIDAY = 'friday';
const DAY_SATURDAY = 'saturday';
const DAY_SUNDAY = 'sunday';
/**
* @var string
*
* @ORM\Column(length=7)
* @Assert\Choice(callback="getAvailablePeriod")
*/
private $period;
/**
* @var string
*
* @ORM\Column(length=10)
* @Assert\Choice(callback="getAvailableDay")
*/
private $day;
/**
* @var integer
*
* @ORM\Column(type="smallint")
*/
private $hour;
/**
* @var integer
*
* @ORM\Column(type="smallint")
*/
private $minute;
/**
* Map between day and corntab schedule. Make sense only for PERIOD_EVERY.
*
* @var array[]
*/
private static $dayMap = [
self::DAY_MONDAY => 1,
self::DAY_TUESDAY => 2,
self::DAY_WEDNESDAY => 3,
self::DAY_TUESDAY => 4,
self::DAY_FRIDAY => 5,
self::DAY_SATURDAY => 6,
self::DAY_SUNDAY => 7,
];
/**
* Get available period's.
*
* @return string[]
*/
public static function getAvailablePeriod()
{
return [
self::PERIOD_EVERY,
self::PERIOD_FIRST,
self::PERIOD_SECOND,
self::PERIOD_THIRD,
self::PERIOD_FOURTH,
self::PERIOD_LAST,
];
}
/**
* Get available day's.
*
* @return string[]
*/
public static function getAvailableDay()
{
return [
self::DAY_MONDAY,
self::DAY_TUESDAY,
self::DAY_WEDNESDAY,
self::DAY_TUESDAY,
self::DAY_FRIDAY,
self::DAY_SATURDAY,
self::DAY_SUNDAY,
];
}
/**
* Set period
*
* @param string $period One of PERIOD_ const's.
*
* @return WeeklyNotificationSchedule
*/
public function setPeriod($period)
{
$this->period = $period;
return $this;
}
/**
* Get period
*
* @return string
*/
public function getPeriod()
{
return $this->period;
}
/**
* Set day
*
* @param string $day One of DAY_ const's.
*
* @return WeeklyNotificationSchedule
*/
public function setDay($day)
{
$this->day = $day;
return $this;
}
/**
* Get day
*
* @return string
*/
public function getDay()
{
return $this->day;
}
/**
* Set hour
*
* @param integer $hour Schedule hours.
*
* @return WeeklyNotificationSchedule
*/
public function setHour($hour)
{
$this->hour = $hour;
return $this;
}
/**
* Get hour
*
* @return integer
*/
public function getHour()
{
return $this->hour;
}
/**
* Set minute
*
* @param integer $minute Schedule minute.
*
* @return WeeklyNotificationSchedule
*/
public function setMinute($minute)
{
$this->minute = $minute;
return $this;
}
/**
* Get minute
*
* @return integer
*/
public function getMinute()
{
return $this->minute;
}
/**
* Get entity type
*
* @return string
*/
public function getEntityType()
{
return 'weekly';
}
/**
* Return metadata for current entity.
*
* @return \ApiBundle\Serializer\Metadata\Metadata
*/
public function getMetadata()
{
return new Metadata(static::class, [
PropertyMetadata::createString('period', [ 'schedule' ]),
PropertyMetadata::createString('day', [ 'schedule' ]),
PropertyMetadata::createString('hour', [ 'schedule' ]),
PropertyMetadata::createString('minute', [ 'schedule' ]),
]);
}
/**
* Return default normalization groups.
*
* @return array
*/
public function defaultGroups()
{
return [ 'schedule' ];
}
/**
* @param array $data Normalized WeeklyNotificationSchedule.
*
* @return WeeklyNotificationSchedule
*/
public static function denormalize(array $data)
{
if (! isset($data['period'], $data['day'], $data['hour'], $data['minute'])) {
throw new \LogicException('Normalized WeeklyNotificationSchedule data must have \'period\', \'day\', \'hour\' and \'minute\' fields.');
}
return WeeklyNotificationSchedule::create()
->setPeriod($data['period'])
->setDay($data['day'])
->setHour($data['hour'])
->setMinute($data['minute']);
}
/**
* Return key identifier for current schedule.
*
* @return string
*/
public function getKey()
{
return sprintf(
'weekly_%s_%s_%s_%s',
$this->period,
$this->day,
$this->hour,
$this->minute
);
}
/**
* Compute all date's for this schedule in specified period.
*
* @param \DateTime $start Start of computing period.
* @param \DateTime $end End of computing period.
*
* @return \DateTime[]
*/
protected function doComputeDates(\DateTime $start, \DateTime $end)
{
$dates = [];
$date = clone $start;
if ($this->period === self::PERIOD_EVERY) {
//
// Process every weekdays days.
//
if ($date->format('N') !== self::$dayMap[$this->day]) {
//
// If start date is not required weekday we should proceed to next
// required weekday.
//
$date->modify('next '. $this->day);
}
while ($date <= $end) {
$tmp = clone $date;
$dates[] = $tmp->setTime($this->hour, $this->minute);
$date->modify('next '. $this->day);
}
} else {
//
// Process specified weekday like second monday, third friday and etc.
//
$date->modify(sprintf(
'%s %s of this month',
$this->period,
$this->day
));
while ($date <= $end) {
$tmp = clone $date;
$dates[] = $tmp->setTime($this->hour, $this->minute);
$date->modify(sprintf(
'%s %s of next month',
$this->period,
$this->day
));
}
}
return $dates;
}
}