Skip to content

Commit

Permalink
use flysystem for storage (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
solverat authored Jan 20, 2023
1 parent 484c32d commit 07ba2c3
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 293 deletions.
4 changes: 4 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Upgrade Notes

## Version 4.3.0
- **[ENHANCEMENT]**: Use Flysystem for Storage [#334](https://github.com/dachcom-digital/pimcore-formbuilder/issues/334)
- Remove `PIMCORE_SYSTEM_TEMP_DIRECTORY/formbuilder-cache` as it is no longer needed

## Version 4.2.3
- **[BUGFIX]**: Fix field collection mapping [#370](https://github.com/dachcom-digital/pimcore-formbuilder/issues/370)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,61 @@

class OutputWorkflowSignalsEvent extends Event
{
protected string $channel;
protected array $signals;
protected ?\Throwable $exception;
protected array $context;

public function __construct(array $signals, ?\Throwable $exception)
public function __construct(string $channel, array $signals, array $context)
{
$this->channel = $channel;
$this->signals = $signals;
$this->exception = $exception;
$this->context = $context;
}

public function getChannel(): string
{
return $this->channel;
}

public function hasContextItem(string $contextItem): bool
{
return array_key_exists($contextItem, $this->context);
}

public function getContextItem(string $contextItem): mixed
{
if (!$this->hasContextItem($contextItem)) {
return null;
}

return $this->context[$contextItem];
}

public function hasException(): bool
{
return $this->exception instanceof \Throwable;
return $this->hasContextItem('exception') && $this->getContextItem('exception') instanceof \Throwable;
}

public function hasGuardException(): bool
{
return $this->exception instanceof OutputWorkflow\GuardChannelException ||
$this->exception instanceof OutputWorkflow\GuardOutputWorkflowException ||
$this->exception instanceof OutputWorkflow\GuardStackedException;
if (!$this->hasException()) {
return false;
}

$exception = $this->getContextItem('exception');

return $exception instanceof OutputWorkflow\GuardChannelException ||
$exception instanceof OutputWorkflow\GuardOutputWorkflowException ||
$exception instanceof OutputWorkflow\GuardStackedException;
}

public function getException(): ?\Throwable
{
return $this->exception;
if (!$this->hasException()) {
return null;
}

return $this->getContextItem('exception');
}

/**
Expand Down
41 changes: 26 additions & 15 deletions src/FormBuilderBundle/EventListener/Core/CleanUpListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,45 @@

namespace FormBuilderBundle\EventListener\Core;

use FormBuilderBundle\Tool\FileLocator;
use Carbon\Carbon;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\StorageAttributes;
use Pimcore\Logger;
use Pimcore\Maintenance\TaskInterface;

class CleanUpListener implements TaskInterface
{
protected FileLocator $fileLocator;

public function __construct(FileLocator $fileLocator)
{
$this->fileLocator = $fileLocator;
public function __construct(
protected FilesystemOperator $formBuilderChunkStorage,
protected FilesystemOperator $formBuilderFilesStorage,
) {
}

public function execute(): void
{
foreach ($this->fileLocator->getFolderContent($this->fileLocator->getFilesFolder()) as $file) {
Logger::log('Remove form builder files folder: ' . $file);
$this->fileLocator->removeDir($file->getPathname());
$minimumModifiedDelta = Carbon::now()->subHour();

foreach ($this->formBuilderFilesStorage->listContents('/') as $file) {
$this->remove($minimumModifiedDelta, $file);
}

foreach ($this->formBuilderChunkStorage->listContents('/') as $file) {
$this->remove($minimumModifiedDelta, $file);
}
}

foreach ($this->fileLocator->getFolderContent($this->fileLocator->getChunksFolder()) as $file) {
Logger::log('Remove form builder chunk folder: ' . $file);
$this->fileLocator->removeDir($file->getPathname());
protected function remove(Carbon $minimumModifiedDelta, StorageAttributes $file): void
{
if (!$minimumModifiedDelta->greaterThan(Carbon::createFromTimestamp($file->lastModified()))) {
return;
}

foreach ($this->fileLocator->getFolderContent($this->fileLocator->getZipFolder()) as $file) {
Logger::log('Remove form builder zip folder: ' . $file);
$this->fileLocator->removeDir($file->getPathname());
if ($file->isDir()) {
$this->formBuilderFilesStorage->deleteDirectory($file->path());
} else {
$this->formBuilderFilesStorage->delete($file->path());
}

Logger::log(sprintf('Removing outdated form builder tmp %s: %s', $file->isDir() ? 'directory' : 'file', $file->path()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ public function shutdownFunnelRequest(ResponseEvent $event): void
return;
}

$this->signalSubscribeHandler->broadcast();
$isFunnelShutdownRequest = $this->funnelDataResolver->isFunnelShutdownRequest($event->getRequest());

if ($this->funnelDataResolver->isFunnelShutdownRequest($event->getRequest())) {
$this->signalSubscribeHandler->broadcast(['funnel_shutdown' => $isFunnelShutdownRequest]);

if ($isFunnelShutdownRequest === true) {
$this->funnelDataResolver->flushFunnelData($event->getRequest());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ public function listen(string $channel, array $context = []): void

public function broadcast(array $context = []): void
{
if ($this->channel === null) {
$channelName = $this->channel;

if ($channelName === null) {
return;
}

Expand All @@ -74,8 +76,9 @@ public function broadcast(array $context = []): void

$this->eventDispatcher->dispatch(
new OutputWorkflowSignalsEvent(
$channelName,
$this->signalStorage->getSignals(),
$context['exception'] ?? null
$context
),
FormBuilderEvents::OUTPUT_WORKFLOW_SIGNALS
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace FormBuilderBundle\OutputWorkflow\Channel\Email\Parser;

use FormBuilderBundle\Stream\File;
use League\Flysystem\FilesystemOperator;
use Pimcore\Mail;
use Pimcore\Model\Document\Email;
use Symfony\Component\Form\FormInterface;
Expand All @@ -13,18 +14,12 @@

class MailParser
{
protected EngineInterface $templating;
protected FormValuesOutputApplierInterface $formValuesOutputApplier;
protected PlaceholderParserInterface $placeholderParser;

public function __construct(
EngineInterface $templating,
FormValuesOutputApplierInterface $formValuesOutputApplier,
PlaceholderParserInterface $placeholderParser
protected EngineInterface $templating,
protected FormValuesOutputApplierInterface $formValuesOutputApplier,
protected PlaceholderParserInterface $placeholderParser,
protected FilesystemOperator $formBuilderFilesStorage
) {
$this->templating = $templating;
$this->formValuesOutputApplier = $formValuesOutputApplier;
$this->placeholderParser = $placeholderParser;
}

/**
Expand Down Expand Up @@ -153,7 +148,7 @@ protected function parseMailAttachment(Mail $mail, array $attachments): void
/** @var File $attachmentFile */
foreach ($attachments as $attachmentFile) {
try {
$mail->attach(file_get_contents($attachmentFile->getPath()), $attachmentFile->getName());
$mail->attach($this->formBuilderFilesStorage->read($attachmentFile->getPath()), $attachmentFile->getName());
} catch (\Exception $e) {
// fail silently.
}
Expand Down
11 changes: 11 additions & 0 deletions src/FormBuilderBundle/Resources/config/pimcore/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ parameters:
- ['onselect','onselect']
form_builder_field_attributes: '%form_builder_form_attributes%'

flysystem:
storages:
form_builder.chunk.storage:
adapter: 'local'
options:
directory: '%kernel.project_dir%/var/tmp/form-builder-chunks'
form_builder.files.storage:
adapter: 'local'
options:
directory: '%kernel.project_dir%/var/tmp/form-builder-files'

form_builder:
area:
presets: ~
Expand Down
3 changes: 0 additions & 3 deletions src/FormBuilderBundle/Resources/config/services/system.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ services:
arguments:
$bundle: "@=service('kernel').getBundle('FormBuilderBundle')"

# tool: file locator
FormBuilderBundle\Tool\FileLocator: ~

# tool: file locator
FormBuilderBundle\Tool\FormDependencyLocator: ~

Expand Down
54 changes: 28 additions & 26 deletions src/FormBuilderBundle/Stream/AttachmentStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
use Doctrine\DBAL\Query\QueryBuilder;
use FormBuilderBundle\Event\OutputWorkflow\OutputWorkflowSignalEvent;
use FormBuilderBundle\Event\OutputWorkflow\OutputWorkflowSignalsEvent;
use FormBuilderBundle\Tool\FileLocator;
use FormBuilderBundle\EventSubscriber\SignalSubscribeHandler;
use League\Flysystem\FilesystemOperator;
use Pimcore\Logger;
use Pimcore\Model\Asset;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand All @@ -15,13 +16,10 @@ class AttachmentStream implements AttachmentStreamInterface
public const SIGNAL_CLEAN_UP = 'tmp_file_attachment_stream';
protected const PACKAGE_IDENTIFIER = 'formbuilder_package_identifier';

protected EventDispatcherInterface $eventDispatcher;
protected FileLocator $fileLocator;

public function __construct(EventDispatcherInterface $eventDispatcher, FileLocator $fileLocator)
{
$this->eventDispatcher = $eventDispatcher;
$this->fileLocator = $fileLocator;
public function __construct(
protected EventDispatcherInterface $eventDispatcher,
protected FilesystemOperator $formBuilderFilesStorage
) {
}

/**
Expand All @@ -46,7 +44,7 @@ public function createAttachmentAsset($data, $fieldName, $formName): ?Asset

$packageIdentifier = '';
foreach ($fileStack->getFiles() as $file) {
$packageIdentifier .= sprintf('%s-%s-%s-%s', filesize($file->getPath()), $file->getId(), $file->getPath(), $file->getName());
$packageIdentifier .= sprintf('%s-%s-%s-%s', $this->formBuilderFilesStorage->fileSize($file->getPath()), $file->getId(), $file->getPath(), $file->getName());
}

// create package identifier to check if we just in another channel
Expand All @@ -55,7 +53,7 @@ public function createAttachmentAsset($data, $fieldName, $formName): ?Asset
$formName = \Pimcore\File::getValidFilename($formName);
$zipKey = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 5);
$zipFileName = sprintf('%s-%s.zip', \Pimcore\File::getValidFilename($fieldName), $zipKey);
$zipPath = sprintf('%s/%s', $this->fileLocator->getZipFolder(), $zipFileName);
$zipPath = sprintf('%s/%s', PIMCORE_SYSTEM_TEMP_DIRECTORY, $zipFileName);

$existingAssetPackage = $this->findExistingAssetPackage($packageIdentifier, $formName);

Expand All @@ -68,7 +66,7 @@ public function createAttachmentAsset($data, $fieldName, $formName): ?Asset
$zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);

foreach ($fileStack->getFiles() as $file) {
$zip->addFile($file->getPath(), $file->getName());
$zip->addFromString($file->getName(), $this->formBuilderFilesStorage->read($file->getPath()));
}

$zip->close();
Expand Down Expand Up @@ -145,7 +143,18 @@ public function createAttachmentAsset($data, $fieldName, $formName): ?Asset
*/
public function cleanUp(OutputWorkflowSignalsEvent $signalsEvent): void
{
// keep assets if guard exception occurs: user may want to retry!
// keep assets:
// - if broadcasting channel is initiating funnel
// - if broadcasting channel is processing funnel and not done yet
// - if guard exception occurs: user may want to retry!

if ($signalsEvent->getChannel() === SignalSubscribeHandler::CHANNEL_FUNNEL_INITIATE) {
return;
}

if ($signalsEvent->getChannel() === SignalSubscribeHandler::CHANNEL_FUNNEL_PROCESS && $signalsEvent->getContextItem('funnel_shutdown') === false) {
return;
}

if ($signalsEvent->hasGuardException() === true) {
return;
Expand All @@ -166,28 +175,21 @@ public function cleanUp(OutputWorkflowSignalsEvent $signalsEvent): void

protected function removeAttachmentFile(File $attachmentFile): void
{
$targetFolder = $this->fileLocator->getFilesFolder();
$target = implode(DIRECTORY_SEPARATOR, [$targetFolder, $attachmentFile->getId()]);

if (!is_dir($target)) {
return;
if ($this->formBuilderFilesStorage->directoryExists($attachmentFile->getId())) {
$this->formBuilderFilesStorage->deleteDirectory($attachmentFile->getId());
}

$this->fileLocator->removeDir($target);
}

protected function extractFiles(array $data): FileStack
{
$files = new FileStack();
foreach ($data as $fileData) {

$fileId = (string) $fileData['id'];
$fileDir = sprintf('%s/%s', $this->fileLocator->getFilesFolder(), $fileId);

if (is_dir($fileDir)) {
$dirFiles = glob($fileDir . '/*');
if (count($dirFiles) === 1) {
$files->addFile(new File($fileId, $fileData['fileName'], $dirFiles[0]));
if ($this->formBuilderFilesStorage->directoryExists($fileId)) {
$dirFiles = $this->formBuilderFilesStorage->listContents($fileId);
$flyFiles = iterator_to_array($dirFiles->getIterator());
if (count($flyFiles) === 1) {
$files->addFile(new File($fileId, $fileData['fileName'], $flyFiles[0]->path()));
}
}
}
Expand Down
Loading

0 comments on commit 07ba2c3

Please sign in to comment.