* Renames a folder and updates related metadata files (by renaming their filenames). * Also rewrites ownership keys for the whole subtree from old → new. */
(string $oldFolder, string $newFolder)
| 1854 | * Also rewrites ownership keys for the whole subtree from old → new. |
| 1855 | */ |
| 1856 | public static function renameFolder(string $oldFolder, string $newFolder): array |
| 1857 | { |
| 1858 | $oldFolder = trim($oldFolder, "/\\ "); |
| 1859 | $newFolder = trim($newFolder, "/\\ "); |
| 1860 | |
| 1861 | // Validate names (per-segment) |
| 1862 | foreach ([$oldFolder, $newFolder] as $f) { |
| 1863 | $parts = array_filter(explode('/', $f), fn($p) => $p !== ''); |
| 1864 | if (empty($parts)) { |
| 1865 | return ["error" => "Invalid folder name(s)."]; |
| 1866 | } |
| 1867 | foreach ($parts as $seg) { |
| 1868 | if (!preg_match(REGEX_FOLDER_NAME, $seg)) { |
| 1869 | return ["error" => "Invalid folder name(s)."]; |
| 1870 | } |
| 1871 | } |
| 1872 | } |
| 1873 | |
| 1874 | [$oldReal, $oldRel, $err] = self::resolveFolderPath($oldFolder, false); |
| 1875 | if ($err) { |
| 1876 | return ["error" => $err]; |
| 1877 | } |
| 1878 | |
| 1879 | $storage = self::storage(); |
| 1880 | $isLocal = $storage->isLocal(); |
| 1881 | $base = $isLocal ? realpath(self::uploadRoot()) : rtrim(self::uploadRoot(), '/\\'); |
| 1882 | if ($base === false || $base === '') { |
| 1883 | return ["error" => "Uploads directory not configured correctly."]; |
| 1884 | } |
| 1885 | |
| 1886 | $newParts = array_filter(explode('/', $newFolder), fn($p) => $p !== ''); |
| 1887 | $newRel = implode('/', $newParts); |
| 1888 | $newPath = $base . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $newParts); |
| 1889 | |
| 1890 | // Parent of new path must exist |
| 1891 | $newParent = dirname($newPath); |
| 1892 | if ($isLocal) { |
| 1893 | if (!is_dir($newParent) || strpos(realpath($newParent), $base) !== 0) { |
| 1894 | return ["error" => "Invalid folder path."]; |
| 1895 | } |
| 1896 | if (file_exists($newPath)) { |
| 1897 | return ["error" => "New folder name already exists."]; |
| 1898 | } |
| 1899 | } else { |
| 1900 | $parentStat = $storage->stat($newParent); |
| 1901 | if ($parentStat === null || ($parentStat['type'] ?? '') !== 'dir') { |
| 1902 | return ["error" => "Invalid folder path."]; |
| 1903 | } |
| 1904 | if ($storage->stat($newPath) !== null) { |
| 1905 | return ["error" => "New folder name already exists."]; |
| 1906 | } |
| 1907 | } |
| 1908 | if (!$storage->move($oldReal, $newPath)) { |
| 1909 | return ["error" => "Failed to rename folder."]; |
| 1910 | } |
| 1911 | |
| 1912 | // Update metadata filenames (prefix-rename) |
| 1913 | MetadataPath::renameSubtree(self::metaRoot(), $oldRel, $newRel); |
no test coverage detected