Merge this operation with the previous operation and return the result.

@param FieldOperation $previous Previous Operation.

@return FieldOperation Merged Operation.
@throws AVException
18733
public function _mergeWithPrevious($previous)
    {
        if (!$previous)
        {
            return $this;
        }
        if ($previous instanceof DeleteOperation)
        {
            return new SetOperation($this->objects);
        }
        if ($previous instanceof SetOperation)
        {
            $oldValue = $previous->getValue();
            $result = $this->_apply($oldValue, null, null);

            return new SetOperation($result);
        }
        if ($previous instanceof AddUniqueOperation)
        {
            $oldList = $previous->getValue();
            $result = $this->_apply($oldList, null, null);

            return new AddUniqueOperation($result);
        }
        throw new AVException('Operation is invalid after previous operation.');
    }
58071
public function prev() {
		$prev = $this->domnode;
		if(!$prev)
			return new Node(null);
		while(true) {
			$prev = $prev->previousSibling;
			if(!$prev)
				return new Node(null);
			if($prev->nodeType == XML_ELEMENT_NODE)
				return new Node($prev);
		}
	}
376812
public static function getCreateOperation($input, $fields) {
		$operation = new CreateTransactionOperation(static::getClass(), $input, $fields);
		$operation->setSQLAdapter(static::getSQLAdapter());
		return $operation;
	}
1271297
private function getNextPreviousCollection($previous)
    {
        $result = false;
        $reverseMap = [
            'chrono_asc' => 'chrono_desc',
            'chrono_desc' => 'chrono_asc',
            'display_desc' => 'display_asc',
            'display_asc' => 'display_desc',
        ];
        $orderBy = $this->orderBy && isset($reverseMap[$this->orderBy]) ? $this->orderBy : 'display_asc';
        if ($previous) {
            $orderBy = $reverseMap[$orderBy];
        }
        $db = $this->app->make(Connection::class);
        $now = $this->app->make('date')->getOverridableNow();
        for ($page = Page::getCurrentPage(); $page && !$page->isError();) {
            switch ($orderBy) {
                case 'chrono_desc':
                    $cID = $db->fetchColumn(
                        <<<'EOT'
select
    Pages.cID
from
    Pages
    inner join CollectionVersions cv
        on Pages.cID = cv.cID
where
    Pages.cID <> ?
    and cvIsApproved = 1 and (cvPublishDate is null or cvPublishDate <= ?) and (cvPublishEndDate is null or cvPublishEndDate >= ?)
    and ((cvDatePublic = ? and cDisplayOrder > ?) or cvDatePublic > ?)
    and cParentID = ?
order by
    cvDatePublic asc,
    cDisplayOrder asc
EOT
                        ,
                        [$page->getCollectionID(), $now, $now, $page->getCollectionDatePublic(), $page->getCollectionDisplayOrder(), $page->getCollectionDatePublic(), $page->getCollectionParentID()]
                    );
                    break;
                case 'chrono_asc':
                    $cID = $db->fetchColumn(
                        <<<'EOT'
select
    Pages.cID
from
    Pages
    inner join CollectionVersions cv
        on Pages.cID = cv.cID
where
    Pages.cID <> ?
    and cvIsApproved = 1 and (cvPublishDate is null or cvPublishDate <= ?) and (cvPublishEndDate is null or cvPublishEndDate >= ?)
    and ((cvDatePublic = ? and cDisplayOrder < ?) or cvDatePublic < ?)
    and cParentID = ?
order by
    cvDatePublic desc,
    cDisplayOrder desc
EOT
                        ,
                        [$page->getCollectionID(), $now, $now, $page->getCollectionDatePublic(), $page->getCollectionDisplayOrder(), $page->getCollectionDatePublic(), $page->getCollectionParentID()]
                    );
                    break;
                case 'display_desc':
                    $cID = $db->fetchColumn(
                        <<<'EOT'
select
    Pages.cID
from
    Pages
    inner join CollectionVersions cv
        on Pages.cID = cv.cID
where
    Pages.cID <> ?
    and cvIsApproved = 1 and (cvPublishDate is null or cvPublishDate <= ?) and (cvPublishEndDate is null or cvPublishEndDate >= ?)
    and cDisplayOrder < ?
    and cParentID = ?
order by
    cDisplayOrder desc
EOT
                        ,
                        [$page->getCollectionID(), $now, $now, $page->getCollectionDisplayOrder(), $page->getCollectionParentID()]
                    );
                    break;
                case 'display_asc':
                    $cID = $db->fetchColumn(
                        <<<'EOT'
select
    Pages.cID
from
    Pages
    inner join CollectionVersions cv
        on Pages.cID = cv.cID
where
    Pages.cID <> ?
    and cvIsApproved = 1 and (cvPublishDate is null or cvPublishDate <= ?) and (cvPublishEndDate is null or cvPublishEndDate >= ?)
    and cDisplayOrder > ?
    and cParentID = ?
order by
    cDisplayOrder asc
EOT
                        ,
                        [$page->getCollectionID(), $now, $now, $page->getCollectionDisplayOrder(), $page->getCollectionParentID()]
                    );
                    break;
            }
            if ($cID !== false) {
                $page = Page::getByID($cID, 'ACTIVE');
                if (!$page->getAttribute('exclude_nav')) {
                    $cp = new Permissions($page);
                    if ($cp->canRead()) {
                        $result = $page;
                        break;
                    }
                }
            } else {
                if ($this->loopSequence) {
                    $c = Page::getCurrentPage();
                    $parent = Page::getByID($c->getCollectionParentID(), 'ACTIVE');
                    switch ($orderBy) {
                        case 'chrono_desc':
                            $sibling = $parent->getFirstChild('cvDatePublic asc, cDisplayOrder asc');
                            break;
                        case 'chrono_asc':
                            $sibling = $parent->getFirstChild('cvDatePublic desc, cDisplayOrder desc');
                            break;
                        case 'display_desc':
                            $sibling = $parent->getFirstChild('cDisplayOrder desc');
                            break;
                        case 'display_asc':
                            $sibling = $parent->getFirstChild('cDisplayOrder asc');
                            break;
                    }
                    if ($sibling && !$sibling->isError()) {
                        if (!$sibling->getAttribute('exclude_nav')) {
                            $cp = new Permissions($sibling);
                            if ($cp->canRead()) {
                                $result = $sibling;
                            }
                        }
                    }
                }
                break;
            }
        }

        return $result;
    }
1146239
public function addOperand(Operand $operand)
    {
        if ($operand->isRequired()) {
            foreach ($this->operands as $previousOperand) {
                $previousOperand->required();
            }
        }

        if ($this->hasOperands()) {
            /** @var Operand $lastOperand */
            $lastOperand = array_slice($this->operands, -1)[0];
            if ($lastOperand->isMultiple()) {
                throw new \InvalidArgumentException(sprintf(
                    'Operand %s is multiple - no more operands allowed',
                    $lastOperand->getName()
                ));
            }
        }

        $this->operands[] = $operand;

        return $this;
    }
228427
public function podiumNew($previous = null)
    {
        $transaction = static::getDb()->beginTransaction();
        try {
            $id = null;
            $loggedId = User::loggedId();
            $sameAuthor = !empty($previous->author_id) && $previous->author_id == $loggedId;
            if ($sameAuthor && Podium::getInstance()->podiumConfig->get('merge_posts')) {
                $separator = '<hr>';
                if (Podium::getInstance()->podiumConfig->get('use_wysiwyg') == '0') {
                    $separator = "\n\n---\n";
                }
                $previous->content .= $separator . $this->content;
                $previous->edited = 1;
                $previous->touch('edited_at');
                if (!$previous->save()) {
                    throw new Exception('Previous Post saving error!');
                }
                $previous->markSeen(false);
                $previous->thread->touch('edited_post_at');
                $id = $previous->id;
                $thread = $previous->thread;
            } else {
                if (!$this->save()) {
                    throw new Exception('Post saving error!');
                }
                $this->markSeen(!$sameAuthor);
                if (!$this->forum->updateCounters(['posts' => 1])) {
                    throw new Exception('Forum Post counter adding error!');
                }
                if (!$this->thread->updateCounters(['posts' => 1])) {
                    throw new Exception('Thread Post counter adding error!');
                }
                $this->thread->touch('new_post_at');
                $this->thread->touch('edited_post_at');
                $id = $this->id;
                $thread = $this->thread;
            }
            if (empty($id)) {
                throw new Exception('Saved Post ID missing');
            }
            Subscription::notify($thread->id);
            if ($this->subscribe && !$thread->subscription) {
                $subscription = new Subscription();
                $subscription->user_id = $loggedId;
                $subscription->thread_id = $thread->id;
                $subscription->post_seen = Subscription::POST_SEEN;
                if (!$subscription->save()) {
                    throw new Exception('Subscription saving error!');
                }
            }
            $transaction->commit();
            PodiumCache::clearAfter('newPost');
            Log::info('Post added', $id, __METHOD__);
            return true;
        } catch (Exception $e) {
            $transaction->rollBack();
            Log::error($e->getMessage(), null, __METHOD__);
        }
        return false;
    }
198402
public function combine($op, $map1/**, $transf2,... */)
    {
        $transformations = func_get_args();
        array_shift($transformations);

        return function(Expression $expr, $compiler) use ($op, $transformations)
        {
            $tree = new SpanExpression(strtoupper($op));

            foreach ($transformations as $transformation) {
                $tree->addExpression($transformation($expr, $compiler));
            }

            return $tree;
        };
    }
652425
public function mergeConditionAttribute( $old, $new ) {
		try {
			$condition = $this->condition_factory->merge( $old, $new );
		} catch ( ConfigurationException $e ) {
			throw new ConfigurationException( 'Route condition is not a valid route string or condition.' );
		}

		return $condition;
	}
1087129
protected function mergeRecords(array $records)
    {
        foreach ($records as $key => $record) {
            if (null === $id = array_get($record, static::ID_FIELD)) {
                throw new InternalServerErrorException('No ' .
                    static::ID_FIELD .
                    ' field found in supplied record(s). Cannot merge record(s) for PATCH operation.');
            }

            $rs = $this->getConnection()->getDocument($this->transactionTable, $id);
            $record = array_merge($rs, $record);
            $records[$key] = $record;
        }

        return $records;
    }
56310
public function _performOperation($key, FieldOperation $operation)
    {
        $oldValue = null;
        if (isset($this->estimatedData[$key]))
        {
            $oldValue = $this->estimatedData[$key];
        }
        $newValue = $operation->_apply($oldValue, $this, $key);
        if ($newValue !== null)
        {
            $this->estimatedData[$key] = $newValue;
        } else if (isset($this->estimatedData[$key]))
        {
            unset($this->estimatedData[$key]);
        }

        if (isset($this->operationSet[$key]))
        {
            $oldOperations = $this->operationSet[$key];
            $newOperations = $operation->_mergeWithPrevious($oldOperations);
            $this->operationSet[$key] = $newOperations;
        } else
        {
            $this->operationSet[$key] = $operation;
        }
        $this->dataAvailability[$key] = true;
    }
825187
public function mergeWith(Field $other)
    {
        if (($name = $other->getName()) !== $this->name) {
            throw new MergeException(sprintf("Fields have different names (%s vs %s)", $this->name, $name));
        }

        // Since mapping is merged between databoxes, two fields may
        // have conflicting names. Indexing is the same for a given
        // type so we reject only those with different types.

        if (($type = $other->getType()) !== $this->type) {
            throw new MergeException(sprintf("Field %s can't be merged, incompatible types (%s vs %s)", $name, $type, $this->type));
        }

        if ($other->isPrivate() !== $this->is_private) {
            throw new MergeException(sprintf("Field %s can't be merged, could not mix private and public fields with same name", $name));
        }

        if ($other->isSearchable() !== $this->is_searchable) {
            throw new MergeException(sprintf("Field %s can't be merged, incompatible searchablility", $name));
        }

        if ($other->getFacetValuesLimit() !== $this->facet) {
            throw new MergeException(sprintf("Field %s can't be merged, incompatible facet eligibility", $name));
        }

        $thesaurus_roots = null;

        if ($this->thesaurus_roots !== null || $other->thesaurus_roots !== null) {
            $thesaurus_roots = array_merge(
                (array) $this->thesaurus_roots,
                (array) $other->thesaurus_roots
            );
        }

        $used_by_collections = array_values(
            array_unique(
                array_merge(
                    $this->used_by_collections,
                    $other->used_by_collections
                ),
                SORT_REGULAR
            )
        );

        return $this->withOptions([
            'thesaurus_roots' => $thesaurus_roots,
            'used_by_collections' => $used_by_collections
        ]);
    }
1151481
public function addPreviousStep(\Amulen\ShopBundle\Entity\ProductOrderStatus $previousStep = null)
    {
        $this->previousSteps[] = $previousStep;

        return $this;
    }
1106771
public function addField($field, $after=null) {

        // Detect duplicates first
        if ($this->getField($field->getName())) {
            throw new coding_exception('Duplicate field '.$field->getName().' specified in table '.$this->getName());
        }

        // Calculate the previous and next fields
        $prevfield = null;
        $nextfield = null;

        if (!$after) {
            $allfields = $this->getFields();
            if (!empty($allfields)) {
                end($allfields);
                $prevfield = $allfields[key($allfields)];
            }
        } else {
            $prevfield = $this->getField($after);
        }
        if ($prevfield && $prevfield->getNext()) {
            $nextfield = $this->getField($prevfield->getNext());
        }

        // Set current field previous and next attributes
        if ($prevfield) {
            $field->setPrevious($prevfield->getName());
            $prevfield->setNext($field->getName());
        }
        if ($nextfield) {
            $field->setNext($nextfield->getName());
            $nextfield->setPrevious($field->getName());
        }
        // Some more attributes
        $field->setLoaded(true);
        $field->setChanged(true);
        // Add the new field
        $this->fields[] = $field;
        // Reorder the field
        $this->orderFields($this->fields);
        // Recalculate the hash
        $this->calculateHash(true);
        // We have one new field, so the table has changed
        $this->setChanged(true);

        return $field;
    }
1272974
protected function mergePipelines($new)
    {
        if (!isset($this->nodes['pipelines']) || !count($this->nodes['pipelines'])) {
            return $new;
        }

        if (!count($new)) {
            return $this->nodes['pipelines'];
        }

        /** @var array $pipelinesKeys */
        $pipelinesKeys = array_merge(
            array_keys($this->nodes['pipelines']),
            array_keys($new)
        );

        return array_reduce($pipelinesKeys, function($carry, $key) use ($new) {
            $existing = $this->nodes['pipelines'];
            if (!isset($new[$key])) {
                $carry[$key] = $existing;
                return $carry;
            }
            if (!isset($existing[$key])) {
                $carry[$key] = $new[$key];
                return $carry;
            }

            $carry[$key] = $this->mergePipeline($existing[$key], $new[$key]);
            return $carry;
        }, []);
    }
530836
protected function merge(array $old, array $new)
    {
        foreach ($new as $key => $value) {
            if (isset($old[$key]) && is_array($old[$key]) && is_array($value)) {
                $old[$key] = $this->merge($old[$key], $value);
            } else {
                $old[$key] = $value;
            }
        }

        return $old;
    }
529573
public function mergeQueryAttribute( $old, $new ) {
		if ( $new === null ) {
			return $old;
		}

		if ( $old === null ) {
			return $new;
		}

		return function ( $query_vars ) use ( $old, $new ) {
			return call_user_func( $new, call_user_func( $old, $query_vars ) );
		};
	}
575356
protected function mergeGroup(array $new, array $old)
    {
        $new['namespace'] = $this->formatNamespace($new, $old);

        $new['prefix'] = $this->formatPrefix($new, $old);

        foreach (['middleware', 'providers', 'scopes', 'before', 'after'] as $option) {
            $new[$option] = $this->formatArrayBasedOption($option, $new);
        }

        if (isset($new['domain'])) {
            unset($old['domain']);
        }

        if (isset($new['conditionalRequest'])) {
            unset($old['conditionalRequest']);
        }

        if (isset($new['uses'])) {
            $new['uses'] = $this->formatUses($new, $old);
        }

        $new['where'] = array_merge(array_get($old, 'where', []), array_get($new, 'where', []));

        return array_merge_recursive(array_except($old, ['namespace', 'prefix', 'where']), $new);
    }