foldershare-8.x-1.2/src/Entity/FolderShareTraits/OperationDuplicateTrait.php
src/Entity/FolderShareTraits/OperationDuplicateTrait.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | <?php namespace Drupal\foldershare\Entity\FolderShareTraits; use Drupal\Core\Database\Database; /** * Duplicate FolderShare entities. * * This trait includes methods to duplicate FolderShare entities into * the same parent folder or the user's root list. * * <B>Internal trait</B> * This trait is internal to the FolderShare module and used to define * features of the FolderShare entity class. It is a mechanism to group * functionality to improve code management. * * @ingroup foldershare */ trait OperationDuplicateTrait { /*--------------------------------------------------------------------- * * Duplicate. * *---------------------------------------------------------------------*/ /** * {@inheritdoc} */ public function createDuplicate() { // This method's actions are slightly in conflict with the base Entity // class's definition for the createDuplicate() method. // // createDuplicate() is supposed to: // - Create and return a clone of $this with all fields filled in, // except for an ID, so that saving it will insert the new entity // into the storage system. // // This is not practical for FolderShare, where duplicating the entity // also needs to duplicate its children. And those children need to // point back to the parent, so the parent has to have been fully // created first and have an entity ID. // // Therefore, this entity's implementation of createDuplicate() creates // AND saves the entity, thereby creating the ID and commiting the new // entity to storage. If the caller calls save() again on the returned // entity, this won't hurt anything. But if they think that skipping a // call to save() will avoid saving the entity, that won't be true. return $this ->duplicate(); } /** * {@inheritdoc} */ public function duplicate() { if ( $this ->isRootItem() === TRUE) { // Create a copy in the user's root list and allow renaming so that // the duplicate has a unique name. return $this ->copyToRoot( '' , TRUE); } else { // Create a copy in the parent folder and allow renaming so that // the duplicate has a unique name. $parent = $this ->getParentFolder(); if ( $parent === NULL) { // There is no parent but it isn't a root item? Corrupted. return NULL; } return $this ->copyToFolder( $parent , '' , TRUE); } } /** * Duplicates multiple items in to the same parents or the user's root list. * * Each of the indicated items is duplicated and added to their parents. * If an item is a folder, the folder's descendants are duplicated as well. * * <B>Background duplicate</B> * File copies occur immediately, but folder copies schedule background * tasks to traverse the folder tree and update descendants. This will * delay completion of the copy to a time in the future that depends upon * the size of the folder tree being copied and server load. * * <B>Process locks</B> * This method locks the root folder tree, or the user's root list, while * duplicating items into the same folder tree or root list. * * <B>Post-operation hooks</B> * This method calls the "hook_foldershare_post_operation_copy" hook for * each item copied. * * <B>Activity log</B> * This method posts a log message after each item is duplicated. * * @param int[] $ids * An array of integer FolderShare entity IDs to duplicate. Invalid IDs * are silently skipped. * * @throws \Drupal\foldershare\Entity\Exception\LockException * Throws an exception if an access lock could not be acquired. * @throws \Drupal\foldershare\Entity\Exception\ValidationException * Throws an exception if a unique name cannot be created for the * duplicate. * @throws \Drupal\foldershare\Entity\Exception\SystemException * For files, throws an exception if a serious system error occurs while * duplicating the underlying local file. System errors may indicate a * file system has become unreadable/unwritable, is full, or is offline. * * @see ::duplicate() * @see ::copyToFolderMultiple() * @see ::copyToRootMultiple() */ public static function duplicateMultiple( array $ids ) { if ( empty ( $ids ) === TRUE) { // Nothing to duplicate. return ; } $connection = Database::getConnection(); // // Group ids by location. // ---------------------- // Duplication is a copy. If an ID refers to a root-level item, then // we'll invoke copyToRoot() on it to copy into the root. But if an ID // refers to a folder-level item, then we'll invoke copyToFolder() // with the appropriate folder as the destination. // // So we need to sort by where an entity is, and thus where to put the // duplicate. $groups = []; foreach ( $ids as $id ) { // Query the database to get the root and parent IDs rather than // load the entire entity. This saves time and memory. $select = $connection ->select(self::BASE_TABLE, 'fs' ); $select ->addField( 'fs' , 'rootid' , 'rootid' ); $select ->addField( 'fs' , 'parentid' , 'parentid' ); $select ->condition( 'id' , $id , '=' ); $results = $select ->execute()->fetchAll(); if ( count ( $results ) === 0) { // The item does not exist. continue ; } $rootId = $results [0]->rootid; $parentId = $results [0]->parentid; if ( $rootId === NULL) { // The item is at the root level. Add it to a group of // root level items. $groups [ 'root' ][] = (int) $id ; } else { // The item is at the folder level. Add it to a group // with the same parent folder. $groups [(int) $parentId ][] = (int) $id ; } } // // Duplicate each group. // --------------------- // Run through the groups and initiate copies into the appropriate // destination. Allow the name to be changed to make the copy unique. if ( empty ( $groups [ 'root' ]) === FALSE) { self::copyToRootMultiple( $groups [ 'root' ], TRUE); unset( $groups [ 'root' ]); } foreach ( $groups as $parentId => $group ) { if ( empty ( $group ) === TRUE) { // Nothing to copy. continue ; } $parent = self::load( $parentId ); if ( $parent === NULL) { // The parent does not exist. File system is corrupted. continue ; } self::copyToFolderMultiple( $group , $parent , TRUE); unset( $parent ); } } } |