203 lines
6.4 KiB
PHP
203 lines
6.4 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; under version 2
|
|
* of the License (non-upgradable).
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Copyright (c) 2016 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
|
|
*
|
|
*/
|
|
|
|
namespace oat\oatbox\filesystem;
|
|
|
|
use League\Flysystem\FileExistsException;
|
|
|
|
class Directory extends FileSystemHandler implements \IteratorAggregate
|
|
{
|
|
const ITERATOR_RECURSIVE = '1';
|
|
const ITERATOR_FILE = '2';
|
|
const ITERATOR_DIRECTORY = '4';
|
|
|
|
/**
|
|
* Get a subDirectory of $this (existing or not)
|
|
*
|
|
* @param $path
|
|
* @return Directory
|
|
*/
|
|
public function getDirectory($path)
|
|
{
|
|
$subDirectory = new self($this->getFileSystemId(), $this->getFullPath($path));
|
|
$subDirectory->setServiceLocator($this->getServiceLocator());
|
|
return $subDirectory;
|
|
}
|
|
|
|
/**
|
|
* Get file located into $this->directory (existing or not)
|
|
*
|
|
* @param $path
|
|
* @return File
|
|
*/
|
|
public function getFile($path)
|
|
{
|
|
$file = new File($this->getFileSystemId(), $this->getFullPath($path));
|
|
$file->setServiceLocator($this->getServiceLocator());
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* Method constraints by IteratorAggregator, wrapper to getFlyIterator
|
|
*
|
|
* @return \ArrayIterator
|
|
*/
|
|
public function getIterator()
|
|
{
|
|
return $this->getFlyIterator();
|
|
}
|
|
|
|
/**
|
|
* Get an iterator of $this directory
|
|
* Flags are combinable like that $this->getFlyIterator(self::ITERATOR_DIRECTORY|self::ITERATOR_DIRECTORY)
|
|
* By default iterator is not recursive and includes directories & files
|
|
*
|
|
* @param null $flags
|
|
* @return \ArrayIterator
|
|
*/
|
|
public function getFlyIterator($flags = null)
|
|
{
|
|
if (is_null($flags)) {
|
|
$flags = self::ITERATOR_DIRECTORY | self::ITERATOR_FILE;
|
|
}
|
|
|
|
$recursive = ($flags & self::ITERATOR_RECURSIVE);
|
|
$withDirectories = ($flags & self::ITERATOR_DIRECTORY);
|
|
$withFiles = ($flags & self::ITERATOR_FILE);
|
|
|
|
$iterator = [];
|
|
$contents = $this->getFileSystem()->listContents($this->getPrefix(), $recursive);
|
|
|
|
if (!empty($contents)) {
|
|
$dirPath = $this->getFileSystem()->get($this->getPrefix())->getPath();
|
|
foreach ($contents as $content) {
|
|
if ($withDirectories && $content['type'] == 'dir') {
|
|
$iterator[] = $this->getDirectory(str_replace($dirPath, '', $content['path']));
|
|
}
|
|
|
|
if ($withFiles && $content['type'] == 'file') {
|
|
$iterator[] = $this->getFile(str_replace($dirPath, '', $content['path']));
|
|
}
|
|
}
|
|
}
|
|
|
|
return new \ArrayIterator($iterator);
|
|
}
|
|
|
|
/**
|
|
* Get relative path from $this directory to given content
|
|
*
|
|
* @param Directory|File $content
|
|
* @return mixed
|
|
* @throws \common_Exception
|
|
* @throws \tao_models_classes_FileNotFoundException
|
|
*/
|
|
public function getRelPath($content)
|
|
{
|
|
if (! $content instanceof File && ! $content instanceof Directory) {
|
|
throw new \common_Exception('Content for ' . __FUNCTION__ . ' has to be a file or directory object. ' .
|
|
is_object($content) ? get_class($content) : gettype($content) . ' given.');
|
|
}
|
|
|
|
return str_replace($this->getPrefix(), '', $content->getPrefix());
|
|
}
|
|
|
|
/**
|
|
* Check if current directory exists
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function exists()
|
|
{
|
|
return $this->getFileSystem()->has($this->getPrefix());
|
|
}
|
|
|
|
/**
|
|
* Delete the current directory
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function deleteSelf()
|
|
{
|
|
return $this->getFileSystem()->deleteDir($this->getPrefix());
|
|
}
|
|
|
|
/**
|
|
* Return a sanitized full path from main directory
|
|
*
|
|
* @param $path
|
|
* @return string
|
|
*/
|
|
protected function getFullPath($path)
|
|
{
|
|
return $this->getPrefix() . '/' . $this->sanitizePath($path);
|
|
}
|
|
|
|
/**
|
|
* Rename
|
|
*
|
|
* Rename directory into $path
|
|
*
|
|
* @param $path
|
|
* @return bool
|
|
* @throws \common_exception_FileSystemError
|
|
*/
|
|
public function rename($path)
|
|
{
|
|
// This implementation supersedes the Flysystem's one. Indeed, while using connectors
|
|
// such as the Amazon S3 (v3) connector, rename on directories does not work. A custom
|
|
// implementation is then needed.
|
|
|
|
$contents = $this->getFileSystem()->listContents($this->getPrefix(), true);
|
|
$fileSystemId = $this->getFileSystemId().'/';
|
|
// Filter files only.
|
|
$filePaths = [];
|
|
foreach ($contents as $content) {
|
|
if ($content['type'] === 'file') {
|
|
$contentPath = $content['path'];
|
|
if(strpos($contentPath, $fileSystemId) === 0) {
|
|
$contentPath = substr($contentPath, strlen($fileSystemId));
|
|
}
|
|
|
|
$filePaths[] = [
|
|
'source' => $contentPath,
|
|
'destination' => str_replace($this->getPrefix(), $path, $content['path'])];
|
|
}
|
|
}
|
|
|
|
foreach ($filePaths as $renaming) {
|
|
try {
|
|
if ($this->getFileSystem()->rename($renaming['source'], $renaming['destination']) === false) {
|
|
throw new \common_exception_FileSystemError("Unable to rename '" . $renaming['source'] . "' into '".$renaming['destination']."'.");
|
|
}
|
|
} catch (FileExistsException $e) {
|
|
throw new \common_exception_FileSystemError("Unable to rename '" . $renaming['source'] . "' into '".$renaming['destination']."'. File already exists.");
|
|
}
|
|
}
|
|
|
|
if (!$this->deleteSelf()) {
|
|
throw new \common_exception_FileSystemError("Could not finalize renaming of '" . $this->getPrefix() . "' into '${path}'.");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|