mirror of
https://github.com/getformwork/formwork.git
synced 2025-01-17 21:49:04 +01:00
Merge pull request #61 from getformwork/feature/stricter-date-parsing
Make date parsing stricter deprecating the use of invalid formats
This commit is contained in:
commit
bbf0446d38
@ -2,10 +2,11 @@
|
||||
|
||||
namespace Formwork\Admin\Fields;
|
||||
|
||||
use Formwork\Core\Formwork;
|
||||
use Formwork\Data\Collection;
|
||||
use Formwork\Data\DataGetter;
|
||||
use DateTime;
|
||||
use Formwork\Utils\Date;
|
||||
use Formwork\Utils\Str;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Validator
|
||||
{
|
||||
@ -112,14 +113,11 @@ class Validator
|
||||
return null;
|
||||
}
|
||||
|
||||
$format = Formwork::instance()->option('date.format');
|
||||
$date = date_create_from_format($format, $value) ?: date_create($value);
|
||||
|
||||
if ($date instanceof DateTime) {
|
||||
return date_format($date, 'Y-m-d');
|
||||
try {
|
||||
return date('Y-m-d', Date::toTimestamp($value, null, true));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new ValidationException('Invalid value for field "' . $field->name() . '" of type "' . $field->type() . '":' . Str::after($e->getMessage(), ':'));
|
||||
}
|
||||
|
||||
throw new ValidationException('Invalid date format for field "' . $field->name() . '" of type "' . $field->type() . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,6 +4,7 @@ namespace Formwork\Admin;
|
||||
|
||||
use Formwork\Admin\Utils\IPAnonymizer;
|
||||
use Formwork\Admin\Utils\Registry;
|
||||
use Formwork\Utils\Date;
|
||||
use Formwork\Utils\FileSystem;
|
||||
use Formwork\Utils\HTTPRequest;
|
||||
use Formwork\Utils\Visitor;
|
||||
@ -151,7 +152,7 @@ class Statistics
|
||||
$uniqueVisits = array_slice($uniqueVisits, -$limit, null, true);
|
||||
|
||||
$label = static function (string $day): string {
|
||||
$time = strtotime($day);
|
||||
$time = Date::toTimestamp($day, self::DATE_FORMAT);
|
||||
$month = Admin::instance()->label('date.months.short')[date('n', $time) - 1];
|
||||
$weekday = Admin::instance()->label('date.weekdays.short')[date('N', $time) % 7];
|
||||
$day = date('j', $time);
|
||||
|
@ -5,6 +5,7 @@ namespace Formwork\Admin;
|
||||
use Formwork\Admin\Utils\Registry;
|
||||
use Formwork\Core\Formwork;
|
||||
use Formwork\Parsers\JSON;
|
||||
use Formwork\Utils\Date;
|
||||
use Formwork\Utils\FileSystem;
|
||||
use Formwork\Utils\Str;
|
||||
use RuntimeException;
|
||||
@ -253,7 +254,7 @@ class Updater
|
||||
$this->release = [
|
||||
'name' => $data['name'],
|
||||
'tag' => $data['tag_name'],
|
||||
'date' => strtotime($data['published_at']),
|
||||
'date' => Date::toTimestamp($data['published_at'], DATE_ISO8601),
|
||||
'archive' => $data['zipball_url']
|
||||
];
|
||||
|
||||
|
@ -10,6 +10,7 @@ use Formwork\Parsers\YAML;
|
||||
use Formwork\Router\RouteParams;
|
||||
use Formwork\Router\Router;
|
||||
use Formwork\Traits\SingletonTrait;
|
||||
use Formwork\Utils\Date;
|
||||
use Formwork\Utils\FileSystem;
|
||||
use Formwork\Utils\Header;
|
||||
use Formwork\Utils\HTTPRequest;
|
||||
@ -336,8 +337,8 @@ final class Formwork
|
||||
return $this->site->errorPage();
|
||||
}
|
||||
if ($this->option('cache.enabled') && ($page->has('publish-date') || $page->has('unpublish-date'))) {
|
||||
if (($page->published() && !$this->site->modifiedSince((int) strtotime($page->get('publish-date'))))
|
||||
|| (!$page->published() && !$this->site->modifiedSince((int) strtotime($page->get('unpublish-date'))))) {
|
||||
if (($page->published() && !$this->site->modifiedSince(Date::toTimestamp($page->get('publish-date'))))
|
||||
|| (!$page->published() && !$this->site->modifiedSince(Date::toTimestamp($page->get('unpublish-date'))))) {
|
||||
// Clear cache if the site was not modified since the page has been published or unpublished
|
||||
$this->cache->clear();
|
||||
FileSystem::touch($this->option('content.path'));
|
||||
|
@ -7,6 +7,7 @@ use Formwork\Metadata\Metadata;
|
||||
use Formwork\Parsers\Markdown;
|
||||
use Formwork\Parsers\YAML;
|
||||
use Formwork\Template\Template;
|
||||
use Formwork\Utils\Date;
|
||||
use Formwork\Utils\FileSystem;
|
||||
use Formwork\Utils\Header;
|
||||
use Formwork\Utils\Str;
|
||||
@ -288,7 +289,7 @@ class Page extends AbstractPage
|
||||
$format = Formwork::instance()->option('date.format');
|
||||
}
|
||||
if ($this->has('publish-date')) {
|
||||
return date($format, strtotime($this->data['publish-date']));
|
||||
return date($format, Date::toTimestamp($this->data['publish-date']));
|
||||
}
|
||||
return parent::date($format);
|
||||
}
|
||||
@ -572,11 +573,11 @@ class Page extends AbstractPage
|
||||
$this->published = $this->data['published'];
|
||||
|
||||
if ($this->has('publish-date')) {
|
||||
$this->published = $this->published && strtotime($this->get('publish-date')) < time();
|
||||
$this->published = $this->published && Date::toTimestamp($this->get('publish-date')) < time();
|
||||
}
|
||||
|
||||
if ($this->has('unpublish-date')) {
|
||||
$this->published = $this->published && strtotime($this->get('unpublish-date')) > time();
|
||||
$this->published = $this->published && Date::toTimestamp($this->get('unpublish-date')) > time();
|
||||
}
|
||||
|
||||
$this->routable = $this->data['routable'];
|
||||
|
62
formwork/Utils/Date.php
Normal file
62
formwork/Utils/Date.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Formwork\Utils;
|
||||
|
||||
use Formwork\Core\Formwork;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Date
|
||||
{
|
||||
/**
|
||||
* Parse a date according to a given format (or the default format if not given) and return the timestamp
|
||||
*
|
||||
* @param $throwOnError Whether to throw an Exception when the method fails or trigger a deprecation error (@internal)
|
||||
*/
|
||||
public static function toTimestamp(string $date, string $format = null, bool $throwOnError = false): int
|
||||
{
|
||||
$isFormatGiven = $format !== null;
|
||||
|
||||
if (!$isFormatGiven) {
|
||||
$format = Formwork::instance()->option('date.format');
|
||||
}
|
||||
|
||||
$dateTime = DateTime::createFromFormat($format, $date);
|
||||
|
||||
if ($dateTime === false) {
|
||||
if ($isFormatGiven) {
|
||||
throw new InvalidArgumentException('Date "' . $date . '" is not formatted according to the format "' . $format . '": ' . static::getLastDateTimeError());
|
||||
}
|
||||
try {
|
||||
$dateTime = new DateTime($date);
|
||||
} catch (Exception $e) {
|
||||
$message = 'Invalid date "' . $date . '": ' . static::getLastDateTimeError();
|
||||
// TODO: this will always be the case in 2.0
|
||||
if ($throwOnError) {
|
||||
throw new InvalidArgumentException($message, $e->getCode(), $e->getPrevious());
|
||||
}
|
||||
trigger_error('Using invalid dates is deprecated since Formwork 1.11.0. ' . $message, E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
return $dateTime instanceof DateTime ? $dateTime->getTimestamp() : strtotime($date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-readable string containing details about last DateTime error
|
||||
*/
|
||||
protected static function getLastDateTimeError(): string
|
||||
{
|
||||
$result = [];
|
||||
$lastError = null;
|
||||
if (($errors = DateTime::getLastErrors()) !== false) {
|
||||
foreach ($errors['errors'] as $position => $error) {
|
||||
$currentError = lcfirst(rtrim($error, '.'));
|
||||
$result[] = ($currentError !== $lastError ? $currentError . ' at position ' : '') . $position;
|
||||
$lastError = $currentError;
|
||||
}
|
||||
}
|
||||
return implode(', ', $result);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user