Issue #2002102 by Berdir, fago, dixon_: Move TypedData primitive types to interfaces.
parent
c56cb20453
commit
2e9c7fefd6
|
@ -85,17 +85,10 @@ class Context extends ComponentContext {
|
|||
* Overrides \Drupal\Component\Plugin\Context\Context::getConstraints().
|
||||
*/
|
||||
public function validate() {
|
||||
$validator = Validation::createValidatorBuilder()
|
||||
->setTranslator(new DrupalTranslator())
|
||||
->getValidator();
|
||||
|
||||
// @todo We won't need to special case "entity" here once #1868004 lands.
|
||||
if (!empty($this->contextDefinition['type']) && $this->contextDefinition['type'] == 'entity') {
|
||||
$value = $this->getTypedContext();
|
||||
// If the context is typed data, defer to its validation.
|
||||
if (!empty($this->contextDefinition['type'])) {
|
||||
return $this->getTypedContext()->validate();
|
||||
}
|
||||
else {
|
||||
$value = $this->getContextValue();
|
||||
}
|
||||
return $validator->validateValue($value, $this->getConstraints());
|
||||
return parent::validate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\BinaryInterface;
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
|
@ -20,11 +22,10 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "binary",
|
||||
* label = @Translation("Binary"),
|
||||
* primitive_type = 8
|
||||
* label = @Translation("Binary")
|
||||
* )
|
||||
*/
|
||||
class Binary extends TypedData {
|
||||
class Binary extends PrimitiveBase implements BinaryInterface {
|
||||
|
||||
/**
|
||||
* The file resource URI.
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\BooleanInterface;
|
||||
|
||||
/**
|
||||
* The boolean data type.
|
||||
|
@ -19,16 +20,9 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "boolean",
|
||||
* label = @Translation("Boolean"),
|
||||
* primitive_type = 1
|
||||
* label = @Translation("Boolean")
|
||||
* )
|
||||
*/
|
||||
class Boolean extends TypedData {
|
||||
class Boolean extends PrimitiveBase implements BooleanInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $value;
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Plugin\DataType\Date.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
|
||||
/**
|
||||
* The date data type.
|
||||
*
|
||||
* The plain value of a date is an instance of the DrupalDateTime class. For
|
||||
* setting the value any value supported by the __construct() of the
|
||||
* DrupalDateTime class will work, including a DateTime object, a timestamp, a
|
||||
* string date, or an array of date parts.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "date",
|
||||
* label = @Translation("Date"),
|
||||
* primitive_type = 5
|
||||
* )
|
||||
*/
|
||||
class Date extends TypedData {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Overrides TypedData::setValue().
|
||||
*/
|
||||
public function setValue($value, $notify = TRUE) {
|
||||
// Notify the parent of any changes to be made.
|
||||
if ($notify && isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
// Don't try to create a date from an empty value.
|
||||
// It would default to the current time.
|
||||
if (!isset($value)) {
|
||||
$this->value = $value;
|
||||
}
|
||||
else {
|
||||
$this->value = $value instanceOf DrupalDateTime ? $value : new DrupalDateTime($value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\TypedData\Type\DateTimeInterface;
|
||||
|
||||
/**
|
||||
* A data type for ISO 8601 date strings.
|
||||
*
|
||||
* The plain value of this data type is a date string in ISO 8601 format.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "datetime_iso8601",
|
||||
* label = @Translation("Date")
|
||||
* )
|
||||
*/
|
||||
class DateTimeIso8601 extends String implements DateTimeInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateTime() {
|
||||
if ($this->value) {
|
||||
return new DrupalDateTime($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDateTime(DrupalDateTime $dateTime) {
|
||||
$this->value = $dateTime->format('c');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Plugin\DataType\Duration.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use DateInterval;
|
||||
|
||||
/**
|
||||
* The duration data type.
|
||||
*
|
||||
* The plain value of a duration is an instance of the DateInterval class. For
|
||||
* setting the value an instance of the DateInterval class, a ISO8601 string as
|
||||
* supported by DateInterval::__construct, or an integer in seconds may be
|
||||
* passed.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "duration",
|
||||
* label = @Translation("Duration"),
|
||||
* primitive_type = 6
|
||||
* )
|
||||
*/
|
||||
class Duration extends TypedData {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var \DateInterval
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Overrides TypedData::setValue().
|
||||
*/
|
||||
public function setValue($value, $notify = TRUE) {
|
||||
// Notify the parent of any changes to be made.
|
||||
if ($notify && isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
// Catch any exceptions thrown due to invalid values being passed.
|
||||
try {
|
||||
if ($value instanceof DateInterval || !isset($value)) {
|
||||
$this->value = $value;
|
||||
}
|
||||
// Treat integer values as time spans in seconds, even if supplied as PHP
|
||||
// string.
|
||||
elseif ((string) (int) $value === (string) $value) {
|
||||
$this->value = new DateInterval('PT' . $value . 'S');
|
||||
}
|
||||
elseif (is_string($value)) {
|
||||
// @todo: Add support for negative intervals on top of the DateInterval
|
||||
// constructor.
|
||||
$this->value = new DateInterval($value);
|
||||
}
|
||||
else {
|
||||
// Unknown value given.
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// An invalid value has been given. Setting any invalid value will let
|
||||
// validation fail.
|
||||
$this->value = $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides TypedData::getString().
|
||||
*/
|
||||
public function getString() {
|
||||
// Generate an ISO 8601 formatted string as supported by
|
||||
// DateInterval::__construct() and setValue().
|
||||
return (string) $this->getValue()->format('%rP%yY%mM%dDT%hH%mM%sS');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Plugin\DataType\DurationIso8601.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\Type\DurationInterface;
|
||||
|
||||
/**
|
||||
* The duration ISO8601 data type.
|
||||
*
|
||||
* The plain value of this data type is a ISO8601 duration string.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "duration_iso8601",
|
||||
* label = @Translation("Duration")
|
||||
* )
|
||||
*/
|
||||
class DurationIso8601 extends String implements DurationInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDuration() {
|
||||
if ($this->value) {
|
||||
// @todo: Add support for negative intervals on top of the DateInterval
|
||||
// constructor.
|
||||
return new \DateInterval($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDuration(\DateInterval $duration) {
|
||||
// Generate an ISO 8601 formatted string as supported by
|
||||
// DateInterval::__construct() and setValue().
|
||||
$this->value = $duration->format('%rP%yY%mM%dDT%hH%mM%sS');
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\Type\StringInterface;
|
||||
|
||||
/**
|
||||
* The Email data type.
|
||||
|
@ -18,10 +19,9 @@ use Drupal\Core\Annotation\Translation;
|
|||
* @DataType(
|
||||
* id = "email",
|
||||
* label = @Translation("Email"),
|
||||
* primitive_type = 2,
|
||||
* constraints = {"Email" = TRUE}
|
||||
* )
|
||||
*/
|
||||
class Email extends String {
|
||||
class Email extends String implements StringInterface {
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\FloatInterface;
|
||||
|
||||
/**
|
||||
* The float data type.
|
||||
|
@ -19,16 +20,9 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "float",
|
||||
* label = @Translation("Float"),
|
||||
* primitive_type = 4
|
||||
* label = @Translation("Float")
|
||||
* )
|
||||
*/
|
||||
class Float extends TypedData {
|
||||
class Float extends PrimitiveBase implements FloatInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
protected $value;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\IntegerInterface;
|
||||
|
||||
/**
|
||||
* The integer data type.
|
||||
|
@ -19,16 +20,9 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "integer",
|
||||
* label = @Translation("Integer"),
|
||||
* primitive_type = 3
|
||||
* label = @Translation("Integer")
|
||||
* )
|
||||
*/
|
||||
class Integer extends TypedData {
|
||||
class Integer extends PrimitiveBase implements IntegerInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $value;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\StringInterface;
|
||||
|
||||
/**
|
||||
* The string data type.
|
||||
|
@ -19,16 +20,9 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "string",
|
||||
* label = @Translation("String"),
|
||||
* primitive_type = 2
|
||||
* label = @Translation("String")
|
||||
* )
|
||||
*/
|
||||
class String extends TypedData {
|
||||
class String extends PrimitiveBase implements StringInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\TimeSpan.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\Type\DurationInterface;
|
||||
|
||||
/**
|
||||
* The time span data type represents durations as number of seconds.
|
||||
*
|
||||
* The plain value is the (integer) number of seconds. Note that time spans only
|
||||
* map correctly to durations as long as the number of seconds does not exceed
|
||||
* a day (there is already a difference in applying a duration of a day or 24
|
||||
* hours due to daylight savings). If that's an issue, consider using
|
||||
* \Drupal\Core\TypedData\Type\DurationIso8601 instead.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "timespan",
|
||||
* label = @Translation("Time span in seconds")
|
||||
* )
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Type\DurationIso8601
|
||||
*/
|
||||
class TimeSpan extends Integer implements DurationInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDuration() {
|
||||
if ($this->value) {
|
||||
// Keep the duration in seconds as there is generally no valid way to
|
||||
// convert it to days, months or years.
|
||||
return new \DateInterval('PT' . $this->value . 'S');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDuration(\DateInterval $duration) {
|
||||
// Note that this applies the assumption of 12 month's a 30 days and
|
||||
// each year having 365 days. There is no accurate conversion for time spans
|
||||
// exceeding a day.
|
||||
$this->value = ($duration->y * 365 * 24 * 60 * 60) +
|
||||
($duration->m * 30 * 24 * 60 * 60) +
|
||||
($duration->d * 24 * 60 * 60) +
|
||||
($duration->h * 60 * 60) +
|
||||
($duration->i * 60) +
|
||||
$duration->s;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\Timestamp.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Plugin\DataType;
|
||||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\TypedData\Type\DateTimeInterface;
|
||||
|
||||
/**
|
||||
* The timestamp data type.
|
||||
*
|
||||
* @DataType(
|
||||
* id = "timestamp",
|
||||
* label = @Translation("String")
|
||||
* )
|
||||
*/
|
||||
class Timestamp extends Integer implements DateTimeInterface {
|
||||
|
||||
/**
|
||||
* The data value as a UNIX timestamp.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDateTime() {
|
||||
if ($this->value) {
|
||||
return new DrupalDateTime($this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDateTime(DrupalDateTime $dateTime) {
|
||||
$this->value = $dateTime->getTimestamp();
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ namespace Drupal\Core\TypedData\Plugin\DataType;
|
|||
|
||||
use Drupal\Core\TypedData\Annotation\DataType;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Drupal\Core\TypedData\PrimitiveBase;
|
||||
use Drupal\Core\TypedData\Type\UriInterface;
|
||||
use Drupal\Core\TypedData\TypedData;
|
||||
|
||||
/**
|
||||
|
@ -18,16 +20,9 @@ use Drupal\Core\TypedData\TypedData;
|
|||
*
|
||||
* @DataType(
|
||||
* id = "uri",
|
||||
* label = @Translation("URI"),
|
||||
* primitive_type = 7
|
||||
* label = @Translation("URI")
|
||||
* )
|
||||
*/
|
||||
class Uri extends TypedData {
|
||||
class Uri extends PrimitiveBase implements UriInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $value;
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Primitive.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData;
|
||||
|
||||
/**
|
||||
* Class that holds constants for all primitive data types.
|
||||
*/
|
||||
final class Primitive {
|
||||
|
||||
/**
|
||||
* The BOOLEAN primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Boolean
|
||||
*/
|
||||
const BOOLEAN = 1;
|
||||
|
||||
/**
|
||||
* The STRING primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\String
|
||||
*/
|
||||
const STRING = 2;
|
||||
|
||||
/**
|
||||
* The INTEGER primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Integer
|
||||
*/
|
||||
const INTEGER = 3;
|
||||
|
||||
/**
|
||||
* The FLOAT primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Float
|
||||
*/
|
||||
const FLOAT = 4;
|
||||
|
||||
/**
|
||||
* The DATE primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Date
|
||||
*/
|
||||
const DATE = 5;
|
||||
|
||||
/**
|
||||
* The DURATION primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Duration
|
||||
*/
|
||||
const DURATION = 6;
|
||||
|
||||
/**
|
||||
* The URI primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Uri
|
||||
*/
|
||||
const URI = 7;
|
||||
|
||||
/**
|
||||
* The BINARY primitive data type.
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\Plugin\DataType\Binary
|
||||
*/
|
||||
const BINARY = 8;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\PrimitiveBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData;
|
||||
|
||||
/**
|
||||
* Base class for primitive data types.
|
||||
*/
|
||||
abstract class PrimitiveBase extends TypedData implements PrimitiveInterface {
|
||||
|
||||
/**
|
||||
* The data value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setValue($value, $notify = TRUE) {
|
||||
// Notify the parent of any changes to be made.
|
||||
if ($notify && isset($this->parent)) {
|
||||
$this->parent->onChange($this->name);
|
||||
}
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\PrimitiveInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData;
|
||||
|
||||
/**
|
||||
* Interface for primitive data.
|
||||
*/
|
||||
interface PrimitiveInterface {
|
||||
|
||||
/**
|
||||
* Gets the primitive data value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue();
|
||||
|
||||
/**
|
||||
* Sets the primitive data value.
|
||||
*
|
||||
* @param mixed|null $value
|
||||
* The value to set in the format as documented for the data type or NULL to
|
||||
* unset the data value.
|
||||
*/
|
||||
public function setValue($value);
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\BinaryInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for binary data.
|
||||
*
|
||||
* The plain value of binary data is a PHP file resource, see
|
||||
* http://php.net/manual/en/language.types.resource.php. For setting the value
|
||||
* a PHP file resource or a (absolute) stream resource URI may be passed.
|
||||
*/
|
||||
interface BinaryInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\BooleanInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for boolean data.
|
||||
*/
|
||||
interface BooleanInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\DateTimeInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
|
||||
/**
|
||||
* Interface for dates, optionally including a time.
|
||||
*/
|
||||
interface DateTimeInterface {
|
||||
|
||||
/**
|
||||
* Returns the date time object.
|
||||
*
|
||||
* @return \Drupal\Core\Datetime\DrupalDateTime|null
|
||||
* A date object or NULL if there is no date.
|
||||
*/
|
||||
public function getDateTime();
|
||||
|
||||
/**
|
||||
* Sets the date time object.
|
||||
*
|
||||
* @param \Drupal\Core\Datetime\DrupalDateTime $dateTime
|
||||
* An instance of a date time object.
|
||||
*/
|
||||
public function setDateTime(DrupalDateTime $dateTime);
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\BinaryInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for binary data.
|
||||
*/
|
||||
interface DurationInterface extends PrimitiveInterface {
|
||||
|
||||
/**
|
||||
* Returns the duration.
|
||||
*
|
||||
* @return \DateInterval|null
|
||||
* A DateInterval object or NULL if there is no duration.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getDuration();
|
||||
|
||||
/**
|
||||
* Sets the duration.
|
||||
*
|
||||
* @param \DateInterval $duration
|
||||
* A duration to set.
|
||||
*/
|
||||
public function setDuration(\DateInterval $duration);
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\FloatInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for floating-point numbers.
|
||||
*
|
||||
* The plain value of a float is a regular PHP float. For setting the value
|
||||
* any PHP variable that casts to a float may be passed.
|
||||
*/
|
||||
interface FloatInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\IntegerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for integer numbers.
|
||||
*
|
||||
* The plain value of an integer is a regular PHP integer. For setting the value
|
||||
* any PHP variable that casts to an integer may be passed.
|
||||
*/
|
||||
interface IntegerInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\StringInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for strings.
|
||||
*
|
||||
* The plain value of a string is a regular PHP string. For setting the value
|
||||
* any PHP variable that casts to a string may be passed.
|
||||
*/
|
||||
interface StringInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\TypedData\Type\UriInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\TypedData\Type;
|
||||
|
||||
use Drupal\Core\TypedData\PrimitiveInterface;
|
||||
|
||||
/**
|
||||
* Interface for URIs.
|
||||
*
|
||||
* The plain value of a URI is an absolute URI represented as PHP string.
|
||||
*/
|
||||
interface UriInterface extends PrimitiveInterface {
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\Core\TypedData;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManager;
|
||||
|
@ -356,9 +357,10 @@ class TypedDataManager extends DefaultPluginManager {
|
|||
$validation_manager = $this->getValidationConstraintManager();
|
||||
|
||||
$type_definition = $this->getDefinition($definition['type']);
|
||||
// Auto-generate a constraint for the primitive type if we have a mapping.
|
||||
if (isset($type_definition['primitive_type'])) {
|
||||
$constraints[] = $validation_manager->create('PrimitiveType', array('type' => $type_definition['primitive_type']));
|
||||
// Auto-generate a constraint for data types implementing a primitive
|
||||
// interface.
|
||||
if (is_subclass_of($type_definition['class'], '\Drupal\Core\TypedData\PrimitiveInterface')) {
|
||||
$constraints[] = $validation_manager->create('PrimitiveType', array());
|
||||
}
|
||||
// Add in constraints specified by the data type.
|
||||
if (isset($type_definition['constraints'])) {
|
||||
|
|
|
@ -91,4 +91,14 @@ class Metadata implements PropertyMetadataInterface {
|
|||
public function getPropertyValue($container) {
|
||||
return $this->typedData->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the typed data object.
|
||||
*
|
||||
* @return \Drupal\Core\TypedData\TypedDataInterface
|
||||
* The typed data object.
|
||||
*/
|
||||
public function getTypedData() {
|
||||
return $this->typedData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,19 +9,17 @@ namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
|
|||
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
use Symfony\Component\Validator\Constraints\Type as SymfonyConstraint;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Supports validating all primitive types.
|
||||
*
|
||||
* @todo: Move this below the TypedData core component.
|
||||
*
|
||||
* @Plugin(
|
||||
* id = "PrimitiveType",
|
||||
* label = @Translation("Primitive type", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class PrimitiveTypeConstraint extends SymfonyConstraint {
|
||||
class PrimitiveTypeConstraint extends Constraint {
|
||||
|
||||
public $message = 'This value should be of type %type.';
|
||||
public $message = 'This value should be of the correct primitive type.';
|
||||
}
|
||||
|
|
|
@ -8,8 +8,14 @@
|
|||
namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
|
||||
|
||||
use DateInterval;
|
||||
use Drupal\Core\TypedData\Primitive;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\TypedData\Type\BinaryInterface;
|
||||
use Drupal\Core\TypedData\Type\BooleanInterface;
|
||||
use Drupal\Core\TypedData\Type\DateTimeInterface;
|
||||
use Drupal\Core\TypedData\Type\DurationInterface;
|
||||
use Drupal\Core\TypedData\Type\FloatInterface;
|
||||
use Drupal\Core\TypedData\Type\IntegerInterface;
|
||||
use Drupal\Core\TypedData\Type\StringInterface;
|
||||
use Drupal\Core\TypedData\Type\UriInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
|
@ -27,42 +33,44 @@ class PrimitiveTypeConstraintValidator extends ConstraintValidator {
|
|||
return;
|
||||
}
|
||||
|
||||
switch ($constraint->type) {
|
||||
case Primitive::BINARY:
|
||||
$valid = is_resource($value);
|
||||
break;
|
||||
case Primitive::BOOLEAN:
|
||||
$valid = is_bool($value) || $value === 0 || $value === '0' || $value === 1 || $value == '1';
|
||||
break;
|
||||
case Primitive::DATE:
|
||||
$valid = $value instanceOf DrupalDateTime && !$value->hasErrors();
|
||||
break;
|
||||
case Primitive::DURATION:
|
||||
$valid = $value instanceof DateInterval;
|
||||
break;
|
||||
case Primitive::FLOAT:
|
||||
$valid = filter_var($value, FILTER_VALIDATE_FLOAT) !== FALSE;
|
||||
break;
|
||||
case Primitive::INTEGER:
|
||||
$valid = filter_var($value, FILTER_VALIDATE_INT) !== FALSE;
|
||||
break;
|
||||
case Primitive::STRING:
|
||||
// PHP integers, floats or booleans are valid strings also, so we
|
||||
// cannot use is_string() here.
|
||||
$valid = is_scalar($value);
|
||||
break;
|
||||
case Primitive::URI:
|
||||
$valid = filter_var($value, FILTER_VALIDATE_URL) ;
|
||||
break;
|
||||
default:
|
||||
$typed_data = $this->context->getMetadata()->getTypedData();
|
||||
$valid = TRUE;
|
||||
if ($typed_data instanceof BinaryInterface && !is_resource($value)) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
if ($typed_data instanceof BooleanInterface && !(is_bool($value) || $value === 0 || $value === '0' || $value === 1 || $value == '1')) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
if ($typed_data instanceof FloatInterface && filter_var($value, FILTER_VALIDATE_FLOAT) === FALSE) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
if ($typed_data instanceof IntegerInterface && filter_var($value, FILTER_VALIDATE_INT) === FALSE) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
if ($typed_data instanceof StringInterface && !is_scalar($value)) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
if ($typed_data instanceof UriInterface && filter_var($value, FILTER_VALIDATE_URL) === FALSE) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
// @todo: Move those to separate constraint validators.
|
||||
try {
|
||||
if ($typed_data instanceof DateTimeInterface && $typed_data->getDateTime()->hasErrors()) {
|
||||
$valid = FALSE;
|
||||
break;
|
||||
}
|
||||
if ($typed_data instanceof DurationInterface && !($typed_data->getDuration() instanceof DateInterval)) {
|
||||
$valid = FALSE;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Invalid durations or dates might throw exceptions.
|
||||
$valid = FALSE;
|
||||
}
|
||||
|
||||
if (!$valid) {
|
||||
// @todo: Provide a good violation message for each problem.
|
||||
$this->context->addViolation($constraint->message, array(
|
||||
'%value' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value),
|
||||
'%type' => $constraint->type,
|
||||
'%value' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class DateTimeItem extends LegacyConfigFieldItem {
|
|||
|
||||
if (!isset(self::$propertyDefinitions)) {
|
||||
self::$propertyDefinitions['value'] = array(
|
||||
'type' => 'date',
|
||||
'type' => 'datetime_iso8601',
|
||||
'label' => t('Date value'),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -132,47 +132,97 @@ class TypedDataTest extends DrupalUnitTestBase {
|
|||
$typed_data->setValue('invalid');
|
||||
$this->assertEqual($typed_data->validate()->count(), 1, 'Validation detected invalid value.');
|
||||
|
||||
// Date type.
|
||||
$value = new DrupalDateTime();
|
||||
$typed_data = $this->createTypedData(array('type' => 'date'), $value);
|
||||
$this->assertTrue($typed_data->getValue() === $value, 'Date value was fetched.');
|
||||
// Date Time type.
|
||||
$value = '2014-01-01T20:00:00+00:00';
|
||||
$typed_data = $this->createTypedData(array('type' => 'datetime_iso8601'), $value);
|
||||
$this->assertTrue($typed_data->getValue() == $value, 'Date value was fetched.');
|
||||
$this->assertEqual($typed_data->getValue(), $typed_data->getDateTime()->format('c'), 'Value representation of a date is ISO 8601');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$new_value = '2014-01-02T20:00:00+00:00';
|
||||
$typed_data->setValue($new_value);
|
||||
$this->assertTrue($typed_data->getDateTime()->format('c') === $new_value, 'Date value was changed and set by an ISO8601 date.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$this->assertTrue($typed_data->getDateTime()->format('Y-m-d') == '2014-01-02', 'Date value was changed and set by date string.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getDateTime(), 'Date wrapper is null-able.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('invalid');
|
||||
$this->assertEqual($typed_data->validate()->count(), 1, 'Validation detected invalid value.');
|
||||
// Check implementation of DateTimeInterface.
|
||||
$typed_data = $this->createTypedData(array('type' => 'datetime_iso8601'), '2014-01-01T20:00:00+00:00');
|
||||
$this->assertTrue($typed_data->getDateTime() instanceof DrupalDateTime);
|
||||
$typed_data->setDateTime(new DrupalDateTime('2014-01-02T20:00:00+00:00'));
|
||||
$this->assertEqual($typed_data->getValue(), '2014-01-02T20:00:00+00:00');
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getDateTime());
|
||||
|
||||
// Timestamp type.
|
||||
$value = REQUEST_TIME;
|
||||
$typed_data = $this->createTypedData(array('type' => 'timestamp'), $value);
|
||||
$this->assertTrue($typed_data->getValue() == $value, 'Timestamp value was fetched.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$new_value = REQUEST_TIME + 1;
|
||||
$typed_data->setValue($new_value);
|
||||
$this->assertTrue($typed_data->getValue()->getTimestamp() === $new_value, 'Date value was changed and set by timestamp.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('2000-01-01');
|
||||
$this->assertTrue($typed_data->getValue()->format('Y-m-d') == '2000-01-01', 'Date value was changed and set by date string.');
|
||||
$this->assertTrue(is_string($typed_data->getString()), 'Date value was converted to string');
|
||||
$this->assertTrue($typed_data->getValue() === $new_value, 'Timestamp value was changed and set.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getValue(), 'Date wrapper is null-able.');
|
||||
$this->assertNull($typed_data->getDateTime(), 'Timestamp wrapper is null-able.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('invalid');
|
||||
$this->assertEqual($typed_data->validate()->count(), 1, 'Validation detected invalid value.');
|
||||
// Check implementation of DateTimeInterface.
|
||||
$typed_data = $this->createTypedData(array('type' => 'timestamp'), REQUEST_TIME);
|
||||
$this->assertTrue($typed_data->getDateTime() instanceof DrupalDateTime);
|
||||
$typed_data->setDateTime(new DrupalDateTime(REQUEST_TIME + 1));
|
||||
$this->assertEqual($typed_data->getValue(), REQUEST_TIME + 1);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getDateTime());
|
||||
|
||||
// Duration type.
|
||||
$value = new DateInterval('PT20S');
|
||||
$typed_data = $this->createTypedData(array('type' => 'duration'), $value);
|
||||
$this->assertTrue($typed_data->getValue() === $value, 'Duration value was fetched.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(10);
|
||||
$this->assertTrue($typed_data->getValue()->s == 10, 'Duration value was changed and set by time span in seconds.');
|
||||
// DurationIso8601 type.
|
||||
$value = 'PT20S';
|
||||
$typed_data = $this->createTypedData(array('type' => 'duration_iso8601'), $value);
|
||||
$this->assertIdentical($typed_data->getValue(), $value, 'DurationIso8601 value was fetched.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('P40D');
|
||||
$this->assertTrue($typed_data->getValue()->d == 40, 'Duration value was changed and set by duration string.');
|
||||
$this->assertTrue(is_string($typed_data->getString()), 'Duration value was converted to string');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
// Test getting the string and passing it back as value.
|
||||
$duration = $typed_data->getString();
|
||||
$typed_data->setValue($duration);
|
||||
$this->assertEqual($typed_data->getString(), $duration, 'Duration formatted as string can be used to set the duration value.');
|
||||
$this->assertEqual($typed_data->getDuration()->d, 40, 'DurationIso8601 value was changed and set by duration string.');
|
||||
$this->assertTrue(is_string($typed_data->getString()), 'DurationIso8601 value was converted to string');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getValue(), 'Duration wrapper is null-able.');
|
||||
$this->assertNull($typed_data->getValue(), 'DurationIso8601 wrapper is null-able.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('invalid');
|
||||
$this->assertEqual($typed_data->validate()->count(), 1, 'Validation detected invalid value.');
|
||||
// Check implementation of DurationInterface.
|
||||
$typed_data = $this->createTypedData(array('type' => 'duration_iso8601'), 'PT20S');
|
||||
$this->assertTrue($typed_data->getDuration() instanceof DateInterval);
|
||||
$typed_data->setDuration(new DateInterval('P40D'));
|
||||
// @todo: Should we make this "nicer"?
|
||||
$this->assertEqual($typed_data->getValue(), 'P0Y0M40DT0H0M0S');
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getDuration());
|
||||
|
||||
// Time span type.
|
||||
$value = 20;
|
||||
$typed_data = $this->createTypedData(array('type' => 'timespan'), $value);
|
||||
$this->assertIdentical($typed_data->getValue(), $value, 'Time span value was fetched.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(60 * 60 * 4);
|
||||
$this->assertEqual($typed_data->getDuration()->s, 14400, 'Time span was changed');
|
||||
$this->assertTrue(is_string($typed_data->getString()), 'Time span value was converted to string');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getValue(), 'Time span wrapper is null-able.');
|
||||
$this->assertEqual($typed_data->validate()->count(), 0);
|
||||
$typed_data->setValue('invalid');
|
||||
$this->assertEqual($typed_data->validate()->count(), 1, 'Validation detected invalid value.');
|
||||
// Check implementation of DurationInterface.
|
||||
$typed_data = $this->createTypedData(array('type' => 'timespan'), 20);
|
||||
$this->assertTrue($typed_data->getDuration() instanceof DateInterval);
|
||||
$typed_data->setDuration(new DateInterval('PT4H'));
|
||||
$this->assertEqual($typed_data->getValue(), 60 * 60 * 4);
|
||||
$typed_data->setValue(NULL);
|
||||
$this->assertNull($typed_data->getDuration());
|
||||
|
||||
// URI type.
|
||||
$uri = 'http://example.com/foo/';
|
||||
|
|
|
@ -9,7 +9,6 @@ use Drupal\Core\Cache\CacheBackendInterface;
|
|||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Utility\ModuleInfo;
|
||||
use Drupal\Core\TypedData\Primitive;
|
||||
use Drupal\system\Plugin\Block\SystemMenuBlock;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
|
Loading…
Reference in New Issue