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(array|Traversable $context, array $operations = [])

Construct a new FlowQuery object from $context and $operations.

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!)

__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.

getIterator()

Called when iterating over this FlowQuery object, triggers evaluation.

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(...))

pushOperation(string $operationName, array $arguments)

Push a new operation onto the operations stack.

string
peekOperationName()

Peek onto the next operation name, if any, or NULL otherwise.

array|Traversable
getContext()

Get the current context.

setContext(array|Traversable $context)

Set the updated context with the operation result applied.

bool
allowsCallOfMethod(string $methodName)

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).

Parameters

array|Traversable $context

The initial context (wrapped objects) for this FlowQuery

array $operations

Exceptions

Exception

static FlowQuery q(mixed $element)

The q function from eel

Parameters

mixed $element

Return Value

FlowQuery

Exceptions

Exception

setOperationResolver(OperationResolverInterface $operationResolver)

Setter for setting the operation resolver from the outside, only needed to successfully run unit tests (hacky!)

Parameters

OperationResolverInterface $operationResolver

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.

Parameters

string $operationName
array $arguments

Return Value

FlowQuery

int count()

Implementation of the countable() interface, which is mapped to the "count" operation.

Return Value

int

ArrayIterator getIterator()

Called when iterating over this FlowQuery object, triggers evaluation.

Should NEVER be called inside an operation!

Return Value

ArrayIterator

protected mixed evaluateOperations()

Evaluate operations

Return Value

mixed

the last operation result if the operation is a final operation, NULL otherwise

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.

Return Value

array

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.

Parameters

string $operationName
array $arguments

string peekOperationName()

Peek onto the next operation name, if any, or NULL otherwise.

Should only be called inside an operation.

Return Value

string

the next operation name or NULL if no next operation found.

array|Traversable getContext()

Get the current context.

Should only be called inside an operation.

Return Value

array|Traversable

setContext(array|Traversable $context)

Set the updated context with the operation result applied.

Should only be called inside an operation.

Parameters

array|Traversable $context

bool allowsCallOfMethod(string $methodName)

No description

Parameters

string $methodName

Return Value

bool