Compare commits
No commits in common. "develop" and "main" have entirely different histories.
8 changed files with 0 additions and 384 deletions
|
@ -1,8 +0,0 @@
|
||||||
pipeline:
|
|
||||||
code-style:
|
|
||||||
image: composer
|
|
||||||
commands:
|
|
||||||
- composer global config repositories.repo-name vcs https://git.digital-competence.de/Packages/php-codesniffer
|
|
||||||
- composer global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
|
|
||||||
- composer global require digicomp/php-codesniffer:@dev
|
|
||||||
- composer global exec -- phpcs --runtime-set ignore_warnings_on_exit 1 --standard=DigiComp Classes/ Tests/
|
|
|
@ -1,28 +0,0 @@
|
||||||
workspace:
|
|
||||||
base: /woodpecker
|
|
||||||
path: package
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- FLOW_VERSION: 7.3
|
|
||||||
PHP_VERSION: 8.1
|
|
||||||
- FLOW_VERSION: 8.3
|
|
||||||
PHP_VERSION: 8.2
|
|
||||||
|
|
||||||
pipeline:
|
|
||||||
functional-tests:
|
|
||||||
image: "thecodingmachine/php:${PHP_VERSION}-v4-cli"
|
|
||||||
environment:
|
|
||||||
# Enable the PDO_SQLITE extension
|
|
||||||
- "PHP_EXTENSION_PDO_SQLITE=1"
|
|
||||||
- "FLOW_VERSION=${FLOW_VERSION}"
|
|
||||||
- "NEOS_BUILD_DIR=/woodpecker/Build-${FLOW_VERSION}"
|
|
||||||
commands:
|
|
||||||
- "sudo mkdir $NEOS_BUILD_DIR"
|
|
||||||
- "sudo chown -R docker:docker $NEOS_BUILD_DIR"
|
|
||||||
- "cd $NEOS_BUILD_DIR"
|
|
||||||
- "composer create-project --no-install neos/flow-base-distribution:^$FLOW_VERSION ."
|
|
||||||
- "composer config repositories.repo-name path /woodpecker/package"
|
|
||||||
- "composer remove --dev --no-update neos/behat || composer remove --no-update neos/behat"
|
|
||||||
- "composer require digicomp/attachment-view-utility:@dev"
|
|
||||||
- "bin/phpunit --configuration Build/BuildEssentials/PhpUnit/FunctionalTests.xml Packages/Application/DigiComp.AttachmentViewUtility/Tests/Functional"
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DigiComp\AttachmentViewUtility;
|
|
||||||
|
|
||||||
use cardinalby\ContentDisposition\ContentDisposition;
|
|
||||||
use GuzzleHttp\Psr7\Response;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\StreamInterface;
|
|
||||||
|
|
||||||
trait AttachmentViewTrait
|
|
||||||
{
|
|
||||||
abstract protected function getAttachmentName(): string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string|resource|StreamInterface|null
|
|
||||||
*/
|
|
||||||
abstract protected function getAttachmentContent();
|
|
||||||
|
|
||||||
abstract protected function getAttachmentMimeType(): string;
|
|
||||||
|
|
||||||
protected function addOptionsForAttachment(): void
|
|
||||||
{
|
|
||||||
if (\property_exists($this, 'supportedOptions')) {
|
|
||||||
$this->supportedOptions['attachmentCharset'] = [
|
|
||||||
'utf-8',
|
|
||||||
'Charset of the content or FALSE if you want to suppress the information in header',
|
|
||||||
'string|false',
|
|
||||||
];
|
|
||||||
$this->supportedOptions['attachmentDisposition'] = [
|
|
||||||
'attachment',
|
|
||||||
'One of "inline" or "attachment"',
|
|
||||||
'string',
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException('supported option could not be set', 1697552694);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render(): ResponseInterface
|
|
||||||
{
|
|
||||||
if ($this->options['attachmentCharset'] === false) {
|
|
||||||
$charset = '';
|
|
||||||
} else {
|
|
||||||
$charset = '; charset=' . $this->options['attachmentCharset'];
|
|
||||||
}
|
|
||||||
return new Response(
|
|
||||||
200,
|
|
||||||
[
|
|
||||||
'Content-Disposition' => ContentDisposition::create(
|
|
||||||
$this->getAttachmentName(),
|
|
||||||
true,
|
|
||||||
$this->options['attachmentDisposition']
|
|
||||||
)->format(),
|
|
||||||
'Content-Type' => $this->getAttachmentMimeType() . $charset,
|
|
||||||
],
|
|
||||||
$this->getAttachmentContent()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DigiComp\AttachmentViewUtility;
|
|
||||||
|
|
||||||
use Neos\Eel\Context;
|
|
||||||
use Neos\Eel\EelEvaluatorInterface;
|
|
||||||
use Neos\Eel\Helper\ArrayHelper;
|
|
||||||
use Neos\Eel\Helper\StringHelper;
|
|
||||||
use Neos\Flow\Annotations as Flow;
|
|
||||||
use Neos\Flow\I18n\EelHelper\TranslationHelper;
|
|
||||||
use Neos\FluidAdaptor\View\TemplateView;
|
|
||||||
use Neos\Utility\TypeHandling;
|
|
||||||
|
|
||||||
trait EelFilenameTrait
|
|
||||||
{
|
|
||||||
protected string $eelExpressionOptionKey = 'filenameEelExpression';
|
|
||||||
|
|
||||||
#[Flow\Inject(name: EelEvaluatorInterface::class, lazy: false)]
|
|
||||||
protected EelEvaluatorInterface $eelEvaluator;
|
|
||||||
|
|
||||||
protected function addOptionFilenameEelExpression(): void
|
|
||||||
{
|
|
||||||
if (\property_exists($this, 'supportedOptions')) {
|
|
||||||
$this->supportedOptions['filenameEelExpression'] = [
|
|
||||||
null,
|
|
||||||
'Callable which creates a filename from variables',
|
|
||||||
'string',
|
|
||||||
true,
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException('supported option could not be set', 1697552694);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAttachmentName(): string
|
|
||||||
{
|
|
||||||
if ($this instanceof TemplateView) {
|
|
||||||
$variables = $this->getRenderingContext()->getVariableProvider()->getAll();
|
|
||||||
} elseif (\property_exists($this, 'variables')) {
|
|
||||||
$variables = $this->variables;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException(
|
|
||||||
'No variables can be detected for this kind of view: ' . TypeHandling::getTypeForValue($this),
|
|
||||||
1697550214
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!\property_exists($this, 'options')) {
|
|
||||||
throw new \RuntimeException('Your view options could not be found', 1697550440);
|
|
||||||
}
|
|
||||||
$expression = $this->options[$this->eelExpressionOptionKey];
|
|
||||||
|
|
||||||
return $this->getEelResult($expression, $variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEelResult(string $expression, array $contextVariables)
|
|
||||||
{
|
|
||||||
$context = new Context(\array_merge($contextVariables, [
|
|
||||||
'Array' => new ArrayHelper(),
|
|
||||||
'String' => new StringHelper(),
|
|
||||||
'Translation' => new TranslationHelper(),
|
|
||||||
]));
|
|
||||||
$this->emitFilenameEelExpressionContext($context);
|
|
||||||
return $this->eelEvaluator->evaluate($expression, $context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @SuppressWarnings("unused")
|
|
||||||
*/
|
|
||||||
#[Flow\Signal]
|
|
||||||
protected function emitFilenameEelExpressionContext(Context $context): void
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
58
README.md
58
README.md
|
@ -1,58 +0,0 @@
|
||||||
# DigiComp.AttachmentViewUtility
|
|
||||||
|
|
||||||
This package helps with recurring tasks of creating views for `neos/flow` projects.
|
|
||||||
|
|
||||||
It delivers two traits:
|
|
||||||
1. `AttachmentViewTrait` creates views which returns downloadable resources
|
|
||||||
2. `EelFilenameTrait` allows to set the filename with an eel expression, which got the view variables as context
|
|
||||||
|
|
||||||
They can be used together or standalone - but the filename trait does not make sense, if your view is not delivered by attachment.
|
|
||||||
|
|
||||||
The `EelContext` contains the `String`, `Array` and `Translation` - Helpers. If you need more, you can connect to the `YourView::filenameEelExpressionContext` signal, which gets the context as argument. That way you can extend the context with whatever you need.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
SimpleAttachmentView.php:
|
|
||||||
```php
|
|
||||||
class SimpleAttachmentView extends AbstractView
|
|
||||||
{
|
|
||||||
use AttachmentViewTrait;
|
|
||||||
use EelFilenameTrait;
|
|
||||||
|
|
||||||
public function __construct(array $options = [])
|
|
||||||
{
|
|
||||||
$this->addOptionFilenameEelExpression();
|
|
||||||
$this->addOptionsForAttachment();
|
|
||||||
parent::__construct($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAttachmentContent()
|
|
||||||
{
|
|
||||||
return 'Hello ' . $this->variables['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAttachmentMimeType(): string
|
|
||||||
{
|
|
||||||
return 'text/plain';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Controller:
|
|
||||||
```php
|
|
||||||
class DefaultController extends ActionController {
|
|
||||||
public function downloadAction()
|
|
||||||
{
|
|
||||||
$this->view->assign('name', 'World');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Views.yaml:
|
|
||||||
```yaml
|
|
||||||
-
|
|
||||||
requestFilter: "isController('Default') && isAction('download')"
|
|
||||||
viewObjectName: "Acme\\Vendor\\SimpleAttachmentView"
|
|
||||||
options:
|
|
||||||
filenameEelExpression: "'hello-' + name + '.txt'"
|
|
||||||
```
|
|
|
@ -1,82 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DigiComp\AttachmentViewUtility\Tests\Functional;
|
|
||||||
|
|
||||||
use DigiComp\AttachmentViewUtility\Tests\Functional\Fixtures\SimpleAttachmentTemplateView;
|
|
||||||
use Neos\Eel\Context;
|
|
||||||
use Neos\Flow\SignalSlot\Dispatcher;
|
|
||||||
use Neos\Flow\Tests\FunctionalTestCase;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
class AttachmentViewTraitTest extends FunctionalTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function itCreatesAttachmentResponses(): void
|
|
||||||
{
|
|
||||||
$view = new SimpleAttachmentTemplateView([
|
|
||||||
'templateSource' => 'TollesTemplate! {testVar}',
|
|
||||||
'filenameEelExpression' => 'testVar + ".txt"',
|
|
||||||
'attachmentCharset' => 'iso-8859-1'
|
|
||||||
]);
|
|
||||||
$view->assign('testVar', '£ and € rates');
|
|
||||||
|
|
||||||
$result = $view->render();
|
|
||||||
static::assertInstanceOf(ResponseInterface::class, $result);
|
|
||||||
static::assertEquals(
|
|
||||||
'attachment; filename="£ and ? rates.txt"; filename*=UTF-8\'\'%C2%A3%20and%20%E2%82%AC%20rates.txt',
|
|
||||||
$result->getHeaderLine('Content-Disposition')
|
|
||||||
);
|
|
||||||
static::assertEquals('text/plain; charset=iso-8859-1', $result->getHeaderLine('Content-Type'));
|
|
||||||
static::assertEquals('TollesTemplate! £ and € rates', (string)$result->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function itIsPossibleToSuppressCharset(): void
|
|
||||||
{
|
|
||||||
$view = new SimpleAttachmentTemplateView([
|
|
||||||
'templateSource' => 'TollesTemplate! {testVar}',
|
|
||||||
'filenameEelExpression' => 'testVar + ".txt"',
|
|
||||||
'attachmentCharset' => false
|
|
||||||
]);
|
|
||||||
$view->assign('testVar', 'WORLD');
|
|
||||||
$result = $view->render();
|
|
||||||
static::assertEquals('text/plain', $result->getHeaderLine('Content-Type'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function itIsPossibleToExtendTheContextBySignalSlot(): void
|
|
||||||
{
|
|
||||||
$view = new SimpleAttachmentTemplateView([
|
|
||||||
'templateSource' => 'TollesTemplate! {testVar}',
|
|
||||||
'filenameEelExpression' => 'greet(testVar) + ".txt"',
|
|
||||||
'attachmentCharset' => false
|
|
||||||
]);
|
|
||||||
$view->assign('testVar', 'WORLD');
|
|
||||||
$dispatcher = $this->objectManager->get(Dispatcher::class);
|
|
||||||
$dispatcher->connect(
|
|
||||||
SimpleAttachmentTemplateView::class,
|
|
||||||
'filenameEelExpressionContext',
|
|
||||||
function (Context $eelContext) {
|
|
||||||
$eelContext->push(
|
|
||||||
function ($name) {
|
|
||||||
return 'Hello ' . $name;
|
|
||||||
},
|
|
||||||
'greet'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$result = $view->render();
|
|
||||||
static::assertEquals(
|
|
||||||
'attachment; filename="Hello WORLD.txt"',
|
|
||||||
$result->getHeaderLine('Content-Disposition')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DigiComp\AttachmentViewUtility\Tests\Functional\Fixtures;
|
|
||||||
|
|
||||||
use DigiComp\AttachmentViewUtility\AttachmentViewTrait;
|
|
||||||
use DigiComp\AttachmentViewUtility\EelFilenameTrait;
|
|
||||||
use Neos\Flow\Mvc\View\SimpleTemplateView;
|
|
||||||
|
|
||||||
class SimpleAttachmentTemplateView extends SimpleTemplateView
|
|
||||||
{
|
|
||||||
use AttachmentViewTrait;
|
|
||||||
use EelFilenameTrait;
|
|
||||||
|
|
||||||
public function __construct(array $options = [])
|
|
||||||
{
|
|
||||||
$this->addOptionFilenameEelExpression();
|
|
||||||
$this->addOptionsForAttachment();
|
|
||||||
parent::__construct($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAttachmentContent()
|
|
||||||
{
|
|
||||||
/** @noinspection MissUsingParentKeywordInspection */
|
|
||||||
return parent::render();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAttachmentMimeType(): string
|
|
||||||
{
|
|
||||||
return 'text/plain';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"name": "digicomp/attachment-view-utility",
|
|
||||||
"type": "neos-package",
|
|
||||||
"description": "",
|
|
||||||
"require": {
|
|
||||||
"cardinalby/content-disposition": "^1.1",
|
|
||||||
"neos/eel": "^7.3 | ^8.3",
|
|
||||||
"neos/flow": "^7.3 | ^8.3",
|
|
||||||
"php": "^8.0"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"DigiComp\\AttachmentViewUtility\\": "Classes"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-develop": "1.0.x-dev"
|
|
||||||
},
|
|
||||||
"applied-flow-migrations": [
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Ferdinand Kuhl",
|
|
||||||
"email": "f.kuhl@digital-competence.de",
|
|
||||||
"homepage": "https://www.digital-competence.de",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"homepage": "https://git.digital-competence.de/Packages/DigiComp.AttachmentViewUtility",
|
|
||||||
"keywords": [
|
|
||||||
"Neos",
|
|
||||||
"Flow",
|
|
||||||
"view",
|
|
||||||
"mvc"
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in a new issue