- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-
- namespace Zend\Validator;
-
- use DateInterval;
- use DateTime;
- use DateTimeZone;
- use Traversable;
- use Zend\Stdlib\ArrayUtils;
-
- class DateStep extends Date
- {
- const NOT_STEP = 'dateStepNotStep';
-
- /**
- * @var array
- */
- protected $messageTemplates = array(
- self::NOT_STEP => "The input is not a valid step"
- );
-
- /**
- * Optional base date value
- *
- * @var string|int|\DateTime
- */
- protected $baseValue = '1970-01-01T00:00:00Z';
-
- /**
- * Date step interval (defaults to 1 day).
- * Uses the DateInterval specification.
- *
- * @var DateInterval
- */
- protected $step;
-
- /**
- * Format to use for parsing date strings
- *
- * @var string
- */
- protected $format = DateTime::ISO8601;
-
- /**
- * Optional timezone to be used when the baseValue
- * and validation values do not contain timezone info
- *
- * @var DateTimeZone
- */
- protected $timezone;
-
- /**
- * Set default options for this instance
- *
- * @param array $options
- */
- public function __construct($options = array())
- {
- if ($options instanceof Traversable) {
- $options = ArrayUtils::iteratorToArray($options);
- } elseif (!is_array($options)) {
- $options = func_get_args();
- $temp['baseValue'] = array_shift($options);
- if (!empty($options)) {
- $temp['step'] = array_shift($options);
- }
- if (!empty($options)) {
- $temp['format'] = array_shift($options);
- }
- if (!empty($options)) {
- $temp['timezone'] = array_shift($options);
- }
-
- $options = $temp;
- }
-
- if (isset($options['baseValue'])) {
- $this->setBaseValue($options['baseValue']);
- }
- if (isset($options['step'])) {
- $this->setStep($options['step']);
- } else {
- $this->setStep(new DateInterval('P1D'));
- }
- if (array_key_exists('format', $options)) {
- $this->setFormat($options['format']);
- }
- if (isset($options['timezone'])) {
- $this->setTimezone($options['timezone']);
- } else {
- $this->setTimezone(new DateTimeZone(date_default_timezone_get()));
- }
-
- parent::__construct($options);
- }
-
- /**
- * Sets the base value from which the step should be computed
- *
- * @param string|int|\DateTime $baseValue
- * @return DateStep
- */
- public function setBaseValue($baseValue)
- {
- $this->baseValue = $baseValue;
- return $this;
- }
-
- /**
- * Returns the base value from which the step should be computed
- *
- * @return string|int|\DateTime
- */
- public function getBaseValue()
- {
- return $this->baseValue;
- }
-
- /**
- * Sets the step date interval
- *
- * @param DateInterval $step
- * @return DateStep
- */
- public function setStep(DateInterval $step)
- {
- $this->step = $step;
- return $this;
- }
-
- /**
- * Returns the step date interval
- *
- * @return DateInterval
- */
- public function getStep()
- {
- return $this->step;
- }
-
- /**
- * Returns the timezone option
- *
- * @return DateTimeZone
- */
- public function getTimezone()
- {
- return $this->timezone;
- }
-
- /**
- * Sets the timezone option
- *
- * @param DateTimeZone $timezone
- * @return DateStep
- */
- public function setTimezone(DateTimeZone $timezone)
- {
- $this->timezone = $timezone;
- return $this;
- }
-
- /**
- * Converts an int or string to a DateTime object
- *
- * @param string|int|\DateTime $param
- * @return \DateTime
- * @throws Exception\InvalidArgumentException
- */
- protected function convertToDateTime($param)
- {
- $dateObj = $param;
- if (is_int($param)) {
- // Convert from timestamp
- $dateObj = date_create("@$param");
- } elseif (is_string($param)) {
- // Custom week format support
- if (strpos($this->getFormat(), 'Y-\WW') === 0
- && preg_match('/^([0-9]{4})\-W([0-9]{2})/', $param, $matches)
- ) {
- $dateObj = new DateTime();
- $dateObj->setISODate($matches[1], $matches[2]);
- } else {
- $dateObj = DateTime::createFromFormat(
- $this->getFormat(), $param, $this->getTimezone()
- );
- }
- }
- if (!($dateObj instanceof DateTime)) {
- throw new Exception\InvalidArgumentException('Invalid date param given');
- }
-
- return $dateObj;
- }
-
- /**
- * Returns true if a date is within a valid step
- *
- * @param string|int|\DateTime $value
- * @return bool
- * @throws Exception\InvalidArgumentException
- */
- public function isValid($value)
- {
- parent::isValid($value);
-
- $this->setValue($value);
-
- $baseDate = $this->convertToDateTime($this->getBaseValue());
- $step = $this->getStep();
-
- // Parse the date
- try {
- $valueDate = $this->convertToDateTime($value);
- } catch (Exception\InvalidArgumentException $ex) {
- return false;
- }
-
- // Same date?
- if ($valueDate == $baseDate) {
- return true;
- }
-
- // Optimization for simple intervals.
- // Handle intervals of just one date or time unit.
- $intervalParts = explode('|', $step->format('%y|%m|%d|%h|%i|%s'));
- $partCounts = array_count_values($intervalParts);
- if (5 === $partCounts["0"]) {
- // Find the unit with the non-zero interval
- $unitKeys = array('years', 'months', 'days', 'hours', 'minutes', 'seconds');
- $intervalParts = array_combine($unitKeys, $intervalParts);
-
- $intervalUnit = null;
- $stepValue = null;
- foreach ($intervalParts as $key => $value) {
- if (0 != $value) {
- $intervalUnit = $key;
- $stepValue = (int) $value;
- break;
- }
- }
-
- // Get absolute time difference
- $timeDiff = $valueDate->diff($baseDate, true);
- $diffParts = explode('|', $timeDiff->format('%y|%m|%d|%h|%i|%s'));
- $diffParts = array_combine($unitKeys, $diffParts);
-
- // Check date units
- if (in_array($intervalUnit, array('years', 'months', 'days'))) {
- switch ($intervalUnit) {
- case 'years':
- if ( 0 == $diffParts['months'] && 0 == $diffParts['days']
- && 0 == $diffParts['hours'] && 0 == $diffParts['minutes']
- && 0 == $diffParts['seconds']
- ) {
- if (($diffParts['years'] % $stepValue) === 0) {
- return true;
- }
- }
- break;
- case 'months':
- if ( 0 == $diffParts['days'] && 0 == $diffParts['hours']
- && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds']
- ) {
- $months = ($diffParts['years'] * 12) + $diffParts['months'];
- if (($months % $stepValue) === 0) {
- return true;
- }
- }
- break;
- case 'days':
- if ( 0 == $diffParts['hours'] && 0 == $diffParts['minutes']
- && 0 == $diffParts['seconds']
- ) {
- $days = $timeDiff->format('%a'); // Total days
- if (($days % $stepValue) === 0) {
- return true;
- }
- }
- break;
- }
- $this->error(self::NOT_STEP);
- return false;
- }
-
- // Check time units
- if (in_array($intervalUnit, array('hours', 'minutes', 'seconds'))) {
-
- // Simple test if $stepValue is 1.
- if (1 == $stepValue) {
- if ('hours' === $intervalUnit
- && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds']
- ) {
- return true;
- } elseif ('minutes' === $intervalUnit && 0 == $diffParts['seconds']) {
- return true;
- } elseif ('seconds' === $intervalUnit) {
- return true;
- }
- }
-
- // Simple test for same day, when using default baseDate
- if ($baseDate->format('Y-m-d') == $valueDate->format('Y-m-d')
- && $baseDate->format('Y-m-d') == '1970-01-01'
- ) {
- switch ($intervalUnit) {
- case 'hours':
- if (0 == $diffParts['minutes'] && 0 == $diffParts['seconds']) {
- if (($diffParts['hours'] % $stepValue) === 0) {
- return true;
- }
- }
- break;
- case 'minutes':
- if (0 == $diffParts['seconds']) {
- $minutes = ($diffParts['hours'] * 60) + $diffParts['minutes'];
- if (($minutes % $stepValue) === 0) {
- return true;
- }
- }
- break;
- case 'seconds':
- $seconds = ($diffParts['hours'] * 60)
- + ($diffParts['minutes'] * 60)
- + $diffParts['seconds'];
- if (($seconds % $stepValue) === 0) {
- return true;
- }
- break;
- }
- $this->error(self::NOT_STEP);
- return false;
- }
- }
- }
-
- // Fall back to slower (but accurate) method for complex intervals.
- // Keep adding steps to the base date until a match is found
- // or until the value is exceeded.
- if ($baseDate < $valueDate) {
- while ($baseDate < $valueDate) {
- $baseDate->add($step);
- if ($baseDate == $valueDate) {
- return true;
- }
- }
- } else {
- while ($baseDate > $valueDate) {
- $baseDate->sub($step);
- if ($baseDate == $valueDate) {
- return true;
- }
- }
- }
-
- $this->error(self::NOT_STEP);
- return false;
- }
- }
# |
Change |
User |
Description |
Committed |
|
#1
|
18334 |
Liz Lam |
initial add of jambox |
9 years ago
|
|