Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
89686bf4
Commit
89686bf4
authored
Feb 18, 2013
by
webchick
Browse files
Issue
#1743686
by EclipseGc, fago, amateescu, damiankloip: Added Condition Plugin System.
parent
b0e08e42
Changes
23
Hide whitespace changes
Inline
Side-by-side
core/lib/Drupal/Component/Plugin/Context/Context.php
View file @
89686bf4
...
...
@@ -8,6 +8,8 @@
namespace
Drupal\Component\Plugin\Context
;
use
Drupal\Component\Plugin\Exception\ContextException
;
use
Symfony\Component\Validator\Constraints\Type
;
use
Symfony\Component\Validator\Validation
;
/**
* A generic context class for wrapping data a plugin needs to operate.
...
...
@@ -39,7 +41,6 @@ public function __construct(array $context_definition) {
* Implements \Drupal\Component\Plugin\Context\ContextInterface::setContextValue().
*/
public
function
setContextValue
(
$value
)
{
$value
=
$this
->
validate
(
$value
);
$this
->
contextValue
=
$value
;
}
...
...
@@ -65,22 +66,22 @@ public function getContextDefinition() {
}
/**
* Implements \Drupal\Component\Plugin\Context\ContextInterface::validate().
*
* The default validation method only supports instance of checks between the
* contextDefintion and the contextValue. Other formats of context
* definitions can be supported through a subclass.
* Implements \Drupal\Component\Plugin\Context\ContextInterface::getConstraints().
*/
public
function
validate
(
$value
)
{
// Check to make sure we have a class name, and that the passed context is
// an instance of that class name.
if
(
!
empty
(
$this
->
contextDefinition
[
'class'
]))
{
if
(
$value
instanceof
$this
->
contextDefinition
[
'class'
])
{
return
$value
;
}
throw
new
ContextException
(
"The context passed was not an instance of
{
$this
->
contextDefinition
[
'class'
]
}
."
);
public
function
getConstraints
()
{
if
(
empty
(
$this
->
contextDefinition
[
'class'
]))
{
throw
new
ContextException
(
"An error was encountered while trying to validate the context."
);
}
throw
new
ContextException
(
"An error was encountered while trying to validate the context."
);
return
array
(
new
Type
(
$this
->
contextDefinition
[
'class'
]));
}
/**
* Implements \Drupal\Component\Plugin\Context\ContextInterface::validate().
*/
public
function
validate
()
{
$validator
=
Validation
::
createValidatorBuilder
()
->
getValidator
();
return
$validator
->
validateValue
(
$this
->
getContextValue
(),
$this
->
getConstraints
());
}
}
core/lib/Drupal/Component/Plugin/Context/ContextInterface.php
View file @
89686bf4
...
...
@@ -7,8 +7,6 @@
namespace
Drupal\Component\Plugin\Context
;
use
Drupal\Component\Plugin\Exception\ContextException
;
/**
* A generic context interface for wrapping data a plugin needs to operate.
*/
...
...
@@ -18,8 +16,9 @@ interface ContextInterface {
* Sets the context value.
*
* @param mixed $value
* The value of this context, generally an object based upon the class
* matching the definition passed to setContextDefinition().
* The value of this context, matching the context definition.
*
* @see \Drupal\Component\Plugin\Context\ContextInterface::setContextDefinition().
*/
public
function
setContextValue
(
$value
);
...
...
@@ -27,42 +26,45 @@ public function setContextValue($value);
* Gets the context value.
*
* @return mixed
* The currently set context value
within this class
.
* The currently set context value
, or NULL if it is not set
.
*/
public
function
getContextValue
();
/**
* Sets the definition that the context must conform to.
*
* @param
mixed
$contextDefinition
* @param
array
$contextDefinition
* A defining characteristic representation of the context against which
* that context can be validated. This is typically a class name, but could
* be extended to support other validation notation.
* that context can be validated. This is typically an array having a
* class name set under the 'class' key, but it could be extended to support
* other notations.
*/
public
function
setContextDefinition
(
array
$contextDefinition
);
/**
* Gets the provided definition that the context must conform to.
*
* @return
mixed
* @return
array
* The defining characteristic representation of the context.
*/
public
function
getContextDefinition
();
/**
* Validate the provided context value against the provided definition.
*
* @param mixed $value
* The context value that should be validated against the context
* definition.
* Gets a list of validation constraints.
*
* @return mixed
* Returns the context value passed to it. If it fails validation, an
* exception will be thrown.
* @return array
* Array of constraints, each being an instance of
* \Symfony\Component\Validator\Constraint.
*/
public
function
getConstraints
();
/**
* Validates the set context value.
*
* @throws \Drupal\Component\Plugin\Exception\ContextException
* If validation fails.
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
* A list of constraint violations. If the list is empty, validation
* succeeded.
*/
public
function
validate
(
$value
);
public
function
validate
();
}
core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
View file @
89686bf4
...
...
@@ -9,6 +9,8 @@
use
Drupal\Component\Plugin\Exception\PluginException
;
use
Drupal\Component\Plugin\Context\Context
;
use
Symfony\Component\Validator\ConstraintViolationList
;
use
Drupal\Component\Plugin\Discovery\DiscoveryInterface
;
/**
* Base class for plugins that are context aware.
...
...
@@ -22,23 +24,49 @@ abstract class ContextAwarePluginBase extends PluginBase implements ContextAware
*/
protected
$context
;
/**
* Overrides \Drupal\Component\Plugin\PluginBase::__construct().
*
* Overrides the construction of context aware plugins to allow for
* unvalidated constructor based injection of contexts.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
*/
public
function
__construct
(
array
$configuration
,
$plugin_id
,
DiscoveryInterface
$discovery
)
{
$context
=
array
();
if
(
isset
(
$configuration
[
'context'
]))
{
$context
=
$configuration
[
'context'
];
unset
(
$configuration
[
'context'
]);
}
parent
::
__construct
(
$configuration
,
$plugin_id
,
$discovery
);
foreach
(
$context
as
$key
=>
$value
)
{
$context_definition
=
$this
->
getContextDefinition
(
$key
);
$this
->
context
[
$key
]
=
new
Context
(
$context_definition
);
$this
->
context
[
$key
]
->
setContextValue
(
$value
);
}
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinitions().
*/
public
function
getContextDefinitions
()
{
$definition
=
$this
->
getDefinition
();
return
!
empty
(
$definition
[
'context'
])
?
$definition
[
'context'
]
:
NULL
;
return
!
empty
(
$definition
[
'context'
])
?
$definition
[
'context'
]
:
array
()
;
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinition().
*/
public
function
getContextDefinition
(
$
key
)
{
public
function
getContextDefinition
(
$
name
)
{
$definition
=
$this
->
getDefinition
();
if
(
empty
(
$definition
[
'context'
][
$
key
]))
{
throw
new
PluginException
(
"The
$
key
context is not a valid context."
);
if
(
empty
(
$definition
[
'context'
][
$
name
]))
{
throw
new
PluginException
(
"The
$
name
context is not a valid context."
);
}
return
$definition
[
'context'
][
$
key
];
return
$definition
[
'context'
][
$
name
];
}
/**
...
...
@@ -46,19 +74,15 @@ public function getContextDefinition($key) {
*/
public
function
getContexts
()
{
$definitions
=
$this
->
getContextDefinitions
();
// If there are no contexts defined by the plugin, return an empty array.
if
(
empty
(
$definitions
))
{
return
array
();
}
if
(
empty
(
$this
->
context
))
{
if
(
$definitions
&&
empty
(
$this
->
context
))
{
throw
new
PluginException
(
"There are no set contexts."
);
}
$contexts
=
array
();
foreach
(
array_keys
(
$definitions
)
as
$
key
)
{
if
(
empty
(
$this
->
context
[
$
key
]))
{
throw
new
PluginException
(
"The
$
key
context is not yet set."
);
foreach
(
array_keys
(
$definitions
)
as
$
name
)
{
if
(
empty
(
$this
->
context
[
$
name
]))
{
throw
new
PluginException
(
"The
$
name
context is not yet set."
);
}
$contexts
[
$
key
]
=
$this
->
context
[
$
key
];
$contexts
[
$
name
]
=
$this
->
context
[
$
name
];
}
return
$contexts
;
}
...
...
@@ -66,44 +90,67 @@ public function getContexts() {
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContext().
*/
public
function
getContext
(
$
key
)
{
public
function
getContext
(
$
name
)
{
// Check for a valid context definition.
$this
->
getContextDefinition
(
$
key
);
$this
->
getContextDefinition
(
$
name
);
// Check for a valid context value.
if
(
empty
(
$this
->
context
[
$
key
]))
{
throw
new
PluginException
(
"The
$
key
context is not yet set."
);
if
(
!
isset
(
$this
->
context
[
$
name
]))
{
throw
new
PluginException
(
"The
$
name
context is not yet set."
);
}
return
$this
->
context
[
$
key
];
return
$this
->
context
[
$
name
];
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValues().
*/
public
function
getContextValues
()
{
$
context
s
=
array
();
foreach
(
$this
->
getContexts
()
as
$
key
=>
$
context
)
{
$context
s
[
$
key
]
=
$context
->
getContextValue
();
$
value
s
=
array
();
foreach
(
$this
->
getContext
Definition
s
()
as
$
name
=>
$
definition
)
{
$
values
[
$name
]
=
isset
(
$this
->
context
[
$
name
])
?
$this
->
context
[
$name
]
->
getContextValue
()
:
NULL
;
}
return
$
context
s
;
return
$
value
s
;
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValue().
*/
public
function
getContextValue
(
$
key
)
{
return
$this
->
getContext
(
$
key
)
->
getContextValue
();
public
function
getContextValue
(
$
name
)
{
return
$this
->
getContext
(
$
name
)
->
getContextValue
();
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::setContextValue().
*/
public
function
setContextValue
(
$
key
,
$value
)
{
$context_definition
=
$this
->
getContextDefinition
(
$
key
);
$this
->
context
[
$
key
]
=
new
Context
(
$context_definition
);
$this
->
context
[
$
key
]
->
setContextValue
(
$value
);
public
function
setContextValue
(
$
name
,
$value
)
{
$context_definition
=
$this
->
getContextDefinition
(
$
name
);
$this
->
context
[
$
name
]
=
new
Context
(
$context_definition
);
$this
->
context
[
$
name
]
->
setContextValue
(
$value
);
// Verify the provided value validates.
$violations
=
$this
->
context
[
$name
]
->
validate
();
if
(
count
(
$violations
)
>
0
)
{
throw
new
PluginException
(
"The provided context value does not pass validation."
);
}
return
$this
;
}
/**
* Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::valdidateContexts().
*/
public
function
validateContexts
()
{
$violations
=
new
ConstraintViolationList
();
// @todo: Implement symfony validator API to let the validator traverse
// and set property paths accordingly.
foreach
(
$this
->
getContextDefinitions
()
as
$name
=>
$definition
)
{
// Validate any set values.
if
(
isset
(
$this
->
context
[
$name
]))
{
$violations
->
addAll
(
$this
->
context
[
$name
]
->
validate
());
}
// @todo: If no value is set, make sure any mapping is validated.
}
return
$violations
;
}
}
core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php
View file @
89686bf4
...
...
@@ -8,35 +8,43 @@
namespace
Drupal\Component\Plugin
;
use
Drupal\Component\Plugin\Exception\PluginException
;
use
Drupal\Component\Plugin\Context\Context
;
/**
* Interface for defining context aware plugins.
*
* Context aware plugins can specify an array of context definitions keyed by
* context name at the plugin definition under the "context" key.
*/
interface
ContextAwarePluginInterface
extends
PluginInspectionInterface
{
/**
* Gets the context definitions of the plugin.
*
* @return array
|null
* The context definitions
if set, otherwise NULL
.
* @return array
* The
array of
context definitions
, keyed by context name
.
*/
public
function
getContextDefinitions
();
/**
* Gets
the
a specific context definition of the plugin.
* Gets a specific context definition of the plugin.
*
* @param string $
key
* @param string $
name
* The name of the context in the plugin definition.
*
* @return mixed
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If the requested context is not defined.
*
* @return array
* The definition against which the context value must validate.
*/
public
function
getContextDefinition
(
$
key
);
public
function
getContextDefinition
(
$
name
);
/**
* Gets the defined contexts.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If contexts are defined but not set.
*
* @return array
* The set context objects.
*/
...
...
@@ -45,47 +53,64 @@ public function getContexts();
/**
* Gets a defined context.
*
* @param string $key
* The name of the context in the plugin configuration. This string is
* usually identical to the representative string in the plugin definition.
* @param string $name
* The name of the context in the plugin definition.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If the requested context is not set.
*
* @return \Drupal\Component\Plugin\Context\ContextInterface
* The context object.
*/
public
function
getContext
(
$
key
);
public
function
getContext
(
$
name
);
/**
* Gets the values for all defined contexts.
*
* @return array
* The set context object values.
* An array of set context values, keyed by context name. If a context is
* unset its value is returned as NULL.
*/
public
function
getContextValues
();
/**
* Gets the value for a defined context.
*
* @param string $key
* The name of the context in the plugin configuration. This string is
* usually identical to the representative string in the plugin definition.
* @param string $name
* The name of the context in the plugin configuration.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If the requested context is not set.
*
* @return mixed
* The currently set context value.
*/
public
function
getContextValue
(
$
key
);
public
function
getContextValue
(
$
name
);
/**
* Sets the value for a defined context.
*
* @param string $
key
* @param string $
name
* The name of the context in the plugin definition.
* @param mixed $value
* The va
riab
le to set the context to. Th
is should
validate against the
* The val
u
e to set the context to. Th
e value has to
validate against the
* provided context definition.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If the value does not pass validation.
*
* @return \Drupal\Component\Plugin\ContextAwarePluginInterface.
* A context aware plugin object for chaining.
*/
public
function
setContextValue
(
$key
,
$value
);
public
function
setContextValue
(
$name
,
$value
);
/**
* Validates the set values for the defined contexts.
*
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
* A list of constraint violations. If the list is empty, validation
* succeeded.
*/
public
function
validateContexts
();
}
core/lib/Drupal/Core/Condition/ConditionInterface.php
0 → 100644
View file @
89686bf4
<?php
/**
* @file
* Contains \Drupal\Core\Condition\ConditionInterface.
*/
namespace
Drupal\Core\Condition
;
use
Drupal\Core\Executable\ExecutableInterface
;
/**
* An interface for condition plugins.
*
* @see \Drupal\Core\Executable\ExecutableInterface
*/
interface
ConditionInterface
extends
ExecutableInterface
{
/**
* Determines whether condition result will be negated.
*
* @return boolean
* Whether the condition result will be negated.
*/
public
function
isNegated
();
/**
* Evaluates the condition and returns TRUE or FALSE accordingly.
*
* @return bool
* TRUE if the condition has been met, FALSE otherwise.
*/
public
function
evaluate
();
}
core/lib/Drupal/Core/Condition/ConditionManager.php
0 → 100644
View file @
89686bf4
<?php
/**
* @file
* Contains \Drupal\Core\Condition\ConditionManager.
*/
namespace
Drupal\Core\Condition
;
use
Drupal\Component\Plugin\PluginManagerBase
;
use
Drupal\Core\Executable\ExecutableManagerInterface
;
use
Drupal\Core\Executable\ExecutableInterface
;
use
Drupal\Component\Plugin\Factory\DefaultFactory
;
use
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator
;
use
Drupal\Core\Plugin\Discovery\AlterDecorator
;
use
Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery
;
use
Drupal\Core\Plugin\Discovery\CacheDecorator
;
/**
* A plugin manager for condition plugins.
*/
class
ConditionManager
extends
PluginManagerBase
implements
ExecutableManagerInterface
{
/**
* Constructs aa ConditionManager object.
*/
public
function
__construct
()
{
$this
->
discovery
=
new
AnnotatedClassDiscovery
(
'Core'
,
'Condition'
);
$this
->
discovery
=
new
DerivativeDiscoveryDecorator
(
$this
->
discovery
);
$this
->
discovery
=
new
AlterDecorator
(
$this
->
discovery
,
'condition_info'
);
$this
->
discovery
=
new
CacheDecorator
(
$this
->
discovery
,
'condition:'
.
language
(
LANGUAGE_TYPE_INTERFACE
)
->
langcode
);
$this
->
factory
=
new
DefaultFactory
(
$this
);
}
/**
* Override of Drupal\Component\Plugin\PluginManagerBase::createInstance().
*/
public
function
createInstance
(
$plugin_id
,
array
$configuration
=
array
())
{
$plugin
=
$this
->
factory
->
createInstance
(
$plugin_id
,
$configuration
);
return
$plugin
->
setExecutableManager
(
$this
);
}
/**
* Implements Drupal\Core\Executable\ExecutableManagerInterface::execute().
*/
public
function
execute
(
ExecutableInterface
$condition
)
{
$result
=
$condition
->
evaluate
();
return
$condition
->
isNegated
()
?
!
$result
:
$result
;
}
}
core/lib/Drupal/Core/Condition/ConditionPluginBase.php
0 → 100644
View file @
89686bf4
<?php
/**
* @file
* Contains \Drupal\Core\Condition\ConditionPluginBase.
*/
namespace
Drupal\Core\Condition
;
use
Drupal\Core\Executable\ExecutablePluginBase
;
/**
* Provides a basis for fulfilling contexts for condition plugins.
*/
abstract
class
ConditionPluginBase
extends
ExecutablePluginBase
implements
ConditionInterface
{
/**
* Implements \Drupal\Core\Form\FormInterface::getFormID().
*/
public
function
getFormID
()
{
$definition
=
$this
->
getDefinition
();
return
implode
(
'_'
,
array
(
$definition
[
'module'
],
$definition
[
'id'
],
'condition'
));
}
/**
* Implements \Drupal\condition\Plugin\ConditionInterface::isNegated().
*/
public
function
isNegated
()
{
return
!
empty
(
$this
->
configuration
[
'negate'
]);
}
/**
* Implements \Drupal\Core\Form\FormInterface::buildForm().
*/
public
function
buildForm
(
array
$form
,
array
&
$form_state
)
{
$form
[
'negate'
]
=
array
(
'#type'
=>
'checkbox'
,
'#title'
=>
t
(
'Negate the condition.'
),
'#default_value'
=>
isset
(
$this
->
configuration
[
'negate'
])
?
$this
->
configuration
[
'negate'
]
:
FALSE
,
);
return
$form
;
}
/**
* Implements \Drupal\Core\Form\FormInterface::validateForm().
*/
public
function
validateForm
(
array
&
$form
,
array
&
$form_state
)
{}
/**
* Implements \Drupal\Core\Form\FormInterface::submitForm().
*/
public
function
submitForm
(
array
&
$form
,
array
&
$form_state
)
{
$this
->
configuration
[
'negate'
]
=
$form_state
[
'values'
][
'negate'
];
}
/**
* Implements \Drupal\Core\Executable\ExecutablePluginBase::execute().
*/
public
function
execute
()
{
return
$this
->
executableManager
->
execute
(
$this
);
}
}
core/lib/Drupal/Core/CoreBundle.php
View file @
89686bf4
...
...
@@ -276,6 +276,8 @@ public function build(ContainerBuilder $container) {
$container
->
register
(
'flood'
,
'Drupal\Core\Flood\DatabaseBackend'
)
->
addArgument
(
new
Reference
(
'database'
));
$container
->
register
(
'plugin.manager.condition'
,
'Drupal\Core\Condition\ConditionManager'
);
$container
->
addCompilerPass
(
new
RegisterMatchersPass
());
$container
->
addCompilerPass
(
new
RegisterRouteFiltersPass
());
// Add a compiler pass for registering event subscribers.
...
...
core/lib/Drupal/Core/Executable/ExecutableException.php
0 → 100644
View file @
89686bf4
<?php
/**
* @file