[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/dragonmantank/cron-expression/src/Cron/ -> DayOfMonthField.php (source)

   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace Cron;
   6  
   7  use DateTime;
   8  use DateTimeInterface;
   9  
  10  /**
  11   * Day of month field.  Allows: * , / - ? L W.
  12   *
  13   * 'L' stands for "last" and specifies the last day of the month.
  14   *
  15   * The 'W' character is used to specify the weekday (Monday-Friday) nearest the
  16   * given day. As an example, if you were to specify "15W" as the value for the
  17   * day-of-month field, the meaning is: "the nearest weekday to the 15th of the
  18   * month". So if the 15th is a Saturday, the trigger will fire on Friday the
  19   * 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If
  20   * the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you
  21   * specify "1W" as the value for day-of-month, and the 1st is a Saturday, the
  22   * trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary
  23   * of a month's days. The 'W' character can only be specified when the
  24   * day-of-month is a single day, not a range or list of days.
  25   *
  26   * @author Michael Dowling <[email protected]>
  27   */
  28  class DayOfMonthField extends AbstractField
  29  {
  30      /**
  31       * {@inheritdoc}
  32       */
  33      protected $rangeStart = 1;
  34  
  35      /**
  36       * {@inheritdoc}
  37       */
  38      protected $rangeEnd = 31;
  39  
  40      /**
  41       * Get the nearest day of the week for a given day in a month.
  42       *
  43       * @param int $currentYear Current year
  44       * @param int $currentMonth Current month
  45       * @param int $targetDay Target day of the month
  46       *
  47       * @return \DateTime|null Returns the nearest date
  48       */
  49      private static function getNearestWeekday(int $currentYear, int $currentMonth, int $targetDay): ?DateTime
  50      {
  51          $tday = str_pad((string) $targetDay, 2, '0', STR_PAD_LEFT);
  52          $target = DateTime::createFromFormat('Y-m-d', "$currentYear}-$currentMonth}-$tday}");
  53  
  54          if ($target === false) {
  55              return null;
  56          }
  57  
  58          $currentWeekday = (int) $target->format('N');
  59  
  60          if ($currentWeekday < 6) {
  61              return $target;
  62          }
  63  
  64          $lastDayOfMonth = $target->format('t');
  65          foreach ([-1, 1, -2, 2] as $i) {
  66              $adjusted = $targetDay + $i;
  67              if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
  68                  $target->setDate($currentYear, $currentMonth, $adjusted);
  69  
  70                  if ((int) $target->format('N') < 6 && (int) $target->format('m') === $currentMonth) {
  71                      return $target;
  72                  }
  73              }
  74          }
  75  
  76          return null;
  77      }
  78  
  79      /**
  80       * {@inheritdoc}
  81       */
  82      public function isSatisfiedBy(DateTimeInterface $date, $value, bool $invert): bool
  83      {
  84          // ? states that the field value is to be skipped
  85          if ('?' === $value) {
  86              return true;
  87          }
  88  
  89          $fieldValue = $date->format('d');
  90  
  91          // Check to see if this is the last day of the month
  92          if ('L' === $value) {
  93              return $fieldValue === $date->format('t');
  94          }
  95  
  96          // Check to see if this is the nearest weekday to a particular value
  97          if (strpos($value, 'W')) {
  98              // Parse the target day
  99              $targetDay = (int) substr($value, 0, strpos($value, 'W'));
 100              // Find out if the current day is the nearest day of the week
 101              $nearest = self::getNearestWeekday(
 102                  (int) $date->format('Y'),
 103                  (int) $date->format('m'),
 104                  $targetDay
 105              );
 106              if ($nearest) {
 107                  return $date->format('j') === $nearest->format('j');
 108              }
 109  
 110              throw new \RuntimeException('Unable to return nearest weekday');
 111          }
 112  
 113          return $this->isSatisfied((int) $date->format('d'), $value);
 114      }
 115  
 116      /**
 117       * @inheritDoc
 118       *
 119       * @param \DateTime|\DateTimeImmutable $date
 120       */
 121      public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface
 122      {
 123          if (! $invert) {
 124              $date = $date->add(new \DateInterval('P1D'));
 125              $date = $date->setTime(0, 0);
 126          } else {
 127              $date = $date->sub(new \DateInterval('P1D'));
 128              $date = $date->setTime(23, 59);
 129          }
 130  
 131          return $this;
 132      }
 133  
 134      /**
 135       * {@inheritdoc}
 136       */
 137      public function validate(string $value): bool
 138      {
 139          $basicChecks = parent::validate($value);
 140  
 141          // Validate that a list don't have W or L
 142          if (false !== strpos($value, ',') && (false !== strpos($value, 'W') || false !== strpos($value, 'L'))) {
 143              return false;
 144          }
 145  
 146          if (!$basicChecks) {
 147              if ('?' === $value) {
 148                  return true;
 149              }
 150  
 151              if ('L' === $value) {
 152                  return true;
 153              }
 154  
 155              if (preg_match('/^(.*)W$/', $value, $matches)) {
 156                  return $this->validate($matches[1]);
 157              }
 158  
 159              return false;
 160          }
 161  
 162          return $basicChecks;
 163      }
 164  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer