FlowQuery
class FlowQuery implements ProtectedContextAwareInterface, IteratorAggregate, Countable (View source)
FlowQuery is jQuery for PHP, a selector and traversal engine for object sets.
It is specifically implemented for being used inside Eel, the Embedded Expression Language for Flow.
Essentially, a FlowQuery object is a container for an ordered set of objects of a certain type. On this container, operations can be applied (like filter(), children(), ...).
All of these operations work on a set, that is, an operation usually expands or shrinks the set of objects.
An operation normally returns a new FlowQuery instance with the operation applied, but there are also some operations like is(...) or count(), which return simple types like boolean or numbers. We call these operations final operations.
Internal Workings
To allow for optimization, calling operations are not immediately executed. Instead, they are appended to a list of operations. Only if one tries to iterate over the FlowQuery object or calls a final operation, the operations get executed and the result is computed.
Implementation of Operations
Operations are implemented by implementing the OperationInterface or, more commonly, subclassing the Operations/AbstractOperation.
An operation must be equivalence preserving, that is, the following equation must always hold:
applyAllOperations(context) = applyRemainingOperations(applyOperation(context))
While an operation is running, it can add new operations to the front of the operation queue (with pushOperation()), so for example count($filter) can first apply filter($filter), followed by count(). However, when doing this, great care must be applied by the operation developer in order to still have finite runs, and to make sure the operation is equivalence preserving.
Furthermore, an operation can pop its following operations from the operation stack, and peek what the next operation is. It is up to the operation developer to ensure equivalence preservation.
An operation may never invoke __call() on the FlowQuery object it receives; as this might lead to an undefined state; i.e. you are not allowed to do: $flowQuery->someOtherOperation() inside an operation.
Final Operations
If an operation is final, it should return the resulting value directly.
Properties
protected array|Traversable | $context | the objects this FlowQuery object wraps |
|
protected array | $operations | Ordered list of operations, each operation is internally represented as array('name' => '...', 'arguments' => array(...)) whereas the name is a string like 'children' and the arguments are a numerically-indexed array |
|
protected OperationResolverInterface | $operationResolver |
Methods
Construct a new FlowQuery object from $context and $operations.
Setter for setting the operation resolver from the outside, only needed to successfully run unit tests (hacky!)
Add a new operation to the operation list and return the new FlowQuery object. If the operation is final, we directly compute the result and return the value.
Implementation of the countable() interface, which is mapped to the "count" operation.
Called when iterating over this FlowQuery object, triggers evaluation.
Evaluate operations
Pop the topmost operation from the stack and return it; i.e. the operation which should be executed next. The returned array has the form: array('name' => '...', 'arguments' => array(...))
Push a new operation onto the operations stack.
Peek onto the next operation name, if any, or NULL otherwise.
Get the current context.
No description
Details
__construct(array|Traversable $context, array $operations = [])
Construct a new FlowQuery object from $context and $operations.
Only the $context parameter belongs to the public API!
If a FlowQuery is given as the $context we unwrap its context to assert q(q(context)) == q(context).
static FlowQuery
q(mixed $element)
The q function from eel
setOperationResolver(OperationResolverInterface $operationResolver)
Setter for setting the operation resolver from the outside, only needed to successfully run unit tests (hacky!)
FlowQuery
__call(string $operationName, array $arguments)
Add a new operation to the operation list and return the new FlowQuery object. If the operation is final, we directly compute the result and return the value.
int
count()
Implementation of the countable() interface, which is mapped to the "count" operation.
ArrayIterator
getIterator()
Called when iterating over this FlowQuery object, triggers evaluation.
Should NEVER be called inside an operation!
protected mixed
evaluateOperations()
Evaluate operations
array
popOperation()
Pop the topmost operation from the stack and return it; i.e. the operation which should be executed next. The returned array has the form: array('name' => '...', 'arguments' => array(...))
Should only be called inside an operation.
pushOperation(string $operationName, array $arguments)
Push a new operation onto the operations stack.
The last-pushed operation is executed FIRST! (LIFO)
Should only be called inside an operation.
string
peekOperationName()
Peek onto the next operation name, if any, or NULL otherwise.
Should only be called inside an operation.
array|Traversable
getContext()
Get the current context.
Should only be called inside an operation.
setContext(array|Traversable $context)
Set the updated context with the operation result applied.
Should only be called inside an operation.
bool
allowsCallOfMethod(string $methodName)
No description