Open phenaproxima opened 10 years ago
Ah this is almost there now we just missing some create method for ObjectPropertyNode. Then be something like:
$var = Token::variable('$node');
$var = ObjectPropertyNode::create($var, 'body');
$var = ArrayLookupNode::create($var, Token::integer(0));
$var = ObjectPropertyNode::create($var, 'value');
$var = ObjectMethodCallNode::create($var, 'get');
// results in $node->body[0]->value->get()
To make it chainable will require adding methods that call these create methods. For example:
class ArrayLookupNode {
public function methodCall($methodName) {
return ObjectMethodCallNode::create($this, $methodName);
}
public function objectProperty($propertyName) {
return ObjectPropertyNode::create($this, $propertyName);
}
}
Since -> is for both object property and method calls, will need both these methods.
Gotcha.
I still think these should be defined on an interface, if for no other reason than it keeps it clear as to what types of nodes support chaining (if I'm not forgetting any, that'll be CallNode, VariableNode, ObjectPropertyNode, and ArrayLookupNode).
I propose something like this:
interface ChainableExpression extends Expression {
/** @return ObjectMethodCallNode **/
public function appendMethodCall($method_name);
/** @return ObjectMethodCallNode **/
public function appendProperty($property_name);
/** @return ArrayLookupNode **/
public function appendIndex($index);
}
I can probably create a PoC of this.
Yes could be interface if there a need to identify which nodes support it. Note that a lot of the traits don't have an associated interface though to identify which nodes support those operations. Whether they should or not... not sure. Just making observation there.
And probably have a Trait for implementation here since I believe the same implementation should be the same across the board.
In DMU, I'm starting to need to build constructs like this:
$node->field_foo[0]->value $node->getTranslation('fr')->field_foo[0]->value
These expressions are getting really complex. I could just use parseExpression and feed it raw PHP, of course, but that's not ideal, especially considering that the chaining stuff we added to CallNode is so elegant and works so well.
What would be amazing -- and I can't honestly call this high priority, but it'd be extremely nice to have -- is the ability to chain different kinds of expressions beyond just CallNodes. Obviously not every type of expression can be chained, so I'm thinking we could devise a ChainableExpression interface (extending Expression), which exposes an appendExpression() method. This method accepts an Expression, and then returns $existingChain->$appendedExpr. And if the resulting chain is itself a chainable expression, it can be chained again.
So I envision something like the following: