public function __construct(model_relation_node $predecessor, model_relation_node $successor, model_relation $relation, $intIndexInRelation) { // validate nodes being suitable in desired reference if (!$predecessor->wantsSuccessor() || !$successor->wantsPredecessor()) { throw new \InvalidArgumentException('provided nodes do not expect each other'); } if ($predecessor->getSuccessorReferenceWidth() !== $successor->getPredecessorReferenceWidth()) { throw new \InvalidArgumentException('provided nodes do not fit on each other'); } // validate referencing direction $dir = $predecessor->canBindOnSuccessor() ? 1 : 0; $dir += $successor->canBindOnPredecessor() ? 2 : 0; switch ($dir) { case 0: case 3: throw new \InvalidArgumentException('provided nodes conflict in referencing direction'); default: $this->referencingLeftToRight = $dir == 1; } $this->predecessorEnd = $predecessor; $this->successorEnd = $successor; $this->relation = $relation; $this->intIndexInRelation = intval($intIndexInRelation); }
/** * Adds node to current relation. * * Relation's definition is extended by adding nodes. Added nodes must be * declaring reference on preceding node. Relation is completed by adding * non-partial node not declaring reference on another succeeding node . * Adding further nodes is rejected then. * * @param model_relation_node $node * @param bool $isPartialNode true if node is considered partially defined, yet * @return $this */ public function add(model_relation_node $node, $isPartialNode = false) { if ($this->isComplete()) { throw new \LogicException('adding to completed relation rejected'); } if (!$node->isValid()) { throw new \InvalidArgumentException('invalid relational node'); } if (!$node->wantsPredecessor()) { throw new \InvalidArgumentException('node is not suitable for linking with preceding node'); } $predecessor = $this->nodeAtIndex(-1); if ($predecessor->getSuccessorReferenceWidth() != $node->getPredecessorReferenceWidth()) { throw new \InvalidArgumentException('mismatching width of reference'); } $bindThere = $predecessor->canBindOnSuccessor(); $bindHere = $node->canBindOnPredecessor(); if (!(($bindThere && !$bindHere) ^ (!$bindThere && $bindHere))) { throw new \InvalidArgumentException('node is not compatible with predecessor in binding reference'); } $this->nodes[] = $node; if (!$isPartialNode && !$node->wantsSuccessor()) { // transfer set of nodes into set of references $this->references = array(); for ($i = 1; $i < count($this->nodes); $i++) { $this->references[] = new model_relation_reference($this->nodes[$i - 1], $this->nodes[$i], $this, count($this->references)); } } return $this; }