Complex classes like ObjectTree often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ObjectTree, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 39 | class ObjectTree extends \Sabre\DAV\Tree { |
||
| 40 | |||
| 41 | /** |
||
| 42 | * @var \OC\Files\View |
||
| 43 | */ |
||
| 44 | protected $fileView; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * @var \OCP\Files\Mount\IMountManager |
||
| 48 | */ |
||
| 49 | protected $mountManager; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * Creates the object |
||
| 53 | */ |
||
| 54 | public function __construct() { |
||
| 56 | |||
| 57 | /** |
||
| 58 | * @param \Sabre\DAV\INode $rootNode |
||
| 59 | * @param \OC\Files\View $view |
||
| 60 | * @param \OCP\Files\Mount\IMountManager $mountManager |
||
| 61 | */ |
||
| 62 | public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) { |
||
| 67 | |||
| 68 | /** |
||
| 69 | * If the given path is a chunked file name, converts it |
||
| 70 | * to the real file name. Only applies if the OC-CHUNKED header |
||
| 71 | * is present. |
||
| 72 | * |
||
| 73 | * @param string $path chunk file path to convert |
||
| 74 | * |
||
| 75 | * @return string path to real file |
||
| 76 | */ |
||
| 77 | private function resolveChunkFile($path) { |
||
| 96 | |||
| 97 | public function cacheNode(Node $node) { |
||
| 100 | |||
| 101 | /** |
||
| 102 | * Returns the INode object for the requested path |
||
| 103 | * |
||
| 104 | * @param string $path |
||
| 105 | * @return \Sabre\DAV\INode |
||
| 106 | * @throws InvalidPath |
||
| 107 | * @throws \Sabre\DAV\Exception\Locked |
||
| 108 | * @throws \Sabre\DAV\Exception\NotFound |
||
| 109 | * @throws \Sabre\DAV\Exception\ServiceUnavailable |
||
| 110 | */ |
||
| 111 | public function getNodeForPath($path) { |
||
| 112 | if (!$this->fileView) { |
||
| 113 | throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup'); |
||
| 114 | } |
||
| 115 | |||
| 116 | $path = trim($path, '/'); |
||
| 117 | |||
| 118 | if (isset($this->cache[$path])) { |
||
| 119 | return $this->cache[$path]; |
||
| 120 | } |
||
| 121 | |||
| 122 | if ($path) { |
||
| 123 | try { |
||
| 124 | $this->fileView->verifyPath($path, basename($path)); |
||
| 125 | } catch (\OCP\Files\InvalidPathException $ex) { |
||
| 126 | throw new InvalidPath($ex->getMessage()); |
||
| 127 | } |
||
| 128 | } |
||
| 129 | |||
| 130 | // Is it the root node? |
||
| 131 | if (!strlen($path)) { |
||
| 132 | return $this->rootNode; |
||
| 133 | } |
||
| 134 | |||
| 135 | if (pathinfo($path, PATHINFO_EXTENSION) === 'part') { |
||
| 136 | // read from storage |
||
| 137 | $absPath = $this->fileView->getAbsolutePath($path); |
||
| 138 | $mount = $this->fileView->getMount($path); |
||
| 139 | $storage = $mount->getStorage(); |
||
| 140 | $internalPath = $mount->getInternalPath($absPath); |
||
| 141 | if ($storage && $storage->file_exists($internalPath)) { |
||
| 142 | /** |
||
| 143 | * @var \OC\Files\Storage\Storage $storage |
||
| 144 | */ |
||
| 145 | // get data directly |
||
| 146 | $data = $storage->getMetaData($internalPath); |
||
| 147 | $info = new FileInfo($absPath, $storage, $internalPath, $data, $mount); |
||
| 148 | } else { |
||
| 149 | $info = null; |
||
| 150 | } |
||
| 151 | } else { |
||
| 152 | // resolve chunk file name to real name, if applicable |
||
| 153 | $path = $this->resolveChunkFile($path); |
||
| 154 | |||
| 155 | // read from cache |
||
| 156 | try { |
||
| 157 | $info = $this->fileView->getFileInfo($path); |
||
| 158 | } catch (StorageNotAvailableException $e) { |
||
| 159 | throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage not available'); |
||
| 160 | } catch (StorageInvalidException $e) { |
||
| 161 | throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid'); |
||
| 162 | } catch (LockedException $e) { |
||
| 163 | throw new \Sabre\DAV\Exception\Locked(); |
||
| 164 | } catch (ForbiddenException $e) { |
||
| 165 | throw new \Sabre\DAV\Exception\Forbidden(); |
||
| 166 | } |
||
| 167 | } |
||
| 168 | |||
| 169 | if (!$info) { |
||
| 170 | throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located'); |
||
| 171 | } |
||
| 172 | |||
| 173 | if ($info->getType() === 'dir') { |
||
| 174 | $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this); |
||
| 175 | } else { |
||
| 176 | $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info); |
||
| 177 | } |
||
| 178 | |||
| 179 | $this->cache[$path] = $node; |
||
| 180 | return $node; |
||
| 181 | |||
| 182 | } |
||
| 183 | |||
| 184 | /** |
||
| 185 | * Moves a file from one location to another |
||
| 186 | * |
||
| 187 | * @param string $sourcePath The path to the file which should be moved |
||
| 188 | * @param string $destinationPath The full destination path, so not just the destination parent node |
||
| 189 | * @throws \Sabre\DAV\Exception\BadRequest |
||
| 190 | * @throws \Sabre\DAV\Exception\ServiceUnavailable |
||
| 191 | * @throws \Sabre\DAV\Exception\Forbidden |
||
| 192 | * @return int |
||
| 193 | */ |
||
| 194 | public function move($sourcePath, $destinationPath) { |
||
| 259 | |||
| 260 | /** |
||
| 261 | * Copies a file or directory. |
||
| 262 | * |
||
| 263 | * This method must work recursively and delete the destination |
||
| 264 | * if it exists |
||
| 265 | * |
||
| 266 | * @param string $source |
||
| 267 | * @param string $destination |
||
| 268 | * @throws \Sabre\DAV\Exception\ServiceUnavailable |
||
| 269 | * @return void |
||
| 270 | */ |
||
| 271 | public function copy($source, $destination) { |
||
| 304 | } |
||
| 305 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.