Jackalope\Transport\DoctrineDBAL\Client::copyNode PHP Method

copyNode() public method

{@inheritDoc}
public copyNode ( $srcAbsPath, $dstAbsPath, $srcWorkspace = null )
    public function copyNode($srcAbsPath, $dstAbsPath, $srcWorkspace = null)
    {
        $this->assertLoggedIn();
        if (null !== $srcWorkspace && !$this->workspaceExists($srcWorkspace)) {
            throw new NoSuchWorkspaceException("Source workspace '{$srcWorkspace}' does not exist.");
        }
        $srcWorkspace = $srcWorkspace ?: $this->workspaceName;
        PathHelper::assertValidAbsolutePath($dstAbsPath, true, true, $this->getNamespacePrefixes());
        $srcNodeId = $this->getSystemIdForNode($srcAbsPath, $srcWorkspace);
        if (!$srcNodeId) {
            throw new PathNotFoundException("Source path '{$srcAbsPath}' not found");
        }
        if ($this->getSystemIdForNode($dstAbsPath)) {
            throw new ItemExistsException("Cannot copy to destination path '{$dstAbsPath}' that already exists.");
        }
        if (!$this->getSystemIdForNode(PathHelper::getParentPath($dstAbsPath))) {
            throw new PathNotFoundException("Parent of the destination path '" . $dstAbsPath . "' has to exist.");
        }
        // Algorithm:
        // 1. Select all nodes with path $srcAbsPath."%" and iterate them
        // 2. create a new node with path $dstAbsPath + leftovers, with a new uuid. Save old => new uuid
        // 3. copy all properties from old node to new node
        // 4. if a reference is in the properties, either update the uuid based on the map if its inside the copied graph or keep it.
        // 5. "May drop mixin types"
        $query = 'SELECT * FROM phpcr_nodes WHERE (path = ? OR path LIKE ?) AND workspace_name = ?';
        $stmt = $this->getConnection()->executeQuery($query, array($srcAbsPath, $srcAbsPath . '/%', $srcWorkspace));
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        $uuidMap = array();
        $resultSetUuids = array();
        // first iterate and build up an array of all the UUIDs in the result set
        foreach ($rows as $row) {
            $resultSetUuids[$row['identifier']] = $row['path'];
        }
        // array of references to remap within the copied tree
        $referenceElsToRemap = array();
        // array references that will need updating in the database
        $referencesToUpdate = array();
        foreach ($rows as $row) {
            $newPath = str_replace($srcAbsPath, $dstAbsPath, $row['path']);
            $stringDom = new \DOMDocument('1.0', 'UTF-8');
            $stringDom->loadXML($row['props']);
            $numericalDom = null;
            if ($row['numerical_props']) {
                $numericalDom = new \DOMDocument('1.0', 'UTF-8');
                $numericalDom->loadXML($row['numerical_props']);
            }
            $propsData = array('stringDom' => $stringDom, 'numericalDom' => $numericalDom, 'references' => array());
            $xpath = new \DOMXpath($stringDom);
            $referenceEls = $xpath->query('.//sv:property[@sv:type="reference" or @sv:type="Reference" or @sv:type="weakreference" or @sv:type="WeakReference"]');
            $references = array();
            foreach ($referenceEls as $referenceEl) {
                $propName = $referenceEl->getAttribute('sv:name');
                $values = array();
                foreach ($xpath->query('./sv:value', $referenceEl) as $valueEl) {
                    $values[] = $valueEl->nodeValue;
                }
                $references[$propName] = array('type' => PropertyType::valueFromName($referenceEl->getAttribute('sv:type')), 'values' => $values);
                if (isset($resultSetUuids[$referenceEl->nodeValue])) {
                    $referenceElsToRemap[] = array($referenceEl, $newPath, $row['type'], $propsData);
                }
            }
            $originalUuid = $row['identifier'];
            // when copying a node, the copy is always a new node. set $isNewNode to true
            $newNodeId = $this->syncNode(null, $newPath, $row['type'], true, array(), $propsData);
            if ($references) {
                $referencesToUpdate[$newNodeId] = array('path' => $row['path'], 'properties' => $references);
            }
            $newUuid = $this->nodeIdentifiers[$newPath];
            $uuidMap[$originalUuid] = $newUuid;
            $query = 'INSERT INTO phpcr_binarydata (node_id, property_name, workspace_name, idx, data)' . '   SELECT ?, b.property_name, ?, b.idx, b.data FROM phpcr_binarydata b WHERE b.node_id = ?';
            try {
                $this->getConnection()->executeUpdate($query, array($newNodeId, $this->workspaceName, $row['id']));
            } catch (DBALException $e) {
                throw new RepositoryException("Unexpected exception while copying node from {$srcAbsPath} to {$dstAbsPath}", $e->getCode(), $e);
            }
        }
        foreach ($referenceElsToRemap as $data) {
            list($referenceEl, $newPath, $type, $propsData) = $data;
            $referenceEl->nodeValue = $uuidMap[$referenceEl->nodeValue];
            $this->syncNode($this->nodeIdentifiers[$newPath], $newPath, $type, false, array(), $propsData);
        }
        $this->syncReferences($referencesToUpdate);
    }

Usage Example

 /**
  * {@inheritDoc}
  */
 public function copyNode($srcAbsPath, $dstAbsPath, $srcWorkspace = null)
 {
     parent::copyNode($srcAbsPath, $dstAbsPath, $srcWorkspace);
     $this->clearCaches();
 }
All Usage Examples Of Jackalope\Transport\DoctrineDBAL\Client::copyNode