diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 187aceb..25f1c6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,11 @@ jobs: - name: Run PHPCS working-directory: ${{ env.DRUPAL_ROOT }} run: | - vendor/bin/phpcs $MODULE_FOLDER --standard=Drupal --extensions=php,module,inc,install,test,info + vendor/bin/phpcs $MODULE_FOLDER --standard=Drupal,DrupalPractice --extensions=php,module,inc,install,test,info + + - name: Run phpstan + working-directory: ${{ env.DRUPAL_ROOT }} + run: vendor/bin/phpstan analyze -c $MODULE_FOLDER/phpstan.neon $MODULE_FOLDER - name: Start services working-directory: ${{ env.DRUPAL_ROOT }} diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..0c4c2ca --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,12 @@ +parameters: + fileExtensions: + - php + - module + - install + paths: + - ./ + excludePaths: + - vendor + level: 3 + checkMissingIterableValueType: false + treatPhpDocTypesAsCertain: false diff --git a/src/AzureBlobStorageAdapter.php b/src/AzureBlobStorageAdapter.php index 0b655dd..722c96a 100644 --- a/src/AzureBlobStorageAdapter.php +++ b/src/AzureBlobStorageAdapter.php @@ -1,15 +1,6 @@ client = $client; - $this->container = $container; + /** + * Constructs a new instance. + * + * @param \MicrosoftAzure\Storage\Blob\BlobRestProxy $client + * The client. + * @param string $container + * The container. + * @param string|null $prefix + * The prefix. + */ + public function __construct( + protected BlobRestProxy $client, + protected string $container, + ?string $prefix = NULL + ) { $this->setPathPrefix($prefix); } - public function write($path, $contents, Config $config) - { + /** + * {@inheritdoc} + */ + public function write($path, $contents, Config $config): array { return $this->upload($path, $contents, $config) + compact('contents'); } - public function writeStream($path, $resource, Config $config) - { + /** + * {@inheritdoc} + */ + public function writeStream($path, $resource, Config $config): array { return $this->upload($path, $resource, $config); } - protected function upload($path, $contents, Config $config) - { + /** + * Upload the given file. + * + * @param string $path + * The path. + * @param string|resource $contents + * The contents. + * @param \League\Flysystem\Config $config + * The config object. + * + * @return array + * The metadata. + */ + protected function upload(string $path, mixed $contents, Config $config): array { $destination = $this->applyPathPrefix($path); $options = $this->getOptionsFromConfig($config); @@ -82,10 +106,8 @@ protected function upload($path, $contents, Config $config) $options->setContentType(Util::guessMimeType($path, $contents)); } - /** - * We manually create the stream to prevent it from closing the resource - * in its destructor. - */ + // We manually create the stream to prevent it from closing the resource + // in its destructor. $stream = GuzzleUtil::streamFor($contents); $response = $this->client->createBlockBlob( $this->container, @@ -104,45 +126,58 @@ protected function upload($path, $contents, Config $config) ]; } - public function update($path, $contents, Config $config) - { + /** + * {@inheritdoc} + */ + public function update($path, $contents, Config $config): array { return $this->upload($path, $contents, $config) + compact('contents'); } - public function updateStream($path, $resource, Config $config) - { + /** + * {@inheritdoc} + */ + public function updateStream($path, $resource, Config $config): array { return $this->upload($path, $resource, $config); } - public function rename($path, $newpath) - { + /** + * {@inheritdoc} + */ + public function rename($path, $newpath): bool { return $this->copy($path, $newpath) && $this->delete($path); } - public function copy($path, $newpath) - { + /** + * {@inheritdoc} + */ + public function copy($path, $newpath): bool { $source = $this->applyPathPrefix($path); $destination = $this->applyPathPrefix($newpath); $this->client->copyBlob($this->container, $destination, $this->container, $source); - return true; + return TRUE; } - public function delete($path) - { + /** + * {@inheritdoc} + */ + public function delete($path): bool { try { $this->client->deleteBlob($this->container, $this->applyPathPrefix($path)); - } catch (ServiceException $exception) { + } + catch (ServiceException $exception) { if ($exception->getCode() !== 404) { throw $exception; } } - return true; + return TRUE; } - public function deleteDir($dirname) - { + /** + * {@inheritdoc} + */ + public function deleteDir($dirname): bool { $prefix = $this->applyPathPrefix($dirname); $options = new ListBlobsOptions(); $options->setPrefix($prefix . '/'); @@ -151,24 +186,30 @@ public function deleteDir($dirname) $this->client->deleteBlob($this->container, $blob->getName()); } - return true; + return TRUE; } - public function createDir($dirname, Config $config) - { + /** + * {@inheritdoc} + */ + public function createDir($dirname, Config $config): array { return ['path' => $dirname, 'type' => 'dir']; } - public function has($path) - { - return $this->getMetadata($path); + /** + * {@inheritdoc} + */ + public function has($path): bool { + return (bool) $this->getMetadata($path); } - public function read($path) - { + /** + * {@inheritdoc} + */ + public function read($path): array { $response = $this->readStream($path); - if ( ! isset($response['stream']) || ! is_resource($response['stream'])) { + if (!isset($response['stream']) || !is_resource($response['stream'])) { return $response; } @@ -178,8 +219,10 @@ public function read($path) return $response; } - public function readStream($path) - { + /** + * {@inheritdoc} + */ + public function readStream($path): array|bool { $location = $this->applyPathPrefix($path); try { @@ -192,17 +235,20 @@ public function readStream($path) $path, $response->getProperties() ) + ['stream' => $response->getContentStream()]; - } catch (ServiceException $exception) { + } + catch (ServiceException $exception) { if ($exception->getCode() !== 404) { throw $exception; } - return false; + return FALSE; } } - public function listContents($directory = '', $recursive = false) - { + /** + * {@inheritdoc} + */ + public function listContents($directory = '', $recursive = FALSE): array { $result = []; $location = $this->applyPathPrefix($directory); @@ -214,7 +260,7 @@ public function listContents($directory = '', $recursive = false) $options->setPrefix($location); $options->setMaxResults($this->maxResultsForContentsListing); - if ( ! $recursive) { + if (!$recursive) { $options->setDelimiter('/'); } @@ -229,7 +275,7 @@ public function listContents($directory = '', $recursive = false) } } - if ( ! $recursive) { + if (!$recursive) { $result = array_merge($result, array_map([$this, 'normalizeBlobPrefix'], $response->getBlobPrefixes())); } @@ -241,44 +287,70 @@ public function listContents($directory = '', $recursive = false) return Util::emulateDirectories($result); } - public function getMetadata($path) - { + /** + * {@inheritdoc} + */ + public function getMetadata($path): array|bool { $path = $this->applyPathPrefix($path); try { - return $this->normalizeBlobProperties( + $metadata = $this->normalizeBlobProperties( $path, $this->client->getBlobProperties($this->container, $path)->getProperties() ); - } catch (ServiceException $exception) { + + if ($metadata === FALSE && in_array($path, ['css', 'js'])) { + return [ + 'type' => 'dir', + 'path' => $path, + ]; + } + + return $metadata; + } + catch (ServiceException $exception) { if ($exception->getCode() !== 404) { throw $exception; } - return false; + return FALSE; } } - public function getSize($path) - { + /** + * {@inheritdoc} + */ + public function getSize($path): array|bool { return $this->getMetadata($path); } - public function getMimetype($path) - { + /** + * {@inheritdoc} + */ + public function getMimetype($path): array|bool { return $this->getMetadata($path); } - public function getTimestamp($path) - { + /** + * {@inheritdoc} + */ + public function getTimestamp($path): array|bool { return $this->getMetadata($path); } - protected function getOptionsFromConfig(Config $config) - { + /** + * Gets the blob options. + * + * @param \League\Flysystem\Config $config + * The config. + * + * @return mixed + * The options. + */ + protected function getOptionsFromConfig(Config $config) { $options = $config->get('blobOptions', new CreateBlockBlobOptions()); foreach (static::$metaOptions as $option) { - if ( ! $config->has($option)) { + if (!$config->has($option)) { continue; } call_user_func([$options, "set$option"], $config->get($option)); @@ -290,11 +362,21 @@ protected function getOptionsFromConfig(Config $config) return $options; } - protected function normalizeBlobProperties($path, BlobProperties $properties) - { + /** + * Normalizes the given blob properties. + * + * @param string $path + * The path. + * @param \MicrosoftAzure\Storage\Blob\Models\BlobProperties $properties + * The properties. + * + * @return array + * The normalized properties. + */ + protected function normalizeBlobProperties(string $path, BlobProperties $properties): array { $path = $this->removePathPrefix($path); - if (substr($path, -1) === '/') { + if (str_ends_with($path, '/')) { return ['type' => 'dir', 'path' => rtrim($path, '/')]; } @@ -309,15 +391,29 @@ protected function normalizeBlobProperties($path, BlobProperties $properties) } /** + * Sets the maximum number of results for content listing. + * * @param int $numberOfResults + * The number of results. */ - public function setMaxResultsForContentsListing($numberOfResults) - { + public function setMaxResultsForContentsListing(int $numberOfResults): void { $this->maxResultsForContentsListing = $numberOfResults; } - protected function normalizeBlobPrefix(BlobPrefix $blobPrefix) - { - return ['type' => 'dir', 'path' => $this->removePathPrefix(rtrim($blobPrefix->getName(), '/'))]; + /** + * Normalizes the given blob prefix. + * + * @param \MicrosoftAzure\Storage\Blob\Models\BlobPrefix $blobPrefix + * The prefix. + * + * @return array + * The normalized blob prefix. + */ + protected function normalizeBlobPrefix(BlobPrefix $blobPrefix): array { + return [ + 'type' => 'dir', + 'path' => $this->removePathPrefix(rtrim($blobPrefix->getName(), '/')), + ]; } + } diff --git a/src/Flysystem/Adapter/AzureBlobStorageAdapter.php b/src/Flysystem/Adapter/AzureBlobStorageAdapter.php index bacde2a..f307fc3 100644 --- a/src/Flysystem/Adapter/AzureBlobStorageAdapter.php +++ b/src/Flysystem/Adapter/AzureBlobStorageAdapter.php @@ -14,7 +14,7 @@ class AzureBlobStorageAdapter extends AzureBlobStorageAdapterBase { /** * {@inheritdoc} */ - public function getMetadata($path) { + public function getMetadata($path): bool|array { $metadata = parent::getMetadata($path); if ($metadata === FALSE && in_array($path, ['css', 'js'])) {