Remove vendor directory

This commit is contained in:
Oliver Davies 2019-02-27 00:19:41 +00:00
parent 9f51fb5b84
commit 37a523757e
8378 changed files with 1 additions and 815945 deletions

1
.gitignore vendored
View file

@ -13,6 +13,7 @@
# Core's dependencies are managed with Composer. # Core's dependencies are managed with Composer.
/web/vendor /web/vendor
/vendor
# Ignore configuration files that may contain sensitive information. # Ignore configuration files that may contain sensitive information.
/web/sites/*/settings*.php /web/sites/*/settings*.php

View file

@ -1,21 +0,0 @@
Zippy is released under the MIT License :
Copyright (c) 2012 Alchemy
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

@ -1,17 +0,0 @@
adapters:="ZipAdapter" "ZipExtensionAdapter" "GNUTar\\TarGNUTarAdapter" "GNUTar\\TarGzGNUTarAdapter" "GNUTar\\TarBz2GNUTarAdapter" "BSDTar\\TarBSDTarAdapter" "BSDTar\\TarGzBSDTarAdapter" "BSDTar\\TarBz2BSDTarAdapter"
.PHONY: test clean
test: node_modules
-./tests/bootstrap.sh stop
./tests/bootstrap.sh start
sleep 1
./vendor/bin/phpunit
FAILURES="";$(foreach adapter,$(adapters),ZIPPY_ADAPTER=$(adapter) ./vendor/bin/phpunit -c phpunit-functional.xml.dist || FAILURES=1;)test -z "$$FAILURES"
-./tests/bootstrap.sh stop
node_modules:
npm install connect serve-static
clean:
rm -rf node_modules

View file

@ -1,49 +0,0 @@
{
"name": "alchemy/zippy",
"type": "library",
"description": "Zippy, the archive manager companion",
"keywords": ["zip", "tar", "bzip", "compression"],
"license": "MIT",
"authors": [
{
"name": "Alchemy",
"email": "dev.team@alchemy.fr",
"homepage": "http://www.alchemy.fr/"
}
],
"require": {
"php": ">=5.5",
"ext-mbstring": "*",
"doctrine/collections": "~1.0",
"symfony/filesystem": "^2.0.5|^3.0",
"symfony/process": "^2.1|^3.0"
},
"require-dev": {
"ext-zip": "*",
"guzzle/guzzle": "~3.0",
"guzzlehttp/guzzle": "^6.0",
"phpunit/phpunit": "^4.0|^5.0",
"symfony/finder": "^2.0.5|^3.0"
},
"suggest": {
"ext-zip": "To use the ZipExtensionAdapter",
"guzzlehttp/guzzle": "To use the GuzzleTeleporter with Guzzle 6",
"guzzle/guzzle": "To use the GuzzleTeleporter with Guzzle 3"
},
"autoload": {
"psr-4": {
"Alchemy\\Zippy\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Alchemy\\Zippy\\Functional\\": "tests/Functional/",
"Alchemy\\Zippy\\Tests\\": "tests/Tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "0.4.x-dev"
}
}
}

View file

@ -1,273 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Adapter\VersionProbe\VersionProbeInterface;
use Alchemy\Zippy\Archive\Archive;
use Alchemy\Zippy\Archive\ArchiveInterface;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Resource\PathUtil;
use Alchemy\Zippy\Resource\ResourceManager;
abstract class AbstractAdapter implements AdapterInterface
{
/** @var ResourceManager */
protected $manager;
/**
* The version probe
*
* @var VersionProbeInterface
*/
protected $probe;
public function __construct(ResourceManager $manager)
{
$this->manager = $manager;
}
/**
* @inheritdoc
*/
public function open($path)
{
$this->requireSupport();
return new Archive($this->createResource($path), $this, $this->manager);
}
/**
* @inheritdoc
*/
public function create($path, $files = null, $recursive = true)
{
$this->requireSupport();
return $this->doCreate($this->makeTargetAbsolute($path), $files, $recursive);
}
/**
* @inheritdoc
*/
public function listMembers(ResourceInterface $resource)
{
$this->requireSupport();
return $this->doListMembers($resource);
}
/**
* @inheritdoc
*/
public function add(ResourceInterface $resource, $files, $recursive = true)
{
$this->requireSupport();
return $this->doAdd($resource, $files, $recursive);
}
/**
* @inheritdoc
*/
public function remove(ResourceInterface $resource, $files)
{
$this->requireSupport();
return $this->doRemove($resource, $files);
}
/**
* @inheritdoc
*/
public function extract(ResourceInterface $resource, $to = null)
{
$this->requireSupport();
return $this->doExtract($resource, $to);
}
/**
* @inheritdoc
*/
public function extractMembers(ResourceInterface $resource, $members, $to = null, $overwrite = false)
{
$this->requireSupport();
return $this->doExtractMembers($resource, $members, $to, $overwrite);
}
/**
* Returns the version probe used by this adapter
*
* @return VersionProbeInterface
*/
public function getVersionProbe()
{
return $this->probe;
}
/**
* Sets the version probe used by this adapter
*
* @param VersionProbeInterface $probe
*
* @return VersionProbeInterface
*/
public function setVersionProbe(VersionProbeInterface $probe)
{
$this->probe = $probe;
return $this;
}
/**
* @inheritdoc
*/
public function isSupported()
{
if (!$this->probe) {
throw new RuntimeException(sprintf(
'No version probe has been set on %s whereas it is required', get_class($this)
));
}
return VersionProbeInterface::PROBE_OK === $this->probe->getStatus();
}
/**
* Throws an exception is the current adapter is not supported
*
* @throws RuntimeException
*/
protected function requireSupport()
{
if (false === $this->isSupported()) {
throw new RuntimeException(sprintf('%s is not supported on your system', get_class($this)));
}
}
/**
* Change current working directory to another
*
* @param string $target the target directory
*
* @return AdapterInterface
*
* @throws RuntimeException In case of failure
*/
protected function chdir($target)
{
if (false === @chdir($target)) {
throw new RuntimeException(sprintf('Unable to chdir to `%s`', $target));
}
return $this;
}
/**
* Creates a resource given a path
*
* @param string $path
*
* @return ResourceInterface
*/
abstract protected function createResource($path);
/**
* Do the removal after having check that the current adapter is supported
*
* @param ResourceInterface $resource
* @param array $files
*
* @return array
*/
abstract protected function doRemove(ResourceInterface $resource, $files);
/**
* Do the add after having check that the current adapter is supported
*
* @param ResourceInterface $resource
* @param array $files
* @param bool $recursive
*
* @return array
*/
abstract protected function doAdd(ResourceInterface $resource, $files, $recursive);
/**
* Do the extract after having check that the current adapter is supported
*
* @param ResourceInterface $resource
* @param $to
*
* @return \SplFileInfo The extracted archive
*/
abstract protected function doExtract(ResourceInterface $resource, $to);
/**
* Do the extract members after having check that the current adapter is supported
*
* @param ResourceInterface $resource
* @param string|string[] $members
* @param string $to
* @param bool $overwrite
*
* @return \SplFileInfo The extracted archive
*/
abstract protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false);
/**
* Do the list members after having check that the current adapter is supported
*
* @param ResourceInterface $resource
*
* @return array
*/
abstract protected function doListMembers(ResourceInterface $resource);
/**
* Do the create after having check that the current adapter is supported
*
* @param string $path
* @param string $file
* @param bool $recursive
*
* @return ArchiveInterface
*/
abstract protected function doCreate($path, $file, $recursive);
/**
* Makes the target path absolute as the adapters might have a different directory
*
* @param string $path The path to convert
*
* @return string The absolute path
*
* @throws InvalidArgumentException In case the path is not writable or does not exist
*/
private function makeTargetAbsolute($path)
{
$directory = dirname($path);
if (!is_dir($directory)) {
throw new InvalidArgumentException(sprintf('Target path %s does not exist.', $directory));
}
if (!is_writable($directory)) {
throw new InvalidArgumentException(sprintf('Target path %s is not writeable.', $directory));
}
return realpath($directory) . '/' . PathUtil::basename($path);
}
}

View file

@ -1,240 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\FileResource;
use Alchemy\Zippy\Archive\MemberInterface;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Parser\ParserFactory;
use Alchemy\Zippy\Parser\ParserInterface;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactory;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
use Alchemy\Zippy\Resource\ResourceManager;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\ProcessBuilder;
abstract class AbstractBinaryAdapter extends AbstractAdapter implements BinaryAdapterInterface
{
/**
* The parser to use to parse command output
*
* @var ParserInterface
*/
protected $parser;
/**
* The deflator process builder factory to use to build binary command line
*
* @var ProcessBuilderFactoryInterface
*/
protected $deflator;
/**
* The inflator process builder factory to use to build binary command line
*
* @var ProcessBuilderFactoryInterface
*/
protected $inflator;
/**
* Constructor
*
* @param ParserInterface $parser An output parser
* @param ResourceManager $manager A resource manager
* @param ProcessBuilderFactoryInterface $inflator A process builder factory for the inflator binary
* @param ProcessBuilderFactoryInterface $deflator A process builder factory for the deflator binary
*/
public function __construct(
ParserInterface $parser,
ResourceManager $manager,
ProcessBuilderFactoryInterface $inflator,
ProcessBuilderFactoryInterface $deflator
) {
$this->parser = $parser;
parent::__construct($manager);
$this->deflator = $deflator;
$this->inflator = $inflator;
}
/**
* @inheritdoc
*/
public function getParser()
{
return $this->parser;
}
/**
* @inheritdoc
*/
public function setParser(ParserInterface $parser)
{
$this->parser = $parser;
return $this;
}
/**
* @inheritdoc
*/
public function getDeflator()
{
return $this->deflator;
}
/**
* @inheritdoc
*/
public function getInflator()
{
return $this->inflator;
}
/**
* @inheritdoc
*/
public function setDeflator(ProcessBuilderFactoryInterface $processBuilder)
{
$this->deflator = $processBuilder;
return $this;
}
public function setInflator(ProcessBuilderFactoryInterface $processBuilder)
{
$this->inflator = $processBuilder;
return $this;
}
/**
* @inheritdoc
*/
public function getInflatorVersion()
{
$this->requireSupport();
return $this->doGetInflatorVersion();
}
/**
* @inheritdoc
*/
public function getDeflatorVersion()
{
$this->requireSupport();
return $this->doGetDeflatorVersion();
}
/**
* Returns a new instance of the invoked adapter
*
* @param ExecutableFinder $finder
* @param ResourceManager $manager
* @param string|null $inflatorBinaryName The inflator binary name to use
* @param string|null $deflatorBinaryName The deflator binary name to use
*
* @return AbstractBinaryAdapter
*/
public static function newInstance(
ExecutableFinder $finder,
ResourceManager $manager,
$inflatorBinaryName = null,
$deflatorBinaryName = null
) {
$inflator = $inflatorBinaryName instanceof ProcessBuilderFactoryInterface ? $inflatorBinaryName : self::findABinary($inflatorBinaryName,
static::getDefaultInflatorBinaryName(), $finder);
$deflator = $deflatorBinaryName instanceof ProcessBuilderFactoryInterface ? $deflatorBinaryName : self::findABinary($deflatorBinaryName,
static::getDefaultDeflatorBinaryName(), $finder);
try {
$outputParser = ParserFactory::create(static::getName());
} catch (InvalidArgumentException $e) {
throw new RuntimeException(sprintf(
'Failed to get a new instance of %s',
get_called_class()), $e->getCode(), $e
);
}
if (null === $inflator) {
throw new RuntimeException(sprintf('Unable to create the inflator'));
}
if (null === $deflator) {
throw new RuntimeException(sprintf('Unable to create the deflator'));
}
return new static($outputParser, $manager, $inflator, $deflator);
}
private static function findABinary($wish, array $defaults, ExecutableFinder $finder)
{
$possibles = $wish ? (array) $wish : $defaults;
$binary = null;
foreach ($possibles as $possible) {
if (null !== $found = $finder->find($possible)) {
$binary = new ProcessBuilderFactory($found);
break;
}
}
return $binary;
}
/**
* Adds files to argument list
*
* @param MemberInterface[]|\SplFileInfo[]|string[] $files An array of files
* @param ProcessBuilder $builder A Builder instance
*
* @return bool
*/
protected function addBuilderFileArgument(array $files, ProcessBuilder $builder)
{
$iterations = 0;
array_walk($files, function($file) use ($builder, &$iterations) {
$builder->add(
$file instanceof \SplFileInfo ?
$file->getRealPath() : ($file instanceof MemberInterface ? $file->getLocation() : $file)
);
$iterations++;
});
return 0 !== $iterations;
}
protected function createResource($path)
{
return new FileResource($path);
}
/**
* Fetch the inflator version after having check that the current adapter is supported
*
* @return string
*/
abstract protected function doGetInflatorVersion();
/**
* Fetch the Deflator version after having check that the current adapter is supported
*
* @return string
*/
abstract protected function doGetDeflatorVersion();
}

View file

@ -1,438 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Archive\Archive;
use Alchemy\Zippy\Archive\Member;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException;
abstract class AbstractTarAdapter extends AbstractBinaryAdapter
{
/**
* @inheritdoc
*/
protected function doCreate($path, $files, $recursive)
{
return $this->doTarCreate($this->getLocalOptions(), $path, $files, $recursive);
}
/**
* @inheritdoc
*/
protected function doListMembers(ResourceInterface $resource)
{
return $this->doTarListMembers($this->getLocalOptions(), $resource);
}
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
return $this->doTarAdd($this->getLocalOptions(), $resource, $files, $recursive);
}
/**
* @inheritdoc
*/
protected function doRemove(ResourceInterface $resource, $files)
{
return $this->doTarRemove($this->getLocalOptions(), $resource, $files);
}
/**
* @inheritdoc
*/
protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
{
return $this->doTarExtractMembers($this->getLocalOptions(), $resource, $members, $to, $overwrite);
}
/**
* @inheritdoc
*/
protected function doExtract(ResourceInterface $resource, $to)
{
return $this->doTarExtract($this->getLocalOptions(), $resource, $to);
}
/**
* @inheritdoc
*/
protected function doGetInflatorVersion()
{
$process = $this
->inflator
->create()
->add('--version')
->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(), $process->getErrorOutput()
));
}
return $this->parser->parseInflatorVersion($process->getOutput() ?: '');
}
/**
* @inheritdoc
*/
protected function doGetDeflatorVersion()
{
return $this->getInflatorVersion();
}
protected function doTarCreate($options, $path, $files = null, $recursive = true)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
if (!$recursive) {
$builder->add('--no-recursion');
}
$builder->add('-c');
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
if (0 === count($files)) {
$nullFile = defined('PHP_WINDOWS_VERSION_BUILD') ? 'NUL' : '/dev/null';
$builder->add('-f');
$builder->add($path);
$builder->add('-T');
$builder->add($nullFile);
$process = $builder->getProcess();
$process->run();
} else {
$builder->add(sprintf('--file=%s', $path));
if (!$recursive) {
$builder->add('--no-recursion');
}
$collection = $this->manager->handle(getcwd(), $files);
$builder->setWorkingDirectory($collection->getContext());
$collection->forAll(function($i, ZippyResource $resource) use ($builder) {
return $builder->add($resource->getTarget());
});
$process = $builder->getProcess();
try {
$process->run();
} catch (ProcessException $e) {
$this->manager->cleanup($collection);
throw $e;
}
$this->manager->cleanup($collection);
}
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return new Archive($this->createResource($path), $this, $this->manager);
}
protected function doTarListMembers($options, ResourceInterface $resource)
{
$builder = $this
->inflator
->create();
foreach ($this->getListMembersOptions() as $option) {
$builder->add($option);
}
$builder
->add('--list')
->add('-v')
->add(sprintf('--file=%s', $resource->getResource()));
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
$members = array();
foreach ($this->parser->parseFileListing($process->getOutput() ?: '') as $member) {
$members[] = new Member(
$resource,
$this,
$member['location'],
$member['size'],
$member['mtime'],
$member['is_dir']
);
}
return $members;
}
protected function doTarAdd($options, ResourceInterface $resource, $files, $recursive = true)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
if (!$recursive) {
$builder->add('--no-recursion');
}
$builder
->add('--append')
->add(sprintf('--file=%s', $resource->getResource()));
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
// there will be an issue if the file starts with a dash
// see --add-file=FILE
$collection = $this->manager->handle(getcwd(), $files);
$builder->setWorkingDirectory($collection->getContext());
$collection->forAll(function($i, ZippyResource $resource) use ($builder) {
return $builder->add($resource->getTarget());
});
$process = $builder->getProcess();
try {
$process->run();
} catch (ProcessException $e) {
$this->manager->cleanup($collection);
throw $e;
}
$this->manager->cleanup($collection);
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $files;
}
protected function doTarRemove($options, ResourceInterface $resource, $files)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
$builder
->add('--delete')
->add(sprintf('--file=%s', $resource->getResource()));
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
if (!$this->addBuilderFileArgument($files, $builder)) {
throw new InvalidArgumentException('Invalid files');
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $files;
}
protected function doTarExtract($options, ResourceInterface $resource, $to = null)
{
if (null !== $to && !is_dir($to)) {
throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
}
$builder = $this
->inflator
->create();
$builder
->add('--extract')
->add(sprintf('--file=%s', $resource->getResource()));
foreach ($this->getExtractOptions() as $option) {
$builder
->add($option);
}
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
if (null !== $to) {
$builder
->add('--directory')
->add($to);
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return new \SplFileInfo($to ?: $resource->getResource());
}
/**
* @param array $options
* @param ResourceInterface $resource
* @param array $members
* @param string $to
* @param bool $overwrite
*
* @return array
*/
protected function doTarExtractMembers($options, ResourceInterface $resource, $members, $to = null, $overwrite = false)
{
if (null !== $to && !is_dir($to)) {
throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
}
$members = (array) $members;
$builder = $this
->inflator
->create();
if ($overwrite == false) {
$builder->add('-k');
}
$builder
->add('--extract')
->add(sprintf('--file=%s', $resource->getResource()));
foreach ($this->getExtractMembersOptions() as $option) {
$builder
->add($option);
}
foreach ((array) $options as $option) {
$builder->add((string) $option);
}
if (null !== $to) {
$builder
->add('--directory')
->add($to);
}
if (!$this->addBuilderFileArgument($members, $builder)) {
throw new InvalidArgumentException('Invalid files');
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $members;
}
/**
* Returns an array of option for the listMembers command
*
* @return array
*/
abstract protected function getListMembersOptions();
/**
* Returns an array of option for the extract command
*
* @return array
*/
abstract protected function getExtractOptions();
/**
* Returns an array of option for the extractMembers command
*
* @return array
*/
abstract protected function getExtractMembersOptions();
/**
* Gets adapter specific additional options
*
* @return array
*/
abstract protected function getLocalOptions();
}

View file

@ -1,222 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\BSDTar\TarBSDTarAdapter;
use Alchemy\Zippy\Adapter\BSDTar\TarBz2BSDTarAdapter;
use Alchemy\Zippy\Adapter\BSDTar\TarGzBSDTarAdapter;
use Alchemy\Zippy\Adapter\GNUTar\TarBz2GNUTarAdapter;
use Alchemy\Zippy\Adapter\GNUTar\TarGNUTarAdapter;
use Alchemy\Zippy\Adapter\GNUTar\TarGzGNUTarAdapter;
use Alchemy\Zippy\Resource\RequestMapper;
use Alchemy\Zippy\Resource\ResourceManager;
use Alchemy\Zippy\Resource\ResourceTeleporter;
use Alchemy\Zippy\Resource\TargetLocator;
use Alchemy\Zippy\Resource\TeleporterContainer;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\ExecutableFinder;
class AdapterContainer implements \ArrayAccess
{
private $items = array();
/**
* Builds the adapter container
*
* @return AdapterContainer
*/
public static function load()
{
$container = new static();
$container['zip.inflator'] = null;
$container['zip.deflator'] = null;
$container['resource-manager'] = function($container) {
return new ResourceManager(
$container['request-mapper'],
$container['resource-teleporter'],
$container['filesystem']
);
};
$container['executable-finder'] = function($container) {
return new ExecutableFinder();
};
$container['request-mapper'] = function($container) {
return new RequestMapper($container['target-locator']);
};
$container['target-locator'] = function() {
return new TargetLocator();
};
$container['teleporter-container'] = function($container) {
return TeleporterContainer::load();
};
$container['resource-teleporter'] = function($container) {
return new ResourceTeleporter($container['teleporter-container']);
};
$container['filesystem'] = function() {
return new Filesystem();
};
$container['Alchemy\\Zippy\\Adapter\\ZipAdapter'] = function($container) {
return ZipAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['zip.inflator'],
$container['zip.deflator']
);
};
$container['gnu-tar.inflator'] = null;
$container['gnu-tar.deflator'] = null;
$container['Alchemy\\Zippy\\Adapter\\GNUTar\\TarGNUTarAdapter'] = function($container) {
return TarGNUTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['gnu-tar.inflator'],
$container['gnu-tar.deflator']
);
};
$container['Alchemy\\Zippy\\Adapter\\GNUTar\\TarGzGNUTarAdapter'] = function($container) {
return TarGzGNUTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['gnu-tar.inflator'],
$container['gnu-tar.deflator']
);
};
$container['Alchemy\\Zippy\\Adapter\\GNUTar\\TarBz2GNUTarAdapter'] = function($container) {
return TarBz2GNUTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['gnu-tar.inflator'],
$container['gnu-tar.deflator']
);
};
$container['bsd-tar.inflator'] = null;
$container['bsd-tar.deflator'] = null;
$container['Alchemy\\Zippy\\Adapter\\BSDTar\\TarBSDTarAdapter'] = function($container) {
return TarBSDTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['bsd-tar.inflator'],
$container['bsd-tar.deflator']
);
};
$container['Alchemy\\Zippy\\Adapter\\BSDTar\\TarGzBSDTarAdapter'] = function($container) {
return TarGzBSDTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['bsd-tar.inflator'],
$container['bsd-tar.deflator']
);
};
$container['Alchemy\\Zippy\\Adapter\\BSDTar\\TarBz2BSDTarAdapter'] = function($container) {
return TarBz2BSDTarAdapter::newInstance(
$container['executable-finder'],
$container['resource-manager'],
$container['bsd-tar.inflator'],
$container['bsd-tar.deflator']);
};
$container['Alchemy\\Zippy\\Adapter\\ZipExtensionAdapter'] = function() {
return ZipExtensionAdapter::newInstance();
};
return $container;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Whether a offset exists
*
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
*
* @param mixed $offset <p>
* An offset to check for.
* </p>
*
* @return bool true on success or false on failure.
* <p>The return value will be casted to boolean if non-boolean was returned.</p>
*/
public function offsetExists($offset)
{
return isset($this->items[$offset]);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to retrieve
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @param mixed $offset <p>
* The offset to retrieve.
* </p>
* @return mixed Can return all value types.
*/
public function offsetGet($offset)
{
if (array_key_exists($offset, $this->items) && is_callable($this->items[$offset])) {
$this->items[$offset] = call_user_func($this->items[$offset], $this);
}
if (array_key_exists($offset, $this->items)) {
return $this->items[$offset];
}
throw new \InvalidArgumentException();
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to set
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @param mixed $offset <p>
* The offset to assign the value to.
* </p>
* @param mixed $value <p>
* The value to set.
* </p>
* @return void
*/
public function offsetSet($offset, $value)
{
$this->items[$offset] = $value;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to unset
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @param mixed $offset <p>
* The offset to unset.
* </p>
* @return void
*/
public function offsetUnset($offset)
{
unset($this->items[$offset]);
}
}

View file

@ -1,133 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Archive\ArchiveInterface;
use Alchemy\Zippy\Exception\NotSupportedException;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
Interface AdapterInterface
{
/**
* Opens an archive
*
* @param string $path The path to the archive
*
* @return ArchiveInterface
*
* @throws InvalidArgumentException In case the provided path is not valid
* @throws RuntimeException In case of failure
*/
public function open($path);
/**
* Creates a new archive
*
* Please note some adapters can not create empty archives.
* They would throw a `NotSupportedException` in case you ask to create an archive without files
*
* @param string $path The path to the archive
* @param string|string[]|\Traversable|null $files A filename, an array of files, or a \Traversable instance
* @param bool $recursive Whether to recurse or not in the provided directories
*
* @return ArchiveInterface
*
* @throws RuntimeException In case of failure
* @throws NotSupportedException In case the operation in not supported
* @throws InvalidArgumentException In case no files could be added
*/
public function create($path, $files = null, $recursive = true);
/**
* Tests if the adapter is supported by the current environment
*
* @return bool
*/
public function isSupported();
/**
* Returns the list of all archive members
*
* @param ResourceInterface $resource The path to the archive
*
* @return array
*
* @throws RuntimeException In case of failure
*/
public function listMembers(ResourceInterface $resource);
/**
* Adds a file to the archive
*
* @param ResourceInterface $resource The path to the archive
* @param string|array|\Traversable $files An array of paths to add, relative to cwd
* @param bool $recursive Whether or not to recurse in the provided directories
*
* @return array
*
* @throws RuntimeException In case of failure
* @throws InvalidArgumentException In case no files could be added
*/
public function add(ResourceInterface $resource, $files, $recursive = true);
/**
* Removes a member of the archive
*
* @param ResourceInterface $resource The path to the archive
* @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance
*
* @return array
*
* @throws RuntimeException In case of failure
* @throws InvalidArgumentException In case no files could be removed
*/
public function remove(ResourceInterface $resource, $files);
/**
* Extracts an entire archive
*
* Note that any existing files will be overwritten by the adapter
*
* @param ResourceInterface $resource The path to the archive
* @param string|null $to The path where to extract the archive
*
* @return \SplFileInfo The extracted archive
*
* @throws RuntimeException In case of failure
* @throws InvalidArgumentException In case the provided path where to extract the archive is not valid
*/
public function extract(ResourceInterface $resource, $to = null);
/**
* Extracts specific members of the archive
*
* @param ResourceInterface $resource The path to the archive
* @param string|string[] $members A path or array of paths matching the members to extract from the resource.
* @param string|null $to The path where to extract the members
* @param bool $overwrite Whether to overwrite existing files in target directory
*
* @return \SplFileInfo The extracted archive
*
* @throws RuntimeException In case of failure
* @throws InvalidArgumentException In case no members could be removed or providedd extract target directory is not valid
*/
public function extractMembers(ResourceInterface $resource, $members, $to = null, $overwrite = false);
/**
* Returns the adapter name
*
* @return string
*/
public static function getName();
}

View file

@ -1,79 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\BSDTar;
use Alchemy\Zippy\Adapter\AbstractTarAdapter;
use Alchemy\Zippy\Adapter\VersionProbe\BSDTarVersionProbe;
use Alchemy\Zippy\Parser\ParserInterface;
use Alchemy\Zippy\Resource\ResourceManager;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
/**
* BSDTAR allows you to create and extract files from archives using BSD tar
*
* @see http://people.freebsd.org/~kientzle/libarchive/man/bsdtar.1.txt
*/
class TarBSDTarAdapter extends AbstractTarAdapter
{
public function __construct(ParserInterface $parser, ResourceManager $manager, ProcessBuilderFactoryInterface $inflator, ProcessBuilderFactoryInterface $deflator)
{
parent::__construct($parser, $manager, $inflator, $deflator);
$this->probe = new BSDTarVersionProbe($inflator, $deflator);
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array();
}
/**
* @inheritdoc
*/
public static function getName()
{
return 'bsd-tar';
}
/**
* @inheritdoc
*/
public static function getDefaultDeflatorBinaryName()
{
return array('bsdtar', 'tar');
}
/**
* @inheritdoc
*/
public static function getDefaultInflatorBinaryName()
{
return array('bsdtar', 'tar');
}
/**
* {@inheritdoc}
*/
protected function getListMembersOptions()
{
return array();
}
/**
* {@inheritdoc}
*/
protected function getExtractOptions()
{
return array();
}
/**
* {@inheritdoc}
*/
protected function getExtractMembersOptions()
{
return array();
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\BSDTar;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Exception\NotSupportedException;
class TarBz2BSDTarAdapter extends TarBSDTarAdapter
{
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
throw new NotSupportedException('Updating a compressed tar archive is not supported.');
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array('--bzip2');
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\BSDTar;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Exception\NotSupportedException;
class TarGzBSDTarAdapter extends TarBSDTarAdapter
{
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
throw new NotSupportedException('Updating a compressed tar archive is not supported.');
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array('--gzip');
}
}

View file

@ -1,94 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Parser\ParserInterface;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
interface BinaryAdapterInterface
{
/**
* Gets the output parser
*
* @return ParserInterface
*/
public function getParser();
/**
* Sets the parser
*
* @param ParserInterface $parser The parser to use
*
* @return AbstractBinaryAdapter
*/
public function setParser(ParserInterface $parser);
/**
* Returns the inflator process builder
*
* @return ProcessBuilderFactoryInterface
*/
public function getInflator();
/**
* Sets the inflator process builder
*
* @param ProcessBuilderFactoryInterface $processBuilder The parser to use
*
* @return AbstractBinaryAdapter
*/
public function setInflator(ProcessBuilderFactoryInterface $processBuilder);
/**
* Returns the deflator process builder
*
* @return ProcessBuilderFactoryInterface
*/
public function getDeflator();
/**
* Sets the deflator process builder
*
* @param ProcessBuilderFactoryInterface $processBuilder The parser to use
*
* @return AbstractBinaryAdapter
*/
public function setDeflator(ProcessBuilderFactoryInterface $processBuilder);
/**
* Returns the inflator binary version
*
* @return string
*/
public function getInflatorVersion();
/**
* Returns the deflator binary version
*
* @return string
*/
public function getDeflatorVersion();
/**
* Gets the inflator adapter binary name
*
* @return array
*/
public static function getDefaultInflatorBinaryName();
/**
* Gets the deflator adapter binary name
*
* @return array
*/
public static function getDefaultDeflatorBinaryName();
}

View file

@ -1,25 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\GNUTar;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Exception\NotSupportedException;
class TarBz2GNUTarAdapter extends TarGNUTarAdapter
{
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
throw new NotSupportedException('Updating a compressed tar archive is not supported.');
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array('--bzip2');
}
}

View file

@ -1,79 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\GNUTar;
use Alchemy\Zippy\Adapter\AbstractTarAdapter;
use Alchemy\Zippy\Adapter\VersionProbe\GNUTarVersionProbe;
use Alchemy\Zippy\Parser\ParserInterface;
use Alchemy\Zippy\Resource\ResourceManager;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
/**
* GNUTarAdapter allows you to create and extract files from archives using GNU tar
*
* @see http://www.gnu.org/software/tar/manual/tar.html
*/
class TarGNUTarAdapter extends AbstractTarAdapter
{
public function __construct(ParserInterface $parser, ResourceManager $manager, ProcessBuilderFactoryInterface $inflator, ProcessBuilderFactoryInterface $deflator)
{
parent::__construct($parser, $manager, $inflator, $deflator);
$this->probe = new GNUTarVersionProbe($inflator, $deflator);
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array();
}
/**
* @inheritdoc
*/
public static function getName()
{
return 'gnu-tar';
}
/**
* @inheritdoc
*/
public static function getDefaultDeflatorBinaryName()
{
return array('gnutar', 'tar');
}
/**
* @inheritdoc
*/
public static function getDefaultInflatorBinaryName()
{
return array('gnutar', 'tar');
}
/**
* {@inheritdoc}
*/
protected function getListMembersOptions()
{
return array('--utc');
}
/**
* {@inheritdoc}
*/
protected function getExtractOptions()
{
return array('--overwrite');
}
/**
* {@inheritdoc}
*/
protected function getExtractMembersOptions()
{
return array('--overwrite');
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace Alchemy\Zippy\Adapter\GNUTar;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Exception\NotSupportedException;
class TarGzGNUTarAdapter extends TarGNUTarAdapter
{
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
throw new NotSupportedException('Updating a compressed tar archive is not supported.');
}
/**
* @inheritdoc
*/
protected function getLocalOptions()
{
return array('--gzip');
}
}

View file

@ -1,31 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\Resource;
class FileResource implements ResourceInterface
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* {@inheritdoc}
*/
public function getResource()
{
return $this->path;
}
}

View file

@ -1,23 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\Resource;
interface ResourceInterface
{
/**
* Returns the actual resource used by an adapter
*
* @return mixed
*/
public function getResource();
}

View file

@ -1,31 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\Resource;
class ZipArchiveResource implements ResourceInterface
{
private $archive;
public function __construct(\ZipArchive $archive)
{
$this->archive = $archive;
}
/**
* {@inheritdoc}
*/
public function getResource()
{
return $this->archive;
}
}

View file

@ -1,77 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
use Symfony\Component\Process\Process;
abstract class AbstractTarVersionProbe implements VersionProbeInterface
{
private $isSupported;
private $inflator;
private $deflator;
public function __construct(ProcessBuilderFactoryInterface $inflator, ProcessBuilderFactoryInterface $deflator)
{
$this->inflator = $inflator;
$this->deflator = $deflator;
}
/**
* {@inheritdoc}
*/
public function getStatus()
{
if (null !== $this->isSupported) {
return $this->isSupported;
}
if (null === $this->inflator || null === $this->deflator) {
return $this->isSupported = VersionProbeInterface::PROBE_NOTSUPPORTED;
}
$good = true;
foreach (array($this->inflator, $this->deflator) as $builder) {
/** @var Process $process */
$process = $builder
->create()
->add('--version')
->getProcess();
$process->run();
if (!$process->isSuccessful()) {
return $this->isSupported = VersionProbeInterface::PROBE_NOTSUPPORTED;
}
$lines = explode("\n", $process->getOutput(), 2);
$good = false !== stripos($lines[0], $this->getVersionSignature());
if (!$good) {
break;
}
}
$this->isSupported = $good ? VersionProbeInterface::PROBE_OK : VersionProbeInterface::PROBE_NOTSUPPORTED;
return $this->isSupported;
}
/**
* Returns the signature of inflator/deflator
*
* @return string
*/
abstract protected function getVersionSignature();
}

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
class BSDTarVersionProbe extends AbstractTarVersionProbe
{
/**
* {@inheritdoc}
*/
protected function getVersionSignature()
{
return 'bsdtar';
}
}

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
class GNUTarVersionProbe extends AbstractTarVersionProbe
{
/**
* {@inheritdoc}
*/
protected function getVersionSignature()
{
return '(gnu tar)';
}
}

View file

@ -1,26 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
interface VersionProbeInterface
{
const PROBE_OK = 0;
const PROBE_NOTSUPPORTED = 1;
/**
* Probes for the support of an adapter.
*
* @return integer One of the self::PROBE_* constants
*/
public function getStatus();
}

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
class ZipExtensionVersionProbe implements VersionProbeInterface
{
/**
* {@inheritdoc}
*/
public function getStatus()
{
return class_exists('\ZipArchive') ? VersionProbeInterface::PROBE_OK : VersionProbeInterface::PROBE_NOTSUPPORTED;
}
}

View file

@ -1,96 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
*/
namespace Alchemy\Zippy\Adapter\VersionProbe;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
class ZipVersionProbe implements VersionProbeInterface
{
private $isSupported;
private $inflator;
private $deflator;
public function __construct(ProcessBuilderFactoryInterface $inflator, ProcessBuilderFactoryInterface $deflator)
{
$this->inflator = $inflator;
$this->deflator = $deflator;
}
/**
* Set the inflator to zip
*
* @param ProcessBuilderFactoryInterface $inflator
* @return ZipVersionProbe
*/
public function setInflator(ProcessBuilderFactoryInterface $inflator)
{
$this->inflator = $inflator;
return $this;
}
/**
* Set the deflator to unzip
*
* @param ProcessBuilderFactoryInterface $deflator
* @return ZipVersionProbe
*/
public function setDeflator(ProcessBuilderFactoryInterface $deflator)
{
$this->deflator = $deflator;
return $this;
}
/**
* {@inheritdoc}
*/
public function getStatus()
{
if (null !== $this->isSupported) {
return $this->isSupported;
}
if (null === $this->inflator || null === $this->deflator) {
return $this->isSupported = VersionProbeInterface::PROBE_NOTSUPPORTED;
}
$processDeflate = $this
->deflator
->create()
->add('-h')
->getProcess();
$processDeflate->run();
$processInflate = $this
->inflator
->create()
->add('-h')
->getProcess();
$processInflate->run();
if (false === $processDeflate->isSuccessful() || false === $processInflate->isSuccessful()) {
return $this->isSupported = VersionProbeInterface::PROBE_NOTSUPPORTED;
}
$lines = explode("\n", $processInflate->getOutput(), 2);
$inflatorOk = false !== stripos($lines[0], 'Info-ZIP');
$lines = explode("\n", $processDeflate->getOutput(), 2);
$deflatorOk = false !== stripos($lines[0], 'Info-ZIP');
return $this->isSupported = ($inflatorOk && $deflatorOk) ? VersionProbeInterface::PROBE_OK : VersionProbeInterface::PROBE_NOTSUPPORTED;
}
}

View file

@ -1,370 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Adapter\VersionProbe\ZipVersionProbe;
use Alchemy\Zippy\Archive\Archive;
use Alchemy\Zippy\Archive\Member;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Exception\NotSupportedException;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Parser\ParserInterface;
use Alchemy\Zippy\ProcessBuilder\ProcessBuilderFactoryInterface;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceManager;
use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException;
/**
* ZipAdapter allows you to create and extract files from archives using Zip
*
* @see http://www.gnu.org/software/tar/manual/tar.html
*/
class ZipAdapter extends AbstractBinaryAdapter
{
public function __construct(
ParserInterface $parser,
ResourceManager $manager,
ProcessBuilderFactoryInterface $inflator,
ProcessBuilderFactoryInterface $deflator
) {
parent::__construct($parser, $manager, $inflator, $deflator);
$this->probe = new ZipVersionProbe($inflator, $deflator);
}
/**
* @inheritdoc
*/
protected function doCreate($path, $files, $recursive)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
if (0 === count($files)) {
throw new NotSupportedException('Can not create empty zip archive');
}
if ($recursive) {
$builder->add('-r');
}
$builder->add($path);
$collection = $this->manager->handle(getcwd(), $files);
$builder->setWorkingDirectory($collection->getContext());
$collection->forAll(function($i, ZippyResource $resource) use ($builder) {
return $builder->add($resource->getTarget());
});
$process = $builder->getProcess();
try {
$process->run();
} catch (ProcessException $e) {
$this->manager->cleanup($collection);
throw $e;
}
$this->manager->cleanup($collection);
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return new Archive($this->createResource($path), $this, $this->manager);
}
/**
* @inheritdoc
*/
protected function doListMembers(ResourceInterface $resource)
{
$process = $this
->deflator
->create()
->add('-l')
->add($resource->getResource())
->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
$members = array();
foreach ($this->parser->parseFileListing($process->getOutput() ?: '') as $member) {
$members[] = new Member(
$resource,
$this,
$member['location'],
$member['size'],
$member['mtime'],
$member['is_dir']
);
}
return $members;
}
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
if ($recursive) {
$builder->add('-r');
}
$builder
->add('-u')
->add($resource->getResource());
$collection = $this->manager->handle(getcwd(), $files);
$builder->setWorkingDirectory($collection->getContext());
$collection->forAll(function($i, ZippyResource $resource) use ($builder) {
return $builder->add($resource->getTarget());
});
$process = $builder->getProcess();
try {
$process->run();
} catch (ProcessException $e) {
$this->manager->cleanup($collection);
throw $e;
}
$this->manager->cleanup($collection);
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
}
/**
* @inheritdoc
*/
protected function doGetDeflatorVersion()
{
$process = $this
->deflator
->create()
->add('-h')
->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $this->parser->parseDeflatorVersion($process->getOutput() ?: '');
}
/**
* @inheritdoc
*/
protected function doGetInflatorVersion()
{
$process = $this
->inflator
->create()
->add('-h')
->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $this->parser->parseInflatorVersion($process->getOutput() ?: '');
}
/**
* @inheritdoc
*/
protected function doRemove(ResourceInterface $resource, $files)
{
$files = (array) $files;
$builder = $this
->inflator
->create();
$builder
->add('-d')
->add($resource->getResource());
if (!$this->addBuilderFileArgument($files, $builder)) {
throw new InvalidArgumentException('Invalid files');
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $files;
}
/**
* @inheritdoc
*/
public static function getName()
{
return 'zip';
}
/**
* @inheritdoc
*/
public static function getDefaultDeflatorBinaryName()
{
return array('unzip');
}
/**
* @inheritdoc
*/
public static function getDefaultInflatorBinaryName()
{
return array('zip');
}
/**
* @inheritdoc
*/
protected function doExtract(ResourceInterface $resource, $to)
{
if (null !== $to && !is_dir($to)) {
throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
}
$builder = $this
->deflator
->create();
$builder
->add('-o')
->add($resource->getResource());
if (null !== $to) {
$builder
->add('-d')
->add($to);
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return new \SplFileInfo($to ?: $resource->getResource());
}
/**
* @inheritdoc
*/
protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
{
if (null !== $to && !is_dir($to)) {
throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
}
$members = (array) $members;
$builder = $this
->deflator
->create();
if ((bool) $overwrite) {
$builder->add('-o');
}
$builder
->add($resource->getResource());
if (null !== $to) {
$builder
->add('-d')
->add($to);
}
if (!$this->addBuilderFileArgument($members, $builder)) {
throw new InvalidArgumentException('Invalid files');
}
$process = $builder->getProcess();
$process->run();
if (!$process->isSuccessful()) {
throw new RuntimeException(sprintf(
'Unable to execute the following command %s {output: %s}',
$process->getCommandLine(),
$process->getErrorOutput()
));
}
return $members;
}
}

View file

@ -1,361 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Adapter;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Adapter\Resource\ZipArchiveResource;
use Alchemy\Zippy\Adapter\VersionProbe\ZipExtensionVersionProbe;
use Alchemy\Zippy\Archive\Archive;
use Alchemy\Zippy\Archive\Member;
use Alchemy\Zippy\Exception\NotSupportedException;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceManager;
/**
* ZipExtensionAdapter allows you to create and extract files from archives
* using PHP Zip extension
*
* @see http://www.php.net/manual/en/book.zip.php
*/
class ZipExtensionAdapter extends AbstractAdapter
{
private $errorCodesMapping = array(
\ZipArchive::ER_EXISTS => "File already exists",
\ZipArchive::ER_INCONS => "Zip archive inconsistent",
\ZipArchive::ER_INVAL => "Invalid argument",
\ZipArchive::ER_MEMORY => "Malloc failure",
\ZipArchive::ER_NOENT => "No such file",
\ZipArchive::ER_NOZIP => "Not a zip archive",
\ZipArchive::ER_OPEN => "Can't open file",
\ZipArchive::ER_READ => "Read error",
\ZipArchive::ER_SEEK => "Seek error"
);
public function __construct(ResourceManager $manager)
{
parent::__construct($manager);
$this->probe = new ZipExtensionVersionProbe();
}
/**
* @inheritdoc
*/
protected function doListMembers(ResourceInterface $resource)
{
$members = array();
for ($i = 0; $i < $resource->getResource()->numFiles; $i++) {
$stat = $resource->getResource()->statIndex($i);
$members[] = new Member(
$resource,
$this,
$stat['name'],
$stat['size'],
new \DateTime('@' . $stat['mtime']),
0 === strlen($resource->getResource()->getFromIndex($i, 1))
);
}
return $members;
}
/**
* @inheritdoc
*/
public static function getName()
{
return 'zip-extension';
}
/**
* @inheritdoc
*/
protected function doExtract(ResourceInterface $resource, $to)
{
return $this->extractMembers($resource, null, $to);
}
/**
* @inheritdoc
*/
protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false)
{
if (null === $to) {
// if no destination is given, will extract to zip current folder
$to = dirname(realpath($resource->getResource()->filename));
}
if (!is_dir($to)) {
$resource->getResource()->close();
throw new InvalidArgumentException(sprintf("%s is not a directory", $to));
}
if (!is_writable($to)) {
$resource->getResource()->close();
throw new InvalidArgumentException(sprintf("%s is not writable", $to));
}
if (null !== $members) {
$membersTemp = (array) $members;
if (empty($membersTemp)) {
$resource->getResource()->close();
throw new InvalidArgumentException("no members provided");
}
$members = array();
// allows $members to be an array of strings or array of Members
foreach ($membersTemp as $member) {
if ($member instanceof Member) {
$member = $member->getLocation();
}
if ($resource->getResource()->locateName($member) === false) {
$resource->getResource()->close();
throw new InvalidArgumentException(sprintf('%s is not in the zip file', $member));
}
if ($overwrite == false) {
if (file_exists($member)) {
$resource->getResource()->close();
throw new RuntimeException('Target file ' . $member . ' already exists.');
}
}
$members[] = $member;
}
}
if (!$resource->getResource()->extractTo($to, $members)) {
$resource->getResource()->close();
throw new InvalidArgumentException(sprintf('Unable to extract archive : %s', $resource->getResource()->getStatusString()));
}
return new \SplFileInfo($to);
}
/**
* @inheritdoc
*/
protected function doRemove(ResourceInterface $resource, $files)
{
$files = (array) $files;
if (empty($files)) {
throw new InvalidArgumentException("no files provided");
}
// either remove all files or none in case of error
foreach ($files as $file) {
if ($resource->getResource()->locateName($file) === false) {
$resource->getResource()->unchangeAll();
$resource->getResource()->close();
throw new InvalidArgumentException(sprintf('%s is not in the zip file', $file));
}
if (!$resource->getResource()->deleteName($file)) {
$resource->getResource()->unchangeAll();
$resource->getResource()->close();
throw new RuntimeException(sprintf('unable to remove %s', $file));
}
}
$this->flush($resource->getResource());
return $files;
}
/**
* @inheritdoc
*/
protected function doAdd(ResourceInterface $resource, $files, $recursive)
{
$files = (array) $files;
if (empty($files)) {
$resource->getResource()->close();
throw new InvalidArgumentException("no files provided");
}
$this->addEntries($resource, $files, $recursive);
return $files;
}
/**
* @inheritdoc
*/
protected function doCreate($path, $files, $recursive)
{
$files = (array) $files;
if (empty($files)) {
throw new NotSupportedException("Cannot create an empty zip");
}
$resource = $this->getResource($path, \ZipArchive::CREATE);
$this->addEntries($resource, $files, $recursive);
return new Archive($resource, $this, $this->manager);
}
/**
* Returns a new instance of the invoked adapter
*
* @return AbstractAdapter
*
* @throws RuntimeException In case object could not be instanciated
*/
public static function newInstance()
{
return new ZipExtensionAdapter(ResourceManager::create());
}
protected function createResource($path)
{
return $this->getResource($path, \ZipArchive::CHECKCONS);
}
private function getResource($path, $mode)
{
$zip = new \ZipArchive();
$res = $zip->open($path, $mode);
if ($res !== true) {
throw new RuntimeException($this->errorCodesMapping[$res]);
}
return new ZipArchiveResource($zip);
}
private function addEntries(ResourceInterface $zipResource, array $files, $recursive)
{
$stack = new \SplStack();
$error = null;
$cwd = getcwd();
$collection = $this->manager->handle($cwd, $files);
$this->chdir($collection->getContext());
$adapter = $this;
try {
$collection->forAll(function($i, ZippyResource $resource) use ($zipResource, $stack, $recursive, $adapter) {
$adapter->checkReadability($zipResource->getResource(), $resource->getTarget());
if (is_dir($resource->getTarget())) {
if ($recursive) {
$stack->push($resource->getTarget() . ((substr($resource->getTarget(), -1) === DIRECTORY_SEPARATOR) ? '' : DIRECTORY_SEPARATOR));
} else {
$adapter->addEmptyDir($zipResource->getResource(), $resource->getTarget());
}
} else {
$adapter->addFileToZip($zipResource->getResource(), $resource->getTarget());
}
return true;
});
// recursively add dirs
while (!$stack->isEmpty()) {
$dir = $stack->pop();
// removes . and ..
$files = array_diff(scandir($dir), array(".", ".."));
if (count($files) > 0) {
foreach ($files as $file) {
$file = $dir . $file;
$this->checkReadability($zipResource->getResource(), $file);
if (is_dir($file)) {
$stack->push($file . DIRECTORY_SEPARATOR);
} else {
$this->addFileToZip($zipResource->getResource(), $file);
}
}
} else {
$this->addEmptyDir($zipResource->getResource(), $dir);
}
}
$this->flush($zipResource->getResource());
$this->manager->cleanup($collection);
} catch (\Exception $e) {
$error = $e;
}
$this->chdir($cwd);
if ($error) {
throw $error;
}
}
/**
* @info is public for PHP 5.3 compatibility, should be private
*
* @param \ZipArchive $zip
* @param string $file
*/
public function checkReadability(\ZipArchive $zip, $file)
{
if (!is_readable($file)) {
$zip->unchangeAll();
$zip->close();
throw new InvalidArgumentException(sprintf('could not read %s', $file));
}
}
/**
* @info is public for PHP 5.3 compatibility, should be private
*
* @param \ZipArchive $zip
* @param string $file
*/
public function addFileToZip(\ZipArchive $zip, $file)
{
if (!$zip->addFile($file)) {
$zip->unchangeAll();
$zip->close();
throw new RuntimeException(sprintf('unable to add %s to the zip file', $file));
}
}
/**
* @info is public for PHP 5.3 compatibility, should be private
*
* @param \ZipArchive $zip
* @param string $dir
*/
public function addEmptyDir(\ZipArchive $zip, $dir)
{
if (!$zip->addEmptyDir($dir)) {
$zip->unchangeAll();
$zip->close();
throw new RuntimeException(sprintf('unable to add %s to the zip file', $dir));
}
}
/**
* Flushes changes to the archive
*
* @param \ZipArchive $zip
*/
private function flush(\ZipArchive $zip) // flush changes by reopening the file
{
$path = $zip->filename;
$zip->close();
$zip->open($path, \ZipArchive::CHECKCONS);
}
}

View file

@ -1,136 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Archive;
use Alchemy\Zippy\Adapter\AdapterInterface;
use Alchemy\Zippy\Resource\ResourceManager;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
/**
* Represents an archive
*/
class Archive implements ArchiveInterface
{
/**
* The path to the archive
*
* @var string
*/
protected $path;
/**
* The archive adapter
*
* @var AdapterInterface
*/
protected $adapter;
/**
* An array of archive members
*
* @var MemberInterface[]
*/
protected $members = array();
/**
* @var ResourceInterface
*/
protected $resource;
/**
*
* @var ResourceManager
*/
protected $manager;
/**
* Constructor
*
* @param ResourceInterface $resource Path to the archive
* @param AdapterInterface $adapter An archive adapter
* @param ResourceManager $manager The resource manager
*/
public function __construct(ResourceInterface $resource, AdapterInterface $adapter, ResourceManager $manager)
{
$this->resource = $resource;
$this->adapter = $adapter;
$this->manager = $manager;
}
/**
* @inheritdoc
*/
public function count()
{
return count($this->getMembers());
}
/**
* Returns an Iterator for the current archive
*
* This method implements the IteratorAggregate interface.
*
* @return \ArrayIterator An iterator
*/
public function getIterator()
{
return new \ArrayIterator($this->getMembers());
}
/**
* @inheritdoc
*/
public function getMembers()
{
return $this->members = $this->adapter->listMembers($this->resource);
}
/**
* @inheritdoc
*/
public function addMembers($sources, $recursive = true)
{
$this->adapter->add($this->resource, $sources, $recursive);
return $this;
}
/**
* @inheritdoc
*/
public function removeMembers($sources)
{
$this->adapter->remove($this->resource, $sources);
return $this;
}
/**
* @inheritdoc
*/
public function extract($toDirectory)
{
$this->adapter->extract($this->resource, $toDirectory);
return $this;
}
/**
* @inheritdoc
*/
public function extractMembers($members, $toDirectory = null)
{
$this->adapter->extractMembers($this->resource, $members, $toDirectory);
return $this;
}
}

View file

@ -1,74 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Archive;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\Exception\InvalidArgumentException;
interface ArchiveInterface extends \IteratorAggregate, \Countable
{
/**
* Adds a file or a folder into the archive
*
* @param string|array|\SplFileInfo $sources The path to the file or a folder
* @param bool $recursive Recurse into sub-directories
*
* @return ArchiveInterface
*
* @throws InvalidArgumentException In case the provided source path is not valid
* @throws RuntimeException In case of failure
*/
public function addMembers($sources, $recursive = true);
/**
* Removes a file from the archive
*
* @param string|array $sources The path to an archive or a folder member
*
* @return ArchiveInterface
*
* @throws RuntimeException In case of failure
*/
public function removeMembers($sources);
/**
* Lists files and directories archive members
*
* @return MemberInterface[] An array of File
*
* @throws RuntimeException In case archive could not be read
*/
public function getMembers();
/**
* Extracts current archive to the given directory
*
* @param string $toDirectory The path the extracted archive
*
* @return ArchiveInterface
*
* @throws RuntimeException In case archive could not be extracted
*/
public function extract($toDirectory);
/**
* Extracts specific members from the archive
*
* @param string|MemberInterface[] $members An array of members path
* @param string $toDirectory The destination $directory
*
* @return ArchiveInterface
*
* @throws RuntimeException In case member could not be extracted
*/
public function extractMembers($members, $toDirectory = null);
}

View file

@ -1,147 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Archive;
use Alchemy\Zippy\Adapter\AdapterInterface;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
/**
* Represents a member of an archive.
*/
class Member implements MemberInterface
{
/**
* The location of the file
*
* @var string
*/
private $location;
/**
* Tells whether the archive member is a directory or not
*
* @var bool
*/
private $isDir;
/**
* The uncompressed size of the file
*
* @var int
*/
private $size;
/**
* The last modified date of the file
*
* @var \DateTime
*/
private $lastModifiedDate;
/**
* The resource to the actual archive
*
* @var string
*/
private $resource;
/**
* An adapter
*
* @var AdapterInterface
*/
private $adapter;
/**
* Constructor
*
* @param ResourceInterface $resource The path of the archive which contain the member
* @param AdapterInterface $adapter The archive adapter interface
* @param string $location The path of the archive member
* @param int $fileSize The uncompressed file size
* @param \DateTime $lastModifiedDate The last modified date of the member
* @param bool $isDir Tells whether the member is a directory or not
*/
public function __construct(
ResourceInterface $resource,
AdapterInterface $adapter,
$location,
$fileSize,
\DateTime $lastModifiedDate,
$isDir
) {
$this->resource = $resource;
$this->adapter = $adapter;
$this->location = $location;
$this->isDir = $isDir;
$this->size = $fileSize;
$this->lastModifiedDate = $lastModifiedDate;
}
/**
* {@inheritdoc}
*/
public function getLocation()
{
return $this->location;
}
/**
* {@inheritdoc}
*/
public function isDir()
{
return $this->isDir;
}
/**
* {@inheritdoc}
*/
public function getLastModifiedDate()
{
return $this->lastModifiedDate;
}
/**
* {@inheritdoc}
*/
public function getSize()
{
return $this->size;
}
/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->location;
}
/**
* {@inheritdoc}
*/
public function extract($to = null, $overwrite = false)
{
$this->adapter->extractMembers($this->resource, $this->location, $to, (bool) $overwrite);
return new \SplFileInfo(sprintf('%s%s', rtrim(null === $to ? getcwd() : $to, '/'), $this->location));
}
/**
* @inheritdoc
* */
public function getResource()
{
return $this->resource;
}
}

View file

@ -1,78 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Archive;
use Alchemy\Zippy\Adapter\Resource\ResourceInterface;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Exception\RuntimeException;
interface MemberInterface
{
/**
* Gets the location of an archive member
*
* @return string
*/
public function getLocation();
/**
* Tells whether the member is a directory or not
*
* @return bool
*/
public function isDir();
/**
* Returns the last modified date of the member
*
* @return \DateTime
*/
public function getLastModifiedDate();
/**
* Returns the (uncompressed) size of the member
*
* If the size is unknown, returns -1
*
* @return integer
*/
public function getSize();
/**
* Extract the member from its archive
*
* Be careful using this method within a loop
* This will execute one extraction process for each file
* Prefer the use of ArchiveInterface::extractMembers in that use case
*
* @param string|null $to The path where to extract the member, if no path is not provided the member is extracted in the same directory of its archive
* @param bool $overwrite Whether to overwrite destination file if it already exists. Defaults to false
*
* @return \SplFileInfo The extracted file
*
* @throws RuntimeException In case of failure
* @throws InvalidArgumentException In case no members could be removed or provide extract target directory is not valid
*/
public function extract($to = null, $overwrite = false);
/**
* Get resource.
*
* @return ResourceInterface
* */
public function getResource();
/**
* @inheritdoc
*/
public function __toString();
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
interface ExceptionInterface
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class FormatNotSupportedException extends RuntimeException
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class IOException extends RuntimeException
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class NoAdapterOnPlatformException extends RuntimeException
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class NotSupportedException extends RuntimeException implements ExceptionInterface
{
}

View file

@ -1,16 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View file

@ -1,28 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Exception;
class TargetLocatorException extends RuntimeException
{
private $resource;
public function __construct($resource, $message, $code = 0, $previous = null)
{
$this->resource = $resource;
parent::__construct($message, $code, $previous);
}
public function getResource()
{
return $this->resource;
}
}

View file

@ -1,49 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
use Alchemy\Zippy\Adapter\AdapterContainer;
use Alchemy\Zippy\Exception\RuntimeException;
abstract class AbstractFileStrategy implements FileStrategyInterface
{
protected $container;
public function __construct(AdapterContainer $container)
{
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function getAdapters()
{
$services = array();
foreach ($this->getServiceNames() as $serviceName) {
try {
$services[] = $this->container[$serviceName];
} catch (RuntimeException $e) {
}
}
return $services;
}
/**
* Returns an array of service names that defines adapters.
*
* @return string[]
*/
abstract protected function getServiceNames();
}

View file

@ -1,31 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
use Alchemy\Zippy\Adapter\AdapterInterface;
interface FileStrategyInterface
{
/**
* Returns an array of adapters that match the strategy
*
* @return AdapterInterface[]
*/
public function getAdapters();
/**
* Returns the file extension that match the strategy
*
* @return string
*/
public function getFileExtension();
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TB2FileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarBz2GNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarBz2BSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tb2';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TBz2FileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarBz2GNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarBz2BSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tbz2';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TGzFileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarGzGNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarGzBSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tgz';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TarBz2FileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarBz2GNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarBz2BSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tar.bz2';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TarFileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarGNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarBSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tar';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class TarGzFileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\GNUTar\\TarGzGNUTarAdapter',
'Alchemy\\Zippy\\Adapter\\BSDTar\\TarGzBSDTarAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'tar.gz';
}
}

View file

@ -1,34 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\FileStrategy;
class ZipFileStrategy extends AbstractFileStrategy
{
/**
* {@inheritdoc}
*/
protected function getServiceNames()
{
return array(
'Alchemy\\Zippy\\Adapter\\ZipAdapter',
'Alchemy\\Zippy\\Adapter\\ZipExtensionAdapter'
);
}
/**
* {@inheritdoc}
*/
public function getFileExtension()
{
return 'zip';
}
}

View file

@ -1,115 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Parser;
use Alchemy\Zippy\Exception\RuntimeException;
/**
* This class is responsible of parsing GNUTar command line output
*/
class BSDTarOutputParser implements ParserInterface
{
const PERMISSIONS = '([ldrwx-]+)';
const HARD_LINK = '(\d+)';
const OWNER = '([a-z][-a-z0-9]*)';
const GROUP = '([a-z][-a-z0-9]*)';
const FILESIZE = '(\d*)';
const DATE = '([a-zA-Z0-9]+\s+[a-z0-9]+\s+[a-z0-9:]+)';
const FILENAME = '(.*)';
/**
* @inheritdoc
*/
public function parseFileListing($output)
{
$lines = array_values(array_filter(explode("\n", $output)));
$members = array();
// BSDTar outputs two differents format of date according to the mtime
// of the member. If the member is younger than six months the year is not shown.
// On 4.5+ FreeBSD system the day is displayed first
$dateFormats = array('M d Y', 'M d H:i', 'd M Y', 'd M H:i');
foreach ($lines as $line) {
$matches = array();
// drw-rw-r-- 0 toto titi 0 Jan 3 1980 practice/
// -rw-rw-r-- 0 toto titi 10240 Jan 22 13:31 practice/records
if (!preg_match_all("#" .
self::PERMISSIONS . "\s+" . // match (drw-r--r--)
self::HARD_LINK . "\s+" . // match (1)
self::OWNER . "\s" . // match (toto)
self::GROUP . "\s+" . // match (titi)
self::FILESIZE . "\s+" . // match (0)
self::DATE . "\s+" . // match (Jan 3 1980)
self::FILENAME . // match (practice)
"#", $line, $matches, PREG_SET_ORDER
)) {
continue;
}
$chunks = array_shift($matches);
if (8 !== count($chunks)) {
continue;
}
$date = null;
foreach ($dateFormats as $format) {
$date = \DateTime::createFromFormat($format, $chunks[6]);
if (false === $date) {
continue;
} else {
break;
}
}
if (false === $date) {
throw new RuntimeException(sprintf('Failed to parse mtime date from %s', $line));
}
$members[] = array(
'location' => $chunks[7],
'size' => $chunks[5],
'mtime' => $date,
'is_dir' => 'd' === $chunks[1][0]
);
}
return $members;
}
/**
* @inheritdoc
*/
public function parseInflatorVersion($output)
{
$chunks = explode(' ', $output, 3);
if (2 > count($chunks)) {
return null;
}
list(, $version) = explode(' ', $output, 3);
return $version;
}
/**
* @inheritdoc
*/
public function parseDeflatorVersion($output)
{
return $this->parseInflatorVersion($output);
}
}

View file

@ -1,98 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Parser;
use Alchemy\Zippy\Exception\RuntimeException;
/**
* This class is responsible of parsing GNUTar command line output
*/
class GNUTarOutputParser implements ParserInterface
{
const PERMISSIONS = '([ldrwx-]+)';
const OWNER = '([a-z][-a-z0-9]*)';
const GROUP = '([a-z][-a-z0-9]*)';
const FILESIZE = '(\d*)';
const ISO_DATE = '([0-9]+-[0-9]+-[0-9]+\s+[0-9]+:[0-9]+)';
const FILENAME = '(.*)';
/**
* @inheritdoc
*/
public function parseFileListing($output)
{
$lines = array_values(array_filter(explode("\n", $output)));
$members = array();
foreach ($lines as $line) {
$matches = array();
// -rw-r--r-- gray/staff 62373 2006-06-09 12:06 apple
if (!preg_match_all("#".
self::PERMISSIONS . "\s+" . // match (-rw-r--r--)
self::OWNER . "/" . // match (gray)
self::GROUP . "\s+" . // match (staff)
self::FILESIZE . "\s+" . // match (62373)
self::ISO_DATE . "\s+" . // match (2006-06-09 12:06)
self::FILENAME . // match (apple)
"#",
$line, $matches, PREG_SET_ORDER
)) {
continue;
}
$chunks = array_shift($matches);
if (7 !== count($chunks)) {
continue;
}
$date = \DateTime::createFromFormat("Y-m-d H:i", $chunks[5]);
if (false === $date) {
throw new RuntimeException(sprintf('Failed to parse mtime date from %s', $line));
}
$members[] = array(
'location' => $chunks[6],
'size' => $chunks[4],
'mtime' => $date,
'is_dir' => 'd' === $chunks[1][0]
);
}
return $members;
}
/**
* @inheritdoc
*/
public function parseInflatorVersion($output)
{
$chunks = explode(' ', $output, 3);
if (2 > count($chunks)) {
return null;
}
list(, $version) = $chunks;
return $version;
}
/**
* @inheritdoc
*/
public function parseDeflatorVersion($output)
{
return $this->parseInflatorVersion($output);
}
}

View file

@ -1,56 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Parser;
use Alchemy\Zippy\Exception\InvalidArgumentException;
class ParserFactory
{
private static $zipDateFormat = 'Y-m-d H:i';
/**
* @param string $format Date format used to parse ZIP file listings
*/
public static function setZipDateFormat($format)
{
self::$zipDateFormat = $format;
}
/**
* Maps the corresponding parser to the selected adapter
*
* @param string $adapterName An adapter name
*
* @return ParserInterface
*
* @throws InvalidArgumentException In case no parser were found
*/
public static function create($adapterName)
{
switch ($adapterName) {
case 'gnu-tar':
return new GNUTarOutputParser();
break;
case 'bsd-tar':
return new BSDTarOutputParser();
break;
case 'zip':
return new ZipOutputParser(self::$zipDateFormat);
break;
default:
throw new InvalidArgumentException(sprintf('No parser available for %s adapter', $adapterName));
break;
}
}
}

View file

@ -1,46 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Parser;
use Alchemy\Zippy\Exception\RuntimeException;
interface ParserInterface
{
/**
* Parses a file listing
*
* @param string $output The string to parse
*
* @return array An array of Member properties (location, mtime, size & is_dir)
*
* @throws RuntimeException In case the parsing process failed
*/
public function parseFileListing($output);
/**
* Parses the inflator binary version
*
* @param string $output
*
* @return string The version
*/
public function parseInflatorVersion($output);
/**
* Parses the deflator binary version
*
* @param string $output
*
* @return string The version
*/
public function parseDeflatorVersion($output);
}

View file

@ -1,109 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Parser;
/**
* This class is responsible of parsing GNUTar command line output
*/
class ZipOutputParser implements ParserInterface
{
const LENGTH = '(\d*)';
const ISO_DATE = '([0-9]+-[0-9]+-[0-9]+\s+[0-9]+:[0-9]+)';
const FILENAME = '(.*)';
/**
* @var string
*/
private $dateFormat;
/**
* @param string $dateFormat
*/
public function __construct($dateFormat = "Y-m-d H:i")
{
$this->dateFormat = $dateFormat;
}
/**
* @inheritdoc
*/
public function parseFileListing($output)
{
$lines = array_values(array_filter(explode("\n", $output)));
$members = array();
foreach ($lines as $line) {
$matches = array();
// 785 2012-10-24 10:39 file
if (!preg_match_all("#" .
self::LENGTH . "\s+" . // match (785)
self::ISO_DATE . "\s+" . // match (2012-10-24 10:39)
self::FILENAME . // match (file)
"#",
$line, $matches, PREG_SET_ORDER
)) {
continue;
}
$chunks = array_shift($matches);
if (4 !== count($chunks)) {
continue;
}
$members[] = array(
'location' => $chunks[3],
'size' => $chunks[1],
'mtime' => \DateTime::createFromFormat($this->dateFormat, $chunks[2]),
'is_dir' => '/' === substr($chunks[3], -1)
);
}
return $members;
}
/**
* @inheritdoc
*/
public function parseInflatorVersion($output)
{
$lines = array_values(array_filter(explode("\n", $output, 3)));
$chunks = explode(' ', $lines[1], 3);
if (2 > count($chunks)) {
return null;
}
list(, $version) = $chunks;
return $version;
}
/**
* @inheritdoc
*/
public function parseDeflatorVersion($output)
{
$lines = array_values(array_filter(explode("\n", $output, 2)));
$firstLine = array_shift($lines);
$chunks = explode(' ', $firstLine, 3);
if (2 > count($chunks)) {
return null;
}
list(, $version) = $chunks;
return $version;
}
}

View file

@ -1,71 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\ProcessBuilder;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Symfony\Component\Process\ProcessBuilder;
class ProcessBuilderFactory implements ProcessBuilderFactoryInterface
{
/**
* The binary path
*
* @var string
*/
protected $binary;
/**
* Constructor
*
* @param string $binary The path to the binary
*
* @throws InvalidArgumentException In case binary path is invalid
*/
public function __construct($binary)
{
$this->useBinary($binary);
}
/**
* @inheritdoc
*/
public function getBinary()
{
return $this->binary;
}
/**
* @inheritdoc
*/
public function useBinary($binary)
{
if (!is_executable($binary)) {
throw new InvalidArgumentException(sprintf('`%s` is not an executable binary', $binary));
}
$this->binary = $binary;
return $this;
}
/**
* @inheritdoc
*/
public function create()
{
if (null === $this->binary) {
throw new InvalidArgumentException('No binary set');
}
return ProcessBuilder::create(array($this->binary))->setTimeout(null);
}
}

View file

@ -1,45 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\ProcessBuilder;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Symfony\Component\Process\ProcessBuilder;
interface ProcessBuilderFactoryInterface
{
/**
* Returns a new instance of Symfony ProcessBuilder
*
* @return ProcessBuilder
*
* @throws InvalidArgumentException
*/
public function create();
/**
* Returns the binary path
*
* @return string
*/
public function getBinary();
/**
* Sets the binary path
*
* @param string $binary A binary path
*
* @return ProcessBuilderFactoryInterface
*
* @throws InvalidArgumentException In case binary is not executable
*/
public function useBinary($binary);
}

View file

@ -1,20 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
abstract class PathUtil
{
public static function basename($path)
{
return (false === $pos = strrpos(strtr($path, '\\', '/'), '/')) ? $path : substr($path, $pos + 1);
}
}

View file

@ -1,59 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Guzzle;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
use GuzzleHttp\ClientInterface;
class GuzzleReader implements ResourceReader
{
/**
* @var ClientInterface
*/
private $client;
/**
* @var \Alchemy\Zippy\Resource\Resource
*/
private $resource;
/**
* @param ZippyResource $resource
* @param ClientInterface $client
*/
public function __construct(ZippyResource $resource, ClientInterface $client = null)
{
$this->resource = $resource;
$this->client = $client;
}
/**
* @return string
*/
public function getContents()
{
return $this->buildRequest()->getBody()->getContents();
}
/**
* @return resource
*/
public function getContentsAsStream()
{
$response = $this->buildRequest()->getBody()->getContents();
$stream = fopen('php://temp', 'r+');
if ($response != '') {
fwrite($stream, $response);
fseek($stream, 0);
}
return $stream;
}
private function buildRequest()
{
return $this->client->request('GET', $this->resource->getOriginal());
}
}

View file

@ -1,37 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Guzzle;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
class GuzzleReaderFactory implements ResourceReaderFactory
{
/**
* @var ClientInterface|null
*/
private $client = null;
public function __construct(ClientInterface $client = null)
{
$this->client = $client;
if (! $this->client) {
$this->client = new Client();
}
}
/**
* @param ZippyResource $resource
* @param string $context
*
* @return ResourceReader
*/
public function getReader(ZippyResource $resource, $context)
{
return new GuzzleReader($resource, $this->client);
}
}

View file

@ -1,67 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Guzzle;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
use Guzzle\Http\Client;
use Guzzle\Http\ClientInterface;
use Guzzle\Http\EntityBodyInterface;
class LegacyGuzzleReader implements ResourceReader
{
/**
* @var ClientInterface
*/
private $client;
/**
* @var \Alchemy\Zippy\Resource\Resource $resource
*/
private $resource;
/**
* This is necessary to prevent the underlying PHP stream from being destroyed
* @link https://github.com/guzzle/guzzle/issues/366#issuecomment-20295409
* @var EntityBodyInterface|null
*/
private $stream = null;
/**
* @param ZippyResource $resource
* @param ClientInterface $client
*/
public function __construct(ZippyResource $resource, ClientInterface $client = null)
{
$this->client = $client ?: new Client();
$this->resource = $resource;
}
/**
* @return string
*/
public function getContents()
{
return $this->buildRequest()->send()->getBody(true);
}
/**
* @return resource
*/
public function getContentsAsStream()
{
if (!$this->stream) {
$this->stream = $this->buildRequest()->send()->getBody(false);
}
return $this->stream->getStream();
}
/**
* @return \Guzzle\Http\Message\RequestInterface
*/
private function buildRequest()
{
return $this->client->get($this->resource->getOriginal());
}
}

View file

@ -1,47 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Guzzle;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
use Guzzle\Http\Client;
use Guzzle\Http\ClientInterface;
use Guzzle\Plugin\Backoff\BackoffPlugin;
use Symfony\Component\EventDispatcher\Event;
class LegacyGuzzleReaderFactory implements ResourceReaderFactory
{
/**
* @var ClientInterface|null
*/
private $client = null;
public function __construct(ClientInterface $client = null)
{
$this->client = $client;
if (!$this->client) {
$this->client = new Client();
$this->client->getEventDispatcher()->addListener('request.error', function(Event $event) {
// override guzzle default behavior of throwing exceptions
// when 4xx & 5xx responses are encountered
$event->stopPropagation();
}, -254);
$this->client->addSubscriber(BackoffPlugin::getExponentialBackoff(5, array(500, 502, 503, 408)));
}
}
/**
* @param ZippyResource $resource
* @param string $context
*
* @return ResourceReader
*/
public function getReader(ZippyResource $resource, $context)
{
return new LegacyGuzzleReader($resource, $this->client);
}
}

View file

@ -1,41 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Stream;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
class StreamReader implements ResourceReader
{
/**
* @var ZippyResource
*/
private $resource;
/**
* @param ZippyResource $resource
*/
public function __construct(ZippyResource $resource)
{
$this->resource = $resource;
}
/**
* @return string
*/
public function getContents()
{
return file_get_contents($this->resource->getOriginal());
}
/**
* @return resource
*/
public function getContentsAsStream()
{
$stream = is_resource($this->resource->getOriginal()) ?
$this->resource->getOriginal() : @fopen($this->resource->getOriginal(), 'rb');
return $stream;
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Reader\Stream;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceReader;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
class StreamReaderFactory implements ResourceReaderFactory
{
/**
* @param ZippyResource $resource
* @param string $context
*
* @return ResourceReader
*/
public function getReader(ZippyResource $resource, $context)
{
return new StreamReader($resource);
}
}

View file

@ -1,66 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
class RequestMapper
{
private $locator;
/**
* Constructor
*
* @param TargetLocator $locator
*/
public function __construct(TargetLocator $locator)
{
$this->locator = $locator;
}
/**
* Maps resources request to a ResourceCollection
*
* @param $context
* @param array $resources
*
* @return ResourceCollection
*/
public function map($context, array $resources)
{
$data = array();
foreach ($resources as $location => $resource) {
if (is_int($location)) {
$data[] = new Resource($resource, $this->locator->locate($context, $resource));
} else {
$data[] = new Resource($resource, ltrim($location, '/'));
}
}
if (count($data) === 1) {
$context = $data[0]->getOriginal();
}
$collection = new ResourceCollection($context, $data, false);
return $collection;
}
/**
* Creates the default RequestMapper
*
* @return RequestMapper
*/
public static function create()
{
return new static(new TargetLocator());
}
}

View file

@ -1,116 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
class Resource
{
private $original;
private $target;
/**
* Constructor
*
* @param string $original
* @param string $target
*/
public function __construct($original, $target)
{
$this->original = $original;
$this->target = $target;
}
/**
* Returns the target
*
* @return string
*/
public function getTarget()
{
return $this->target;
}
/**
* Returns the original path
*
* @return string
*/
public function getOriginal()
{
return $this->original;
}
/**
* Returns whether the resource can be processed in place given a context or not.
*
* For example :
* - /path/to/file1 can be processed to file1 in /path/to context
* - /path/to/subdir/file2 can be processed to subdir/file2 in /path/to context
*
* @param string $context
*
* @return bool
*/
public function canBeProcessedInPlace($context)
{
if (!is_string($this->original)) {
return false;
}
if (!$this->isLocal()) {
return false;
}
$data = parse_url($this->original);
return sprintf('%s/%s', rtrim($context, '/'), $this->target) === $data['path'];
}
/**
* Returns a context for computing this resource in case it is possible.
*
* Useful to avoid teleporting.
*
* @return null|string
*/
public function getContextForProcessInSinglePlace()
{
if (!is_string($this->original)) {
return null;
}
if (!$this->isLocal()) {
return null;
}
if (PathUtil::basename($this->original) === $this->target) {
return dirname($this->original);
}
return null;
}
/**
* Returns true if the resource is local.
*
* @return bool
*/
private function isLocal()
{
if (!is_string($this->original)) {
return false;
}
$data = parse_url($this->original);
return isset($data['path']);
}
}

View file

@ -1,89 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Doctrine\Common\Collections\ArrayCollection;
class ResourceCollection extends ArrayCollection
{
private $context;
/**
* @var bool
*/
private $temporary;
/**
* Constructor
* @param string $context
* @param Resource[] $elements An array of Resource
* @param bool $temporary
*/
public function __construct($context, array $elements, $temporary)
{
array_walk($elements, function($element) {
if (!$element instanceof Resource) {
throw new InvalidArgumentException('ResourceCollection only accept Resource elements');
}
});
$this->context = $context;
$this->temporary = (bool) $temporary;
parent::__construct($elements);
}
/**
* Returns the context related to the collection
*
* @return string
*/
public function getContext()
{
return $this->context;
}
/**
* Tells whether the collection is temporary or not.
*
* A ResourceCollection is temporary when it required a temporary folder to
* fetch data
*
* @return bool
*/
public function isTemporary()
{
return $this->temporary;
}
/**
* Returns true if all resources can be processed in place, false otherwise
*
* @return bool
*/
public function canBeProcessedInPlace()
{
if (count($this) === 1) {
if (null !== $context = $this->first()->getContextForProcessInSinglePlace()) {
$this->context = $context;
return true;
}
}
foreach ($this as $resource) {
if (!$resource->canBeProcessedInPlace($this->context)) {
return false;
}
}
return true;
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Resource\Resource AS ZippyResource;
class ResourceLocator
{
public function mapResourcePath(ZippyResource $resource, $context)
{
return rtrim($context, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $resource->getTarget();
}
}

View file

@ -1,105 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOException as SfIOException;
class ResourceManager
{
private $mapper;
private $teleporter;
private $filesystem;
/**
* Constructor
*
* @param RequestMapper $mapper
* @param ResourceTeleporter $teleporter
* @param Filesystem $filesystem
*/
public function __construct(RequestMapper $mapper, ResourceTeleporter $teleporter, Filesystem $filesystem)
{
$this->mapper = $mapper;
$this->filesystem = $filesystem;
$this->teleporter = $teleporter;
}
/**
* Handles an archival request.
*
* The request is an array of string|streams to compute in a context (current
* working directory most of the time)
* Some keys can be associative. In these cases, the key is used the target
* for the file.
*
* @param string $context
* @param array $request
*
* @return ResourceCollection
*
* @throws IOException In case of write failure
*/
public function handle($context, array $request)
{
$collection = $this->mapper->map($context, $request);
if (!$collection->canBeProcessedInPlace()) {
$context = sprintf('%s/%s', sys_get_temp_dir(), uniqid('zippy_'));
try {
$this->filesystem->mkdir($context);
} catch (SfIOException $e) {
throw new IOException(sprintf('Could not create temporary folder %s', $context), $e->getCode(), $e);
}
foreach ($collection as $resource) {
$this->teleporter->teleport($context, $resource);
}
$collection = new ResourceCollection($context, $collection->toArray(), true);
}
return $collection;
}
/**
* This method must be called once the ResourceCollection has been processed.
*
* It will remove temporary files
*
* @todo this should be done in the __destruct method of ResourceCollection
*
* @param ResourceCollection $collection
*/
public function cleanup(ResourceCollection $collection)
{
if ($collection->isTemporary()) {
try {
$this->filesystem->remove($collection->getContext());
} catch (IOException $e) {
// log this ?
}
}
}
/**
* Creates a default ResourceManager
*
* @return ResourceManager
*/
public static function create()
{
return new static(RequestMapper::create(), ResourceTeleporter::create(), new Filesystem());
}
}

View file

@ -1,16 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource;
interface ResourceReader
{
/**
* @return string
*/
public function getContents();
/**
* @return resource
*/
public function getContentsAsStream();
}

View file

@ -1,16 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
interface ResourceReaderFactory
{
/**
* @param ZippyResource $resource
* @param string $context
*
* @return ResourceReader
*/
public function getReader(ZippyResource $resource, $context);
}

View file

@ -1,55 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
class ResourceTeleporter
{
private $container;
/**
* Constructor
*
* @param TeleporterContainer $container
*/
public function __construct(TeleporterContainer $container)
{
$this->container = $container;
}
/**
* Teleports a resource to its target in the context
*
* @param string $context
* @param ZippyResource $resource
*
* @return ResourceTeleporter
*/
public function teleport($context, ZippyResource $resource)
{
$this
->container
->fromResource($resource)
->teleport($resource, $context);
return $this;
}
/**
* Creates the ResourceTeleporter with the default TeleporterContainer
*
* @return ResourceTeleporter
*/
public static function create()
{
return new static(TeleporterContainer::load());
}
}

View file

@ -1,8 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource;
interface ResourceWriter
{
public function writeFromReader(ResourceReader $reader, $target);
}

View file

@ -1,158 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Exception\TargetLocatorException;
class TargetLocator
{
/**
* Locates the target for a resource in a context
*
* For example, adding /path/to/file where the context (current working
* directory) is /path/to will return `file` as target
*
* @param string $context
* @param string|resource $resource
*
* @return string
*
* @throws TargetLocatorException when the resource is invalid
*/
public function locate($context, $resource)
{
switch (true) {
case is_resource($resource):
return $this->locateResource($resource);
case is_string($resource):
return $this->locateString($context, $resource);
case $resource instanceof \SplFileInfo:
return $this->locateString($context, $resource->getRealPath());
default:
throw new TargetLocatorException($resource, 'Unknown resource format');
}
}
/**
* Locate the target for a resource.
*
* @param resource $resource
*
* @return string
*
* @throws TargetLocatorException
*/
private function locateResource($resource)
{
$meta = stream_get_meta_data($resource);
$data = parse_url($meta['uri']);
if (!isset($data['path'])) {
throw new TargetLocatorException($resource, 'Unable to retrieve path from resource');
}
return PathUtil::basename($data['path']);
}
/**
* Locate the target for a string.
*
* @param $context
* @param string $resource
*
* @return string
*
* @throws TargetLocatorException
*/
private function locateString($context, $resource)
{
$url = parse_url($resource);
if (isset($url['scheme']) && $this->isLocalFilesystem($url['scheme'])) {
$resource = $url['path'] = $this->cleanupPath($url['path']);
}
// resource is a URI
if (isset($url['scheme'])) {
if ($this->isLocalFilesystem($url['scheme']) && $this->isFileInContext($url['path'], $context)) {
return $this->getRelativePathFromContext($url['path'], $context);
}
return PathUtil::basename($resource);
}
// resource is a local path
if ($this->isFileInContext($resource, $context)) {
$resource = $this->cleanupPath($resource);
return $this->getRelativePathFromContext($resource, $context);
} else {
return PathUtil::basename($resource);
}
}
/**
* Removes backward path sequences (..)
*
* @param string $path
*
* @return string
*
* @throws TargetLocatorException In case the path is invalid
*/
private function cleanupPath($path)
{
if (false === $cleanPath = realpath($path)) {
throw new TargetLocatorException($path, sprintf('%s is an invalid location', $path));
}
return $cleanPath;
}
/**
* Checks whether the path belong to the context
*
* @param string $path A resource path
* @param string $context
*
* @return bool
*/
private function isFileInContext($path, $context)
{
return 0 === strpos($path, $context);
}
/**
* Gets the relative path from the context for the given path
*
* @param string $path A resource path
* @param string $context
*
* @return string
*/
private function getRelativePathFromContext($path, $context)
{
return ltrim(str_replace($context, '', $path), '/\\');
}
/**
* Checks if a scheme refers to a local filesystem
*
* @param string $scheme
*
* @return bool
*/
private function isLocalFilesystem($scheme)
{
return 'plainfile' === $scheme || 'file' === $scheme;
}
}

View file

@ -1,64 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Exception\IOException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
/**
* Class AbstractTeleporter
* @package Alchemy\Zippy\Resource\Teleporter
*
* @deprecated Typehint against TeleporterInterface instead and use GenericTeleporter
* with custom reader/writers instead. This class will be removed in v0.5.x
*/
abstract class AbstractTeleporter implements TeleporterInterface
{
/**
* Writes the target
*
* @param string $data
* @param ZippyResource $resource
* @param string $context
*
* @return TeleporterInterface
*
* @throws IOException
*/
protected function writeTarget($data, ZippyResource $resource, $context)
{
$target = $this->getTarget($context, $resource);
if (!file_exists(dirname($target)) && false === mkdir(dirname($target))) {
throw new IOException(sprintf('Could not create parent directory %s', dirname($target)));
}
if (false === file_put_contents($target, $data)) {
throw new IOException(sprintf('Could not write to %s', $target));
}
return $this;
}
/**
* Returns the relative target of a Resource
*
* @param string $context
* @param ZippyResource $resource
*
* @return string
*/
protected function getTarget($context, ZippyResource $resource)
{
return sprintf('%s/%s', rtrim($context, '/'), $resource->getTarget());
}
}

View file

@ -1,60 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Exception\IOException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceLocator;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
use Alchemy\Zippy\Resource\ResourceWriter;
class GenericTeleporter implements TeleporterInterface
{
/**
* @var ResourceReaderFactory
*/
private $readerFactory;
/**
* @var ResourceWriter
*/
private $resourceWriter;
/**
* @var ResourceLocator
*/
private $resourceLocator;
/**
* @param ResourceReaderFactory $readerFactory
* @param ResourceWriter $resourceWriter
* @param ResourceLocator $resourceLocator
*/
public function __construct(
ResourceReaderFactory $readerFactory,
ResourceWriter $resourceWriter,
ResourceLocator $resourceLocator = null
) {
$this->readerFactory = $readerFactory;
$this->resourceWriter = $resourceWriter;
$this->resourceLocator = $resourceLocator ?: new ResourceLocator();
}
/**
* Teleports a file from a destination to an other
*
* @param ZippyResource $resource A Resource
* @param string $context The current context
*
* @throws IOException when file could not be written on local
* @throws InvalidArgumentException when path to file is not valid
*/
public function teleport(ZippyResource $resource, $context)
{
$reader = $this->readerFactory->getReader($resource, $context);
$target = $this->resourceLocator->mapResourcePath($resource, $context);
$this->resourceWriter->writeFromReader($reader, $target);
}
}

View file

@ -1,45 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Resource\Reader\Guzzle\GuzzleReaderFactory;
use Alchemy\Zippy\Resource\ResourceLocator;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
use Alchemy\Zippy\Resource\Writer\FilesystemWriter;
/**
* Guzzle Teleporter implementation for HTTP resources
*
* @deprecated Use \Alchemy\Zippy\Resource\GenericTeleporter instead. This class will be removed in v0.5.x
*/
class GuzzleTeleporter extends GenericTeleporter
{
/**
* @param ResourceReaderFactory $readerFactory
* @param ResourceLocator $resourceLocator
*/
public function __construct(ResourceReaderFactory $readerFactory = null, ResourceLocator $resourceLocator = null)
{
parent::__construct($readerFactory ?: new GuzzleReaderFactory(), new FilesystemWriter(), $resourceLocator);
}
/**
* Creates the GuzzleTeleporter
*
* @deprecated This method will be removed in v0.5.x
* @return GuzzleTeleporter
*/
public static function create()
{
return new static();
}
}

View file

@ -1,51 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Resource\Reader\Guzzle\LegacyGuzzleReaderFactory;
use Alchemy\Zippy\Resource\ResourceLocator;
use Alchemy\Zippy\Resource\ResourceReaderFactory;
use Alchemy\Zippy\Resource\Writer\FilesystemWriter;
use Guzzle\Http\Client;
/**
* Guzzle Teleporter implementation for HTTP resources
*
* @deprecated Use \Alchemy\Zippy\Resource\GenericTeleporter instead. This class will be removed in v0.5.x
*/
class LegacyGuzzleTeleporter extends GenericTeleporter
{
/**
* @param Client $client
* @param ResourceReaderFactory $readerFactory
* @param ResourceLocator $resourceLocator
*/
public function __construct(
Client $client = null,
ResourceReaderFactory $readerFactory = null,
ResourceLocator $resourceLocator = null
) {
parent::__construct($readerFactory ?: new LegacyGuzzleReaderFactory($client), new FilesystemWriter(),
$resourceLocator);
}
/**
* Creates the GuzzleTeleporter
*
* @deprecated
* @return LegacyGuzzleTeleporter
*/
public static function create()
{
return new static();
}
}

View file

@ -1,82 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Exception\IOException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\ResourceLocator;
use Symfony\Component\Filesystem\Exception\IOException as SfIOException;
use Symfony\Component\Filesystem\Filesystem;
/**
* This class transports an object using the local filesystem
*/
class LocalTeleporter extends AbstractTeleporter
{
/**
* @var Filesystem
*/
private $filesystem;
/**
* @var ResourceLocator
*/
private $resourceLocator;
/**
* Constructor
*
* @param Filesystem $filesystem
*/
public function __construct(Filesystem $filesystem)
{
$this->filesystem = $filesystem;
$this->resourceLocator = new ResourceLocator();
}
/**
* {@inheritdoc}
*/
public function teleport(ZippyResource $resource, $context)
{
$target = $this->resourceLocator->mapResourcePath($resource, $context);
$path = $resource->getOriginal();
if (!file_exists($path)) {
throw new InvalidArgumentException(sprintf('Invalid path %s', $path));
}
try {
if (is_file($path)) {
$this->filesystem->copy($path, $target);
} elseif (is_dir($path)) {
$this->filesystem->mirror($path, $target);
} else {
throw new InvalidArgumentException(sprintf('Invalid file or directory %s', $path));
}
} catch (SfIOException $e) {
throw new IOException(sprintf('Could not write %s', $target), $e->getCode(), $e);
}
}
/**
* Creates the LocalTeleporter
*
* @return LocalTeleporter
* @deprecated This method will be removed in a future release (0.5.x)
*/
public static function create()
{
return new static(new Filesystem());
}
}

View file

@ -1,38 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Resource\Reader\Stream\StreamReaderFactory;
use Alchemy\Zippy\Resource\ResourceLocator;
use Alchemy\Zippy\Resource\Writer\StreamWriter;
/**
* This class transport an object using php stream wrapper
*/
class StreamTeleporter extends GenericTeleporter
{
public function __construct()
{
parent::__construct(new StreamReaderFactory(), new StreamWriter(), new ResourceLocator());
}
/**
* Creates the StreamTeleporter
*
* @return StreamTeleporter
* @deprecated This method will be removed in a future release (0.5.x)
*/
public static function create()
{
return new static();
}
}

View file

@ -1,30 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource\Teleporter;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Exception\IOException;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
interface TeleporterInterface
{
/**
* Teleports a file from a destination to an other
*
* @param ZippyResource $resource A Resource
* @param string $context The current context
*
* @throws IOException when file could not be written on local
* @throws InvalidArgumentException when path to file is not valid
*/
public function teleport(ZippyResource $resource, $context);
}

View file

@ -1,189 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy\Resource;
use Alchemy\Zippy\Exception\InvalidArgumentException;
use Alchemy\Zippy\Resource\Reader\Guzzle\GuzzleReaderFactory;
use Alchemy\Zippy\Resource\Reader\Guzzle\LegacyGuzzleReaderFactory;
use Alchemy\Zippy\Resource\Resource as ZippyResource;
use Alchemy\Zippy\Resource\Teleporter\GenericTeleporter;
use Alchemy\Zippy\Resource\Teleporter\LocalTeleporter;
use Alchemy\Zippy\Resource\Teleporter\StreamTeleporter;
use Alchemy\Zippy\Resource\Teleporter\TeleporterInterface;
use Alchemy\Zippy\Resource\Writer\FilesystemWriter;
use Symfony\Component\Filesystem\Filesystem;
/**
* A container of TeleporterInterface
*/
class TeleporterContainer implements \ArrayAccess, \Countable
{
/**
* @var TeleporterInterface[]
*/
private $teleporters = array();
/**
* @var callable[]
*/
private $factories = array();
/**
* Returns the appropriate TeleporterInterface for a given Resource
*
* @param ZippyResource $resource
*
* @return TeleporterInterface
*/
public function fromResource(ZippyResource $resource)
{
switch (true) {
case is_resource($resource->getOriginal()):
$teleporter = 'stream-teleporter';
break;
case is_string($resource->getOriginal()):
$data = parse_url($resource->getOriginal());
if (!isset($data['scheme']) || 'file' === $data['scheme']) {
$teleporter = 'local-teleporter';
} elseif (in_array($data['scheme'], array('http', 'https')) && isset($this->factories['guzzle-teleporter'])) {
$teleporter = 'guzzle-teleporter';
} else {
$teleporter = 'stream-teleporter';
}
break;
default:
throw new InvalidArgumentException('No teleporter found');
}
return $this->getTeleporter($teleporter);
}
private function getTeleporter($typeName)
{
if (!isset($this->teleporters[$typeName])) {
$factory = $this->factories[$typeName];
$this->teleporters[$typeName] = $factory();
}
return $this->teleporters[$typeName];
}
/**
* Instantiates TeleporterContainer and register default teleporters
*
* @return TeleporterContainer
*/
public static function load()
{
$container = new static();
$container->factories['stream-teleporter'] = function () {
return new StreamTeleporter();
};
$container->factories['local-teleporter'] = function () {
return new LocalTeleporter(new Filesystem());
};
if (class_exists('GuzzleHttp\Client')) {
$container->factories['guzzle-teleporter'] = function () {
return new GenericTeleporter(
new GuzzleReaderFactory(),
new FilesystemWriter(),
new ResourceLocator()
);
};
}
elseif (class_exists('Guzzle\Http\Client')) {
$container->factories['guzzle-teleporter'] = function () {
return new GenericTeleporter(
new LegacyGuzzleReaderFactory(),
new FilesystemWriter(),
new ResourceLocator()
);
};
}
return $container;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Whether a offset exists
*
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
*
* @param mixed $offset <p>
* An offset to check for.
* </p>
*
* @return bool true on success or false on failure.
* </p>
* <p>
* The return value will be casted to boolean if non-boolean was returned.
*/
public function offsetExists($offset)
{
return isset($this->teleporters[$offset]);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to retrieve
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @param mixed $offset <p>
* The offset to retrieve.
* </p>
* @return mixed Can return all value types.
*/
public function offsetGet($offset)
{
return $this->getTeleporter($offset);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to set
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @param mixed $offset <p>
* The offset to assign the value to.
* </p>
* @param mixed $value <p>
* The value to set.
* </p>
* @return void
*/
public function offsetSet($offset, $value)
{
throw new \BadMethodCallException();
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Offset to unset
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @param mixed $offset <p>
* The offset to unset.
* </p>
* @return void
*/
public function offsetUnset($offset)
{
throw new \BadMethodCallException();
}
public function count()
{
return count($this->teleporters);
}
}

View file

@ -1,23 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Writer;
use Alchemy\Zippy\Resource\ResourceReader;
use Alchemy\Zippy\Resource\ResourceWriter;
class FilesystemWriter implements ResourceWriter
{
/**
* @param ResourceReader $reader
* @param string $target
*/
public function writeFromReader(ResourceReader $reader, $target)
{
$directory = dirname($target);
if (!is_dir($directory)) {
mkdir($directory, 0777, true);
}
file_put_contents($target, $reader->getContentsAsStream());
}
}

View file

@ -1,27 +0,0 @@
<?php
namespace Alchemy\Zippy\Resource\Writer;
use Alchemy\Zippy\Resource\ResourceReader;
use Alchemy\Zippy\Resource\ResourceWriter;
class StreamWriter implements ResourceWriter
{
/**
* @param ResourceReader $reader
* @param string $target
*/
public function writeFromReader(ResourceReader $reader, $target)
{
$directory = dirname($target);
if (!is_dir($directory)) {
mkdir($directory, 0777, true);
}
$targetResource = fopen($target, 'w+');
$sourceResource = $reader->getContentsAsStream();
stream_copy_to_stream($sourceResource, $targetResource);
fclose($targetResource);
}
}

View file

@ -1,220 +0,0 @@
<?php
/*
* This file is part of Zippy.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Zippy;
use Alchemy\Zippy\Adapter\AdapterContainer;
use Alchemy\Zippy\Adapter\AdapterInterface;
use Alchemy\Zippy\Archive\ArchiveInterface;
use Alchemy\Zippy\Exception\ExceptionInterface;
use Alchemy\Zippy\Exception\FormatNotSupportedException;
use Alchemy\Zippy\Exception\NoAdapterOnPlatformException;
use Alchemy\Zippy\Exception\RuntimeException;
use Alchemy\Zippy\FileStrategy\FileStrategyInterface;
use Alchemy\Zippy\FileStrategy\TarBz2FileStrategy;
use Alchemy\Zippy\FileStrategy\TarFileStrategy;
use Alchemy\Zippy\FileStrategy\TarGzFileStrategy;
use Alchemy\Zippy\FileStrategy\TB2FileStrategy;
use Alchemy\Zippy\FileStrategy\TBz2FileStrategy;
use Alchemy\Zippy\FileStrategy\TGzFileStrategy;
use Alchemy\Zippy\FileStrategy\ZipFileStrategy;
class Zippy
{
/**
* @var AdapterContainer
*/
public $adapters;
/**
* @var FileStrategyInterface[][]
*/
private $strategies = array();
public function __construct(AdapterContainer $adapters)
{
$this->adapters = $adapters;
}
/**
* Creates an archive
*
* @param string $path
* @param string|array|\Traversable|null $files
* @param bool $recursive
* @param string|null $type
*
* @return ArchiveInterface
*
* @throws RuntimeException In case of failure
*/
public function create($path, $files = null, $recursive = true, $type = null)
{
if (null === $type) {
$type = $this->guessAdapterExtension($path);
}
try {
return $this
->getAdapterFor($this->sanitizeExtension($type))
->create($path, $files, $recursive);
} catch (ExceptionInterface $e) {
throw new RuntimeException('Unable to create archive', $e->getCode(), $e);
}
}
/**
* Opens an archive.
*
* @param string $path
*
* @return ArchiveInterface
*
* @throws RuntimeException In case of failure
*/
public function open($path)
{
$type = $this->guessAdapterExtension($path);
try {
return $this
->getAdapterFor($this->sanitizeExtension($type))
->open($path);
} catch (ExceptionInterface $e) {
throw new RuntimeException('Unable to open archive', $e->getCode(), $e);
}
}
/**
* Adds a strategy.
*
* The last strategy added is preferred over the other ones.
* You can add a strategy twice ; when doing this, the first one is removed
* when inserting the second one.
*
* @param FileStrategyInterface $strategy
*
* @return Zippy
*/
public function addStrategy(FileStrategyInterface $strategy)
{
$extension = $this->sanitizeExtension($strategy->getFileExtension());
if (!isset($this->strategies[$extension])) {
$this->strategies[$extension] = array();
}
if (false !== $key = array_search($strategy, $this->strategies[$extension], true)) {
unset($this->strategies[$extension][$key]);
}
array_unshift($this->strategies[$extension], $strategy);
return $this;
}
/**
* Returns the strategies as they are stored
*
* @return array
*/
public function getStrategies()
{
return $this->strategies;
}
/**
* Returns an adapter for a file extension
*
* @param string $extension The extension
*
* @return AdapterInterface
*
* @throws FormatNotSupportedException When no strategy is defined for this extension
* @throws NoAdapterOnPlatformException When no adapter is supported for this extension on this platform
*/
public function getAdapterFor($extension)
{
$extension = $this->sanitizeExtension($extension);
if (!$extension || !isset($this->strategies[$extension])) {
throw new FormatNotSupportedException(sprintf('No strategy for %s extension', $extension));
}
foreach ($this->strategies[$extension] as $strategy) {
foreach ($strategy->getAdapters() as $adapter) {
if ($adapter->isSupported()) {
return $adapter;
}
}
}
throw new NoAdapterOnPlatformException(sprintf('No adapter available for %s on this platform', $extension));
}
/**
* Creates Zippy and loads default strategies
*
* @return Zippy
*/
public static function load()
{
$adapters = AdapterContainer::load();
$factory = new static($adapters);
$factory->addStrategy(new ZipFileStrategy($adapters));
$factory->addStrategy(new TarFileStrategy($adapters));
$factory->addStrategy(new TarGzFileStrategy($adapters));
$factory->addStrategy(new TarBz2FileStrategy($adapters));
$factory->addStrategy(new TB2FileStrategy($adapters));
$factory->addStrategy(new TBz2FileStrategy($adapters));
$factory->addStrategy(new TGzFileStrategy($adapters));
return $factory;
}
/**
* Sanitize an extension.
*
* Strips dot from the beginning, converts to lowercase and remove trailing
* whitespaces
*
* @param string $extension
*
* @return string
*/
private function sanitizeExtension($extension)
{
return ltrim(trim(mb_strtolower($extension)), '.');
}
/**
* Finds an extension that has strategy registered given a file path
*
* Returns null if no matching strategy found.
*
* @param string $path
*
* @return string|null
*/
private function guessAdapterExtension($path)
{
$path = strtolower(trim($path));
foreach ($this->strategies as $extension => $strategy) {
if ($extension === substr($path, (strlen($extension) * -1))) {
return $extension;
}
}
return null;
}
}

View file

@ -1,19 +0,0 @@
Copyright (c) 2013-2017 Alexander <iam.asm89@gmail.com>
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

@ -1,83 +0,0 @@
# Stack/Cors
Library and middleware enabling cross-origin resource sharing for your
http-{foundation,kernel} using application. It attempts to implement the
[W3C Recommendation] for cross-origin resource sharing.
[W3C Recommendation]: http://www.w3.org/TR/cors/
Master [![Build Status](https://secure.travis-ci.org/asm89/stack-cors.png?branch=master)](http://travis-ci.org/asm89/stack-cors)
## Installation
Require `asm89/stack-cors` using composer.
## Usage
This package can be used as a library or as [stack middleware].
[stack middleware]: http://stackphp.com/
### Options
| Option | Description | Default value |
|------------------------|------------------------------------------------------------|---------------|
| allowedMethods | Matches the request method. | `array()` |
| allowedOrigins | Matches the request origin. | `array()` |
| allowedOriginsPatterns | Matches the request origin with `preg_match`. | `array()` |
| allowedHeaders | Sets the Access-Control-Allow-Headers response header. | `array()` |
| exposedHeaders | Sets the Access-Control-Expose-Headers response header. | `false` |
| maxAge | Sets the Access-Control-Max-Age response header. | `false` |
| supportsCredentials | Sets the Access-Control-Allow-Credentials header. | `false` |
The _allowedMethods_ and _allowedHeaders_ options are case-insensitive.
You don't need to provide both _allowedOrigins_ and _allowedOriginsPatterns_. If one of the strings passed matches, it is considered a valid origin.
If `array('*')` is provided to _allowedMethods_, _allowedOrigins_ or _allowedHeaders_ all methods / origins / headers are allowed.
### Example: using the library
```php
<?php
use Asm89\Stack\CorsService;
$cors = new CorsService(array(
'allowedHeaders' => array('x-allowed-header', 'x-other-allowed-header'),
'allowedMethods' => array('DELETE', 'GET', 'POST', 'PUT'),
'allowedOrigins' => array('localhost'),
'allowedOriginsPatterns' => array('/localhost:\d/'),
'exposedHeaders' => false,
'maxAge' => false,
'supportsCredentials' => false,
));
$cors->addActualRequestHeaders(Response $response, $origin);
$cors->handlePreflightRequest(Request $request);
$cors->isActualRequestAllowed(Request $request);
$cors->isCorsRequest(Request $request);
$cors->isPreflightRequest(Request $request);
```
## Example: using the stack middleware
```php
<?php
use Asm89\Stack\Cors;
$app = new Cors($app, array(
// you can use array('*') to allow any headers
'allowedHeaders' => array('x-allowed-header', 'x-other-allowed-header'),
// you can use array('*') to allow any methods
'allowedMethods' => array('DELETE', 'GET', 'POST', 'PUT'),
// you can use array('*') to allow requests from any origin
'allowedOrigins' => array('localhost'),
// you can enter regexes that are matched to the origin request header
'allowedOriginsPatterns' => array('/localhost:\d/'),
'exposedHeaders' => false,
'maxAge' => false,
'supportsCredentials' => false,
));
```

View file

@ -1,43 +0,0 @@
{
"name": "asm89/stack-cors",
"description": "Cross-origin resource sharing library and stack middleware",
"keywords": ["stack", "cors"],
"homepage": "https://github.com/asm89/stack-cors",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Alexander",
"email": "iam.asm89@gmail.com"
}
],
"require": {
"php": ">=5.5.9",
"symfony/http-foundation": "~2.7|~3.0|~4.0",
"symfony/http-kernel": "~2.7|~3.0|~4.0"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^4.8.10",
"squizlabs/php_codesniffer": "^2.3"
},
"autoload": {
"psr-4": {
"Asm89\\Stack\\": "src/Asm89/Stack/"
}
},
"autoload-dev": {
"psr-4": {
"Asm89\\Stack\\": "test/Asm89/Stack/"
}
},
"scripts": {
"test": "phpunit",
"check-style": "phpcs -p --standard=PSR2 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src",
"fix-style": "phpcbf -p --standard=PSR2 --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src"
},
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
}
}

View file

@ -1,64 +0,0 @@
<?php
/*
* This file is part of asm89/stack-cors.
*
* (c) Alexander <iam.asm89@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Asm89\Stack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class Cors implements HttpKernelInterface
{
/**
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
private $app;
/**
* @var \Asm89\Stack\CorsService
*/
private $cors;
private $defaultOptions = array(
'allowedHeaders' => array(),
'allowedMethods' => array(),
'allowedOrigins' => array(),
'allowedOriginsPatterns' => array(),
'exposedHeaders' => false,
'maxAge' => false,
'supportsCredentials' => false,
);
public function __construct(HttpKernelInterface $app, array $options = array())
{
$this->app = $app;
$this->cors = new CorsService(array_merge($this->defaultOptions, $options));
}
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
if (!$this->cors->isCorsRequest($request)) {
return $this->app->handle($request, $type, $catch);
}
if ($this->cors->isPreflightRequest($request)) {
return $this->cors->handlePreflightRequest($request);
}
if (!$this->cors->isActualRequestAllowed($request)) {
return new Response('Not allowed.', 403);
}
$response = $this->app->handle($request, $type, $catch);
return $this->cors->addActualRequestHeaders($response, $request);
}
}

View file

@ -1,203 +0,0 @@
<?php
/*
* This file is part of asm89/stack-cors.
*
* (c) Alexander <iam.asm89@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Asm89\Stack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class CorsService
{
private $options;
public function __construct(array $options = array())
{
$this->options = $this->normalizeOptions($options);
}
private function normalizeOptions(array $options = array())
{
$options += array(
'allowedOrigins' => array(),
'allowedOriginsPatterns' => array(),
'supportsCredentials' => false,
'allowedHeaders' => array(),
'exposedHeaders' => array(),
'allowedMethods' => array(),
'maxAge' => 0,
);
// normalize array('*') to true
if (in_array('*', $options['allowedOrigins'])) {
$options['allowedOrigins'] = true;
}
if (in_array('*', $options['allowedHeaders'])) {
$options['allowedHeaders'] = true;
} else {
$options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
}
if (in_array('*', $options['allowedMethods'])) {
$options['allowedMethods'] = true;
} else {
$options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
}
return $options;
}
public function isActualRequestAllowed(Request $request)
{
return $this->checkOrigin($request);
}
public function isCorsRequest(Request $request)
{
return $request->headers->has('Origin') && !$this->isSameHost($request);
}
public function isPreflightRequest(Request $request)
{
return $this->isCorsRequest($request)
&& $request->getMethod() === 'OPTIONS'
&& $request->headers->has('Access-Control-Request-Method');
}
public function addActualRequestHeaders(Response $response, Request $request)
{
if (!$this->checkOrigin($request)) {
return $response;
}
$response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
if (!$response->headers->has('Vary')) {
$response->headers->set('Vary', 'Origin');
} else {
$response->headers->set('Vary', $response->headers->get('Vary') . ', Origin');
}
if ($this->options['supportsCredentials']) {
$response->headers->set('Access-Control-Allow-Credentials', 'true');
}
if ($this->options['exposedHeaders']) {
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->options['exposedHeaders']));
}
return $response;
}
public function handlePreflightRequest(Request $request)
{
if (true !== $check = $this->checkPreflightRequestConditions($request)) {
return $check;
}
return $this->buildPreflightCheckResponse($request);
}
private function buildPreflightCheckResponse(Request $request)
{
$response = new Response();
if ($this->options['supportsCredentials']) {
$response->headers->set('Access-Control-Allow-Credentials', 'true');
}
$response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
if ($this->options['maxAge']) {
$response->headers->set('Access-Control-Max-Age', $this->options['maxAge']);
}
$allowMethods = $this->options['allowedMethods'] === true
? strtoupper($request->headers->get('Access-Control-Request-Method'))
: implode(', ', $this->options['allowedMethods']);
$response->headers->set('Access-Control-Allow-Methods', $allowMethods);
$allowHeaders = $this->options['allowedHeaders'] === true
? strtoupper($request->headers->get('Access-Control-Request-Headers'))
: implode(', ', $this->options['allowedHeaders']);
$response->headers->set('Access-Control-Allow-Headers', $allowHeaders);
return $response;
}
private function checkPreflightRequestConditions(Request $request)
{
if (!$this->checkOrigin($request)) {
return $this->createBadRequestResponse(403, 'Origin not allowed');
}
if (!$this->checkMethod($request)) {
return $this->createBadRequestResponse(405, 'Method not allowed');
}
$requestHeaders = array();
// if allowedHeaders has been set to true ('*' allow all flag) just skip this check
if ($this->options['allowedHeaders'] !== true && $request->headers->has('Access-Control-Request-Headers')) {
$headers = strtolower($request->headers->get('Access-Control-Request-Headers'));
$requestHeaders = array_filter(explode(',', $headers));
foreach ($requestHeaders as $header) {
if (!in_array(trim($header), $this->options['allowedHeaders'])) {
return $this->createBadRequestResponse(403, 'Header not allowed');
}
}
}
return true;
}
private function createBadRequestResponse($code, $reason = '')
{
return new Response($reason, $code);
}
private function isSameHost(Request $request)
{
return $request->headers->get('Origin') === $request->getSchemeAndHttpHost();
}
private function checkOrigin(Request $request)
{
if ($this->options['allowedOrigins'] === true) {
// allow all '*' flag
return true;
}
$origin = $request->headers->get('Origin');
if (in_array($origin, $this->options['allowedOrigins'])) {
return true;
}
foreach ($this->options['allowedOriginsPatterns'] as $pattern) {
if (preg_match($pattern, $origin)) {
return true;
}
}
return false;
}
private function checkMethod(Request $request)
{
if ($this->options['allowedMethods'] === true) {
// allow all '*' flag
return true;
}
$requestMethod = strtoupper($request->headers->get('Access-Control-Request-Method'));
return in_array($requestMethod, $this->options['allowedMethods']);
}
}

7
vendor/autoload.php vendored
View file

@ -1,7 +0,0 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit5b1c1b80ca16f098d2571547d6c6045f::getLoader();

1
vendor/bin/dcg vendored
View file

@ -1 +0,0 @@
../chi-teck/drupal-code-generator/bin/dcg

1
vendor/bin/drupal vendored
View file

@ -1 +0,0 @@
../drupal/console/bin/drupal

1
vendor/bin/drush vendored
View file

@ -1 +0,0 @@
../drush/drush/drush

View file

@ -1 +0,0 @@
../nikic/php-parser/bin/php-parse

1
vendor/bin/psysh vendored
View file

@ -1 +0,0 @@
../psy/psysh/bin/psysh

1
vendor/bin/release vendored
View file

@ -1 +0,0 @@
../consolidation/self-update/scripts/release

1
vendor/bin/robo vendored
View file

@ -1 +0,0 @@
../consolidation/robo/robo

View file

@ -1 +0,0 @@
../symfony/var-dumper/Resources/bin/var-dump-server

View file

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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; either version 2 of the License, or
(at your option) any later version.
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -1,46 +0,0 @@
# Drupal Code Generator
[![Build Status](https://travis-ci.org/Chi-teck/drupal-code-generator.svg?branch=master)](https://travis-ci.org/Chi-teck/drupal-code-generator)
A command line code generator for Drupal.
## Installation
1. Download the latest [stable release](https://github.com/Chi-teck/drupal-code-generator/releases/latest) of the code generator.
2. Make the file executable.
3. Move it to a directory that is part of your `PATH`.
```shell
release_url=https://api.github.com/repos/chi-teck/drupal-code-generator/releases/latest
wget $(wget -qO- $release_url | awk -F'"' '/browser_download_url/ { print $4 }')
chmod +x dcg.phar
sudo mv dcg.phar /usr/local/bin/dcg
dcg --version
```
Installation using Composer is also supported.
## Upgrade
Simply repeat installation commands.
## Usage
```shell
# Display main menu.
dcg
# Display Drupal 8 submenu.
dcg d8
# Call generator directly.
dcg d8:plugin:field:widget
# Generate code non interactively.
dcg twig-extension -a '{"name": "Example", "machine_name": "example", "class": "ExampleTwigExtension"}'
```
## Extending
All custom generators should be placed to _$HOME/.dcg/Command_ directory. The following command will help you to get started with creating own generators.
```bash
# Create custom DCG command.
dcg dcg-command -d $HOME/.dcg/Command
```
## License
GNU General Public License, version 2 or later.

View file

@ -1,35 +0,0 @@
#!/usr/bin/env php
<?php
use DrupalCodeGenerator\ApplicationFactory;
use DrupalCodeGenerator\Command\Navigation;
use DrupalCodeGenerator\GeneratorDiscovery;
use DrupalCodeGenerator\Utils;
use Symfony\Component\Filesystem\Filesystem;
// The autoloader may have a different location if DCG is installed as a local
// Composer package.
$autoloader = file_exists(__DIR__ . '/../vendor/autoload.php')
? require __DIR__ . '/../vendor/autoload.php'
: require __DIR__ . '/../../../autoload.php';
// Create an application.
$application = ApplicationFactory::create();
// Discover generators.
$discovery = new GeneratorDiscovery(new Filesystem());
$commands_directories[] = ApplicationFactory::getRoot() . '/src/Command';
$home = Utils::getHomeDirectory();
if (file_exists($home . '/.dcg/Command')) {
$commands_directories[] = $home . '/.dcg/Command';
$autoloader->addPsr4('DrupalCodeGenerator\\', $home . '/.dcg');
}
$generators = $discovery->getGenerators($commands_directories);
$application->addCommands($generators);
// Add the navigation command.
$application->add(new Navigation($generators));
$application->setDefaultCommand('navigation');
// Run.
$application->run();

Some files were not shown because too many files have changed in this diff Show more