Merge branch '2.7' into 2.8

* 2.7:
  [HttpFoundation] Fix UPSERT for PgSql >= 9.5
  [Form] fixed DateTime transformers
  [PropertyAccess][DX] Enhance exception that say that some methods are missing if they don't
This commit is contained in:
Nicolas Grekas 2016-06-16 07:02:45 +02:00
commit 8060715778
9 changed files with 69 additions and 53 deletions

View File

@ -243,7 +243,7 @@ class DbalSessionHandler implements \SessionHandlerInterface
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)"; return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)";
case 'postgresql' === $platform && version_compare($this->con->getServerVersion(), '9.5', '>='): case 'postgresql' === $platform && version_compare($this->con->getServerVersion(), '9.5', '>='):
return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ". return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ".
"ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->timeCol) = (:data, :time) WHERE $this->idCol = :id"; "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->timeCol)";
} }
} }
} }

View File

@ -56,8 +56,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
* @return array Localized date. * @return array Localized date.
* *
* @throws TransformationFailedException If the given value is not an * @throws TransformationFailedException If the given value is not an
* instance of \DateTime or if the * instance of \DateTime or \DateTimeInterface
* output timezone is not supported.
*/ */
public function transform($dateTime) public function transform($dateTime)
{ {
@ -81,11 +80,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
$dateTime = clone $dateTime; $dateTime = clone $dateTime;
} }
try { $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
} }
$result = array_intersect_key(array( $result = array_intersect_key(array(
@ -118,8 +113,6 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
* *
* @throws TransformationFailedException If the given value is not an array, * @throws TransformationFailedException If the given value is not an array,
* if the value could not be transformed * if the value could not be transformed
* or if the input timezone is not
* supported.
*/ */
public function reverseTransform($value) public function reverseTransform($value)
{ {

View File

@ -75,8 +75,8 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
* @return string|array Localized date string/array. * @return string|array Localized date string/array.
* *
* @throws TransformationFailedException If the given value is not an instance * @throws TransformationFailedException If the given value is not an instance
* of \DateTime or if the date could not * of \DateTime or \DateTimeInterface or
* be transformed. * if the date could not be transformed.
*/ */
public function transform($dateTime) public function transform($dateTime)
{ {
@ -105,8 +105,7 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
* @return \DateTime Normalized date * @return \DateTime Normalized date
* *
* @throws TransformationFailedException if the given value is not a string, * @throws TransformationFailedException if the given value is not a string,
* if the date could not be parsed or * if the date could not be parsed
* if the input timezone is not supported
*/ */
public function reverseTransform($value) public function reverseTransform($value)
{ {
@ -132,11 +131,7 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
} }
if ('UTC' !== $this->inputTimezone) { if ('UTC' !== $this->inputTimezone) {
try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
$dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
} }
return $dateTime; return $dateTime;

View File

@ -19,7 +19,14 @@ use Symfony\Component\Form\Exception\TransformationFailedException;
class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
{ {
/** /**
* {@inheritdoc} * Transforms a normalized date into a localized date.
*
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
*
* @return string The formatted date.
*
* @throws TransformationFailedException If the given value is not an
* instance of \DateTime or \DateTimeInterface
*/ */
public function transform($dateTime) public function transform($dateTime)
{ {
@ -32,7 +39,10 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
} }
if ($this->inputTimezone !== $this->outputTimezone) { if ($this->inputTimezone !== $this->outputTimezone) {
$dateTime = clone $dateTime; if (!$dateTime instanceof \DateTimeImmutable) {
$dateTime = clone $dateTime;
}
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
} }
@ -40,7 +50,14 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
} }
/** /**
* {@inheritdoc} * Transforms a formatted string following RFC 3339 into a normalized date.
*
* @param string $rfc3339 Formatted string
*
* @return \DateTime Normalized date
*
* @throws TransformationFailedException If the given value is not a string,
* if the value could not be transformed
*/ */
public function reverseTransform($rfc3339) public function reverseTransform($rfc3339)
{ {
@ -58,12 +75,8 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
} }
if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) { if ($this->inputTimezone !== $dateTime->getTimezone()->getName()) {
try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
$dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
} }
if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) { if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) {

View File

@ -86,35 +86,30 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
* Transforms a DateTime object into a date string with the configured format * Transforms a DateTime object into a date string with the configured format
* and timezone. * and timezone.
* *
* @param \DateTime|\DateTimeInterface $value A DateTime object * @param \DateTime|\DateTimeInterface $dateTime A DateTime object
* *
* @return string A value as produced by PHP's date() function * @return string A value as produced by PHP's date() function
* *
* @throws TransformationFailedException If the given value is not a \DateTime * @throws TransformationFailedException If the given value is not an
* instance or if the output timezone * instance of \DateTime or \DateTimeInterface
* is not supported.
*/ */
public function transform($value) public function transform($dateTime)
{ {
if (null === $value) { if (null === $dateTime) {
return ''; return '';
} }
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) { if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
} }
if (!$value instanceof \DateTimeImmutable) { if (!$dateTime instanceof \DateTimeImmutable) {
$value = clone $value; $dateTime = clone $dateTime;
} }
try { $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
$value = $value->setTimezone(new \DateTimeZone($this->outputTimezone));
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
return $value->format($this->generateFormat); return $dateTime->format($this->generateFormat);
} }
/** /**
@ -125,8 +120,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
* @return \DateTime An instance of \DateTime * @return \DateTime An instance of \DateTime
* *
* @throws TransformationFailedException If the given value is not a string, * @throws TransformationFailedException If the given value is not a string,
* if the date could not be parsed or * or could not be transformed
* if the input timezone is not supported.
*/ */
public function reverseTransform($value) public function reverseTransform($value)
{ {

View File

@ -29,20 +29,19 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
* @return int A timestamp * @return int A timestamp
* *
* @throws TransformationFailedException If the given value is not an instance * @throws TransformationFailedException If the given value is not an instance
* of \DateTime or if the output * of \DateTime or \DateTimeInterface
* timezone is not supported.
*/ */
public function transform($value) public function transform($dateTime)
{ {
if (null === $value) { if (null === $dateTime) {
return; return;
} }
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) { if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
} }
return $value->getTimestamp(); return $dateTime->getTimestamp();
} }
/** /**
@ -53,7 +52,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
* @return \DateTime A \DateTime object * @return \DateTime A \DateTime object
* *
* @throws TransformationFailedException If the given value is not a timestamp * @throws TransformationFailedException If the given value is not a timestamp
* or if the given timestamp is invalid. * or if the given timestamp is invalid
*/ */
public function reverseTransform($value) public function reverseTransform($value)
{ {

View File

@ -678,7 +678,7 @@ class PdoSessionHandler implements \SessionHandlerInterface
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='):
return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ". return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ".
"ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (:data, :lifetime, :time) WHERE $this->idCol = :id"; "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
} }
} }

View File

@ -714,6 +714,17 @@ class PropertyAccessor implements PropertyAccessorInterface
// we call the getter and hope the __call do the job // we call the getter and hope the __call do the job
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_MAGIC; $access[self::ACCESS_TYPE] = self::ACCESS_TYPE_MAGIC;
$access[self::ACCESS_NAME] = $setter; $access[self::ACCESS_NAME] = $setter;
} elseif (null !== $methods = $this->findAdderAndRemover($reflClass, $singulars)) {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_NOT_FOUND;
$access[self::ACCESS_NAME] = sprintf(
'The property "%s" in class "%s" can be defined with the methods "%s()" but '.
'the new value must be an array or an instance of \Traversable, '.
'"%s" given.',
$property,
$reflClass->name,
implode('()", "', $methods),
is_object($value) ? get_class($value) : gettype($value)
);
} else { } else {
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_NOT_FOUND; $access[self::ACCESS_TYPE] = self::ACCESS_TYPE_NOT_FOUND;
$access[self::ACCESS_NAME] = sprintf( $access[self::ACCESS_NAME] = sprintf(

View File

@ -194,4 +194,15 @@ abstract class PropertyAccessorCollectionTest extends PropertyAccessorArrayAcces
$this->assertFalse($this->propertyAccessor->isWritable($car, 'axes', $axes)); $this->assertFalse($this->propertyAccessor->isWritable($car, 'axes', $axes));
} }
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
* expectedExceptionMessageRegExp /The property "axes" in class "Mock_PropertyAccessorCollectionTest_Car[^"]*" can be defined with the methods "addAxis()", "removeAxis()" but the new value must be an array or an instance of \Traversable, "string" given./
*/
public function testSetValueFailsIfAdderAndRemoverExistButValueIsNotTraversable()
{
$car = $this->getMock(__CLASS__.'_Car');
$this->propertyAccessor->setValue($car, 'axes', 'Not an array or Traversable');
}
} }