Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
D
drupal
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Custom Issue Tracker
Custom Issue Tracker
Labels
Merge Requests
220
Merge Requests
220
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
project
drupal
Commits
dad3ef55
Commit
dad3ef55
authored
Mar 08, 2013
by
webchick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue
#1913328
by fago: Provide general list and map classes.
parent
b62c536c
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
665 additions
and
152 deletions
+665
-152
core/lib/Drupal/Core/Entity/Field/Type/Field.php
core/lib/Drupal/Core/Entity/Field/Type/Field.php
+5
-145
core/lib/Drupal/Core/TypedData/ItemList.php
core/lib/Drupal/Core/TypedData/ItemList.php
+212
-0
core/lib/Drupal/Core/TypedData/Type/Any.php
core/lib/Drupal/Core/TypedData/Type/Any.php
+27
-0
core/lib/Drupal/Core/TypedData/Type/Map.php
core/lib/Drupal/Core/TypedData/Type/Map.php
+181
-0
core/lib/Drupal/Core/TypedData/TypedDataManager.php
core/lib/Drupal/Core/TypedData/TypedDataManager.php
+28
-6
core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
...ystem/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
+202
-0
core/modules/system/system.api.php
core/modules/system/system.api.php
+2
-1
core/modules/system/system.module
core/modules/system/system.module
+8
-0
No files found.
core/lib/Drupal/Core/Entity/Field/Type/Field.php
View file @
dad3ef55
...
...
@@ -10,11 +10,7 @@
use
Drupal\Core\Entity\Field\FieldInterface
;
use
Drupal\user\Plugin\Core\Entity\User
;
use
Drupal\Core\TypedData\ContextAwareInterface
;
use
Drupal\Core\TypedData\ContextAwareTypedData
;
use
Drupal\Core\TypedData\TypedDataInterface
;
use
ArrayIterator
;
use
IteratorAggregate
;
use
InvalidArgumentException
;
use
Drupal\Core\TypedData\ItemList
;
/**
* Represents an entity field; that is, a list of field item objects.
...
...
@@ -27,7 +23,7 @@
*
* @see \Drupal\Core\Entity\Field\FieldInterface
*/
class
Field
extends
ContextAwareTypedData
implements
IteratorAggregate
,
FieldInterface
{
class
Field
extends
ItemList
implements
FieldInterface
{
/**
* Numerically indexed array of field items, implementing the
...
...
@@ -50,7 +46,7 @@ public function __construct(array $definition, $name = NULL, ContextAwareInterfa
}
/**
* Overrides \Drupal\Core\TypedData\
TypedData
::getValue().
* Overrides \Drupal\Core\TypedData\
ItemList
::getValue().
*/
public
function
getValue
()
{
if
(
isset
(
$this
->
list
))
{
...
...
@@ -68,10 +64,7 @@ public function getValue() {
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::setValue().
*
* @param array|null $values
* An array of values of the field items, or NULL to unset the field.
* Overrides \Drupal\Core\TypedData\ItemList::setValue().
*/
public
function
setValue
(
$values
)
{
if
(
!
isset
(
$values
)
||
$values
===
array
())
{
...
...
@@ -91,7 +84,7 @@ public function setValue($values) {
// Set the values.
foreach
(
$values
as
$delta
=>
$value
)
{
if
(
!
is_numeric
(
$delta
))
{
throw
new
InvalidArgumentException
(
'Unable to set a value with a non-numeric delta in a list.'
);
throw
new
\
InvalidArgumentException
(
'Unable to set a value with a non-numeric delta in a list.'
);
}
elseif
(
!
isset
(
$this
->
list
[
$delta
]))
{
$this
->
list
[
$delta
]
=
$this
->
createItem
(
$delta
,
$value
);
...
...
@@ -103,111 +96,6 @@ public function setValue($values) {
}
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getString().
*/
public
function
getString
()
{
$strings
=
array
();
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$item
)
{
$strings
[]
=
$item
->
getString
();
}
return
implode
(
', '
,
array_filter
(
$strings
));
}
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getConstraints().
*/
public
function
getConstraints
()
{
// Apply the constraints to the list items only.
return
array
();
}
/**
* Implements \ArrayAccess::offsetExists().
*/
public
function
offsetExists
(
$offset
)
{
return
isset
(
$this
->
list
)
&&
array_key_exists
(
$offset
,
$this
->
list
);
}
/**
* Implements \ArrayAccess::offsetUnset().
*/
public
function
offsetUnset
(
$offset
)
{
if
(
isset
(
$this
->
list
))
{
unset
(
$this
->
list
[
$offset
]);
}
}
/**
* Implements \ArrayAccess::offsetGet().
*/
public
function
offsetGet
(
$offset
)
{
if
(
!
is_numeric
(
$offset
))
{
throw
new
InvalidArgumentException
(
'Unable to get a value with a non-numeric delta in a list.'
);
}
// Allow getting not yet existing items as well.
// @todo: Maybe add a public createItem() method in addition?
elseif
(
!
isset
(
$this
->
list
[
$offset
]))
{
$this
->
list
[
$offset
]
=
$this
->
createItem
(
$offset
);
}
return
$this
->
list
[
$offset
];
}
/**
* Helper for creating a list item object.
*
* @return \Drupal\Core\TypedData\TypedDataInterface
*/
protected
function
createItem
(
$offset
=
0
,
$value
=
NULL
)
{
return
typed_data
()
->
getPropertyInstance
(
$this
,
$offset
,
$value
);
}
/**
* Implements \Drupal\Core\TypedData\ListInterface::getItemDefinition().
*/
public
function
getItemDefinition
()
{
return
array
(
'list'
=>
FALSE
)
+
$this
->
definition
;
}
/**
* Implements \ArrayAccess::offsetSet().
*/
public
function
offsetSet
(
$offset
,
$value
)
{
if
(
!
isset
(
$offset
))
{
// The [] operator has been used so point at a new entry.
$offset
=
$this
->
list
?
max
(
array_keys
(
$this
->
list
))
+
1
:
0
;
}
if
(
is_numeric
(
$offset
))
{
// Support setting values via typed data objects.
if
(
$value
instanceof
TypedDataInterface
)
{
$value
=
$value
->
getValue
();
}
$this
->
offsetGet
(
$offset
)
->
setValue
(
$value
);
}
else
{
throw
new
InvalidArgumentException
(
'Unable to set a value with a non-numeric delta in a list.'
);
}
}
/**
* Implements \IteratorAggregate::getIterator().
*/
public
function
getIterator
()
{
if
(
isset
(
$this
->
list
))
{
return
new
ArrayIterator
(
$this
->
list
);
}
return
new
ArrayIterator
(
array
());
}
/**
* Implements \Countable::count().
*/
public
function
count
()
{
return
isset
(
$this
->
list
)
?
count
(
$this
->
list
)
:
0
;
}
/**
* Implements \Drupal\Core\Entity\Field\FieldInterface::getPropertyDefinition().
*/
...
...
@@ -257,34 +145,6 @@ public function __unset($property_name) {
return
$this
->
offsetGet
(
0
)
->
__unset
(
$property_name
);
}
/**
* Implements \Drupal\Core\TypedData\ListInterface::isEmpty().
*/
public
function
isEmpty
()
{
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$item
)
{
if
(
!
$item
->
isEmpty
())
{
return
FALSE
;
}
}
}
return
TRUE
;
}
/**
* Magic method: Implements a deep clone.
*/
public
function
__clone
()
{
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$delta
=>
$item
)
{
$this
->
list
[
$delta
]
=
clone
$item
;
if
(
$item
instanceof
ContextAwareInterface
)
{
$this
->
list
[
$delta
]
->
setContext
(
$delta
,
$this
);
}
}
}
}
/**
* Implements \Drupal\Core\TypedData\AccessibleInterface::access().
*/
...
...
core/lib/Drupal/Core/TypedData/ItemList.php
0 → 100644
View file @
dad3ef55
<?php
/**
* @file
* Contains \Drupal\Core\TypedData\List.
*/
namespace
Drupal\Core\TypedData
;
/**
* A generic list class.
*
* This class can serve as list for any type of items.
* Note: The class cannot be called "List" as list is a reserved PHP keyword.
*/
class
ItemList
extends
ContextAwareTypedData
implements
\
IteratorAggregate
,
ListInterface
{
/**
* Numerically indexed array items.
*
* @var array
*/
protected
$list
=
array
();
/**
* Overrides \Drupal\Core\TypedData\TypedData::getValue().
*/
public
function
getValue
()
{
if
(
isset
(
$this
->
list
))
{
$values
=
array
();
foreach
(
$this
->
list
as
$delta
=>
$item
)
{
$values
[
$delta
]
=
$item
->
getValue
();
}
return
$values
;
}
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::setValue().
*
* @param array|null $values
* An array of values of the field items, or NULL to unset the field.
*/
public
function
setValue
(
$values
)
{
if
(
!
isset
(
$values
)
||
$values
===
array
())
{
$this
->
list
=
$values
;
}
else
{
if
(
!
is_array
(
$values
))
{
throw
new
\
InvalidArgumentException
(
'Cannot set a list with a non-array value.'
);
}
// Clear the values of properties for which no value has been passed.
if
(
isset
(
$this
->
list
))
{
$this
->
list
=
array_intersect_key
(
$this
->
list
,
$values
);
}
// Set the values.
foreach
(
$values
as
$delta
=>
$value
)
{
if
(
!
is_numeric
(
$delta
))
{
throw
new
\
InvalidArgumentException
(
'Unable to set a value with a non-numeric delta in a list.'
);
}
elseif
(
!
isset
(
$this
->
list
[
$delta
]))
{
$this
->
list
[
$delta
]
=
$this
->
createItem
(
$delta
,
$value
);
}
else
{
$this
->
list
[
$delta
]
->
setValue
(
$value
);
}
}
}
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getString().
*/
public
function
getString
()
{
$strings
=
array
();
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$item
)
{
$strings
[]
=
$item
->
getString
();
}
// Remove any empty strings resulting from empty items.
return
implode
(
', '
,
array_filter
(
$strings
,
'drupal_strlen'
));
}
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getConstraints().
*/
public
function
getConstraints
()
{
// Apply the constraints to the list items only.
return
array
();
}
/**
* Implements \ArrayAccess::offsetExists().
*/
public
function
offsetExists
(
$offset
)
{
return
isset
(
$this
->
list
)
&&
array_key_exists
(
$offset
,
$this
->
list
)
&&
$this
->
offsetGet
(
$offset
)
->
getValue
()
!==
NULL
;
}
/**
* Implements \ArrayAccess::offsetUnset().
*/
public
function
offsetUnset
(
$offset
)
{
if
(
isset
(
$this
->
list
))
{
unset
(
$this
->
list
[
$offset
]);
}
}
/**
* Implements \ArrayAccess::offsetGet().
*/
public
function
offsetGet
(
$offset
)
{
if
(
!
is_numeric
(
$offset
))
{
throw
new
\
InvalidArgumentException
(
'Unable to get a value with a non-numeric delta in a list.'
);
}
// Allow getting not yet existing items as well.
// @todo: Maybe add a public createItem() method in addition?
elseif
(
!
isset
(
$this
->
list
[
$offset
]))
{
$this
->
list
[
$offset
]
=
$this
->
createItem
(
$offset
);
}
return
$this
->
list
[
$offset
];
}
/**
* Helper for creating a list item object.
*
* @return \Drupal\Core\TypedData\TypedDataInterface
*/
protected
function
createItem
(
$offset
=
0
,
$value
=
NULL
)
{
return
typed_data
()
->
getPropertyInstance
(
$this
,
$offset
,
$value
);
}
/**
* Implements \Drupal\Core\TypedData\ListInterface::getItemDefinition().
*/
public
function
getItemDefinition
()
{
return
array
(
'list'
=>
FALSE
)
+
$this
->
definition
;
}
/**
* Implements \ArrayAccess::offsetSet().
*/
public
function
offsetSet
(
$offset
,
$value
)
{
if
(
!
isset
(
$offset
))
{
// The [] operator has been used so point at a new entry.
$offset
=
$this
->
list
?
max
(
array_keys
(
$this
->
list
))
+
1
:
0
;
}
if
(
is_numeric
(
$offset
))
{
// Support setting values via typed data objects.
if
(
$value
instanceof
TypedDataInterface
)
{
$value
=
$value
->
getValue
();
}
$this
->
offsetGet
(
$offset
)
->
setValue
(
$value
);
}
else
{
throw
new
\
InvalidArgumentException
(
'Unable to set a value with a non-numeric delta in a list.'
);
}
}
/**
* Implements \IteratorAggregate::getIterator().
*/
public
function
getIterator
()
{
if
(
isset
(
$this
->
list
))
{
return
new
\
ArrayIterator
(
$this
->
list
);
}
return
new
\
ArrayIterator
(
array
());
}
/**
* Implements \Countable::count().
*/
public
function
count
()
{
return
isset
(
$this
->
list
)
?
count
(
$this
->
list
)
:
0
;
}
/**
* Implements \Drupal\Core\TypedData\ListInterface::isEmpty().
*/
public
function
isEmpty
()
{
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$item
)
{
if
(
$item
instanceof
ComplexDataInterface
||
$item
instanceof
ListInterface
)
{
if
(
!
$item
->
isEmpty
())
{
return
FALSE
;
}
}
// Other items are treated as empty if they have no value only.
elseif
(
$item
->
getValue
()
!==
NULL
)
{
return
FALSE
;
}
}
}
return
TRUE
;
}
/**
* Magic method: Implements a deep clone.
*/
public
function
__clone
()
{
if
(
isset
(
$this
->
list
))
{
foreach
(
$this
->
list
as
$delta
=>
$item
)
{
$this
->
list
[
$delta
]
=
clone
$item
;
if
(
$item
instanceof
ContextAwareInterface
)
{
$this
->
list
[
$delta
]
->
setContext
(
$delta
,
$this
);
}
}
}
}
}
core/lib/Drupal/Core/TypedData/Type/Any.php
0 → 100644
View file @
dad3ef55
<?php
/**
* @file
* Contains \Drupal\Core\TypedData\Type\Any.
*/
namespace
Drupal\Core\TypedData\Type
;
use
Drupal\Core\TypedData\TypedData
;
/**
* The "any" data type.
*
* The "any" data type does not implement a list or complex data interface, nor
* is it mappable to any primitive type. Thus, it may contain any PHP data for
* which no further metadata is available.
*/
class
Any
extends
TypedData
{
/**
* The data value.
*
* @var mixed
*/
protected
$value
;
}
core/lib/Drupal/Core/TypedData/Type/Map.php
0 → 100644
View file @
dad3ef55
<?php
/**
* @file
* Contains \Drupal\Core\TypedData\Type\Map.
*/
namespace
Drupal\Core\TypedData\Type
;
use
Drupal\Core\TypedData\ContextAwareTypedData
;
use
Drupal\Core\TypedData\ComplexDataInterface
;
/**
* The "map" data type.
*
* The "map" data type represent a simple complex data type, e.g. for
* representing associative arrays. It can also serve as base class for any
* complex data type.
*
* By default there is no metadata for contained properties. Extending classes
* may want to override Map::getPropertyDefinitions() to define it.
*/
class
Map
extends
ContextAwareTypedData
implements
\
IteratorAggregate
,
ComplexDataInterface
{
/**
* An array of values for the contained properties.
*
* @var array
*/
protected
$values
=
array
();
/**
* The array of properties, each implementing the TypedDataInterface.
*
* @var array
*/
protected
$properties
;
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
*/
public
function
getPropertyDefinitions
()
{
$definitions
=
array
();
foreach
(
$this
->
values
as
$name
=>
$value
)
{
$definitions
[
$name
]
=
array
(
'type'
=>
'any'
,
);
}
return
$definitions
;
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getValue().
*/
public
function
getValue
()
{
return
$this
->
values
;
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::setValue().
*
* @param array|null $values
* An array of property values.
*/
public
function
setValue
(
$values
)
{
if
(
isset
(
$values
)
&&
!
is_array
(
$values
))
{
throw
new
\
InvalidArgumentException
(
"Invalid values given. Values must be represented as an associative array."
);
}
$this
->
values
=
$values
;
unset
(
$this
->
properties
);
}
/**
* Overrides \Drupal\Core\TypedData\TypedData::getString().
*/
public
function
getString
()
{
$strings
=
array
();
foreach
(
$this
->
getProperties
()
as
$property
)
{
$strings
[]
=
$property
->
getString
();
}
// Remove any empty strings resulting from empty items.
return
implode
(
', '
,
array_filter
(
$strings
,
'drupal_strlen'
));
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::get().
*/
public
function
get
(
$property_name
)
{
if
(
!
$this
->
getPropertyDefinition
(
$property_name
))
{
throw
new
\
InvalidArgumentException
(
'Property '
.
check_plain
(
$property_name
)
.
' is unknown.'
);
}
if
(
!
isset
(
$this
->
properties
[
$property_name
]))
{
$this
->
properties
[
$property_name
]
=
typed_data
()
->
getPropertyInstance
(
$this
,
$property_name
,
isset
(
$this
->
values
[
$property_name
])
?
$this
->
values
[
$property_name
]
:
NULL
);
}
return
$this
->
properties
[
$property_name
];
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::set().
*/
public
function
set
(
$property_name
,
$value
)
{
$this
->
get
(
$property_name
)
->
setValue
(
$value
);
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getProperties().
*/
public
function
getProperties
(
$include_computed
=
FALSE
)
{
$properties
=
array
();
foreach
(
$this
->
getPropertyDefinitions
()
as
$name
=>
$definition
)
{
if
(
$include_computed
||
empty
(
$definition
[
'computed'
]))
{
$properties
[
$name
]
=
$this
->
get
(
$name
);
}
}
return
$properties
;
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyValues().
*/
public
function
getPropertyValues
()
{
$values
=
array
();
foreach
(
$this
->
getProperties
()
as
$name
=>
$property
)
{
$values
[
$name
]
=
$property
->
getValue
();
}
return
$values
;
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::setPropertyValues().
*/
public
function
setPropertyValues
(
$values
)
{
foreach
(
$values
as
$name
=>
$value
)
{
$this
->
get
(
$name
)
->
setValue
(
$value
);
}
}
/**
* Implements \IteratorAggregate::getIterator().
*/
public
function
getIterator
()
{
return
new
\
ArrayIterator
(
$this
->
getProperties
());
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinition().
*/
public
function
getPropertyDefinition
(
$name
)
{
$definitions
=
$this
->
getPropertyDefinitions
();
if
(
isset
(
$definitions
[
$name
]))
{
return
$definitions
[
$name
];
}
else
{
return
FALSE
;
}
}
/**
* Implements \Drupal\Core\TypedData\ComplexDataInterface::isEmpty().
*/
public
function
isEmpty
()
{
foreach
(
$this
->
getProperties
()
as
$property
)
{
if
(
$property
->
getValue
()
!==
NULL
)
{
return
FALSE
;
}
}
return
TRUE
;
}
/**
* Magic method: Implements a deep clone.
*/
public
function
__clone
()
{
foreach
(
$this
->
getProperties
()
as
$name
=>
$property
)
{
$this
->
properties
[
$name
]
=
clone
$property
;
if
(
$property
instanceof
ContextAwareInterface
)
{
$this
->
properties
[
$name
]
->
setContext
(
$name
,
$this
);
}
}
}
}
core/lib/Drupal/Core/TypedData/TypedDataManager.php
View file @
dad3ef55
...
...
@@ -8,6 +8,7 @@
namespace
Drupal\Core\TypedData
;
use
InvalidArgumentException
;
use
Drupal\Component\Plugin\Discovery\ProcessDecorator
;
use
Drupal\Component\Plugin\PluginManagerBase
;
use
Drupal\Core\Plugin\Discovery\CacheDecorator
;
use
Drupal\Core\Plugin\Discovery\HookDiscovery
;
...
...
@@ -36,6 +37,17 @@ class TypedDataManager extends PluginManagerBase {
*/
protected
$constraintManager
;
/**
* Type definition defaults which are merged in by the ProcessDecorator.
*
* @see \Drupal\Component\Plugin\PluginManagerBase::processDefinition()
*
* @var array