Product text import from agency XLSX workbooks
VITEC Import module: Products tab is now a searchable/sortable product overview. "Edit Product" opens an XLSX upload with per-field source mapping (component + cell), old/new preview and checkbox apply via DataHandler; the mapping and manual matches are persisted and preselect the next workbook. Category workbooks are detected and rejected. - new: ProductXlsxReader (PhpSpreadsheet), ProductTextImportController, Products/ProductTexts templates, 4 module routes - related products: per-pair card text in new side table tx_vitec_product_related_text (survives MM rewrites), emitted as `cardtext` in the product JSON; missing MM relations added add-only - card copy read from Body Copy (D) with fallback to CTA/Card Copy (E) - the workbooks fill either depending on row type - product detail page <title> now uses seotitle with title fallback (provider made singleton and fed from the JSON renderer) - per-user recent-search badges; last loaded workbook stored per product (tx_vitec_product_workbook), Edit Product reopens on it - composer: add phpoffice/phpspreadsheet ^5.9 - diagnostics: migrations/check_workbook.php
This commit is contained in:
1 parent
12eb40614b
commit
7bd1161abf
28 files changed
+2594
-39
No files matched your search
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evomedien\Vitec\Middleware;
|
||||
|
||||
use Evomedien\Vitec\Service\DownloadFileResolver;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use TYPO3\CMS\Core\Http\Response;
|
||||
use TYPO3\CMS\Core\Http\Stream;
|
||||
|
||||
/**
|
||||
* Forced file download for download records: /download/file/<uid>
|
||||
*
|
||||
* This is the frontend target of the "Download" record links from the link
|
||||
* browser (config.recordLinks.download builds exactly this path). A direct
|
||||
* fileadmin URL would open PDFs inline; this endpoint streams the file with
|
||||
* Content-Disposition: attachment, so the browser saves it.
|
||||
*
|
||||
* The file lookup lives in Service\DownloadFileResolver (FAL -> Collateral
|
||||
* naming convention -> filepath column). Unknown uid, hidden record or
|
||||
* missing file fall through to the regular pipeline - the reply is then the
|
||||
* normal 404 page, never a broken download.
|
||||
*/
|
||||
final class DownloadFileMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
try {
|
||||
$path = $request->getUri()->getPath();
|
||||
if (preg_match('#^/download/file/(\\d+)/?$#', $path, $matches) === 1) {
|
||||
$file = DownloadFileResolver::resolve((int)$matches[1]);
|
||||
if ($file !== null) {
|
||||
$filename = str_replace(['"', "\r", "\n"], '', $file['name']);
|
||||
|
||||
return new Response(
|
||||
new Stream($file['path'], 'rb'),
|
||||
200,
|
||||
[
|
||||
'Content-Type' => $file['mimeType'] !== '' ? $file['mimeType'] : 'application/octet-stream',
|
||||
'Content-Length' => (string)$file['size'],
|
||||
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// fall through to the regular pipeline
|
||||
}
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user