Skip to content

Commit

Permalink
Merge pull request #87 from lruozzi9/upgrade-league-flysystem
Browse files Browse the repository at this point in the history
Add support for league/flysystem 2
  • Loading branch information
loevgaard authored May 23, 2023
2 parents 14eebc0 + 6f31517 commit 68f93e1
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 72 deletions.
5 changes: 4 additions & 1 deletion composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
"Sylius\\Component\\Inventory\\Model\\StockableInterface",
"Sylius\\Component\\Locale\\Context\\LocaleContextInterface",
"Sylius\\Component\\Locale\\Model\\LocaleInterface",
"Sylius\\Component\\Product\\Resolver\\ProductVariantResolverInterface"
"Sylius\\Component\\Product\\Resolver\\ProductVariantResolverInterface",
"League\\Flysystem\\FileNotFoundException",
"League\\Flysystem\\FilesystemInterface",
"League\\Flysystem\\RootViolationException"
]
}
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"doctrine/orm": "^2.7",
"doctrine/persistence": "^1.3 || ^2.0",
"knplabs/knp-menu": "^3.1",
"league/flysystem": "^1.1",
"league/flysystem-bundle": "^1.1",
"league/flysystem": "^1.1 || ^2.1",
"league/flysystem-bundle": "^1.1 || ^2.4",
"liip/imagine-bundle": "^2.4",
"psr/event-dispatcher": "^1.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
Expand Down
42 changes: 36 additions & 6 deletions src/Controller/Action/Shop/ShowFeedAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Setono\SyliusFeedPlugin\Controller\Action\Shop;

use InvalidArgumentException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\FilesystemOperator;
use RuntimeException;
use Setono\SyliusFeedPlugin\Generator\FeedPathGeneratorInterface;
use Setono\SyliusFeedPlugin\Repository\FeedRepositoryInterface;
Expand All @@ -14,6 +16,10 @@
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Mime\MimeTypesInterface;

/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedClass
*/
final class ShowFeedAction
{
private FeedRepositoryInterface $repository;
Expand All @@ -24,23 +30,39 @@ final class ShowFeedAction

private FeedPathGeneratorInterface $feedPathGenerator;

private FilesystemInterface $filesystem;
/** @var FilesystemInterface|FilesystemOperator */
private $filesystem;

private MimeTypesInterface $mimeTypes;

/**
* @psalm-suppress UndefinedDocblockClass
*
* @param FilesystemInterface|FilesystemOperator $filesystem
*/
public function __construct(
FeedRepositoryInterface $repository,
ChannelContextInterface $channelContext,
LocaleContextInterface $localeContext,
FeedPathGeneratorInterface $feedPathGenerator,
FilesystemInterface $filesystem,
$filesystem,
MimeTypesInterface $mimeTypes
) {
$this->repository = $repository;
$this->channelContext = $channelContext;
$this->localeContext = $localeContext;
$this->feedPathGenerator = $feedPathGenerator;
$this->filesystem = $filesystem;
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
$this->filesystem = $filesystem;
} elseif ($filesystem instanceof FilesystemOperator) {
$this->filesystem = $filesystem;
} else {
throw new InvalidArgumentException(sprintf(
'The filesystem must be an instance of %s or %s',
FilesystemInterface::class,
FilesystemOperator::class
));
}
$this->mimeTypes = $mimeTypes;
}

Expand All @@ -56,11 +78,19 @@ public function __invoke(string $code): StreamedResponse

$feedPath = $this->feedPathGenerator->generate($feed, $channelCode, $localeCode);

if (!$this->filesystem->has((string) $feedPath)) {
throw new NotFoundHttpException(sprintf('The feed with id %s has not been generated', $code));
$filesystem = $this->filesystem;
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
if (!$filesystem->has((string) $feedPath)) {
throw new NotFoundHttpException(sprintf('The feed with id %s has not been generated', $code));
}
} else {
if (!$filesystem->fileExists((string) $feedPath)) {
throw new NotFoundHttpException(sprintf('The feed with id %s has not been generated', $code));
}
}

$stream = $this->filesystem->readStream((string) $feedPath);
/** @var resource|false $stream */
$stream = $filesystem->readStream((string) $feedPath);
if (false === $stream) {
throw new RuntimeException(sprintf('An error occurred trying to read the feed file %s', $feedPath));
}
Expand Down
32 changes: 24 additions & 8 deletions src/DependencyInjection/Compiler/RegisterFilesystemPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use InvalidArgumentException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\FilesystemOperator;
use RuntimeException;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -38,14 +40,28 @@ public function process(ContainerBuilder $container): void
$definitionClass = $container->getDefinition($parameterValue)->getClass();
Assert::notNull($definitionClass);

if (!is_a($definitionClass, FilesystemInterface::class, true)) {
throw new InvalidDefinitionException(sprintf(
'The config parameter "%s" references a service %s, which is not an instance of %s. Fix this by creating a valid service that implements %s.',
$parameter,
$definitionClass,
FilesystemInterface::class,
FilesystemInterface::class
));
if (interface_exists(FilesystemInterface::class)) {
if (!is_a($definitionClass, FilesystemInterface::class, true)) {
throw new InvalidDefinitionException(sprintf(
'The config parameter "%s" references a service %s, which is not an instance of %s. Fix this by creating a valid service that implements %s.',
$parameter,
$definitionClass,
FilesystemInterface::class,
FilesystemInterface::class,
));
}
} elseif (interface_exists(FilesystemOperator::class)) {
if (!is_a($definitionClass, FilesystemOperator::class, true)) {
throw new InvalidDefinitionException(sprintf(
'The config parameter "%s" references a service %s, which is not an instance of %s. Fix this by creating a valid service that implements %s.',
$parameter,
$definitionClass,
FilesystemOperator::class,
FilesystemOperator::class,
));
}
} else {
throw new RuntimeException('It looks like both of league/flysystem v1 and v2 are not installed!');
}

$container->setAlias($parameter, $parameterValue);
Expand Down
38 changes: 33 additions & 5 deletions src/EventListener/DeleteGeneratedFilesSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,44 @@

namespace Setono\SyliusFeedPlugin\EventListener;

use InvalidArgumentException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\RootViolationException;
use League\Flysystem\UnableToDeleteDirectory;
use Setono\SyliusFeedPlugin\Model\FeedInterface;
use Setono\SyliusFeedPlugin\Workflow\FeedGraph;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\TransitionEvent;
use Webmozart\Assert\Assert;

/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedClass
*/
final class DeleteGeneratedFilesSubscriber implements EventSubscriberInterface
{
private FilesystemInterface $filesystem;
/** @var FilesystemInterface|FilesystemOperator */
private $filesystem;

public function __construct(FilesystemInterface $filesystem)
/**
* @psalm-suppress UndefinedDocblockClass
*
* @param FilesystemInterface|FilesystemOperator $filesystem
*/
public function __construct($filesystem)
{
$this->filesystem = $filesystem;
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
$this->filesystem = $filesystem;
} elseif ($filesystem instanceof FilesystemOperator) {
$this->filesystem = $filesystem;
} else {
throw new InvalidArgumentException(sprintf(
'The filesystem must be an instance of %s or %s',
FilesystemInterface::class,
FilesystemOperator::class
));
}
}

public static function getSubscribedEvents(): array
Expand All @@ -38,8 +61,13 @@ public function delete(TransitionEvent $event): void
Assert::isInstanceOf($feed, FeedInterface::class);

try {
$this->filesystem->deleteDir($feed->getCode());
} catch (RootViolationException $e) {
$filesystem = $this->filesystem;
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
$filesystem->deleteDir($feed->getCode());
} else {
$filesystem->deleteDirectory($feed->getCode());
}
} catch (RootViolationException|UnableToDeleteDirectory $e) {
}
}
}
76 changes: 62 additions & 14 deletions src/EventListener/MoveGeneratedFeedSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

namespace Setono\SyliusFeedPlugin\EventListener;

use InvalidArgumentException;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\UnableToDeleteFile;
use RuntimeException;
use Setono\SyliusFeedPlugin\Generator\FeedPathGeneratorInterface;
use Setono\SyliusFeedPlugin\Generator\TemporaryFeedPathGenerator;
Expand All @@ -15,24 +18,56 @@
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\TransitionEvent;

/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedClass
*/
final class MoveGeneratedFeedSubscriber implements EventSubscriberInterface
{
private FilesystemInterface $temporaryFilesystem;
/** @var FilesystemInterface|FilesystemOperator */
private $temporaryFilesystem;

private FilesystemInterface $filesystem;
/** @var FilesystemInterface|FilesystemOperator */
private $filesystem;

private FeedPathGeneratorInterface $temporaryFeedPathGenerator;

private FeedPathGeneratorInterface $feedPathGenerator;

/**
* @psalm-suppress UndefinedDocblockClass
*
* @param FilesystemInterface|FilesystemOperator $temporaryFilesystem
* @param FilesystemInterface|FilesystemOperator $filesystem
*/
public function __construct(
FilesystemInterface $temporaryFilesystem,
FilesystemInterface $filesystem,
$temporaryFilesystem,
$filesystem,
FeedPathGeneratorInterface $temporaryFeedPathGenerator,
FeedPathGeneratorInterface $feedPathGenerator
) {
$this->temporaryFilesystem = $temporaryFilesystem;
$this->filesystem = $filesystem;
if (interface_exists(FilesystemInterface::class) && $temporaryFilesystem instanceof FilesystemInterface) {
$this->temporaryFilesystem = $temporaryFilesystem;
} elseif ($temporaryFilesystem instanceof FilesystemOperator) {
$this->temporaryFilesystem = $temporaryFilesystem;
} else {
throw new InvalidArgumentException(sprintf(
'The filesystem must be an instance of %s or %s',
FilesystemInterface::class,
FilesystemOperator::class
));
}
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
$this->filesystem = $filesystem;
} elseif ($filesystem instanceof FilesystemOperator) {
$this->filesystem = $filesystem;
} else {
throw new InvalidArgumentException(sprintf(
'The filesystem must be an instance of %s or %s',
FilesystemInterface::class,
FilesystemOperator::class
));
}
$this->temporaryFeedPathGenerator = $temporaryFeedPathGenerator;
$this->feedPathGenerator = $feedPathGenerator;
}
Expand Down Expand Up @@ -62,8 +97,10 @@ public function move(TransitionEvent $event): void
(string) $channel->getCode(),
(string) $locale->getCode()
);
$temporaryFilesystem = $this->temporaryFilesystem;
$temporaryPath = TemporaryFeedPathGenerator::getBaseFile($temporaryDir);
$tempFile = $this->temporaryFilesystem->readStream((string) $temporaryPath);
/** @var resource|false $tempFile */
$tempFile = $temporaryFilesystem->readStream((string) $temporaryPath);
if (false === $tempFile) {
throw new \RuntimeException(sprintf(
'The file with path "%s" could not be found',
Expand All @@ -78,20 +115,31 @@ public function move(TransitionEvent $event): void
(string) $locale->getCode()
);
$path = sprintf('%s/%s', $newPath->getPath(), uniqid('feed-', true));
$res = $this->filesystem->writeStream($path, $tempFile);
$filesystem = $this->filesystem;

if (false === $res) {
throw new RuntimeException('An error occurred when trying to write the feed to the filesystem');
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
/** @var resource|false $res */
$res = $filesystem->writeStream($path, $tempFile);

if (false === $res) {
throw new RuntimeException('An error occurred when trying to write the feed to the filesystem');
}
} else {
$filesystem->writeStream($path, $tempFile);
}

try {
$this->filesystem->delete((string) $newPath);
} catch (FileNotFoundException $e) {
$filesystem->delete((string) $newPath);
} catch (FileNotFoundException|UnableToDeleteFile $e) {
}

$this->filesystem->rename($path, (string) $newPath);
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
$filesystem->rename($path, (string) $newPath);
} else {
$filesystem->move($path, (string) $newPath);
}

$this->temporaryFilesystem->delete((string) $temporaryPath);
$temporaryFilesystem->delete((string) $temporaryPath);
}
}
}
Expand Down
31 changes: 27 additions & 4 deletions src/Generator/TemporaryFeedPathGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@

namespace Setono\SyliusFeedPlugin\Generator;

use InvalidArgumentException;
use League\Flysystem\FilesystemInterface;
use League\Flysystem\FilesystemOperator;
use Setono\SyliusFeedPlugin\Model\FeedInterface;
use SplFileInfo;
use Webmozart\Assert\Assert;

/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress UndefinedClass
*/
final class TemporaryFeedPathGenerator implements FeedPathGeneratorInterface
{
public const BASE_FILENAME = '_feed';
Expand All @@ -29,11 +35,28 @@ public static function getBaseFile(SplFileInfo $dir): SplFileInfo
return new SplFileInfo($dir->getPathname() . '/' . self::BASE_FILENAME);
}

public static function getPartialFile(SplFileInfo $dir, FilesystemInterface $filesystem): SplFileInfo
/**
* @psalm-suppress UndefinedDocblockClass
*
* @param FilesystemInterface|FilesystemOperator $filesystem
*/
public static function getPartialFile(SplFileInfo $dir, $filesystem): SplFileInfo
{
do {
$path = $dir->getPathname() . '/' . uniqid('partial-', true);
} while ($filesystem->has($path));
if (interface_exists(FilesystemInterface::class) && $filesystem instanceof FilesystemInterface) {
do {
$path = $dir->getPathname() . '/' . uniqid('partial-', true);
} while ($filesystem->has($path));
} elseif ($filesystem instanceof FilesystemOperator) {
do {
$path = $dir->getPathname() . '/' . uniqid('partial-', true);
} while ($filesystem->fileExists($path));
} else {
throw new InvalidArgumentException(sprintf(
'The filesystem must be an instance of %s or %s',
FilesystemInterface::class,
FilesystemOperator::class
));
}

return new SplFileInfo($path);
}
Expand Down
Loading

0 comments on commit 68f93e1

Please sign in to comment.