From 21b4c734a69debf96bee63ccae6ea889da00b547 Mon Sep 17 00:00:00 2001 From: Justin Hileman Date: Mon, 9 Sep 2013 10:23:36 -0700 Subject: [PATCH] Add a VariableProperty trait. Use this when creating extended RuleBuilder DSLs with custom operators and magick like that. It doesn't do *us* any good, since we're targeting PHP 5.3 with this library, but it does help on the extensibility front. --- .../RuleBuilder/VariablePropertyTrait.php | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/Ruler/RuleBuilder/VariablePropertyTrait.php diff --git a/src/Ruler/RuleBuilder/VariablePropertyTrait.php b/src/Ruler/RuleBuilder/VariablePropertyTrait.php new file mode 100644 index 0000000..8673935 --- /dev/null +++ b/src/Ruler/RuleBuilder/VariablePropertyTrait.php @@ -0,0 +1,105 @@ + + */ +trait VariablePropertyTrait +{ + private $parent; + + /** + * Set the parent Variable reference. + * + * @param Variable $parent Parent Variable instance + */ + public function setParent(Variable $parent) + { + $this->parent = $parent; + } + + /** + * 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); + } +}