/** * Renames the current file * * If the filename already exists and the overwrite flag is set to false, * a new filename will be created. * * This operation will be reverted if a filesystem transaction is in * progress and is later rolled back. * * @param string $new_filename The new full path to the file or a new filename in the current directory * @param boolean $overwrite If the new filename already exists, `TRUE` will cause the file to be overwritten, `FALSE` will cause the new filename to change * @return fFile The file object, to allow for method chaining */ public function rename($new_filename, $overwrite) { $this->tossIfDeleted(); if (!$this->getParent()->isWritable()) { throw new fEnvironmentException('The file, %s, can not be renamed because the directory containing it is not writable', $this->file); } // If the filename does not contain any folder traversal, rename the file in the current directory if (preg_match('#^[^/\\\\]+$#D', $new_filename)) { $new_filename = $this->getParent()->getPath() . $new_filename; } $info = fFilesystem::getPathInfo($new_filename); if (!file_exists($info['dirname'])) { throw new fProgrammerException('The new filename specified, %s, is inside of a directory that does not exist', $new_filename); } // Make the filename absolute $new_filename = fDirectory::makeCanonical(realpath($info['dirname'])) . $info['basename']; if ($this->file == $new_filename && $overwrite) { return $this; } if (file_exists($new_filename) && !$overwrite) { $new_filename = fFilesystem::makeUniqueName($new_filename); } if (file_exists($new_filename)) { if (!is_writable($new_filename)) { throw new fEnvironmentException('The new filename specified, %s, already exists, but is not writable', $new_filename); } if (fFilesystem::isInsideTransaction()) { fFilesystem::recordWrite(new fFile($new_filename)); } // Windows requires that the existing file be deleted before being replaced unlink($new_filename); } else { $new_dir = new fDirectory($info['dirname']); if (!$new_dir->isWritable()) { throw new fEnvironmentException('The new filename specified, %s, is inside of a directory that is not writable', $new_filename); } } rename($this->file, $new_filename); // Allow filesystem transactions if (fFilesystem::isInsideTransaction()) { fFilesystem::recordRename($this->file, $new_filename); } fFilesystem::updateFilenameMap($this->file, $new_filename); return $this; }