fix: render product detail pages on TYPO3 13
- ObjectManager replaced by GeneralUtility::makeInstance(), the
services fetched that way are public
- QueryBuilder::add('orderBy') and the remaining execute() calls,
detailAction returns a response
- PHP 8 warnings for missing array keys (same values as on PHP 7.4)
- Webcam images are external URLs: plain img tag, f:image only takes
FAL files
- typo3_encore 7 needs the PKG:ssch/typo3-encore: prefix and
external = 1 so TYPO3's path check does not drop the entry
- CDN image rewriting as a middleware instead of EXT:replacer, which
is not PHP 8.5 clean; same pattern, only for page responses
- vhs 8 for the ViewHelpers the templates use
- OpenGraph meta tag manager skips the backend
- myEpUrl with trailing slash as in production
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
4eb1de2e29
commit
34f2d55f2c
23 files changed
+222
-57
No files matched your search
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace EP\EpTheme\Middleware;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Http\Stream;
|
||||
|
||||
/**
|
||||
* Points image URLs in frontend pages at the CDN (formerly EXT:replacer).
|
||||
*
|
||||
* Only images go to the CDN. The theme's own css/js/fonts are served by the production
|
||||
* host: they are already minified by Webpack, gzipped by mod_deflate and content-hashed
|
||||
* for a year of immutable browser caching, and keeping them on the page's own origin
|
||||
* means they arrive over the connection the browser has already opened rather than
|
||||
* costing a second DNS lookup and TLS handshake on the critical path.
|
||||
*
|
||||
* It also keeps them clear of the pull zone's habit of occasionally wedging a single
|
||||
* cache key (10.0s -> 504 errorcode 106 until that key is purged, while the origin
|
||||
* serves the same bytes in under 100ms). For an image that degrades one element; for
|
||||
* js/main.<hash>.js it would take every visitor's JavaScript down.
|
||||
*
|
||||
* typo3temp is scoped to generated images on purpose - assets/compressed holds other
|
||||
* extensions' concatenated css/js, which belongs on the origin for the same reason.
|
||||
* The quote character is captured rather than matched literally, so url() values
|
||||
* written with single quotes are rewritten too.
|
||||
*
|
||||
* Registered after the page resolver, so the /api/* responses of ep_products never pass here.
|
||||
*/
|
||||
final class CdnImageMiddleware implements MiddlewareInterface
|
||||
{
|
||||
private const PATTERN = '/(["\'])\/?(fileadmin|uploads|typo3temp\/assets\/(?:_processed_|images))/';
|
||||
|
||||
public function __construct(private readonly ExtensionConfiguration $extensionConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$response = $handler->handle($request);
|
||||
|
||||
$cdnBaseUrl = rtrim((string)($this->extensionConfiguration->get('ep_theme', 'cdnBaseUrl') ?? ''), '/');
|
||||
$contentType = $response->getHeaderLine('Content-Type');
|
||||
if ($cdnBaseUrl === ''
|
||||
|| !(str_starts_with($contentType, 'text/html') || str_starts_with($contentType, 'application/json'))
|
||||
) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$body = (string)$response->getBody();
|
||||
$replaced = preg_replace(self::PATTERN, '$1' . $cdnBaseUrl . '/$2', $body);
|
||||
if ($replaced === null || $replaced === $body) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$stream = new Stream('php://temp', 'rw');
|
||||
$stream->write($replaced);
|
||||
return $response->withBody($stream);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user