diff --git a/Classes/Command/GcsCommandController.php b/Classes/Command/GcsCommandController.php index de0a37d..21f5191 100644 --- a/Classes/Command/GcsCommandController.php +++ b/Classes/Command/GcsCommandController.php @@ -194,7 +194,7 @@ public function updateResourceMetadataCommand(string $collection = 'persistent', try { $previousSha1 = null; - while ($resourceRecord = $queryResult->fetch(\PDO::FETCH_ASSOC)) { + while ($resourceRecord = $queryResult->fetchAssociative()) { if ($resourceRecord['sha1'] === $previousSha1) { continue; } diff --git a/Classes/GcsStorage.php b/Classes/GcsStorage.php index 2eae615..fd65b69 100644 --- a/Classes/GcsStorage.php +++ b/Classes/GcsStorage.php @@ -372,14 +372,14 @@ public function getStreamByResourcePath($relativePath) * @return StorageObject[] * @api */ - public function getObjects() + public function getObjects(): array { $objects = []; foreach ($this->resourceManager->getCollectionsByStorage($this) as $collection) { $objects[] = $this->getObjectsByCollection($collection); } - return array_merge([], ...$objects); // the empty array covers cases when no loops were made + return array_merge([], ...$objects); // the empty array covers cases when no loops were made for PHP < 7.4 } /** diff --git a/Classes/GcsTarget.php b/Classes/GcsTarget.php index 0b06856..3f4f381 100644 --- a/Classes/GcsTarget.php +++ b/Classes/GcsTarget.php @@ -21,6 +21,7 @@ use Google\Cloud\Storage\StorageObject; use GuzzleHttp\Psr7\Uri; use Neos\Error\Messages\Error; +use Neos\Error\Messages\Message; use Neos\Flow\Annotations as Flow; use Neos\Flow\Log\Utility\LogEnvironment; use Neos\Flow\ObjectManagement\ObjectManagerInterface; @@ -180,7 +181,7 @@ class GcsTarget implements TargetInterface * @param array $options Options for this target * @throws Exception */ - public function __construct($name, array $options = []) + public function __construct(string $name, array $options = []) { $this->name = $name; foreach ($options as $key => $value) { @@ -207,7 +208,7 @@ public function __construct($name, array $options = []) $this->persistentResourceUriSignatureLifetime = (int)$uriOptionValue; break; default: - if ($value !== null) { + if ($uriOptionValue !== null) { throw new Exception(sprintf('An unknown option "%s" was specified in the configuration of the "%s" resource GcsTarget. Please check your settings.', $uriOptionKey, $name), 1568876031); } } @@ -407,7 +408,7 @@ private function publishCollectionFromDifferentGoogleCloudStorage(CollectionInte $storageBucket->object($storage->getKeyPrefix() . $object->getSha1())->copy($targetBucket, $options); } catch (GoogleException $e) { - $googleError = json_decode($e->getMessage()); + $googleError = json_decode($e->getMessage(), false); if ($googleError instanceof \stdClass && isset($googleError->error->message)) { $this->messageCollector->append(sprintf('Could not copy resource with SHA1 hash %s of collection %s from bucket %s to %s: %s', $object->getSha1(), $collection->getName(), $storageBucketName, $this->bucketName, $googleError->error->message)); } else { @@ -487,11 +488,11 @@ public function publishResource(PersistentResource $resource, CollectionInterfac 'cacheControl' => 'public, max-age=1209600', ]); } catch (GoogleException $e) { - $googleError = json_decode($e->getMessage()); + $googleError = json_decode($e->getMessage(), false); if ($googleError instanceof \stdClass && isset($googleError->error->message)) { - $this->messageCollector->append(sprintf('Could not copy resource with SHA1 hash %s of collection %s from bucket %s to %s: %s', $resource->getSha1(), $collection->getName(), $storage->getBucketName(), $this->bucketName, $googleError->error->message), Error::SEVERITY_ERROR, 1446721791); + $this->messageCollector->append(sprintf('Could not copy resource with SHA1 hash %s of collection %s from bucket %s to %s: %s', $resource->getSha1(), $collection->getName(), $storage->getBucketName(), $this->bucketName, $googleError->error->message), Message::SEVERITY_ERROR, 1446721791); } else { - $this->messageCollector->append(sprintf('Could not copy resource with SHA1 hash %s of collection %s from bucket %s to %s: %s', $resource->getSha1(), $collection->getName(), $storage->getBucketName(), $this->bucketName, $e->getMessage()), Error::SEVERITY_ERROR, 1446721791); + $this->messageCollector->append(sprintf('Could not copy resource with SHA1 hash %s of collection %s from bucket %s to %s: %s', $resource->getSha1(), $collection->getName(), $storage->getBucketName(), $this->bucketName, $e->getMessage()), Message::SEVERITY_ERROR, 1446721791); } return; } @@ -500,7 +501,7 @@ public function publishResource(PersistentResource $resource, CollectionInterfac } else { $sourceStream = $resource->getStream(); if ($sourceStream === false) { - $this->messageCollector->append(sprintf('Could not publish resource with SHA1 hash %s of collection %s because there seems to be no corresponding data in the storage.', $resource->getSha1(), $collection->getName()), Error::SEVERITY_ERROR, 1446721810); + $this->messageCollector->append(sprintf('Could not publish resource with SHA1 hash %s of collection %s because there seems to be no corresponding data in the storage.', $resource->getSha1(), $collection->getName()), Message::SEVERITY_ERROR, 1446721810); return; } $this->publishFile($sourceStream, $this->getRelativePublicationPathAndFilename($resource), $resource); @@ -609,14 +610,14 @@ protected function publishFile($sourceStream, string $relativeTargetPathAndFilen $this->logger->debug(sprintf('Converted resource data of object "%s" in bucket "%s" with SHA1 hash "%s" to GZIP with level %s.', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown', $this->gzipCompressionLevel), LogEnvironment::fromMethodName(__METHOD__)); } catch (\Exception $e) { - $this->messageCollector->append(sprintf('Failed publishing resource as object "%s" in bucket "%s" with SHA1 hash "%s": %s', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown', $e->getMessage()), Error::SEVERITY_WARNING, 1520257344878); + $this->messageCollector->append(sprintf('Failed publishing resource as object "%s" in bucket "%s" with SHA1 hash "%s": %s', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown', $e->getMessage()), Message::SEVERITY_WARNING, 1520257344878); } } try { $this->getCurrentBucket()->upload($sourceStream, $uploadParameters); $this->logger->debug(sprintf('Successfully published resource as object "%s" in bucket "%s" with SHA1 hash "%s"', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown'), LogEnvironment::fromMethodName(__METHOD__)); } catch (\Exception $e) { - $this->messageCollector->append(sprintf('Failed publishing resource as object "%s" in bucket "%s" with SHA1 hash "%s": %s', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown', $e->getMessage()), Error::SEVERITY_WARNING, 1506847965352); + $this->messageCollector->append(sprintf('Failed publishing resource as object "%s" in bucket "%s" with SHA1 hash "%s": %s', $objectName, $this->bucketName, $metaData->getSha1() ?: 'unknown', $e->getMessage()), Message::SEVERITY_WARNING, 1506847965352); } finally { if (is_resource($sourceStream)) { fclose($sourceStream); diff --git a/README.md b/README.md index 3239004..d30a35f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Packagist](https://img.shields.io/packagist/dm/flownative/google-cloudstorage)](https://packagist.org/packages/flownative/google-cloudstorage) [![Maintenance level: Love](https://img.shields.io/badge/maintenance-%E2%99%A1%E2%99%A1%E2%99%A1-ff69b4.svg)](https://www.flownative.com/en/products/open-source.html) -# Google Cloud Storage Adaptor for Neos >= 4.2 / 5.x / 7.x and Flow >=5.2 / 6.x / 7.x +# Google Cloud Storage Adaptor for Neos and Flow This [Flow](https://flow.neos.io) package allows you to store assets (resources) in [Google Cloud Storage](https://cloud.google.com/storage/) and publish resources to GCS. Because [Neos CMS](https://www.neos.io) is using Flow's resource management under the hood, @@ -20,8 +20,8 @@ Using this connector, you can run a Neos website which does not store any asset ## Installation -The Flownative Google Cloud Storage connector is installed as a regular Flow package via Composer. For your existing -project, simply include `flownative/google-cloudstorage` into the dependencies of your Flow or Neos distribution: +The Flownative Google Cloud Storage connector is installed as a regular Flow package via Composer. Simply +include `flownative/google-cloudstorage` into the dependencies of your Flow or Neos distribution: ```bash $ composer require flownative/google-cloudstorage @@ -33,7 +33,7 @@ In order to communicate with the Google API, you need to provide the credentials to GCS (see next section for instructions for setting up the service user). Add the following configuration to the `Settings.yaml` for your desired Flow context (for example in `Configuration/Production/Settings.yaml`) and make sure to replace the private key with your own data: - + ```yaml Flownative: Google: @@ -188,7 +188,7 @@ On the backside, the URLs are kind of ugly, because they only consist of a domai ``` https://storage.googleapis.com/bucket.example.com/a865defc2a48f060f15c3f4f21f2f1e78f154789 -``` +``` ### Two Buckets @@ -235,7 +235,7 @@ The possible placeholders are: - `{fileExtension}` The resource's file extension, for example "svg" For legacy and convenience reasons, the default pattern depends on the setup being used: - + - no pattern and no baseUri set: `https://storage.googleapis.com/{bucketName}/{keyPrefix}{sha1}` - no pattern set: `{baseUri}/{keyPrefix}{sha1}/{filename}` @@ -278,6 +278,7 @@ class CloudStorageDemo { ``` The following options are passed to your render method: + - targetClass - bucketName - keyPrefix @@ -295,7 +296,7 @@ to generate a special signed link, which allows access to a given resource for a The Google Cloud Storage Target can take care of signing links to persistent resources. Just enable signing and specify a signature lifetime (in seconds) like in the following example. Be aware though, that anyone with such a -generated link can download the given protected resource wile the link is valid. +generated link can download the given protected resource wile the link is valid. ```yaml targets: