diff --git a/.travis.yml b/.travis.yml index c6434b9..ff79e9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,9 @@ before_script: - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS restuploadbundle;'; fi" - php Tests/Fixtures/App/app/console doctrine:schema:update --force --env=test -script: phpunit +script: + - sh -c "export TEST_FILESYSTEM="Gaufrette"; phpunit" + - sh -c "export TEST_FILESYSTEM="Flysystem"; phpunit" notifications: email: diff --git a/DependencyInjection/CompilerPass/ProcessorCompilerPass.php b/DependencyInjection/CompilerPass/ProcessorCompilerPass.php index eaede69..773d6c3 100644 --- a/DependencyInjection/CompilerPass/ProcessorCompilerPass.php +++ b/DependencyInjection/CompilerPass/ProcessorCompilerPass.php @@ -1,4 +1,5 @@ useAttributeAsKey('name') ->prototype('array') ->children() + ->enumNode('type') + ->values(array('gaufrette', 'flysystem')) + ->defaultValue('gaufrette') + ->end() ->scalarNode('filesystem')->isRequired()->end() ->scalarNode('naming_strategy') ->defaultValue('srio_rest_upload.naming.default_strategy') diff --git a/DependencyInjection/Factory/StorageFactory.php b/DependencyInjection/Factory/StorageFactory.php index 0b3b775..2233a67 100644 --- a/DependencyInjection/Factory/StorageFactory.php +++ b/DependencyInjection/Factory/StorageFactory.php @@ -1,22 +1,39 @@ setPublic(false); + $adapterDefinition->replaceArgument(0, new Reference($config['filesystem'])); + + $container->setDefinition($adapterId, $adapterDefinition); + } elseif ($config['type'] === 'flysystem') { + $adapterDefinition = new DefinitionDecorator('srio_rest_upload.storage.flysystem_adapter'); + $adapterDefinition->setPublic(false); + $adapterDefinition->replaceArgument(0, new Reference($config['filesystem'])); + + $container->setDefinition($adapterId, $adapterDefinition); + } + $container ->setDefinition($id, new Definition('SRIO\RestUploadBundle\Storage\FileStorage')) ->addArgument($config['name']) - ->addArgument(new Reference($config['filesystem'])) + ->addArgument(new Reference($adapterId)) ->addArgument(new Reference($config['storage_strategy'])) ->addArgument(new Reference($config['naming_strategy'])) ; diff --git a/DependencyInjection/SRIORestUploadExtension.php b/DependencyInjection/SRIORestUploadExtension.php index 10162ad..6f0acf5 100644 --- a/DependencyInjection/SRIORestUploadExtension.php +++ b/DependencyInjection/SRIORestUploadExtension.php @@ -8,18 +8,17 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; - use SRIO\RestUploadBundle\DependencyInjection\Factory\StorageFactory; /** - * This is the class that loads and manages your bundle configuration + * This is the class that loads and manages your bundle configuration. * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} */ class SRIORestUploadExtension extends Extension { /** - * {@inheritDoc} + * {@inheritdoc} */ public function load(array $configs, ContainerBuilder $container) { @@ -36,6 +35,7 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('processors.xml'); $loader->load('handlers.xml'); $loader->load('strategy.xml'); + $loader->load('storage.xml'); $this->createStorageServices($container, $config['storages']); } @@ -60,10 +60,11 @@ private function createStorageServices(ContainerBuilder $container, array $stora /** * Create a single storage service. * - * @param StorageFactory $factory - * @param ContainerBuilder $containerBuilder + * @param StorageFactory $factory + * @param ContainerBuilder $containerBuilder * @param $name - * @param array $config + * @param array $config + * * @return string */ private function createStorage(StorageFactory $factory, ContainerBuilder $containerBuilder, $name, array $config) diff --git a/Entity/ResumableUploadSession.php b/Entity/ResumableUploadSession.php index e2fbd4c..be51bff 100644 --- a/Entity/ResumableUploadSession.php +++ b/Entity/ResumableUploadSession.php @@ -1,10 +1,10 @@ form = $form; $this->config = $config; @@ -66,10 +67,11 @@ public function handleUpload (Request $request, FormInterface $form = null, arra * This method return a Response object that will be sent back * to the client or will be caught by controller. * - * @param Request $request + * @param Request $request + * * @return \SRIO\RestUploadBundle\Upload\UploadResult */ - abstract public function handleRequest (Request $request); + abstract public function handleRequest(Request $request); /** * Create the form data that the form will be able to handle. @@ -77,7 +79,8 @@ abstract public function handleRequest (Request $request); * It walk one the form and make an intersection between its keys and * provided data. * - * @param array $data + * @param array $data + * * @return array */ protected function createFormData(array $data) @@ -90,7 +93,8 @@ protected function createFormData(array $data) /** * Get keys of the form. * - * @param FormInterface $form + * @param FormInterface $form + * * @return array */ protected function getFormKeys(FormInterface $form) @@ -106,7 +110,8 @@ protected function getFormKeys(FormInterface $form) /** * Get a request content handler. * - * @param Request $request + * @param Request $request + * * @return RequestContentHandlerInterface */ protected function getRequestContentHandler(Request $request) @@ -121,8 +126,9 @@ protected function getRequestContentHandler(Request $request) /** * Check that needed headers are here. * - * @param Request $request the request - * @param array $headers the headers to check + * @param Request $request the request + * @param array $headers the headers to check + * * @throws \SRIO\RestUploadBundle\Exception\UploadException */ protected function checkHeaders(Request $request, array $headers) @@ -140,8 +146,10 @@ protected function checkHeaders(Request $request, array $headers) /** * Set the uploaded file on the form data. * - * @param UploadedFile $file + * @param UploadedFile $file + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @deprecated */ protected function setUploadedFile(UploadedFile $file) diff --git a/Processor/FormDataUploadProcessor.php b/Processor/FormDataUploadProcessor.php index 99d9997..dadbffa 100644 --- a/Processor/FormDataUploadProcessor.php +++ b/Processor/FormDataUploadProcessor.php @@ -1,10 +1,10 @@ 'file', - self::KEY_FIELD_FORM => 'form' + self::KEY_FIELD_FORM => 'form', ), $config); return parent::handleUpload($request, $form, $config); } /** - * @param Request $request + * @param Request $request + * * @return \SRIO\RestUploadBundle\Upload\UploadResult + * * @throws \Exception|\SRIO\RestUploadBundle\Exception\UploadException */ public function handleRequest(Request $request) @@ -76,7 +78,9 @@ public function handleRequest(Request $request) $uploadedFile = $request->files->get($this->config[self::KEY_FIELD_FILE]); $contents = file_get_contents($uploadedFile->getPathname()); $file = $this->storageHandler->store($response, $contents, array( - FileStorage::METADATA_CONTENT_TYPE => $uploadedFile->getMimeType() + 'metadata' => array( + FileStorage::METADATA_CONTENT_TYPE => $uploadedFile->getMimeType(), + ), )); $response->setFile($file); diff --git a/Processor/MultipartUploadProcessor.php b/Processor/MultipartUploadProcessor.php index 606e8c3..fc65eea 100644 --- a/Processor/MultipartUploadProcessor.php +++ b/Processor/MultipartUploadProcessor.php @@ -1,19 +1,21 @@ getContent($request); $file = $this->storageHandler->store($result, $content, array( - FileStorage::METADATA_CONTENT_TYPE => $contentType + 'metadata' => array( + FileStorage::METADATA_CONTENT_TYPE => $contentType, + ), )); $result->setFile($file); @@ -54,8 +58,10 @@ public function handleRequest(Request $request) * * Note: MUST be called before getContent, and just one time. * - * @param Request $request + * @param Request $request + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return array */ protected function getFormData(Request $request) @@ -84,8 +90,9 @@ protected function getFormData(Request $request) * * Note: MUST be called after getFormData, and just one time. * - * @param \Symfony\Component\HttpFoundation\Request $request - * @param Request $request + * @param \Symfony\Component\HttpFoundation\Request $request + * @param Request $request + * * @return array */ protected function getContent(Request $request) @@ -96,11 +103,12 @@ protected function getContent(Request $request) /** * Check multipart headers. * - * @param Request $request - * @param array $headers + * @param Request $request + * @param array $headers + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException */ - protected function checkHeaders (Request $request, array $headers = array()) + protected function checkHeaders(Request $request, array $headers = array()) { list($contentType) = $this->parseContentTypeAndBoundary($request); @@ -118,8 +126,10 @@ protected function checkHeaders (Request $request, array $headers = array()) /** * Get a part of request. * - * @param Request $request + * @param Request $request + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return array */ protected function getPart(Request $request) @@ -161,9 +171,11 @@ protected function getPart(Request $request) /** * Get part of a resource. * - * @param Request $request + * @param Request $request * @param $boundary + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return string */ protected function getRequestPart(Request $request, $boundary) @@ -189,7 +201,7 @@ protected function getRequestPart(Request $request, $boundary) continue; } - $boundaryCount++; + ++$boundaryCount; } elseif ($line == $delimiter) { break; } elseif ($line == $endDelimiter || $line == $endDelimiter."\r\n") { @@ -205,8 +217,10 @@ protected function getRequestPart(Request $request, $boundary) /** * Parse the content type and boudary from Content-Type header. * - * @param Request $request + * @param Request $request + * * @return array + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException */ protected function parseContentTypeAndBoundary(Request $request) diff --git a/Processor/ProcessorInterface.php b/Processor/ProcessorInterface.php index 0df98e8..55bec57 100644 --- a/Processor/ProcessorInterface.php +++ b/Processor/ProcessorInterface.php @@ -1,4 +1,5 @@ getRepository(); $resumableUpload = $repository->findOneBy(array( - 'sessionId' => $uploadId + 'sessionId' => $uploadId, )); if ($resumableUpload == null) { @@ -86,8 +85,10 @@ public function handleRequest(Request $request) /** * Handle a start session. * - * @param Request $request + * @param Request $request + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return UploadResult */ protected function handleStartSession(Request $request) @@ -124,7 +125,9 @@ protected function handleStartSession(Request $request) // Create file from storage handler $file = $this->storageHandler->store($result, '', array( - FileStorage::METADATA_CONTENT_TYPE => $request->headers->get('X-Upload-Content-Type') + 'metadata' => array( + FileStorage::METADATA_CONTENT_TYPE => $request->headers->get('X-Upload-Content-Type'), + ), )); /** @var $resumableUpload ResumableUploadSession */ @@ -143,7 +146,7 @@ protected function handleStartSession(Request $request) // Compute redirect location path $location = $request->getPathInfo().'?'.http_build_query(array_merge($request->query->all(), array( - self::PARAMETER_UPLOAD_ID => $resumableUpload->getSessionId() + self::PARAMETER_UPLOAD_ID => $resumableUpload->getSessionId(), ))); $response = new Response(null); @@ -158,16 +161,24 @@ protected function handleStartSession(Request $request) /** * Handle an upload resume. * - * @param Request $request - * @param ResumableUploadSession $uploadSession + * @param Request $request + * @param ResumableUploadSession $uploadSession + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return UploadResult */ protected function handleResume(Request $request, ResumableUploadSession $uploadSession) { $filePath = $uploadSession->getFilePath(); + $context = new UploadContext(); $context->setStorageName($uploadSession->getStorageName()); + $file = $this->storageHandler->getFilesystem($context)->get($filePath); + $context->setFile(new UploadedFile( + $this->storageHandler->getStorage($context), + $file + )); $contentLength = $request->headers->get('Content-Length'); if ($request->headers->has('Content-Range')) { @@ -181,7 +192,7 @@ protected function handleResume(Request $request, ResumableUploadSession $upload )); } elseif ($range['start'] === '*') { if ($contentLength == 0) { - $file = $this->storageHandler->get($context, $filePath); + $file = $this->storageHandler->getFilesystem($context)->get($filePath); return $this->requestUploadStatus($context, $uploadSession, $file, $range); } @@ -189,7 +200,7 @@ protected function handleResume(Request $request, ResumableUploadSession $upload throw new UploadProcessorException('Content-Length must be 0 if asking upload status'); } - $uploaded = $this->storageHandler->size($context, $filePath); + $uploaded = $this->storageHandler->getFilesystem($context)->getSize($filePath); if ($range['start'] != $uploaded) { throw new UploadProcessorException(sprintf( 'Unable to start at %d while uploaded is %d', @@ -201,31 +212,33 @@ protected function handleResume(Request $request, ResumableUploadSession $upload $range = array( 'start' => 0, 'end' => $uploadSession->getContentLength() - 1, - 'total' => $uploadSession->getContentLength() - 1 + 'total' => $uploadSession->getContentLength() - 1, ); } // Handle upload from $handler = $this->getRequestContentHandler($request); - $writer = $this->storageHandler->getStream($context, $filePath); - if ($writer->open(new StreamMode('c')) !== true) { - throw new UploadProcessorException('Unable to open stream'); - } + $stream = $this->storageHandler->getFilesystem($context)->getStreamCopy($filePath); - $writer->seek($range['start']); + fseek($stream, $range['start']); $wrote = 0; while (!$handler->eof()) { - if (($bytes = $writer->write($handler->gets())) !== false) { + if (($bytes = fwrite($stream, $handler->gets())) !== false) { $wrote += $bytes; } else { - throw new UploadProcessorException('Unable to wrote to file'); + throw new UploadProcessorException('Unable to write to file'); } } - $writer->close(); - // Get file in context and its size - $file = $this->storageHandler->get($context, $filePath); + $uploadedFile = $this->storageHandler->storeStream($context, $stream, array( + 'metadata' => array( + FileStorage::METADATA_CONTENT_TYPE => $request->headers->get('X-Upload-Content-Type'), + ), + ), true); + fclose($stream); + + $file = $uploadedFile->getFile(); $size = $file->getSize(); // If upload is completed, create the upload file, else @@ -235,19 +248,20 @@ protected function handleResume(Request $request, ResumableUploadSession $upload } elseif ($size == $uploadSession->getContentLength()) { return $this->handleCompletedUpload($context, $uploadSession, $file); } else { - throw new UploadProcessorException('Wrote file size is greater that expected Content-Length'); + throw new UploadProcessorException('Written file size is greater that expected Content-Length'); } } /** * Handle a completed upload. * - * @param \SRIO\RestUploadBundle\Upload\UploadContext $context - * @param ResumableUploadSession $uploadSession - * @param \Gaufrette\File $file + * @param \SRIO\RestUploadBundle\Upload\UploadContext $context + * @param ResumableUploadSession $uploadSession + * @param FileAdapterInterface $file + * * @return UploadResult */ - protected function handleCompletedUpload(UploadContext $context, ResumableUploadSession $uploadSession, File $file) + protected function handleCompletedUpload(UploadContext $context, ResumableUploadSession $uploadSession, FileAdapterInterface $file) { $result = new UploadResult(); $result->setForm($this->form); @@ -274,13 +288,14 @@ protected function handleCompletedUpload(UploadContext $context, ResumableUpload /** * Return the upload status. * - * @param \SRIO\RestUploadBundle\Upload\UploadContext $context - * @param ResumableUploadSession $uploadSession - * @param \Gaufrette\File $file - * @param array $range + * @param \SRIO\RestUploadBundle\Upload\UploadContext $context + * @param ResumableUploadSession $uploadSession + * @param FileAdapterInterface $file + * @param array $range + * * @return UploadResult */ - protected function requestUploadStatus(UploadContext $context, ResumableUploadSession $uploadSession, File $file, array $range) + protected function requestUploadStatus(UploadContext $context, ResumableUploadSession $uploadSession, FileAdapterInterface $file, array $range) { if (!$file->exists()) { $length = 0; @@ -310,8 +325,10 @@ protected function requestUploadStatus(UploadContext $context, ResumableUploadSe * - `end` End index of range * - `total` Total number of bytes * - * @param string $contentRange + * @param string $contentRange + * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return array */ protected function parseContentRange($contentRange) @@ -324,7 +341,7 @@ protected function parseContentRange($contentRange) $range = array( 'start' => $matches[1] === '*' ? '*' : ($matches[2] === '' ? null : (int) $matches[2]), 'end' => $matches[3] === '' ? null : (int) $matches[3], - 'total' => (int) $matches[4] + 'total' => (int) $matches[4], ); if (empty($range['total'])) { @@ -339,7 +356,7 @@ protected function parseContentRange($contentRange) } elseif ($range['start'] > $range['end']) { throw new UploadProcessorException('Content-Range start must be lower than end'); } elseif ($range['end'] > $range['total']) { - throw new UploadProcessorException('Content-Range end must be lower or equals to total length'); + throw new UploadProcessorException('Content-Range end must be lower or equal to total length'); } return $range; @@ -357,7 +374,6 @@ protected function getRepository() /** * Create a session ID. - * */ protected function createSessionId() { diff --git a/Processor/SimpleUploadProcessor.php b/Processor/SimpleUploadProcessor.php index ae137f4..f24dc85 100644 --- a/Processor/SimpleUploadProcessor.php +++ b/Processor/SimpleUploadProcessor.php @@ -1,18 +1,21 @@ storageHandler->store($result, $content, array( - FileStorage::METADATA_CONTENT_TYPE => $request->headers->get('Content-Type') + 'metadata' => array( + FileStorage::METADATA_CONTENT_TYPE => $request->headers->get('Content-Type'), + ), )); $result->setFile($file); diff --git a/Request/RequestContentHandler.php b/Request/RequestContentHandler.php index 3f897c1..37d6ddb 100644 --- a/Request/RequestContentHandler.php +++ b/Request/RequestContentHandler.php @@ -1,4 +1,5 @@ + + + + SRIO\RestUploadBundle\Storage\FlysystemFilesystemAdapter + SRIO\RestUploadBundle\Storage\GaufretteFilesystemAdapter + + + + + null + + + null + + + diff --git a/Storage/FileAdapterInterface.php b/Storage/FileAdapterInterface.php new file mode 100644 index 0000000..363183d --- /dev/null +++ b/Storage/FileAdapterInterface.php @@ -0,0 +1,34 @@ +name = $name; $this->filesystem = $filesystem; @@ -50,86 +47,73 @@ public function __construct($name, Filesystem $filesystem, StorageStrategy $stor } /** - * Store a file content. + * Store a file's content. * - * @param UploadContext $context - * @param $content - * @param array $metadataMap + * @param UploadContext $context + * @param string $content + * @param array $config + * @param bool $overwrite + * * @return UploadedFile */ - public function store (UploadContext $context, $content, array $metadataMap = array()) + public function store(UploadContext $context, $content, array $config = array(), $overwrite = false) { - $name = $this->namingStrategy->getName($context); - $directory = $this->storageStrategy->getDirectory($context, $name); - $path = $directory.'/'.$name; - - $adapter = $this->filesystem->getAdapter(); - if ($adapter instanceof MetadataSupporter) { - $adapter->setMetadata($path, $this->resolveMetadataMap($context, $metadataMap)); + $path = $this->getFilePathFromContext($context); + if ($overwrite === true) { + $this->filesystem->put($path, $content, $config); + } else { + $this->filesystem->write($path, $content, $config); } - $this->filesystem->write($path, $content); - $file = $this->filesystem->get($path); return new UploadedFile($this, $file); } /** - * Resolve the metadata map. + * Store a file's content. * - * @param UploadContext $context - * @param array $metadataMap - * @return array + * @param UploadContext $context + * @param resource $resource + * @param array $config + * @param bool $overwrite + * + * @return UploadedFile */ - protected function resolveMetadataMap(UploadContext $context, array $metadataMap) + public function storeStream(UploadContext $context, $resource, array $config = array(), $overwrite = false) { - $allowedMetadataKeys = array(self::METADATA_CONTENT_TYPE); - $map = array(); - - foreach ($allowedMetadataKeys as $key) { - if (array_key_exists($key, $metadataMap)) { - $map[$key] = $metadataMap[$key]; - } + $path = $this->getFilePathFromContext($context); + if ($overwrite === true) { + $this->filesystem->putStream($path, $resource, $config); + } else { + $this->filesystem->writeStream($path, $resource, $config); } + $file = $this->filesystem->get($path); - return $map; + return new UploadedFile($this, $file); } /** - * Get file size. + * Get or creates a file path from UploadContext. * - * @param $name - * @return int - */ - public function size($name) - { - return $this->filesystem->size($name); - } - - /** - * Get file. + * @param UploadContext $context * - * @param $name - * @return File + * @return string */ - public function get($name) + protected function getFilePathFromContext(UploadContext $context) { - return $this->filesystem->get($name); - } + if ($context->getFile() != null) { + return $context->getFile()->getFile()->getName(); + } - /** - * Get a stream from file. - * - * @param $name - * @return \Gaufrette\Stream|\Gaufrette\Stream\InMemoryBuffer - */ - public function getStream($name) - { - return $this->filesystem->createStream($name); + $name = $this->namingStrategy->getName($context); + $directory = $this->storageStrategy->getDirectory($context, $name); + $path = $directory.'/'.$name; + + return $path; } /** - * @return \Gaufrette\Filesystem + * @return FilesystemAdapterInterface */ public function getFilesystem() { @@ -145,7 +129,7 @@ public function getName() } /** - * @return \Doctrine\ORM\Mapping\NamingStrategy + * @return NamingStrategy */ public function getNamingStrategy() { @@ -153,7 +137,7 @@ public function getNamingStrategy() } /** - * @return \SRIO\RestUploadBundle\Strategy\StorageStrategy + * @return StorageStrategy */ public function getStorageStrategy() { diff --git a/Storage/FilesystemAdapterInterface.php b/Storage/FilesystemAdapterInterface.php new file mode 100644 index 0000000..fda6969 --- /dev/null +++ b/Storage/FilesystemAdapterInterface.php @@ -0,0 +1,167 @@ +file = $file; + } + + /** + * {@inheritdoc} + */ + public function exists() + { + return $this->file->exists(); + } + + /** + * {@inheritdoc} + */ + public function getSize() + { + return $this->file->getSize(); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->file->getPath(); + } + + /** + * {@inheritdoc} + */ + public function getFile() + { + return $this->file; + } +} diff --git a/Storage/FlysystemFilesystemAdapter.php b/Storage/FlysystemFilesystemAdapter.php new file mode 100644 index 0000000..87934bb --- /dev/null +++ b/Storage/FlysystemFilesystemAdapter.php @@ -0,0 +1,202 @@ +filesystem = $filesystem; + } + + /** + * {@inheritdoc} + */ + public function getFilesystem() + { + return $this->filesystem; + } + + /** + * {@inheritdoc} + */ + public function getAdapter() + { + return $this->filesystem->getAdapter(); + } + + /** + * {@inheritdoc} + */ + public function has($path) + { + return $this->filesystem->has($path); + } + + /** + * {@inheritdoc} + */ + public function get($path) + { + return new FlysystemFileAdapter(new File($this->filesystem, $path)); + } + + /** + * {@inheritdoc} + */ + public function write($path, $content, array $config = array()) + { + try { + return $this->filesystem->write($path, $content, $config); + } catch (FileExistsException $ex) { + throw $this->createFileExistsException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function writeStream($path, $resource, array $config = array()) + { + try { + return $this->filesystem->writeStream($path, $resource, $config); + } catch (FileExistsException $ex) { + throw $this->createFileExistsException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function put($path, $content, array $config = array()) + { + return $this->filesystem->put($path, $content, $config); + } + + /** + * {@inheritdoc} + */ + public function putStream($path, $resource, array $config = array()) + { + return $this->filesystem->putStream($path, $resource, $config); + } + + /** + * {@inheritdoc} + */ + public function read($path) + { + try { + return $this->filesystem->read($path); + } catch (FileNotFoundException $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function readStream($path) + { + try { + return $this->filesystem->readStream($path); + } catch (FileNotFoundException $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function delete($path) + { + try { + return $this->filesystem->delete($path); + } catch (FileNotFoundException $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function getStreamCopy($path) + { + $stream = $this->readStream($path); + + // Neatly overflow into a file on disk after more than 10MBs. + $mbLimit = 10 * 1024 * 1024; + $streamCopy = fopen("php://temp/maxmemory:$mbLimit", 'w+b'); + + stream_copy_to_stream($stream, $streamCopy); + rewind($streamCopy); + + return $streamCopy; + } + + /** + * {@inheritdoc} + */ + public function getModifiedTimestamp($path) + { + if (false === $timestamp = $this->filesystem->getTimestamp($path)) { + throw $this->createFileNotFoundException($path); + } + + return $timestamp; + } + + /** + * {@inheritdoc} + */ + public function getSize($path) + { + if (false === $size = $this->filesystem->getSize($path)) { + throw $this->createFileNotFoundException($path); + } + + return $size; + } + + /** + * {@inheritdoc} + */ + public function getMimeType($path) + { + if (false === $mimeType = $this->filesystem->getMimetype($path)) { + throw $this->createFileNotFoundException($path); + } + + return $mimeType; + } + + protected function createFileNotFoundException($path, $previousEx = null) + { + if ($previousEx === null) { + $previousEx = new FileNotFoundException($path); + } + + return new WrappingFileNotFoundException($previousEx->getMessage(), $previousEx->getCode(), $previousEx); + } + + protected function createFileExistsException($path, $previousEx = null) + { + if ($previousEx === null) { + $previousEx = new FileExistsException($path); + } + + return new WrappingFileExistsException($previousEx->getMessage(), $previousEx->getCode(), $previousEx); + } +} diff --git a/Storage/GaufretteFileAdapter.php b/Storage/GaufretteFileAdapter.php new file mode 100644 index 0000000..1b9047c --- /dev/null +++ b/Storage/GaufretteFileAdapter.php @@ -0,0 +1,50 @@ +file = $file; + } + + /** + * {@inheritdoc} + */ + public function exists() + { + return $this->file->exists(); + } + + /** + * {@inheritdoc} + */ + public function getSize() + { + return $this->file->getSize(); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->file->getKey(); + } + + /** + * {@inheritdoc} + */ + public function getFile() + { + return $this->file; + } +} diff --git a/Storage/GaufretteFilesystemAdapter.php b/Storage/GaufretteFilesystemAdapter.php new file mode 100644 index 0000000..d30db67 --- /dev/null +++ b/Storage/GaufretteFilesystemAdapter.php @@ -0,0 +1,283 @@ +filesystem = $filesystem; + } + + /** + * {@inheritdoc} + */ + public function getFilesystem() + { + return $this->filesystem; + } + + /** + * {@inheritdoc} + */ + public function getAdapter() + { + return $this->filesystem->getAdapter(); + } + + /** + * {@inheritdoc} + */ + public function has($path) + { + return $this->filesystem->has($path); + } + + /** + * {@inheritdoc} + */ + public function get($path) + { + return new GaufretteFileAdapter($this->filesystem->get($path)); + } + + /** + * {@inheritdoc} + */ + public function write($path, $content, array $config = array()) + { + return $this->writeContents($path, $content, $config, false); + } + + /** + * {@inheritdoc} + */ + public function writeStream($path, $resource, array $config = array()) + { + // This is not ideal, stream_get_contents will read the full stream into memory before we can + // flow it into the write function. Watch out with big files and Gaufrette! + return $this->writeContents($path, stream_get_contents($resource, -1, 0), $config, false); + } + + /** + * {@inheritdoc} + */ + public function put($path, $content, array $config = array()) + { + return $this->writeContents($path, $content, $config, true); + } + + /** + * {@inheritdoc} + */ + public function putStream($path, $resource, array $config = array()) + { + // This is not ideal, stream_get_contents will read the full stream into memory before we can + // flow it into the write function. Watch out with big files and Gaufrette! + return $this->writeContents($path, stream_get_contents($resource, -1, 0), $config, true); + } + + /** + * General function for all writes. + * + * @param $path + * @param $content + * @param array $config + * @param bool $overwrite + * + * @return bool + */ + protected function writeContents($path, $content, array $config = array(), $overwrite = false) + { + if (!empty($config['metadata'])) { + $adapter = $this->getAdapter(); + if ($adapter instanceof MetadataSupporter) { + $allowed = empty($config['allowedMetadataKeys']) + ? array(FileStorage::METADATA_CONTENT_TYPE) + : array_merge($config['allowedMetadataKeys'], array(FileStorage::METADATA_CONTENT_TYPE)); + + $adapter->setMetadata($path, $this->resolveMetadataMap($allowed, $config['metadata'])); + } + } + + try { + $this->filesystem->write($path, $content, $overwrite); + + return true; + } catch (\RuntimeException $ex) { + return false; + } + } + + /** + * Resolve the metadata map. + * + * @param array $allowedMetadataKeys + * @param array $metadataMap + * + * @return array + */ + protected function resolveMetadataMap(array $allowedMetadataKeys, array $metadataMap) + { + $map = array(); + + foreach ($allowedMetadataKeys as $key) { + if (array_key_exists($key, $metadataMap)) { + $map[$key] = $metadataMap[$key]; + } + } + + return $map; + } + + /** + * {@inheritdoc} + */ + public function read($path) + { + try { + $this->filesystem->read($path); + + return true; + } catch (FileNotFound $ex) { + throw $this->createFileNotFoundException($path, $ex); + } catch (\RuntimeException $ex) { + return false; + } + } + + /** + * {@inheritdoc} + */ + public function readStream($path) + { + if (!$this->filesystem->has($path)) { + throw $this->createFileNotFoundException($path); + } + + // If castable to a real stream (local filesystem for instance) use that stream. + $streamWrapper = $this->filesystem->createStream($path); + $streamWrapper->open(new StreamMode('rb')); + $stream = $streamWrapper->cast(0); + + if ($stream === false) { + // This is not ideal, read will first read the full file into memory before we can + // flow it into the temp stream. Watch out with big files and Gaufrette! + $stream = fopen('php://temp', 'w+b'); + fwrite($stream, $this->read($path)); + rewind($stream); + } + + return $stream; + } + + /** + * {@inheritdoc} + */ + public function getStreamCopy($path) + { + if (!$this->filesystem->has($path)) { + throw $this->createFileNotFoundException($path); + } + + // If castable to a real stream (local filesystem for instance) use that stream. + $streamWrapper = $this->filesystem->createStream($path); + $streamWrapper->open(new StreamMode('rb')); + $stream = $streamWrapper->cast(0); + + // Neatly overflow into a file on disk after more than 10MBs. + $mbLimit = 10 * 1024 * 1024; + $streamCopy = fopen("php://temp/maxmemory:$mbLimit", 'w+b'); + if ($stream === false) { + // This is not ideal, read will first read the full file into memory before we can + // flow it into the temp stream. Watch out with big files and Gaufrette! + $data = $this->read($path); + fwrite($streamCopy, $data); + } else { + stream_copy_to_stream($stream, $streamCopy); + } + + rewind($streamCopy); + + return $streamCopy; + } + + /** + * {@inheritdoc} + */ + public function delete($path) + { + try { + return $this->filesystem->delete($path); + } catch (FileNotFound $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function getModifiedTimestamp($path) + { + try { + return $this->filesystem->mtime($path); + } catch (FileNotFound $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function getSize($path) + { + try { + return $this->filesystem->size($path); + } catch (FileNotFound $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + /** + * {@inheritdoc} + */ + public function getMimeType($path) + { + try { + return $this->filesystem->mimeType($path); + } catch (FileNotFound $ex) { + throw $this->createFileNotFoundException($path, $ex); + } + } + + protected function createFileNotFoundException($path, $previousEx = null) + { + if ($previousEx === null) { + $previousEx = new FileNotFound($path); + } + + return new WrappingFileNotFoundException($previousEx->getMessage(), $previousEx->getCode(), $previousEx); + } + + protected function createFileExistsException($path, $previousEx = null) + { + if ($previousEx === null) { + $previousEx = new FileAlreadyExists($path); + } + + return new WrappingFileExistsException($previousEx->getMessage(), $previousEx->getCode(), $previousEx); + } +} diff --git a/Storage/UploadedFile.php b/Storage/UploadedFile.php index 26c400f..039beb8 100644 --- a/Storage/UploadedFile.php +++ b/Storage/UploadedFile.php @@ -1,7 +1,6 @@ storage = $storage; $this->file = $file; } /** - * @return \Gaufrette\File + * @return FileAdapterInterface */ public function getFile() { diff --git a/Strategy/DefaultNamingStrategy.php b/Strategy/DefaultNamingStrategy.php index 5fc02ee..613c360 100644 --- a/Strategy/DefaultNamingStrategy.php +++ b/Strategy/DefaultNamingStrategy.php @@ -1,4 +1,5 @@ size = $uploaded->getFile()->getSize(); // TODO Add mimetype on `UploadedFile` - $this->mimeType = $uploaded->getStorage()->getFilesystem()->mimeType($this->path); + $this->mimeType = $uploaded->getStorage()->getFilesystem()->getMimeType($this->path); // TODO Add original name $this->originalName = $uploaded->getFile()->getName(); diff --git a/Tests/Fixtures/Entity/ResumableUploadSession.php b/Tests/Fixtures/Entity/ResumableUploadSession.php index 681fe45..8ad681d 100644 --- a/Tests/Fixtures/Entity/ResumableUploadSession.php +++ b/Tests/Fixtures/Entity/ResumableUploadSession.php @@ -1,4 +1,5 @@ add('name', 'text', array( 'required' => true, - 'constraints' => array(new NotBlank()) + 'constraints' => array(new NotBlank()), )) ; } @@ -27,13 +28,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'csrf_protection' => false, - 'data_class' => 'SRIO\RestUploadBundle\Tests\Fixtures\Entity\Media' + 'csrf_protection' => false, + 'data_class' => 'SRIO\RestUploadBundle\Tests\Fixtures\Entity\Media', )); } public function getName() { - return null; + return; } } diff --git a/Tests/Processor/AbstractProcessorTestCase.php b/Tests/Processor/AbstractProcessorTestCase.php index a210bf7..211f021 100644 --- a/Tests/Processor/AbstractProcessorTestCase.php +++ b/Tests/Processor/AbstractProcessorTestCase.php @@ -1,4 +1,5 @@ getNewClient(); $image = $this->getResource($client, 'apple.gif'); $data = array('test' => 'OK'); $jsonData = json_encode($data); @@ -33,7 +33,7 @@ public function testGetPartsString() public function testGetPartsResource() { - $client = static::createClient(); + $client = $this->getNewClient(); $image = $this->getResource($client, 'apple.gif'); $data = array('test' => 'OK'); $jsonData = json_encode($data); @@ -91,7 +91,7 @@ protected function createMultipartRequestWithContent($boundary, $content) ->will($this->returnValue($content)); $request->headers = new HeaderBag(array( - 'Content-Type' => 'multipart/related; boundary="'.$boundary.'"' + 'Content-Type' => 'multipart/related; boundary="'.$boundary.'"', )); return $request; diff --git a/Tests/Processor/ResumableUploadProcessorTest.php b/Tests/Processor/ResumableUploadProcessorTest.php index 0a831d5..8d7c44f 100644 --- a/Tests/Processor/ResumableUploadProcessorTest.php +++ b/Tests/Processor/ResumableUploadProcessorTest.php @@ -1,4 +1,5 @@ getNewClient(); $filePath = $this->getResourcePath($client, 'apple.gif'); $content = file_get_contents($filePath); @@ -17,7 +18,7 @@ public function testBinaryStringContent() public function testBinaryResourceContent() { - $client = static::createClient(); + $client = $this->getNewClient(); $filePath = $this->getResourcePath($client, 'apple.gif'); $content = fopen($filePath, 'r'); $expectedContent = file_get_contents($filePath); @@ -27,7 +28,7 @@ public function testBinaryResourceContent() public function testStringContent() { - $client = static::createClient(); + $client = $this->getNewClient(); $filePath = $this->getResourcePath($client, 'lorem.txt'); $content = file_get_contents($filePath); @@ -36,7 +37,7 @@ public function testStringContent() public function testStringResourceContent() { - $client = static::createClient(); + $client = $this->getNewClient(); $filePath = $this->getResourcePath($client, 'lorem.txt'); $content = fopen($filePath, 'r'); $expectedContent = file_get_contents($filePath); diff --git a/Tests/Upload/AbstractUploadTestCase.php b/Tests/Upload/AbstractUploadTestCase.php index 624d9a6..aa1be62 100644 --- a/Tests/Upload/AbstractUploadTestCase.php +++ b/Tests/Upload/AbstractUploadTestCase.php @@ -1,4 +1,5 @@ getContainer()->getParameter('kernel.root_dir').'/../../Resources/'.$name; } + + /** + * Creates a Client. + * + * @param array $options An array of options to pass to the createKernel class + * @param array $server An array of server parameters + * + * @return Client A Client instance + */ + protected function getNewClient(array $options = array(), array $server = array()) + { + $options = array_merge(array('environment' => isset($_SERVER['TEST_FILESYSTEM']) ? strtolower($_SERVER['TEST_FILESYSTEM']) : 'gaufrette'), $options); + + return static::createClient($options, $server); + } } diff --git a/Tests/Upload/MultipartUploadTest.php b/Tests/Upload/MultipartUploadTest.php index 90c867d..a441a63 100644 --- a/Tests/Upload/MultipartUploadTest.php +++ b/Tests/Upload/MultipartUploadTest.php @@ -1,11 +1,12 @@ getNewClient(); $queryParameters = array('name' => 'test'); $boundary = uniqid(); @@ -14,14 +15,14 @@ public function testWithoutContent() $client->request('POST', '/upload?uploadType=multipart', array(), array(), array( 'CONTENT_TYPE' => 'multipart/related; boundary="'.$boundary.'"', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $this->assertResponseHasErrors($client); } public function testWithoutHeaders() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('name' => 'test'); $boundary = uniqid(); @@ -36,7 +37,7 @@ public function testWithoutHeaders() public function testWithoutBoundary() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('name' => 'test'); $boundary = uniqid(); @@ -47,14 +48,14 @@ public function testWithoutBoundary() $client->request('POST', '/upload?uploadType=multipart', array(), array(), array( 'CONTENT_TYPE' => 'multipart/related', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $this->assertResponseHasErrors($client); } public function testBinaryBeforeMeta() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('name' => 'test'); $boundary = uniqid(); @@ -65,14 +66,14 @@ public function testBinaryBeforeMeta() $client->request('POST', '/upload?uploadType=multipart', array(), array(), array( 'CONTENT_TYPE' => 'multipart/related; boundary="'.$boundary.'"', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $this->assertResponseHasErrors($client); } public function testMultipartUpload() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('name' => 'test'); $boundary = uniqid(); @@ -83,7 +84,7 @@ public function testMultipartUpload() $client->request('POST', '/upload?uploadType=multipart', array(), array(), array( 'CONTENT_TYPE' => 'multipart/related; boundary="'.$boundary.'"', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $response = $client->getResponse(); diff --git a/Tests/Upload/ResumableUploadTest.php b/Tests/Upload/ResumableUploadTest.php index 30f5118..f10b6f2 100644 --- a/Tests/Upload/ResumableUploadTest.php +++ b/Tests/Upload/ResumableUploadTest.php @@ -1,8 +1,8 @@ getResource($client, 'apple.gif'); $client->request('PUT', $location, array(), array(), array( 'CONTENT_TYPE' => 'image/gif', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $this->assertSuccessful($client, $content); @@ -36,7 +36,7 @@ public function testChunkedUpload() $client->request('PUT', $location, array(), array(), array( 'CONTENT_TYPE' => 'image/gif', 'CONTENT_LENGTH' => strlen($part), - 'HTTP_Content-Range' => 'bytes '.$start.'-'.$end.'/'.strlen($content) + 'HTTP_Content-Range' => 'bytes '.$start.'-'.$end.'/'.strlen($content), ), $part); $response = $client->getResponse(); @@ -46,7 +46,7 @@ public function testChunkedUpload() $client->request('PUT', $location, array(), array(), array( 'CONTENT_LENGTH' => 0, - 'HTTP_Content-Range' => 'bytes */'.strlen($content) + 'HTTP_Content-Range' => 'bytes */'.strlen($content), )); $response = $client->getResponse(); @@ -60,7 +60,7 @@ public function testChunkedUpload() protected function startSession() { - $client = static::createClient(); + $client = $this->getNewClient(); $content = $this->getResource($client, 'apple.gif'); $parameters = array('name' => 'test'); $json = json_encode($parameters); @@ -69,7 +69,7 @@ protected function startSession() 'CONTENT_TYPE' => 'application/json', 'CONTENT_LENGTH' => strlen($json), 'HTTP_X-Upload-Content-Type' => 'image/gif', - 'HTTP_X-Upload-Content-Length' => strlen($content) + 'HTTP_X-Upload-Content-Length' => strlen($content), ), $json); $response = $client->getResponse(); diff --git a/Tests/Upload/SimpleUploadTest.php b/Tests/Upload/SimpleUploadTest.php index cef90bb..6472903 100644 --- a/Tests/Upload/SimpleUploadTest.php +++ b/Tests/Upload/SimpleUploadTest.php @@ -1,11 +1,12 @@ getNewClient(); $queryParameters = array('uploadType' => 'simple', 'name' => 'test'); $content = $this->getResource($client, 'apple.gif'); @@ -19,12 +20,12 @@ public function testWithEmptyContentTypeHeaderSimpleUpload() public function testWithoutFormSimpleUpload() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('uploadType' => 'simple'); $content = $this->getResource($client, 'apple.gif'); $client->request('POST', '/upload?'.http_build_query($queryParameters), array(), array(), array( 'CONTENT_TYPE' => 'image/gif', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), )); $response = $client->getResponse(); @@ -33,7 +34,7 @@ public function testWithoutFormSimpleUpload() public function testWithoutContentSimpleUpload() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('uploadType' => 'simple', 'name' => 'test'); $client->request('POST', '/upload?'.http_build_query($queryParameters)); @@ -43,13 +44,13 @@ public function testWithoutContentSimpleUpload() public function testSimpleUpload() { - $client = static::createClient(); + $client = $this->getNewClient(); $queryParameters = array('uploadType' => 'simple', 'name' => 'test'); $content = $this->getResource($client, 'apple.gif'); $client->request('POST', '/upload?'.http_build_query($queryParameters), array(), array(), array( 'CONTENT_TYPE' => 'image/gif', - 'CONTENT_LENGTH' => strlen($content) + 'CONTENT_LENGTH' => strlen($content), ), $content); $response = $client->getResponse(); diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php index 8bb424b..fd32322 100644 --- a/Tests/bootstrap.php +++ b/Tests/bootstrap.php @@ -9,3 +9,11 @@ $loader = require $loaderFile; AnnotationRegistry::registerLoader(array($loader, 'loadClass')); + +$testEnv = isset($_SERVER['TEST_FILESYSTEM']) ? $_SERVER['TEST_FILESYSTEM'] : 'gaufrette'; +$message = "Currently testing filesystem layer: \"$testEnv\" (options: Gaufrette, Flysystem. see 'test.sh' script)"; +if (PHP_SAPI === 'cli') { + echo "\e[48;5;202m$message\e[49m\r\n\r\n"; +} else { + echo $message; +} diff --git a/Upload/StorageHandler.php b/Upload/StorageHandler.php index 06022bb..0553c1e 100644 --- a/Upload/StorageHandler.php +++ b/Upload/StorageHandler.php @@ -1,14 +1,15 @@ getStorage($context)->store($context, $contents, $metadataMap); + return $this->getStorage($context)->store($context, $contents, $config, $overwrite); } /** - * Get file size. + * Store a file's content. * - * @param UploadContext $context - * @param $name - * @return int - */ - public function size(UploadContext $context, $name) - { - return $this->getStorage($context)->size($name); - } - - /** - * Get file. + * @param UploadContext $context + * @param resource $resource + * @param array $config + * @param bool $overwrite * - * @param UploadContext $context - * @param $name - * @return \Gaufrette\File + * @return UploadedFile */ - public function get(UploadContext $context, $name) + public function storeStream(UploadContext $context, $resource, array $config = array(), $overwrite = false) { - return $this->getStorage($context)->get($name); + return $this->getStorage($context)->storeStream($context, $resource, $config, $overwrite); } /** - * Get a stream for that file. - * - * @param UploadContext $context - * @param $name - * @return \Gaufrette\Stream|\Gaufrette\Stream\InMemoryBuffer + * @return FilesystemAdapterInterface */ - public function getStream(UploadContext $context, $name) + public function getFilesystem(UploadContext $context) { - return $this->getStorage($context)->getStream($name); + return $this->getStorage($context)->getFilesystem(); } /** * Get storage by upload context. * - * @param UploadContext $context + * @param UploadContext $context + * * @return FileStorage + * * @throws \SRIO\RestUploadBundle\Exception\UploadException */ public function getStorage(UploadContext $context) diff --git a/Upload/UploadContext.php b/Upload/UploadContext.php index fc727bf..9d83971 100644 --- a/Upload/UploadContext.php +++ b/Upload/UploadContext.php @@ -1,4 +1,5 @@ request = $request; $this->form = $form; diff --git a/Upload/UploadHandler.php b/Upload/UploadHandler.php index ebc5f02..6219c52 100644 --- a/Upload/UploadHandler.php +++ b/Upload/UploadHandler.php @@ -1,10 +1,10 @@ getProcessor($request, $config); @@ -87,6 +88,7 @@ public function handleRequest (Request $request, FormInterface $form = null, arr * @param array $config * * @throws \SRIO\RestUploadBundle\Exception\UploadProcessorException + * * @return ProcessorInterface */ protected function getProcessor(Request $request, array $config) @@ -107,6 +109,7 @@ protected function getProcessor(Request $request, array $config) * Get the current upload type parameter. * * @param array $extraConfiguration + * * @internal param $parameter * @internal param $config * diff --git a/Upload/UploadResult.php b/Upload/UploadResult.php index d3bd4dc..7bf379c 100644 --- a/Upload/UploadResult.php +++ b/Upload/UploadResult.php @@ -1,4 +1,5 @@ =5.3.3", "symfony/symfony": ">=2.3.0", - "incenteev/composer-parameter-handler": "~2.0", - "knplabs/knp-gaufrette-bundle": ">=0.1.7", - "knplabs/gaufrette": ">=0.1.7" + "incenteev/composer-parameter-handler": "~2.0" }, "require-dev": { "sensio/framework-extra-bundle": ">=2.3.0", "doctrine/orm": "~2.2,>=2.2.3", "doctrine/doctrine-bundle": ">=1.2.0", - "phpunit/phpunit": "3.7.*" + "phpunit/phpunit": "3.7.*", + "knplabs/knp-gaufrette-bundle": ">=0.1.7", + "oneup/flysystem-bundle": "~1.4" }, "suggest": { "doctrine/orm": ">=2.2.3,<2.4-dev", - "doctrine/doctrine-bundle": ">=1.2.0" + "doctrine/doctrine-bundle": ">=1.2.0", + "knplabs/knp-gaufrette-bundle": "Required if you use the knplabs/gaufrette filesystem abstraction layer", + "oneup/flysystem-bundle": "Required if you use the league/flysystem filesystem abstraction layer" }, "autoload": { "psr-0": { "SRIO\\RestUploadBundle": "" } }, + "scripts": { + "test": "./test.sh", + "contrib": [ + "php-cs-fixer fix .", + "./test.sh" + ] + }, "target-dir": "SRIO/RestUploadBundle" } diff --git a/composer.lock b/composer.lock index 2357722..252683e 100644 --- a/composer.lock +++ b/composer.lock @@ -1,9 +1,11 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], - "hash": "86368d95905d81e6e711c580ffd0ef6a", + "hash": "311ba3a33cd2676b03c438cc656e468d", + "content-hash": "7823c733c01ea7064433c00d6af263f7", "packages": [ { "name": "doctrine/annotations", @@ -43,7 +45,7 @@ ], "authors": [ { - "name": "Jonathan H. Wage", + "name": "Jonathan Wage", "email": "jonwage@gmail.com", "homepage": "http://www.jwage.com/", "role": "Creator" @@ -64,7 +66,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -139,7 +141,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -206,7 +208,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -279,7 +281,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -344,7 +346,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -398,7 +400,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -604,6 +606,162 @@ ], "time": "2014-03-24 22:15:03" }, + { + "name": "league/flysystem", + "version": "1.0.27", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "conflict": { + "league/flysystem-sftp": "<1.0.6" + }, + "require-dev": { + "ext-fileinfo": "*", + "mockery/mockery": "~0.9", + "phpspec/phpspec": "^2.2", + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-copy": "Allows you to use Copy.com storage", + "league/flysystem-dropbox": "Allows you to use Dropbox storage", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "time": "2016-08-10 08:55:11" + }, + { + "name": "oneup/flysystem-bundle", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/1up-lab/OneupFlysystemBundle.git", + "reference": "2459169ed38e38bff1471ce0b25d4b341d0a938f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/1up-lab/OneupFlysystemBundle/zipball/2459169ed38e38bff1471ce0b25d4b341d0a938f", + "reference": "2459169ed38e38bff1471ce0b25d4b341d0a938f", + "shasum": "" + }, + "require": { + "league/flysystem": "^1.0.14", + "php": ">=5.4.0", + "symfony/framework-bundle": "~2.0|~3.0" + }, + "require-dev": { + "league/flysystem-aws-s3-v2": "~1.0", + "league/flysystem-cached-adapter": "~1.0", + "league/flysystem-copy": "~1.0", + "league/flysystem-dropbox": "~1.0", + "league/flysystem-gridfs": "~1.0", + "league/flysystem-rackspace": "~1.0", + "league/flysystem-sftp": "~1.0", + "league/flysystem-webdav": "~1.0", + "league/flysystem-ziparchive": "~1.0", + "phpunit/phpunit": "4.4.*", + "symfony/browser-kit": "~2.0|~3.0", + "symfony/finder": "~2.0|~3.0" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "league/flysystem-aws-s3-v2": "Use S3 storage with AWS SDK v2", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-copy": "Allows you to use Copy.com storage", + "league/flysystem-dropbox": "Use Dropbox storage", + "league/flysystem-gridfs": "Allows you to use GridFS adapter", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Oneup\\FlysystemBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Schmid", + "email": "js@1up.io", + "homepage": "http://1up.io", + "role": "Developer" + } + ], + "description": "Integrates Flysystem filesystem abstraction library to your Symfony2 project.", + "homepage": "http://1up.io", + "keywords": [ + "Flysystem", + "Symfony2", + "abstraction", + "filesystem" + ], + "time": "2016-05-31 11:05:39" + }, { "name": "psr/log", "version": "1.0.0", @@ -648,12 +806,12 @@ "target-dir": "Symfony/Component/Icu", "source": { "type": "git", - "url": "https://github.com/symfony/Icu.git", + "url": "https://github.com/symfony/icu.git", "reference": "98e197da54df1f966dd5e8a4992135703569c987" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Icu/zipball/98e197da54df1f966dd5e8a4992135703569c987", + "url": "https://api.github.com/repos/symfony/icu/zipball/98e197da54df1f966dd5e8a4992135703569c987", "reference": "98e197da54df1f966dd5e8a4992135703569c987", "shasum": "" }, @@ -688,6 +846,7 @@ "icu", "intl" ], + "abandoned": "symfony/intl", "time": "2013-10-04 10:06:38" }, { @@ -787,15 +946,13 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "The Symfony PHP framework", @@ -810,12 +967,12 @@ "version": "v1.15.1", "source": { "type": "git", - "url": "https://github.com/fabpot/Twig.git", + "url": "https://github.com/twigphp/Twig.git", "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fabpot/Twig/zipball/1fb5784662f438d7d96a541e305e28b812e2eeed", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/1fb5784662f438d7d96a541e305e28b812e2eeed", "reference": "1fb5784662f438d7d96a541e305e28b812e2eeed", "shasum": "" }, @@ -1549,6 +1706,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, "platform": { "php": ">=5.3.3" }, diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..67a226b --- /dev/null +++ b/test.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +export TEST_FILESYSTEM="Gaufrette" +vendor/bin/phpunit + +export TEST_FILESYSTEM="Flysystem" +vendor/bin/phpunit \ No newline at end of file