-
Notifications
You must be signed in to change notification settings - Fork 139
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from bobthecow/feature/builder-concerns
Extract the RuleBuilder DSL from the base Variable and VariableProperty classes.
- Loading branch information
Showing
10 changed files
with
766 additions
and
389 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Ruler package, an OpenSky project. | ||
* | ||
* (c) 2013 OpenSky Project Inc | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Ruler\RuleBuilder; | ||
|
||
use Ruler\Operator; | ||
use Ruler\RuleBuilder\VariableProperty; | ||
use Ruler\Variable as BaseVariable; | ||
|
||
/** | ||
* A propositional Variable. | ||
* | ||
* Variables are placeholders in Propositions and Comparison Operators. During | ||
* evaluation, they are replaced with terminal Values, either from the Variable | ||
* default or from the current Context. | ||
* | ||
* The RuleBuilder Variable extends the base Variable class with a fluent | ||
* interface for creating VariableProperties, Operators and Rules without all | ||
* kinds of awkward object instantiation. | ||
* | ||
* @author Justin Hileman <[email protected]> | ||
*/ | ||
class Variable extends BaseVariable implements \ArrayAccess | ||
{ | ||
private $properties = array(); | ||
|
||
/** | ||
* Get a VariableProperty for accessing methods, indexes and properties of | ||
* the current variable. | ||
* | ||
* @param string $name Property name | ||
* @param mixed $value The default VariableProperty value | ||
* | ||
* @return VariableProperty | ||
*/ | ||
public function getProperty($name, $value = null) | ||
{ | ||
if (!isset($this->properties[$name])) { | ||
$this->properties[$name] = new VariableProperty($this, $name, $value); | ||
} | ||
|
||
return $this->properties[$name]; | ||
} | ||
|
||
/** | ||
* Fluent interface method for checking whether a VariableProperty has been defined. | ||
* | ||
* @param string $name Property name | ||
* | ||
* @return bool | ||
*/ | ||
public function offsetExists($name) | ||
{ | ||
return isset($this->properties[$name]); | ||
} | ||
|
||
/** | ||
* Fluent interface method for creating or accessing VariableProperties. | ||
* | ||
* @see getProperty | ||
* | ||
* @param string $name Property name | ||
* | ||
* @return VariableProperty | ||
*/ | ||
public function offsetGet($name) | ||
{ | ||
return $this->getProperty($name); | ||
} | ||
|
||
/** | ||
* Fluent interface method for setting default a VariableProperty value. | ||
* | ||
* @see setValue | ||
* | ||
* @param string $name Property name | ||
* @param mixed $value The default Variable value | ||
*/ | ||
public function offsetSet($name, $value) | ||
{ | ||
$this->getProperty($name)->setValue($value); | ||
} | ||
|
||
/** | ||
* Fluent interface method for removing a VariableProperty reference. | ||
* | ||
* @param string $name Property name | ||
*/ | ||
public function offsetUnset($name) | ||
{ | ||
unset($this->properties[$name]); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a contains comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\Contains | ||
*/ | ||
public function contains($variable) | ||
{ | ||
return new Operator\Contains($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a contains comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\DoesNotContain | ||
*/ | ||
public function doesNotContain($variable) | ||
{ | ||
return new Operator\DoesNotContain($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a GreaterThan comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\GreaterThan | ||
*/ | ||
public function greaterThan($variable) | ||
{ | ||
return new Operator\GreaterThan($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a GreaterThanOrEqualTo comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\GreaterThanOrEqualTo | ||
*/ | ||
public function greaterThanOrEqualTo($variable) | ||
{ | ||
return new Operator\GreaterThanOrEqualTo($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a LessThan comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\LessThan | ||
*/ | ||
public function lessThan($variable) | ||
{ | ||
return new Operator\LessThan($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a LessThanOrEqualTo comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\LessThanOrEqualTo | ||
*/ | ||
public function lessThanOrEqualTo($variable) | ||
{ | ||
return new Operator\LessThanOrEqualTo($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a EqualTo comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\EqualTo | ||
*/ | ||
public function equalTo($variable) | ||
{ | ||
return new Operator\EqualTo($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a NotEqualTo comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\NotEqualTo | ||
*/ | ||
public function notEqualTo($variable) | ||
{ | ||
return new Operator\NotEqualTo($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a SameAs comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\SameAs | ||
*/ | ||
public function sameAs($variable) | ||
{ | ||
return new Operator\SameAs($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Fluent interface helper to create a NotSameAs comparison operator. | ||
* | ||
* @param mixed $variable Right side of comparison operator | ||
* | ||
* @return Operator\SameAs | ||
*/ | ||
public function notSameAs($variable) | ||
{ | ||
return new Operator\NotSameAs($this, $this->asVariable($variable)); | ||
} | ||
|
||
/** | ||
* Private helper to retrieve a Variable instance for the given $variable. | ||
* | ||
* @param mixed $variable BaseVariable instance or value | ||
* | ||
* @return BaseVariable | ||
*/ | ||
private function asVariable($variable) | ||
{ | ||
return ($variable instanceof BaseVariable) ? $variable : new BaseVariable(null, $variable); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Ruler package, an OpenSky project. | ||
* | ||
* (c) 2013 OpenSky Project Inc | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Ruler\RuleBuilder; | ||
|
||
use Ruler\Context; | ||
use Ruler\RuleBuilder\Variable; | ||
use Ruler\Value; | ||
use Ruler\Variable as BaseVariable; | ||
|
||
/** | ||
* A propositional VariableProperty. | ||
* | ||
* A VariableProperty is a special propositional Variable which maps to a | ||
* property, method or offset of another Variable. During evaluation, they are | ||
* replaced with terminal Values from properties of their parent Variable, | ||
* either from their default Value, or from the current Context. | ||
* | ||
* The RuleBuilder VariableProperty extends the base VariableProperty class with | ||
* a fluent interface for creating VariableProperties, Operators and Rules | ||
* without all kinds of awkward object instantiation. | ||
* | ||
* (Note that this class doesn't *literally* extend the base VariableProperty | ||
* class, due to PHP's complete inability to use multiple inheritance. Nor does | ||
* it use a trait like it probably should, because this library targets | ||
* PHP 5.3+. Instead it uses a highly refined "copy and paste" technique, | ||
* perfected over years of diligent practice.) | ||
* | ||
* @author Justin Hileman <[email protected]> | ||
*/ | ||
class VariableProperty extends Variable | ||
{ | ||
private $parent; | ||
|
||
/** | ||
* VariableProperty class constructor. | ||
* | ||
* @param BaseVariable $parent Parent Variable instance | ||
* @param string $name Property name | ||
* @param mixed $value Default Property value (default: null) | ||
*/ | ||
public function __construct(BaseVariable $parent, $name, $value = null) | ||
{ | ||
$this->parent = $parent; | ||
parent::__construct($name, $value); | ||
} | ||
|
||
/** | ||
* Prepare a Value for this VariableProperty given the current Context. | ||
* | ||
* To retrieve a Value, the parent Variable is first resolved given the | ||
* current context. Then, depending on its type, a method, property or | ||
* offset of the parent Value is returned. | ||
* | ||
* If the parent Value is an object, and this VariableProperty name is | ||
* "bar", it will do a prioritized lookup for: | ||
* | ||
* 1. A method named `bar` | ||
* 2. A public property named `bar` | ||
* 3. ArrayAccess + offsetExists named `bar` | ||
* | ||
* If it is an array: | ||
* | ||
* 1. Array index `bar` | ||
* | ||
* Otherwise, return the default value for this VariableProperty. | ||
* | ||
* @param Context $context The current Context | ||
* | ||
* @return Value | ||
*/ | ||
public function prepareValue(Context $context) | ||
{ | ||
$name = $this->getName(); | ||
$value = $this->parent->prepareValue($context)->getValue(); | ||
|
||
if (is_object($value) && !$value instanceof \Closure) { | ||
if (method_exists($value, $name)) { | ||
return $this->asValue(call_user_func(array($value, $name))); | ||
} elseif (isset($value->$name)) { | ||
return $this->asValue($value->$name); | ||
} elseif ($value instanceof \ArrayAccess && $value->offsetExists($name)) { | ||
return $this->asValue($value->offsetGet($name)); | ||
} | ||
} elseif (is_array($value) && array_key_exists($name, $value)) { | ||
return $this->asValue($value[$name]); | ||
} | ||
|
||
return $this->asValue($this->getValue()); | ||
} | ||
|
||
/** | ||
* Private helper to retrieve a Value instance for the given $value. | ||
* | ||
* @param mixed $value Value instance or value | ||
* | ||
* @return Value | ||
*/ | ||
private function asValue($value) | ||
{ | ||
return ($value instanceof Value) ? $value : new Value($value); | ||
} | ||
} |
Oops, something went wrong.