chill-bundles/Doctrine/Type/NativeDateIntervalType.php

112 lines
3.1 KiB
PHP

<?php
namespace Chill\MainBundle\Doctrine\Type;
use Doctrine\DBAL\Types\DateIntervalType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
/**
* Re-declare the date interval to use the implementation of date interval in
* postgreql
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class NativeDateIntervalType extends DateIntervalType
{
const FORMAT = '%rP%YY%MM%DDT%HH%IM%SS';
public function getName(): string
{
return \Doctrine\DBAL\Types\Type::DATEINTERVAL;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
{
return 'INTERVAL';
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if (null === $value) {
return null;
}
if ($value instanceof \DateInterval) {
return $value->format(self::FORMAT);
}
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateInterval']);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null || $value instanceof \DateInterval) {
return $value;
}
try {
$strings = explode(' ', $value);
if (count($strings) === 0) {
return null;
}
$intervalSpec = 'P';
\reset($strings);
do {
$intervalSpec .= $this->convertEntry($strings);
} while (next($strings) !== FALSE);
return new \DateInterval($intervalSpec);
} catch (\Exception $exception) {
throw $this->createConversionException($value, $exception);
}
}
private function convertEntry(&$strings)
{
$current = \current($strings);
if (is_numeric($current)) {
$next = \next($strings);
switch($next) {
case 'year':
case 'years':
$unit = 'Y';
break;
case 'mon':
case 'mons':
$unit = 'M';
break;
case 'day':
case 'days':
$unit = 'D';
break;
default:
throw $this->createConversionException(implode('', $strings));
}
return $current.$unit;
} elseif (\preg_match('/([0-9]{2}\:[0-9]{2}:[0-9]{2})/', $current) === 1) {
$tExploded = explode(':', $current);
$intervalSpec = 'T';
$intervalSpec.= $tExploded[0].'H';
$intervalSpec.= $tExploded[1].'M';
$intervalSpec.= $tExploded[2].'S';
return $intervalSpec;
}
}
protected function createConversionException($value, $exception = null)
{
return ConversionException::conversionFailedFormat($value, $this->getName(), 'xx year xx mons xx days 01:02:03', $exception);
}
}