Move a block to a new parent in a specific placeholder and order (sort)

This method performs the change and persists/flushes to the database.

@param integer $id
@param integer $parentId
@param integer $placeholder
@param array   $sort
962341
public function moveBlock($id, $parentId, $placeholder, $sort, $draft = true)
    {
        $block = $this->find($id, $draft);

        $parent = ($parentId) ? $this->find($parentId) : null;

        $block->setPosition($placeholder);

        $block->setParent($parent);

        if ($parent) {
            $parent->addChild($block);
        }

        $this->save($block);

        array_walk($sort, function (&$id) { $id = (int) $id; });
        $contained = $this->findById($sort, $draft);

        if ($contained) {
            $contained = $this->setSortsByDirective($contained, $sort);

            foreach ($contained as $node) {
                if ($node->getOwner()->getId() == $block->getOwner()->getId()) {
                    $this->save($node);
                }
            }
        }
    }
46576
protected function recursiveReorder($root, $parentId, $left)
    {
        $right = $left + 1;
        $children = array_get($root, 'children', []);
        foreach ($children as $child) {
            $right = $this->recursiveReorder($child, $root['id'], $right);
        }
        $this->move($root['id'], $parentId, $left, $right);
        $left = $right + 1;

        return $left;
    }
561489
public function move($id, $direction)
    {
        $instance = $this->_getOrThrow($id);
        $unordered = [];
        $direction = !in_array($direction, ['up', 'down']) ? 'up' : $direction;
        $position = false;
        $list = $this->_getInstances();

        foreach ($list as $k => $field) {
            if ($field->id === $instance->id) {
                $position = $k;
            }

            $unordered[] = $field;
        }

        if ($position !== false) {
            $ordered = array_move($unordered, $position, $direction);
            $before = md5(serialize($unordered));
            $after = md5(serialize($ordered));

            if ($before != $after) {
                foreach ($ordered as $k => $field) {
                    $field->set('ordering', $k);
                    $this->FieldInstances->save($field);
                }
            }
        }

        $this->title(__d('field', 'Reorder Field'));
        $this->redirect($this->referer());
    }
1036503
private void updateParentsAlloc(int id) {
        while (id > 1) {
            int parentId = id >>> 1;
            byte val1 = value(id);
            byte val2 = value(id ^ 1);
            byte val = val1 < val2 ? val1 : val2;
            setValue(parentId, val);
            id = parentId;
        }
    }
413397
protected function moveUp($id)
    {
        $model = $this->getModel($id);
        $orderAttrName = $this->positionAttribute;
        $orderDir = SORT_DESC;

        $swapModel = $model::find()
            ->where(['<', $orderAttrName, $model->$orderAttrName])
            ->orderBy([$orderAttrName => $orderDir])
            ->one();

        if ($swapModel) {
            $newOrderNumeric = $swapModel->$orderAttrName;
            $swapModel->$orderAttrName = $model->$orderAttrName;
            $model->$orderAttrName = $newOrderNumeric;
            $swapModel->save() && $model->save();
        }

        return $this->redirect($model);
    }
1304611
public static function move_up_issuer($id) {
        require_capability('moodle/site:config', context_system::instance());
        $current = new issuer($id);

        $sortorder = $current->get('sortorder');
        if ($sortorder == 0) {
            return false;
        }

        $sortorder = $sortorder - 1;
        $current->set('sortorder', $sortorder);

        $filters = array('sortorder' => $sortorder);
        $children = issuer::get_records($filters, 'id');
        foreach ($children as $needtoswap) {
            $needtoswap->set('sortorder', $sortorder + 1);
            $needtoswap->update();
        }

        // OK - all set.
        $result = $current->update();

        return $result;
    }
499786
public function deleteByParent( $parentId, $parentType ) {

		//$modelClass	= static::$modelClass;

		//return $modelClass::deleteByParent( $parentId, $parentType );

		$models	= $this->getByParent( $parentId, $parentType );

		foreach ( $models as $model ) {

			$this->delete( $model );
		}
	}
75344
public function move($fileIDs, $parentID)
    {
        if (is_array($fileIDs)) {
            $fileIDs = implode(',', $fileIDs);
        }

        $data = [
            'file_ids'  => $fileIDs,
            'parent_id' => $parentID
        ];

        return $this->post('files/move', $data, \true);
    }
865491
public function moveDown($id, $count = 1) {
        $pk = $this->getRepository()->getPrimaryKey();
        $node = $this->getNode($id, true);

        if (!$node || empty($node['Parent']['id'])) {
            return false;
        }

        $left = $this->getConfig('leftField');
        $right = $this->getConfig('rightField');
        $nodeLeft = $node[$left];
        $nodeRight = $node[$right];
        $inc = ($count * 2);

        $newNodeLeft = $nodeLeft + $inc;
        $newNodeRight = $nodeRight + $inc;

        // Can't go outside of the parent
        $parentRight = $node['Parent'][$right];

        if ($newNodeLeft >= $parentRight) {
            $newNodeLeft = $parentRight - 2;
            $newNodeRight = $parentRight - 1;
        }

        // Exit early if the values are the same
        if ($nodeLeft === $newNodeLeft) {
            return true;
        }

        // Move following nodes up
        $this->_moveNode(function(Query $query) use ($left, $right, $nodeRight, $newNodeRight) {
            $query->where($left, '>', $nodeRight)->where($right, '<=', $newNodeRight);
        }, [
            $left => Query::expr($left, '-', 2),
            $right => Query::expr($right, '-', 2)
        ]);

        // Move node down
        $this->_moveNode(function(Query $query) use ($pk, $id) {
            $query->where($pk, $id);
        }, [
            $left => $newNodeLeft,
            $right => $newNodeRight
        ]);

        return true;
    }
1087160
private function updateNavigationListOrder($id, $listOrder, $parentId = 0)
    {
        $row = Page::find($id);
        $row->parent_id = $parentId;
        //if ($row->url_parent_id != 0) {
            // update the url parent id as well
            $row->url_parent_id = $parentId;
        //}

        $row->updateUrl();
        $row[$this->orderProperty] = $listOrder;
        $row->save();

        return $row;
    }
647926
function move( $newParentNodeID, $nodeID = 0 )
    {
        if ( $nodeID == 0 )
        {
            $node = $this;
            $nodeID = $node->attribute( 'node_id' );
        }
        else
        {
            $node = eZContentObjectTreeNode::fetch( $nodeID );
        }

        $oldPath = $node->attribute( 'path_string' );
        $oldParentNodeID = $node->attribute( 'parent_node_id' );
        $newParentNodeID =(int) $newParentNodeID;
        if ( $oldParentNodeID != $newParentNodeID )
        {
            $node->updateAndStoreModified();
            // Who moves which content should be logged.
            $object = $node->object();
            eZAudit::writeAudit( 'content-move', array( 'Node ID' => $node->attribute( 'node_id' ),
                                                        'Old parent node ID' => $oldParentNodeID, 'New parent node ID' => $newParentNodeID,
                                                        'Object ID' => $object->attribute( 'id' ), 'Content Name' => $object->attribute( 'name' ),
                                                        'Comment' => 'Moved the node to the given node: eZContentObjectTreeNode::move()' ) );

            $newParentNode = eZContentObjectTreeNode::fetch( $newParentNodeID );
            $newParentPath = $newParentNode->attribute( 'path_string' );
            $newParentDepth = $newParentNode->attribute( 'depth' );
            $newPath = $newParentPath . $nodeID;
            $oldDepth = $node->attribute( 'depth' );

            $oldPathLength = strlen( $oldPath );
            $moveQuery = "UPDATE
                                 ezcontentobject_tree
                          SET
                                 parent_node_id = $newParentNodeID
                          WHERE
                                 node_id = $nodeID";
            $db = eZDB::instance();
            $subStringString = $db->subString( 'path_string', $oldPathLength );
            $newPathString   = $db->concatString( array( "'$newPath'", $subStringString ) );
            $moveQuery1 = "UPDATE
                                 ezcontentobject_tree
                           SET
                                 path_identification_string = " .
                                 $db->concatString(
                                     array(
                                         "'" . $db->escapeString( $newParentNode->PathIdentificationString ) . "'",
                                         $db->subString(
                                             "path_identification_string",
                                             mb_strlen( $node->PathIdentificationString ) + 1
                                         )
                                     )
                                 ) . ",
                                 path_string = $newPathString,
                                 depth = depth + $newParentDepth - $oldDepth + 1
                           WHERE
                                 path_string LIKE '$oldPath%'";
            $db->begin();
            $db->query( $moveQuery );
            $db->query( $moveQuery1 );

            /// role system clean up
            // Clean up policies and limitations

            $expireRoleCache = false;

            $limitationsToFix = eZPolicyLimitation::findByType( 'SubTree', $node->attribute( 'path_string' ), false );
            if ( count( $limitationsToFix ) > 0 )
            {
                $limitationIDString = $db->generateSQLINStatement( $limitationsToFix, 'limitation_id' );
                $subStringString =  $db->subString( 'value', $oldPathLength );
                $newValue = $db->concatString( array( "'$newPath'", $subStringString ) );

                $query = "UPDATE
                                ezpolicy_limitation_value
                          SET
                                value = $newValue
                          WHERE
                                value LIKE '$oldPath%' AND $limitationIDString";

                $db->query( $query );

                $expireRoleCache = true;
            }

            // clean up limitations on role assignment level
            $countRows = $db->arrayQuery( "SELECT COUNT(*) AS row_count FROM ezuser_role WHERE limit_identifier='Subtree' AND limit_value LIKE '$oldPath%'" );
            $assignmentsToFixCount = $countRows[0]['row_count'];

            if ( $assignmentsToFixCount > 0 )
            {
                $subStringString =  $db->subString( 'limit_value', $oldPathLength );
                $newValue = $db->concatString( array( "'$newPath'", $subStringString ) );

                $db->query( "UPDATE
                                ezuser_role
                             SET
                                limit_value = $newValue
                             WHERE
                                limit_identifier='Subtree' AND limit_value LIKE '$oldPath%'"
                          );

               $expireRoleCache = true;
           }

            if ( $expireRoleCache )
            {
                eZRole::expireCache();
            }

            // Update "is_invisible" node attribute.
            $newNode = eZContentObjectTreeNode::fetch( $nodeID );
            eZContentObjectTreeNode::updateNodeVisibility( $newNode, $newParentNode );
            $db->commit();
        }
    }
454601
public function reorder($elementToBeAfterID = 0)
    {
        $element = $this->element;
        $parentId = $element->ParentID;
        $currentPosition = (int) $element->Sort;
        $sortAfterPosition = 0;

        if ($elementToBeAfterID) {
            /** @var BaseElement $afterBlock */
            $afterElement = BaseElement::get()->byID($elementToBeAfterID);

            if (!$afterElement) {
                throw new InvalidArgumentException(sprintf(
                    '%s#%s not found',
                    BaseElement::class,
                    $elementToBeAfterID
                ));
            }

            // Must be weak comparison as sometimes integers are returned from the DB as strings
            if ($afterElement->ParentID != $parentId) {
                throw new InvalidArgumentException(
                    'Trying to sort element to be placed after an element from a different elemental area'
                );
            }

            $sortAfterPosition = (int) $afterElement->Sort;
        }

        // We are updating records with SQL queries to avoid the ORM triggering the creation of new versions
        // for each element that is affected by this reordering.
        $baseTableName = Convert::raw2sql(DataObject::getSchema()->tableName(BaseElement::class));

        // Update both the draft and live versions of the records
        $tableNames = [$baseTableName];
        if (BaseElement::has_extension(Versioned::class)) {
            $tableNames[] = $element->stageTable($baseTableName, Versioned::LIVE);
        }

        foreach ($tableNames as $tableName) {
            $tableName = sprintf('"%s"', $tableName);

            if ($sortAfterPosition < $currentPosition) {
                $operator = '+';
                $filter = "$tableName.\"Sort\" > $sortAfterPosition AND $tableName.\"Sort\" < $currentPosition";
                $newBlockPosition = $sortAfterPosition + 1;
            } else {
                $operator = '-';
                $filter = "$tableName.\"Sort\" <= $sortAfterPosition AND $tableName.\"Sort\" > $currentPosition";
                $newBlockPosition = $sortAfterPosition;
            }

            $query = SQLUpdate::create()
                ->setTable("$tableName")
                ->assignSQL('"Sort"', "$tableName.\"Sort\" $operator 1")
                ->addWhere([$filter, "$tableName.\"ParentID\"" => $parentId]);

            $query->execute();
        }

        // Now use the ORM to write a new version of the record that we are directly reordering
        $element->Sort = $newBlockPosition;
        $element->write();

        return $element;
    }
14426
private function moveAsFirstChildOf(Page $page, Page $parent = null)
    {
        if (null === $parent) {
            throw new BadRequestHttpException('Parent uid doesn\'t exists');
        }

        $this->granted('EDIT', $parent);

        if (!$parent->hasMainSection()) {
            $this->getPageRepository()->saveWithSection($parent);
        }

        $this->getPageRepository()->moveAsFirstChildOf($page, $parent);
    }
1108361
public void setParentId(String parentId)
   {
      this.parentId = (parentId == null || parentId.equals("") ? null : parentId);
      setGroupName(groupName);
   }
8383
public function createBlock($owner, $type, $parentId, $placeholder, $sort, $data = null, $draft = true)
    {
        /** @var AbstractBlockService $service */
        $service = $this->getService($type);
        $parent = $parentId ? $this->find($parentId, $draft) : null;

        // This should replaced with a more hardened function
        if (is_null($data)) {
            $data = array();
        }
        $data['owner'] = $owner;

        $block = $service->createBlock($data);

        $block->setPosition($placeholder);
        $block->setSort(0); // < default, gets recalculated later for entire level
        $block->setSortParent(-1); // < need to be calculated when putting in the tree

        // Set owner
        if (is_null($parent) || false === $parent->isShared()) {
            $block->setOwner($owner);
        }

        $block->setParent($parent);

        // Save now, rest will be in changeset. All we do is a create a stub entry anyway.
        $this->save($block, $draft);

        if (count($sort) > 1) {
            // Replace the zero value in the posted sort array
            // with the newly created id to perform sorting
            $id = $block->getId();
            $sort = array_map(
                function ($v) use ($id) {
                    return $v == "" || $v == "0" ? $id : $v;
                },
                $sort
            );

            array_walk($sort, function (&$id) { $id = (int) $id; });
            $contained = $this->findById($sort, $draft);

            if ($contained) {
                $contained = $this->setSortsByDirective($contained, $sort);

                foreach ($contained as $node) {
                    // If nodes are in the same parent and if their owners match we
                    // save the changes. We don't want to save sort changes made to
                    // nodes belonging to inherited trees.
                    if ($node->getParent() === $block->getParent() &&
                        (($node->getOwner() === null && $block->getOwner() === null) ||
                        ($node->getOwner()->getId() == $block->getOwner()->getId()))) {
                        $this->save($node, $draft);
                    }
                }
            }
        }

        return $block;
    }
543419
public function sortAction($id, $direction)
    {
        $entity = $this->getRepository()->sort($id, $direction);

        $last = $this->getRequest()->headers->get('referer');

        return $this->redirect($last);
    }
1238318
public function move_item_right($id) {
        global $DB;

        $peers = $this->get_items_peers($id);
        $itemkey = array_search($id, $peers);
        if (!isset($peers[$itemkey-1])) {
            print_error('listcantmoveright');
        } else {
            $DB->set_field($this->table, "parent", $peers[$itemkey-1], array("id"=>$peers[$itemkey]));
            $newparent = $this->find_item($peers[$itemkey-1]);
            if (isset($newparent->children)) {
                $newpeers = $newparent->children->get_child_ids();
            }
            if ($newpeers) {
                $newpeers[] = $peers[$itemkey];
                $this->reorder_peers($newpeers);
            }
        }
    }