/**
  * @test
  */
 public function setFilenameDoesNotAppendFileExtensionIfItIsEmpty()
 {
     $resource = new Resource();
     $resource->setFilename('FileWithoutExtension');
     $this->assertSame('', $resource->getFileExtension());
     $this->assertSame('FileWithoutExtension', $resource->getFilename());
 }
 /**
  * @param FlowResource $originalResource
  * @param array $adjustments
  * @return array resource, width, height as keys
  * @throws ImageFileException
  * @throws InvalidConfigurationException
  * @throws \TYPO3\Flow\Resource\Exception
  */
 public function processImage(FlowResource $originalResource, array $adjustments)
 {
     $additionalOptions = array();
     $adjustmentsApplied = false;
     // TODO: Special handling for SVG should be refactored at a later point.
     if ($originalResource->getMediaType() === 'image/svg+xml') {
         $originalResourceStream = $originalResource->getStream();
         $resource = $this->resourceManager->importResource($originalResourceStream, $originalResource->getCollectionName());
         fclose($originalResourceStream);
         $resource->setFilename($originalResource->getFilename());
         return ['width' => null, 'height' => null, 'resource' => $resource];
     }
     $resourceUri = $originalResource->createTemporaryLocalCopy();
     $resultingFileExtension = $originalResource->getFileExtension();
     $transformedImageTemporaryPathAndFilename = $this->environment->getPathToTemporaryDirectory() . uniqid('ProcessedImage-') . '.' . $resultingFileExtension;
     if (!file_exists($resourceUri)) {
         throw new ImageFileException(sprintf('An error occurred while transforming an image: the resource data of the original image does not exist (%s, %s).', $originalResource->getSha1(), $resourceUri), 1374848224);
     }
     $imagineImage = $this->imagineService->open($resourceUri);
     if ($this->imagineService instanceof \Imagine\Imagick\Imagine && $originalResource->getFileExtension() === 'gif' && $this->isAnimatedGif(file_get_contents($resourceUri)) === true) {
         $imagineImage->layers()->coalesce();
         $layers = $imagineImage->layers();
         $newLayers = array();
         foreach ($layers as $index => $imagineFrame) {
             $imagineFrame = $this->applyAdjustments($imagineFrame, $adjustments, $adjustmentsApplied);
             $newLayers[] = $imagineFrame;
         }
         $imagineImage = array_shift($newLayers);
         $layers = $imagineImage->layers();
         foreach ($newLayers as $imagineFrame) {
             $layers->add($imagineFrame);
         }
         $additionalOptions['animated'] = true;
     } else {
         $imagineImage = $this->applyAdjustments($imagineImage, $adjustments, $adjustmentsApplied);
     }
     if ($adjustmentsApplied === true) {
         $imagineImage->save($transformedImageTemporaryPathAndFilename, $this->getOptionsMergedWithDefaults($additionalOptions));
         $imageSize = $imagineImage->getSize();
         // TODO: In the future the collectionName of the new resource should be configurable.
         $resource = $this->resourceManager->importResource($transformedImageTemporaryPathAndFilename, $originalResource->getCollectionName());
         if ($resource === false) {
             throw new ImageFileException('An error occurred while importing a generated image file as a resource.', 1413562208);
         }
         unlink($transformedImageTemporaryPathAndFilename);
         $pathInfo = UnicodeFunctions::pathinfo($originalResource->getFilename());
         $resource->setFilename(sprintf('%s-%ux%u.%s', $pathInfo['filename'], $imageSize->getWidth(), $imageSize->getHeight(), $pathInfo['extension']));
     } else {
         $originalResourceStream = $originalResource->getStream();
         $resource = $this->resourceManager->importResource($originalResourceStream, $originalResource->getCollectionName());
         fclose($originalResourceStream);
         $resource->setFilename($originalResource->getFilename());
         $imageSize = $this->getImageSize($originalResource);
         $imageSize = new Box($imageSize['width'], $imageSize['height']);
     }
     $this->imageSizeCache->set($resource->getCacheEntryIdentifier(), array('width' => $imageSize->getWidth(), 'height' => $imageSize->getHeight()));
     $result = array('width' => $imageSize->getWidth(), 'height' => $imageSize->getHeight(), 'resource' => $resource);
     return $result;
 }
 /**
  * Map the given resource to a media model class.
  *
  * @param Resource $resource
  * @param array $additionalProperties Optional properties that can be taken into account for deciding the model class. what you get here can depend on the caller, so you should always fallback to something based on the resource.
  * @return string
  */
 public function map(Resource $resource, array $additionalProperties = array())
 {
     $mediaType = MediaTypes::getMediaTypeFromFilename($resource->getFilename());
     foreach ($this->settings['patterns'] as $pattern => $mappingInformation) {
         if (preg_match($pattern, $mediaType)) {
             return $mappingInformation['className'];
         }
     }
     return $this->settings['default'];
 }
 /**
  * Publishes the given persistent resource from the given storage
  *
  * @param \TYPO3\Flow\Resource\Resource $resource The resource to publish
  * @param CollectionInterface $collection The collection the given resource belongs to
  * @return void
  * @throws Exception
  */
 public function publishResource(Resource $resource, CollectionInterface $collection)
 {
     $sourceStream = $resource->getStream();
     if ($sourceStream === FALSE) {
         throw new Exception(sprintf('Could not publish resource %s with SHA1 hash %s of collection %s because there seems to be no corresponding data in the storage.', $resource->getFilename(), $resource->getSha1(), $collection->getName()), 1375258146);
     }
     $this->publishFile($sourceStream, $this->getRelativePublicationPathAndFilename($resource));
     fclose($sourceStream);
 }
 /**
  * Returns the web URI to be used to publish the specified persistent resource
  *
  * @param \TYPO3\Flow\Resource\Resource $resource The resource to build the URI for
  * @return string The web URI
  */
 protected function buildPersistentResourceWebUri(\TYPO3\Flow\Resource\Resource $resource)
 {
     $filename = $resource->getFilename();
     $rewrittenFilename = $filename === '' || $filename === NULL ? '' : '/' . $this->rewriteFilenameForUri($filename);
     return $this->getResourcesBaseUri() . 'Persistent/' . $resource->getResourcePointer()->getHash() . $rewrittenFilename;
 }
 /**
  * Deletes the given Resource from the Resource Repository and, if the storage data is no longer used in another
  * Resource object, also deletes the data from the storage.
  *
  * This method will also remove the Resource object from the (internal) ResourceRepository.
  *
  * @param Resource $resource The resource to delete
  * @param boolean $unpublishResource If the resource should be unpublished before deleting it from the storage
  * @return boolean TRUE if the resource was deleted, otherwise FALSE
  * @api
  */
 public function deleteResource(Resource $resource, $unpublishResource = TRUE)
 {
     $collectionName = $resource->getCollectionName();
     $result = $this->resourceRepository->findBySha1($resource->getSha1());
     if (count($result) > 1) {
         $this->systemLogger->log(sprintf('Not removing storage data of resource %s (%s) because it is still in use by %s other Resource object(s).', $resource->getFilename(), $resource->getSha1(), count($result) - 1), LOG_DEBUG);
     } else {
         if (!isset($this->collections[$collectionName])) {
             $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s) because it refers to the unknown collection "%s".', $resource->getFilename(), $resource->getSha1(), $collectionName), LOG_WARNING);
             return FALSE;
         }
         $storage = $this->collections[$collectionName]->getStorage();
         if (!$storage instanceof WritableStorageInterface) {
             $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s) because it its collection "%s" is read-only.', $resource->getFilename(), $resource->getSha1(), $collectionName), LOG_WARNING);
             return FALSE;
         }
         try {
             $storage->deleteResource($resource);
         } catch (\Exception $exception) {
             $this->systemLogger->log(sprintf('Could not remove storage data of resource %s (%s): %s.', $resource->getFilename(), $resource->getSha1(), $exception->getMessage()), LOG_WARNING);
             return FALSE;
         }
         if ($unpublishResource) {
             /** @var TargetInterface $target */
             $target = $this->collections[$collectionName]->getTarget();
             $target->unpublishResource($resource);
             $this->systemLogger->log(sprintf('Removed storage data and unpublished resource %s (%s) because it not used by any other Resource object.', $resource->getFilename(), $resource->getSha1()), LOG_DEBUG);
         } else {
             $this->systemLogger->log(sprintf('Removed storage data of resource %s (%s) because it not used by any other Resource object.', $resource->getFilename(), $resource->getSha1()), LOG_DEBUG);
         }
     }
     $resource->setDeleted();
     $this->resourceRepository->remove($resource);
     return TRUE;
 }
 /**
  * {@inheritDoc}
  */
 public function getFilename()
 {
     $this->__initializer__ && $this->__initializer__->__invoke($this, 'getFilename', array());
     return parent::getFilename();
 }
 /**
  * Finds other resources which are referring to the same resource data and filename
  *
  * @param Resource $resource The resource used for finding similar resources
  * @return QueryResultInterface The result, including the given resource
  */
 public function findSimilarResources(Resource $resource)
 {
     $query = $this->createQuery();
     $query->matching($query->logicalAnd($query->equals('sha1', $resource->getSha1()), $query->equals('filename', $resource->getFilename())));
     return $query->execute();
 }
Example #9
0
 /**
  * Returns a stream handle which can be used internally to open / copy the given resource
  * stored in this storage.
  *
  * @param \TYPO3\Flow\Resource\Resource $resource The resource stored in this storage
  * @return resource | boolean A URI (for example the full path and filename) leading to the resource file or FALSE if it does not exist
  * @api
  */
 public function getStreamByResource(Resource $resource)
 {
     try {
         return fopen('s3://' . $this->bucketName . '/' . $this->keyPrefix . $resource->getSha1(), 'r');
     } catch (\Exception $e) {
         if (strpos($e->getMessage(), '<Code>NoSuchKey</Code>') !== false) {
             return false;
         }
         $message = sprintf('Could not retrieve stream for resource %s (s3://%s/%s%s). %s', $resource->getFilename(), $this->bucketName, $this->keyPrefix, $resource->getSha1(), $e->getMessage());
         $this->systemLogger->log($message, \LOG_ERR);
         throw new Exception($message, 1445682605);
     }
 }