1
0
Fork 0
mirror of https://github.com/wallabag/wallabag.git synced 2025-08-06 17:41:01 +00:00

twig implementation

This commit is contained in:
Nicolas Lœuillet 2013-08-03 19:26:54 +02:00
parent 2b840e0cfb
commit 4f5b44bd3b
1418 changed files with 108207 additions and 1586 deletions

View file

@ -0,0 +1,4 @@
vendor/
composer.lock
phpunit.xml

View file

@ -0,0 +1,18 @@
CHANGELOG
=========
2.3.0
-----
* added the dumpFile() method to atomically write files
2.2.0
-----
* added a delete option for the mirror() method
2.1.0
-----
* 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value
* created the component

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Filesystem\Exception;
/**
* Exception interface for all exceptions thrown by the component.
*
* @author Romain Neutron <imprec@gmail.com>
*
* @api
*/
interface ExceptionInterface
{
}

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Filesystem\Exception;
/**
* Exception class thrown when a filesystem operation failure happens
*
* @author Romain Neutron <imprec@gmail.com>
*
* @api
*/
class IOException extends \RuntimeException implements ExceptionInterface
{
}

View file

@ -0,0 +1,471 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Filesystem;
use Symfony\Component\Filesystem\Exception\IOException;
/**
* Provides basic utility to manipulate the file system.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Filesystem
{
/**
* Copies a file.
*
* This method only copies the file if the origin file is newer than the target file.
*
* By default, if the target already exists, it is not overridden.
*
* @param string $originFile The original filename
* @param string $targetFile The target filename
* @param boolean $override Whether to override an existing file or not
*
* @throws IOException When copy fails
*/
public function copy($originFile, $targetFile, $override = false)
{
if (stream_is_local($originFile) && !is_file($originFile)) {
throw new IOException(sprintf('Failed to copy %s because file not exists', $originFile));
}
$this->mkdir(dirname($targetFile));
if (!$override && is_file($targetFile)) {
$doCopy = filemtime($originFile) > filemtime($targetFile);
} else {
$doCopy = true;
}
if ($doCopy) {
// https://bugs.php.net/bug.php?id=64634
$source = fopen($originFile, 'r');
$target = fopen($targetFile, 'w+');
stream_copy_to_stream($source, $target);
fclose($source);
fclose($target);
unset($source, $target);
if (!is_file($targetFile)) {
throw new IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile));
}
}
}
/**
* Creates a directory recursively.
*
* @param string|array|\Traversable $dirs The directory path
* @param integer $mode The directory mode
*
* @throws IOException On any directory creation failure
*/
public function mkdir($dirs, $mode = 0777)
{
foreach ($this->toIterator($dirs) as $dir) {
if (is_dir($dir)) {
continue;
}
if (true !== @mkdir($dir, $mode, true)) {
throw new IOException(sprintf('Failed to create %s', $dir));
}
}
}
/**
* Checks the existence of files or directories.
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check
*
* @return Boolean true if the file exists, false otherwise
*/
public function exists($files)
{
foreach ($this->toIterator($files) as $file) {
if (!file_exists($file)) {
return false;
}
}
return true;
}
/**
* Sets access and modification time of file.
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
* @param integer $time The touch time as a unix timestamp
* @param integer $atime The access time as a unix timestamp
*
* @throws IOException When touch fails
*/
public function touch($files, $time = null, $atime = null)
{
foreach ($this->toIterator($files) as $file) {
$touch = $time ? @touch($file, $time, $atime) : @touch($file);
if (true !== $touch) {
throw new IOException(sprintf('Failed to touch %s', $file));
}
}
}
/**
* Removes files or directories.
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
*
* @throws IOException When removal fails
*/
public function remove($files)
{
$files = iterator_to_array($this->toIterator($files));
$files = array_reverse($files);
foreach ($files as $file) {
if (!file_exists($file) && !is_link($file)) {
continue;
}
if (is_dir($file) && !is_link($file)) {
$this->remove(new \FilesystemIterator($file));
if (true !== @rmdir($file)) {
throw new IOException(sprintf('Failed to remove directory %s', $file));
}
} else {
// https://bugs.php.net/bug.php?id=52176
if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) {
if (true !== @rmdir($file)) {
throw new IOException(sprintf('Failed to remove file %s', $file));
}
} else {
if (true !== @unlink($file)) {
throw new IOException(sprintf('Failed to remove file %s', $file));
}
}
}
}
}
/**
* Change mode for an array of files or directories.
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode
* @param integer $mode The new mode (octal)
* @param integer $umask The mode mask (octal)
* @param Boolean $recursive Whether change the mod recursively or not
*
* @throws IOException When the change fail
*/
public function chmod($files, $mode, $umask = 0000, $recursive = false)
{
foreach ($this->toIterator($files) as $file) {
if ($recursive && is_dir($file) && !is_link($file)) {
$this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
}
if (true !== @chmod($file, $mode & ~$umask)) {
throw new IOException(sprintf('Failed to chmod file %s', $file));
}
}
}
/**
* Change the owner of an array of files or directories
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner
* @param string $user The new owner user name
* @param Boolean $recursive Whether change the owner recursively or not
*
* @throws IOException When the change fail
*/
public function chown($files, $user, $recursive = false)
{
foreach ($this->toIterator($files) as $file) {
if ($recursive && is_dir($file) && !is_link($file)) {
$this->chown(new \FilesystemIterator($file), $user, true);
}
if (is_link($file) && function_exists('lchown')) {
if (true !== @lchown($file, $user)) {
throw new IOException(sprintf('Failed to chown file %s', $file));
}
} else {
if (true !== @chown($file, $user)) {
throw new IOException(sprintf('Failed to chown file %s', $file));
}
}
}
}
/**
* Change the group of an array of files or directories
*
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group
* @param string $group The group name
* @param Boolean $recursive Whether change the group recursively or not
*
* @throws IOException When the change fail
*/
public function chgrp($files, $group, $recursive = false)
{
foreach ($this->toIterator($files) as $file) {
if ($recursive && is_dir($file) && !is_link($file)) {
$this->chgrp(new \FilesystemIterator($file), $group, true);
}
if (is_link($file) && function_exists('lchgrp')) {
if (true !== @lchgrp($file, $group)) {
throw new IOException(sprintf('Failed to chgrp file %s', $file));
}
} else {
if (true !== @chgrp($file, $group)) {
throw new IOException(sprintf('Failed to chgrp file %s', $file));
}
}
}
}
/**
* Renames a file or a directory.
*
* @param string $origin The origin filename or directory
* @param string $target The new filename or directory
* @param Boolean $overwrite Whether to overwrite the target if it already exists
*
* @throws IOException When target file or directory already exists
* @throws IOException When origin cannot be renamed
*/
public function rename($origin, $target, $overwrite = false)
{
// we check that target does not exist
if (!$overwrite && is_readable($target)) {
throw new IOException(sprintf('Cannot rename because the target "%s" already exist.', $target));
}
if (true !== @rename($origin, $target)) {
throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target));
}
}
/**
* Creates a symbolic link or copy a directory.
*
* @param string $originDir The origin directory path
* @param string $targetDir The symbolic link name
* @param Boolean $copyOnWindows Whether to copy files if on Windows
*
* @throws IOException When symlink fails
*/
public function symlink($originDir, $targetDir, $copyOnWindows = false)
{
if (!function_exists('symlink') && $copyOnWindows) {
$this->mirror($originDir, $targetDir);
return;
}
$this->mkdir(dirname($targetDir));
$ok = false;
if (is_link($targetDir)) {
if (readlink($targetDir) != $originDir) {
$this->remove($targetDir);
} else {
$ok = true;
}
}
if (!$ok) {
if (true !== @symlink($originDir, $targetDir)) {
$report = error_get_last();
if (is_array($report)) {
if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) {
throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
}
}
throw new IOException(sprintf('Failed to create symbolic link from %s to %s', $originDir, $targetDir));
}
}
}
/**
* Given an existing path, convert it to a path relative to a given starting path
*
* @param string $endPath Absolute path of target
* @param string $startPath Absolute path where traversal begins
*
* @return string Path of target relative to starting path
*/
public function makePathRelative($endPath, $startPath)
{
// Normalize separators on windows
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$endPath = strtr($endPath, '\\', '/');
$startPath = strtr($startPath, '\\', '/');
}
// Split the paths into arrays
$startPathArr = explode('/', trim($startPath, '/'));
$endPathArr = explode('/', trim($endPath, '/'));
// Find for which directory the common path stops
$index = 0;
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
$index++;
}
// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
$depth = count($startPathArr) - $index;
// Repeated "../" for each level need to reach the common path
$traverser = str_repeat('../', $depth);
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
// Construct $endPath from traversing to the common path, then to the remaining $endPath
$relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : '');
return (strlen($relativePath) === 0) ? './' : $relativePath;
}
/**
* Mirrors a directory to another.
*
* @param string $originDir The origin directory
* @param string $targetDir The target directory
* @param \Traversable $iterator A Traversable instance
* @param array $options An array of boolean options
* Valid options are:
* - $options['override'] Whether to override an existing file on copy or not (see copy())
* - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
* - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
*
* @throws IOException When file type is unknown
*/
public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
{
$targetDir = rtrim($targetDir, '/\\');
$originDir = rtrim($originDir, '/\\');
// Iterate in destination folder to remove obsolete entries
if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
$deleteIterator = $iterator;
if (null === $deleteIterator) {
$flags = \FilesystemIterator::SKIP_DOTS;
$deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
}
foreach ($deleteIterator as $file) {
$origin = str_replace($targetDir, $originDir, $file->getPathname());
if (!$this->exists($origin)) {
$this->remove($file);
}
}
}
$copyOnWindows = false;
if (isset($options['copy_on_windows']) && !function_exists('symlink')) {
$copyOnWindows = $options['copy_on_windows'];
}
if (null === $iterator) {
$flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
}
foreach ($iterator as $file) {
$target = str_replace($originDir, $targetDir, $file->getPathname());
if ($copyOnWindows) {
if (is_link($file) || is_file($file)) {
$this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
} elseif (is_dir($file)) {
$this->mkdir($target);
} else {
throw new IOException(sprintf('Unable to guess "%s" file type.', $file));
}
} else {
if (is_link($file)) {
$this->symlink($file, $target);
} elseif (is_dir($file)) {
$this->mkdir($target);
} elseif (is_file($file)) {
$this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
} else {
throw new IOException(sprintf('Unable to guess "%s" file type.', $file));
}
}
}
}
/**
* Returns whether the file path is an absolute path.
*
* @param string $file A file path
*
* @return Boolean
*/
public function isAbsolutePath($file)
{
if (strspn($file, '/\\', 0, 1)
|| (strlen($file) > 3 && ctype_alpha($file[0])
&& substr($file, 1, 1) === ':'
&& (strspn($file, '/\\', 2, 1))
)
|| null !== parse_url($file, PHP_URL_SCHEME)
) {
return true;
}
return false;
}
/**
* @param mixed $files
*
* @return \Traversable
*/
private function toIterator($files)
{
if (!$files instanceof \Traversable) {
$files = new \ArrayObject(is_array($files) ? $files : array($files));
}
return $files;
}
/**
* Atomically dumps content into a file.
*
* @param string $filename The file to be written to.
* @param string $content The data to write into the file.
* @param integer $mode The file mode (octal).
* @throws IOException If the file cannot be written to.
*/
public function dumpFile($filename, $content, $mode = 0666)
{
$dir = dirname($filename);
if (!is_dir($dir)) {
$this->mkdir($dir);
} elseif (!is_writable($dir)) {
throw new IOException(sprintf('Unable to write in the %s directory\n', $dir));
}
$tmpFile = tempnam($dir, basename($filename));
if (false === @file_put_contents($tmpFile, $content)) {
throw new IOException(sprintf('Failed to write file "%s".', $filename));
}
$this->rename($tmpFile, $filename, true);
$this->chmod($filename, $mode);
}
}

View file

@ -0,0 +1,19 @@
Copyright (c) 2004-2013 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,45 @@
Filesystem Component
====================
Filesystem provides basic utility to manipulate the file system:
```php
<?php
use Symfony\Component\Filesystem\Filesystem;
$filesystem = new Filesystem();
$filesystem->copy($originFile, $targetFile, $override = false);
$filesystem->mkdir($dirs, $mode = 0777);
$filesystem->touch($files, $time = null, $atime = null);
$filesystem->remove($files);
$filesystem->chmod($files, $mode, $umask = 0000, $recursive = false);
$filesystem->chown($files, $user, $recursive = false);
$filesystem->chgrp($files, $group, $recursive = false);
$filesystem->rename($origin, $target);
$filesystem->symlink($originDir, $targetDir, $copyOnWindows = false);
$filesystem->makePathRelative($endPath, $startPath);
$filesystem->mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array());
$filesystem->isAbsolutePath($file);
```
Resources
---------
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/Filesystem/
$ composer.phar install --dev
$ phpunit

View file

@ -0,0 +1,982 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Filesystem\Tests;
use Symfony\Component\Filesystem\Filesystem;
/**
* Test class for Filesystem.
*/
class FilesystemTest extends \PHPUnit_Framework_TestCase
{
/**
* @var string $workspace
*/
private $workspace = null;
/**
* @var \Symfony\Component\Filesystem\Filesystem $filesystem
*/
private $filesystem = null;
private static $symlinkOnWindows = null;
public static function setUpBeforeClass()
{
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
self::$symlinkOnWindows = true;
$originDir = tempnam(sys_get_temp_dir(), 'sl');
$targetDir = tempnam(sys_get_temp_dir(), 'sl');
if (true !== @symlink($originDir, $targetDir)) {
$report = error_get_last();
if (is_array($report) && false !== strpos($report['message'], 'error code(1314)')) {
self::$symlinkOnWindows = false;
}
}
}
}
public function setUp()
{
$this->filesystem = new Filesystem();
$this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
mkdir($this->workspace, 0777, true);
$this->workspace = realpath($this->workspace);
}
public function tearDown()
{
$this->clean($this->workspace);
}
/**
* @param string $file
*/
private function clean($file)
{
if (is_dir($file) && !is_link($file)) {
$dir = new \FilesystemIterator($file);
foreach ($dir as $childFile) {
$this->clean($childFile);
}
rmdir($file);
} else {
unlink($file);
}
}
public function testCopyCreatesNewFile()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
file_put_contents($sourceFilePath, 'SOURCE FILE');
$this->filesystem->copy($sourceFilePath, $targetFilePath);
$this->assertFileExists($targetFilePath);
$this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testCopyFails()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
$this->filesystem->copy($sourceFilePath, $targetFilePath);
}
public function testCopyOverridesExistingFileIfModified()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
file_put_contents($sourceFilePath, 'SOURCE FILE');
file_put_contents($targetFilePath, 'TARGET FILE');
touch($targetFilePath, time() - 1000);
$this->filesystem->copy($sourceFilePath, $targetFilePath);
$this->assertFileExists($targetFilePath);
$this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
}
public function testCopyDoesNotOverrideExistingFileByDefault()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
file_put_contents($sourceFilePath, 'SOURCE FILE');
file_put_contents($targetFilePath, 'TARGET FILE');
// make sure both files have the same modification time
$modificationTime = time() - 1000;
touch($sourceFilePath, $modificationTime);
touch($targetFilePath, $modificationTime);
$this->filesystem->copy($sourceFilePath, $targetFilePath);
$this->assertFileExists($targetFilePath);
$this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
}
public function testCopyOverridesExistingFileIfForced()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';
file_put_contents($sourceFilePath, 'SOURCE FILE');
file_put_contents($targetFilePath, 'TARGET FILE');
// make sure both files have the same modification time
$modificationTime = time() - 1000;
touch($sourceFilePath, $modificationTime);
touch($targetFilePath, $modificationTime);
$this->filesystem->copy($sourceFilePath, $targetFilePath, true);
$this->assertFileExists($targetFilePath);
$this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
}
public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
{
$sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
$targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
$targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';
file_put_contents($sourceFilePath, 'SOURCE FILE');
$this->filesystem->copy($sourceFilePath, $targetFilePath);
$this->assertTrue(is_dir($targetFileDirectory));
$this->assertFileExists($targetFilePath);
$this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
}
public function testMkdirCreatesDirectoriesRecursively()
{
$directory = $this->workspace
.DIRECTORY_SEPARATOR.'directory'
.DIRECTORY_SEPARATOR.'sub_directory';
$this->filesystem->mkdir($directory);
$this->assertTrue(is_dir($directory));
}
public function testMkdirCreatesDirectoriesFromArray()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
$directories = array(
$basePath.'1', $basePath.'2', $basePath.'3'
);
$this->filesystem->mkdir($directories);
$this->assertTrue(is_dir($basePath.'1'));
$this->assertTrue(is_dir($basePath.'2'));
$this->assertTrue(is_dir($basePath.'3'));
}
public function testMkdirCreatesDirectoriesFromTraversableObject()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
$directories = new \ArrayObject(array(
$basePath.'1', $basePath.'2', $basePath.'3'
));
$this->filesystem->mkdir($directories);
$this->assertTrue(is_dir($basePath.'1'));
$this->assertTrue(is_dir($basePath.'2'));
$this->assertTrue(is_dir($basePath.'3'));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testMkdirCreatesDirectoriesFails()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
$dir = $basePath.'2';
file_put_contents($dir, '');
$this->filesystem->mkdir($dir);
}
public function testTouchCreatesEmptyFile()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.'1';
$this->filesystem->touch($file);
$this->assertFileExists($file);
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testTouchFails()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';
$this->filesystem->touch($file);
}
public function testTouchCreatesEmptyFilesFromArray()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
$files = array(
$basePath.'1', $basePath.'2', $basePath.'3'
);
$this->filesystem->touch($files);
$this->assertFileExists($basePath.'1');
$this->assertFileExists($basePath.'2');
$this->assertFileExists($basePath.'3');
}
public function testTouchCreatesEmptyFilesFromTraversableObject()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
$files = new \ArrayObject(array(
$basePath.'1', $basePath.'2', $basePath.'3'
));
$this->filesystem->touch($files);
$this->assertFileExists($basePath.'1');
$this->assertFileExists($basePath.'2');
$this->assertFileExists($basePath.'3');
}
public function testRemoveCleansFilesAndDirectoriesIteratively()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
mkdir($basePath);
mkdir($basePath.'dir');
touch($basePath.'file');
$this->filesystem->remove($basePath);
$this->assertTrue(!is_dir($basePath));
}
public function testRemoveCleansArrayOfFilesAndDirectories()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
mkdir($basePath.'dir');
touch($basePath.'file');
$files = array(
$basePath.'dir', $basePath.'file'
);
$this->filesystem->remove($files);
$this->assertTrue(!is_dir($basePath.'dir'));
$this->assertTrue(!is_file($basePath.'file'));
}
public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
mkdir($basePath.'dir');
touch($basePath.'file');
$files = new \ArrayObject(array(
$basePath.'dir', $basePath.'file'
));
$this->filesystem->remove($files);
$this->assertTrue(!is_dir($basePath.'dir'));
$this->assertTrue(!is_file($basePath.'file'));
}
public function testRemoveIgnoresNonExistingFiles()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
mkdir($basePath.'dir');
$files = array(
$basePath.'dir', $basePath.'file'
);
$this->filesystem->remove($files);
$this->assertTrue(!is_dir($basePath.'dir'));
}
public function testRemoveCleansInvalidLinks()
{
$this->markAsSkippedIfSymlinkIsMissing();
$basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
mkdir($basePath);
mkdir($basePath.'dir');
// create symlink to unexisting file
@symlink($basePath.'file', $basePath.'link');
$this->filesystem->remove($basePath);
$this->assertTrue(!is_dir($basePath));
}
public function testFilesExists()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
mkdir($basePath);
touch($basePath.'file1');
mkdir($basePath.'folder');
$this->assertTrue($this->filesystem->exists($basePath.'file1'));
$this->assertTrue($this->filesystem->exists($basePath.'folder'));
}
public function testFilesExistsTraversableObjectOfFilesAndDirectories()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
mkdir($basePath.'dir');
touch($basePath.'file');
$files = new \ArrayObject(array(
$basePath.'dir', $basePath.'file'
));
$this->assertTrue($this->filesystem->exists($files));
}
public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR;
mkdir($basePath.'dir');
touch($basePath.'file');
touch($basePath.'file2');
$files = new \ArrayObject(array(
$basePath.'dir', $basePath.'file', $basePath.'file2'
));
unlink($basePath.'file');
$this->assertFalse($this->filesystem->exists($files));
}
public function testInvalidFileNotExists()
{
$basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;
$this->assertFalse($this->filesystem->exists($basePath.time()));
}
public function testChmodChangesFileMode()
{
$this->markAsSkippedIfChmodIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$file = $dir.DIRECTORY_SEPARATOR.'file';
touch($file);
$this->filesystem->chmod($file, 0400);
$this->filesystem->chmod($dir, 0753);
$this->assertEquals(753, $this->getFilePermissions($dir));
$this->assertEquals(400, $this->getFilePermissions($file));
}
public function testChmodWrongMod()
{
$this->markAsSkippedIfChmodIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
touch($dir);
$this->filesystem->chmod($dir, 'Wrongmode');
}
public function testChmodRecursive()
{
$this->markAsSkippedIfChmodIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$file = $dir.DIRECTORY_SEPARATOR.'file';
touch($file);
$this->filesystem->chmod($file, 0400, 0000, true);
$this->filesystem->chmod($dir, 0753, 0000, true);
$this->assertEquals(753, $this->getFilePermissions($dir));
$this->assertEquals(753, $this->getFilePermissions($file));
}
public function testChmodAppliesUmask()
{
$this->markAsSkippedIfChmodIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
touch($file);
$this->filesystem->chmod($file, 0770, 0022);
$this->assertEquals(750, $this->getFilePermissions($file));
}
public function testChmodChangesModeOfArrayOfFiles()
{
$this->markAsSkippedIfChmodIsMissing();
$directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$files = array($directory, $file);
mkdir($directory);
touch($file);
$this->filesystem->chmod($files, 0753);
$this->assertEquals(753, $this->getFilePermissions($file));
$this->assertEquals(753, $this->getFilePermissions($directory));
}
public function testChmodChangesModeOfTraversableFileObject()
{
$this->markAsSkippedIfChmodIsMissing();
$directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$files = new \ArrayObject(array($directory, $file));
mkdir($directory);
touch($file);
$this->filesystem->chmod($files, 0753);
$this->assertEquals(753, $this->getFilePermissions($file));
$this->assertEquals(753, $this->getFilePermissions($directory));
}
public function testChown()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$this->filesystem->chown($dir, $this->getFileOwner($dir));
}
public function testChownRecursive()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$file = $dir.DIRECTORY_SEPARATOR.'file';
touch($file);
$this->filesystem->chown($dir, $this->getFileOwner($dir), true);
}
public function testChownSymlink()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link);
$this->filesystem->chown($link, $this->getFileOwner($link));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testChownSymlinkFails()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link);
$this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testChownFail()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
}
public function testChgrp()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$this->filesystem->chgrp($dir, $this->getFileGroup($dir));
}
public function testChgrpRecursive()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$file = $dir.DIRECTORY_SEPARATOR.'file';
touch($file);
$this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
}
public function testChgrpSymlink()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link);
$this->filesystem->chgrp($link, $this->getFileGroup($link));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testChgrpSymlinkFails()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link);
$this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testChgrpFail()
{
$this->markAsSkippedIfPosixIsMissing();
$dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
mkdir($dir);
$this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
}
public function testRename()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
touch($file);
$this->filesystem->rename($file, $newPath);
$this->assertFileNotExists($file);
$this->assertFileExists($newPath);
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testRenameThrowsExceptionIfTargetAlreadyExists()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
touch($file);
touch($newPath);
$this->filesystem->rename($file, $newPath);
}
public function testRenameOverwritesTheTargetIfItAlreadyExists()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
touch($file);
touch($newPath);
$this->filesystem->rename($file, $newPath, true);
$this->assertFileNotExists($file);
$this->assertFileExists($newPath);
}
/**
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
*/
public function testRenameThrowsExceptionOnError()
{
$file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
$newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
$this->filesystem->rename($file, $newPath);
}
public function testSymlink()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link);
$this->assertTrue(is_link($link));
$this->assertEquals($file, readlink($link));
}
/**
* @depends testSymlink
*/
public function testRemoveSymlink()
{
$this->markAsSkippedIfSymlinkIsMissing();
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
$this->filesystem->remove($link);
$this->assertTrue(!is_link($link));
}
public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
symlink($this->workspace, $link);
$this->filesystem->symlink($file, $link);
$this->assertTrue(is_link($link));
$this->assertEquals($file, readlink($link));
}
public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link = $this->workspace.DIRECTORY_SEPARATOR.'link';
touch($file);
symlink($file, $link);
$this->filesystem->symlink($file, $link);
$this->assertTrue(is_link($link));
$this->assertEquals($file, readlink($link));
}
public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
{
$this->markAsSkippedIfSymlinkIsMissing();
$file = $this->workspace.DIRECTORY_SEPARATOR.'file';
$link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
$link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';
touch($file);
$this->filesystem->symlink($file, $link1);
$this->filesystem->symlink($file, $link2);
$this->assertTrue(is_link($link1));
$this->assertEquals($file, readlink($link1));
$this->assertTrue(is_link($link2));
$this->assertEquals($file, readlink($link2));
}
/**
* @dataProvider providePathsForMakePathRelative
*/
public function testMakePathRelative($endPath, $startPath, $expectedPath)
{
$path = $this->filesystem->makePathRelative($endPath, $startPath);
$this->assertEquals($expectedPath, $path);
}
/**
* @return array
*/
public function providePathsForMakePathRelative()
{
$paths = array(
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
array('/aa/bb', '/aa/bb', './'),
array('/aa/bb', '/aa/bb/', './'),
array('/aa/bb/', '/aa/bb', './'),
array('/aa/bb/', '/aa/bb/', './'),
array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
array('/aa/bb/cc', '/aa', 'bb/cc/'),
array('/aa/bb/cc', '/aa/', 'bb/cc/'),
array('/aa/bb/cc/', '/aa', 'bb/cc/'),
array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
array('/a/aab/bb', '/a/aa', '../aab/bb/'),
array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
);
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
}
return $paths;
}
public function testMirrorCopiesFilesAndDirectoriesRecursively()
{
$sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
$directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
$file1 = $directory.'file1';
$file2 = $sourcePath.'file2';
mkdir($sourcePath);
mkdir($directory);
file_put_contents($file1, 'FILE1');
file_put_contents($file2, 'FILE2');
$targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
$this->filesystem->mirror($sourcePath, $targetPath);
$this->assertTrue(is_dir($targetPath));
$this->assertTrue(is_dir($targetPath.'directory'));
$this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
$this->assertFileEquals($file2, $targetPath.'file2');
$this->filesystem->remove($file1);
$this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
$this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
$this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
$this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
file_put_contents($file1, 'FILE1');
$this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
$this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
$this->filesystem->remove($directory);
$this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
$this->assertFalse($this->filesystem->exists($targetPath.'directory'));
$this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
}
public function testMirrorCopiesLinks()
{
$this->markAsSkippedIfSymlinkIsMissing();
$sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
mkdir($sourcePath);
file_put_contents($sourcePath.'file1', 'FILE1');
symlink($sourcePath.'file1', $sourcePath.'link1');
$targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
$this->filesystem->mirror($sourcePath, $targetPath);
$this->assertTrue(is_dir($targetPath));
$this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
$this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
}
public function testMirrorCopiesLinkedDirectoryContents()
{
$this->markAsSkippedIfSymlinkIsMissing();
$sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
mkdir($sourcePath.'nested/', 0777, true);
file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
// Note: We symlink directory, not file
symlink($sourcePath.'nested', $sourcePath.'link1');
$targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;
$this->filesystem->mirror($sourcePath, $targetPath);
$this->assertTrue(is_dir($targetPath));
$this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
$this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
}
/**
* @dataProvider providePathsForIsAbsolutePath
*/
public function testIsAbsolutePath($path, $expectedResult)
{
$result = $this->filesystem->isAbsolutePath($path);
$this->assertEquals($expectedResult, $result);
}
/**
* @return array
*/
public function providePathsForIsAbsolutePath()
{
return array(
array('/var/lib', true),
array('c:\\\\var\\lib', true),
array('\\var\\lib', true),
array('var/lib', false),
array('../var/lib', false),
array('', false),
array(null, false)
);
}
public function testDumpFile()
{
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
$this->filesystem->dumpFile($filename, 'bar', 0753);
$this->assertFileExists($filename);
$this->assertSame('bar', file_get_contents($filename));
// skip mode check on windows
if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
$this->assertEquals(753, $this->getFilePermissions($filename));
}
}
public function testDumpFileOverwritesAnExistingFile()
{
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
file_put_contents($filename, 'FOO BAR');
$this->filesystem->dumpFile($filename, 'bar');
$this->assertFileExists($filename);
$this->assertSame('bar', file_get_contents($filename));
}
/**
* Returns file permissions as three digits (i.e. 755)
*
* @param string $filePath
*
* @return integer
*/
private function getFilePermissions($filePath)
{
return (int) substr(sprintf('%o', fileperms($filePath)), -3);
}
private function getFileOwner($filepath)
{
$this->markAsSkippedIfPosixIsMissing();
$infos = stat($filepath);
if ($datas = posix_getpwuid($infos['uid'])) {
return $datas['name'];
}
}
private function getFileGroup($filepath)
{
$this->markAsSkippedIfPosixIsMissing();
$infos = stat($filepath);
if ($datas = posix_getgrgid($infos['gid'])) {
return $datas['name'];
}
}
private function markAsSkippedIfSymlinkIsMissing()
{
if (!function_exists('symlink')) {
$this->markTestSkipped('symlink is not supported');
}
if (defined('PHP_WINDOWS_VERSION_MAJOR') && false === self::$symlinkOnWindows) {
$this->markTestSkipped('symlink requires "Create symbolic links" privilege on windows');
}
}
private function markAsSkippedIfChmodIsMissing()
{
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$this->markTestSkipped('chmod is not supported on windows');
}
}
private function markAsSkippedIfPosixIsMissing()
{
if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('posix_isatty')) {
$this->markTestSkipped('Posix is not supported');
}
}
}

View file

@ -0,0 +1,31 @@
{
"name": "symfony/filesystem",
"type": "library",
"description": "Symfony Filesystem Component",
"keywords": [],
"homepage": "http://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-0": { "Symfony\\Component\\Filesystem\\": "" }
},
"target-dir": "Symfony/Component/Filesystem",
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
}
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="vendor/autoload.php"
>
<testsuites>
<testsuite name="Symfony Filesystem Component Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Tests</directory>
</exclude>
</whitelist>
</filter>
</phpunit>