Commit 649ed4ae authored by jaapjansma's avatar jaapjansma

proof-of-concept

parent 68ad6a68
<?php
/**
* Interface for an ActionProvider.
*/
interface CRM_ActionProvider_Interface {
/**
* Execute the action.
*/
public function execute(CRM_ActionProvider_ParameterInterface $inputParameters);
}
\ No newline at end of file
<?php
/**
* This interface provides the data transfer.
*/
interface CRM_ActionProvider_ParameterInterface {
}
<?php
namespace Civi\ActionProvider\Action;
use \Civi\ActionProvider\Parameter\ParameterBagInterface;
use \Civi\ActionProvider\Parameter\ParameterBag;
use \Civi\ActionProvider\Parameter\SpecificationBag;
use \Civi\ActionProvider\Exception\InvalidParametersException;
use \Civi\ActionProvider\Exception\InvalidConfigurationException;
/**
* This is the abstract class for an action.
*
* Each action has a configuration which could be set in the user interface.
* The parameters passed to the execute function are the data comming from the upper system such as the data in the trigger
* with civirules. Or the data in the table with SqlTasks.
*
*/
abstract class AbstractAction {
/**
* @var ParameterBag
*/
protected $configuration;
/**
* Run the action
*
* @param ParameterInterface $parameters
* The parameters to this action.
* @return void
*/
abstract protected function doAction(ParameterBagInterface $parameters);
/**
* Returns the specification of the configuration options for the actual action.
*
* @return SpecificationBag
*/
abstract public function getConfigurationSpecification();
/**
* Returns the specification of the parameters of the actual action.
*
* @return SpecificationBag
*/
abstract public function getParameterSpecification();
/**
* Returns the human readable title of this action
*/
abstract public function getTitle();
/**
* Returns the system name of the action.
*
* We generate one based on the namespace of the class
* and the class name.
*
* @return string
*/
public function getName() {
$className = get_class($this);
return str_replace('\\', '_', $className);
}
/**
* Execute the action.
*
* The execute method will first validate the given configuration and the given
* parameters against their specifcation.
*
* After that it will fire the doAction method which is implemented in a child class to do the
* actual action.
* This method is basicly a wrapper around doAction.
*
* @param ParameterBagInterface $parameters;
*/
public function execute(ParameterBagInterface $parameters) {
if (!$this->validateConfiguration()) {
throw new InvalidConfigurationException("Found invalid configuration for the action: ".$this->getTitle());
}
if (!$this->validateParameters($parameters)) {
throw new InvalidParametersException("Found invalid configuration for the action: ".$this->getTitle());
}
$this->doAction($parameters);
}
/**
* @return bool
*/
protected function validateParameters(ParameterBagInterface $parameters) {
return SpecificationBag::validate($parameters, $this->getParameterSpecification());
}
/**
* @return bool;
*/
protected function validateConfiguration() {
return SpecificationBag::validate($this->configuration, $this->getConfigurationSpecification());
}
/**
* @return ParameterBag
*/
public function getConfiguration() {
return $this->configuration;
}
/**
* @param ParameterBag $configuration
*/
public function setConfiguration(ParameterBag $configuration) {
$this->configuration = $configuration;
return $this;
}
}
<?php
namespace Civi\ActionProvider\Action;
use \Civi\ActionProvider\Action\AbstractAction;
use \Civi\ActionProvider\Parameter\ParameterBagInterface;
use \Civi\ActionProvider\Parameter\SpecificationBag;
use \Civi\ActionProvider\Parameter\Specification;
use CRM_ActionProvider_ExtensionUtil as E;
class AddToGroup extends AbstractAction {
/**
* Run the action
*
* @param ParameterInterface $parameters
* The parameters to this action.
* @return void
*/
protected function doAction(ParameterBagInterface $parameters) {
civicrm_api3('GroupContact', 'create', array(
'contact_id' => $parameters->getParameter('contact_id'),
'group_id' => $this->configuration->getParameter('group_id'),
));
}
/**
* Returns the specification of the configuration options for the actual action.
*
* @return SpecificationBag
*/
public function getConfigurationSpecification() {
return new SpecificationBag(array(
new Specification('group_id', 'Integer', E::ts('Group ID'), true)
));
}
/**
* Returns the specification of the parameters of the actual action.
*
* @return SpecificationBag
*/
public function getParameterSpecification() {
return new SpecificationBag(array(
new Specification('contact_id', 'Integer', E::ts('Contact ID'), true)
));
}
/**
* Returns the human readable title of this action
*/
public function getTitle() {
return E::ts('Add to group');
}
}
<?php
namespace Civi\ActionProvider\Exception;
class InvalidConfigurationException extends \Exception {
}
<?php
namespace Civi\ActionProvider\Exception;
class InvalidParameterException extends \Exception {
}
<?php
namespace Civi\ActionProvider\Parameter;
use \Civi\ActionProvider\Parameter\ParameterBagInterface;
class ParameterBag implements ParameterBagInterface, \IteratorAggregate {
protected $parameters = array();
/**
* Get the parameter.
*/
public function getParameter($name) {
if (isset($this->parameters[$name])) {
return $this->parameters[$name];
}
return null;
}
/**
* Tests whether the parameter with the name exists.
*/
public function doesParameterExists($name) {
if (isset($this->parameters[$name])) {
return true;
}
return false;
}
/**
* Sets parameter.
*/
public function setParameter($name, $value) {
$this->parameters[$name] = $value;
}
public function getIterator() {
return new \ArrayIterator($this->parameters);
}
}
<?php
namespace Civi\ActionProvider\Parameter;
interface ParameterBagInterface {
/**
* Get the parameter.
*/
public function getParameter($name);
/**
* Tests whether the parameter with the name exists.
*/
public function doesParameterExists($name);
/**
* Sets parameter.
*/
public function setParameter($name, $value);
}
<?php
namespace Civi\ActionProvider\Parameter;
class Specification {
/**
* @var mixed
*/
protected $defaultValue;
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $title;
/**
* @var string
*/
protected $description;
/**
* @var bool
*/
protected $required = FALSE;
/**
* @var array
*/
protected $options = array();
/**
* @var bool
*/
protected $multiple = FALSE;
/**
* @var string
*/
protected $dataType;
/**
* @var string
*/
protected $fkEntity;
/**
* @param $name
* @param $dataType
*/
public function __construct($name, $dataType = 'String', $title='', $required = false, $defaultValue = null, $fkEntity = null, $options = array(), $multiple = false) {
$this->setName($name);
$this->setDataType($dataType);
$this->setTitle($title);
$this->setRequired($required);
$this->setDefaultValue($defaultValue);
$this->setFkEntity($fkEntity);
$this->setOptions($options);
$this->setMultiple($multiple);
}
/**
* @return mixed
*/
public function getDefaultValue() {
return $this->defaultValue;
}
/**
* @param mixed $defaultValue
*
* @return $this
*/
public function setDefaultValue($defaultValue) {
$this->defaultValue = $defaultValue;
return $this;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @param string $name
*
* @return $this
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* @return string
*/
public function getTitle() {
return $this->title;
}
/**
* @param string $title
*
* @return $this
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* @return string
*/
public function getDescription() {
return $this->description;
}
/**
* @param string $description
*
* @return $this
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
/**
* @return bool
*/
public function isRequired() {
return $this->required;
}
/**
* @param bool $required
*
* @return $this
*/
public function setRequired($required) {
$this->required = $required;
return $this;
}
/**
* @return string
*/
public function getDataType() {
return $this->dataType;
}
/**
* @param $dataType
*
* @return $this
* @throws \Exception
*/
public function setDataType($dataType) {
if (!in_array($dataType, $this->getValidDataTypes())) {
throw new \Exception(sprintf('Invalid data type "%s', $dataType));
}
$this->dataType = $dataType;
return $this;
}
/**
* Add valid types that are not not part of \CRM_Utils_Type::dataTypes
*
* @return array
*/
private function getValidDataTypes() {
$extraTypes = array('Boolean', 'Text', 'Float');
$extraTypes = array_combine($extraTypes, $extraTypes);
return array_merge(\CRM_Utils_Type::dataTypes(), $extraTypes);
}
/**
* @return array
*/
public function getOptions() {
return $this->options;
}
/**
* @param array $options
*
* @return $this
*/
public function setOptions($options) {
$this->options = $options;
return $this;
}
/**
* @param $option
*/
public function addOption($option) {
$this->options[] = $option;
}
/**
* @return bool
*/
public function isMultiple() {
return $this->multiple;
}
/**
* @param bool $multiple
*
* @return $this
*/
public function setMultiple($multiple) {
$this->multiple = $multiple;
return $this;
}
/**
* @return string
*/
public function getFkEntity() {
return $this->fkEntity;
}
/**
* @param string $fkEntity
*
* @return $this
*/
public function setFkEntity($fkEntity) {
$this->fkEntity = $fkEntity;
return $this;
}
public function toArray() {
$ret = array();
foreach (get_object_vars($this) as $key => $val) {
$key = strtolower(preg_replace('/(?=[A-Z])/', '_$0', $key));
$ret[$key] = $val;
}
return $ret;
}
}
<?php
namespace Civi\ActionProvider\Parameter;
class SpecificationBag implements \IteratorAggregate {
protected $parameterSpecifications = array();
public function __construct($specifcations = array()) {
foreach($specifcations as $spec) {
$this->parameterSpecifications[$spec->getName()] = $spec;
}
}
/**
* Validates the parameters.
*
* @param ParameterBagInterface $parameters
* @param SpecificationBag $specification
* @return bool
*/
public static function validate(ParameterBagInterface $parameters, SpecificationBag $specification) {
foreach($specification as $spec) {
// First check whether the value is present and should be present.
$value = $parameters->getParameter($spec->getName());
if (isset($value)) {
// Check the type
if (!\CRM_Utils_Type::validate($value, $spec->getDataType(), false)) {
return false;
}
} elseif ($spec->isRequired()) {
return false;
}
}
return true;
}
/**
* @param Specification $specification
* The specification object.
* @return SpecificationBag
*/
public function addSpecification(Specification $specification) {
$this->parameterSpecifications[$specification->getName()] = $specification;
return $this;
}
/**
* @param Specification $specification
* The specification object.
* @return SpecificationBag
*/
public function removeSpecification(Specification $specification) {
foreach($this->parameterSpecifications as $key => $spec) {
if ($spec == $specification) {
unset($this->parameterSpecifications[$key]);
}
}
return $this;
}
/**
* @param string $name
* The name of the parameter.
* @return SpecificationBag
*/
public function removeSpecificationbyName($name) {
foreach($this->parameterSpecifications as $key => $spec) {
if ($spec->getName() == $name) {
unset($this->parameterSpecifications[$key]);
}
}
return $this;
}
/**
* @param string $name
* The name of the parameter.
* @return Specification|null
*/
public function getSpecificationByName($name) {
foreach($this->parameterSpecifications as $key => $spec) {
if ($spec->getName() == $name) {
return $this->parameterSpecifications[$key];
}
}
return null;
}
public function getIterator() {
return new \ArrayIterator($this->parameterSpecifications);
}
}
<?php
namespace Civi\ActionProvider;
use \Civi\ActionProvider\Action\AddToGroup;
/**
* Singleton
*/
class Provider {
protected $availableActions = array();
private static $instance = null;
private function __construct() {
$actions = array(
new AddToGroup(),
);
foreach($actions as $action) {
$this->availableActions[$action->getName()] = $action;
}
}
/**
* @return Provider
*/
public static function getInstance() {
if (!self::$instance) {
self::$instance = new Provider();
}
return self::$instance;
}
public function getActions() {
return $this->availableActions;
}
public function getActionByName($name) {
if (isset($this->availableActions[$name])) {
return $this->availableActions[$name];
}
return null;
}
}
......@@ -20,6 +20,9 @@
<ver>4.7</ver>
</compatibility>
<comments>This is a module in a prototype stage</comments>
<classloader>
<psr4 prefix="Civi\" path="Civi" />
</classloader>
<civix>
<namespace>CRM/ActionProvider</namespace>
</civix>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please