Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kanti committed Feb 16, 2022
0 parents commit c2e2c3a
Show file tree
Hide file tree
Showing 11 changed files with 1,100 additions and 0 deletions.
68 changes: 68 additions & 0 deletions .github/workflows/tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Tasks

on: [push, pull_request]

jobs:
lint-php:
name: Linting php with grumphp
runs-on: ubuntu-latest
container:
image: kanti/buildy:7.4
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ~/.composer/cache/files
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- run: composer install --no-interaction --no-progress --ignore-platform-req=ext*
- run: ./vendor/bin/grumphp run --ansi

ter-release:
name: TER release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
needs: [ lint-php]
env:
TYPO3_EXTENSION_KEY: 'ssi_include'
REPOSITORY_URL: 'https://github.com/andersundsehr/ssi_include'
TYPO3_API_TOKEN: ${{ secrets.TYPO3_API_TOKEN }}
TYPO3_API_USERNAME: ${{ secrets.TYPO3_API_USERNAME }}
TYPO3_API_PASSWORD: ${{ secrets.TYPO3_API_PASSWORD }}

steps:
- uses: actions/checkout@v2
- name: Get the version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
extensions: intl, mbstring, xml, soap, zip, curl
tools: composer

- name: Install typo3/tailor
run: composer global require typo3/tailor --prefer-dist --no-progress

- name: Upload EXT:ssi_include to TER
run: |
sed -i 's/\\AUS\\SsiInclude\\Utility\\VersionUtility::getVersion()/'\''${{ steps.get_version.outputs.VERSION }}'\''/g' ext_emconf.php \
&& git config --global user.email "no@one" \
&& git config --global user.name "No One" \
&& git add ext_emconf.php \
&& jq '.require = .["ter-require"]' composer.json | sponge composer.json \
&& composer i --no-dev \
&& git add vendor -f \
&& git commit -m 'x' -n \
&& git archive -o archive.zip HEAD --prefix=ssi_include-${{ steps.get_version.outputs.VERSION }}/ \
&& git reset --hard HEAD~ \
&& curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/andersundsehr/ssi_include/releases/tags/${{ steps.get_version.outputs.VERSION }} > release.json \
&& php ~/.composer/vendor/bin/tailor ter:publish ${{ steps.get_version.outputs.VERSION }} --artefact=archive.zip \
--comment="$(cat release.json | jq -r '.name')
$(cat release.json | jq -r '.body')
$(cat release.json | jq -r '.html_url')"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
composer.lock
public/
vendor/
34 changes: 34 additions & 0 deletions Classes/Middleware/InternalSsiRedirectMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace AUS\SsiInclude\Middleware;

use AUS\SsiInclude\ViewHelpers\RenderIncludeViewHelper;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Http\HtmlResponse;

class InternalSsiRedirectMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (isset($request->getQueryParams()['ssi_include'])) {
$ssiInclude = $request->getQueryParams()['ssi_include'];
if (!preg_match('/^([a-zA-Z0-9_]+)$/', $ssiInclude)) {
return new HtmlResponse('ssi_include invalid', 400);
}
$cacheFileName = RenderIncludeViewHelper::SSI_INCLUDE_DIR . $ssiInclude;
$absolutePath = Environment::getPublicPath() . $cacheFileName;
if (!file_exists($absolutePath)) {
// ignore response use the content of the file:
$handler->handle($request->withAttribute('noCache', true));
}
return new HtmlResponse(file_get_contents($absolutePath) ?: '');
}
return $handler->handle($request);
}
}
25 changes: 25 additions & 0 deletions Classes/Utility/VersionUtility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace AUS\SsiInclude\Utility;

use PackageVersions\Versions;
use Throwable;

final class VersionUtility
{
private function __construct()
{
}

public static function getVersion(): string
{
$str = 'dev';
try {
return explode('@', Versions::getVersion('kanti/web-vitals-tracker'))[0] ?? $str;
} catch (Throwable $e) {
return $str;
}
}
}
100 changes: 100 additions & 0 deletions Classes/ViewHelpers/RenderIncludeViewHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace AUS\SsiInclude\ViewHelpers;

use Exception;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\ViewHelpers\RenderViewHelper;
use Webimpress\SafeWriter\FileWriter;

class RenderIncludeViewHelper extends RenderViewHelper
{
public const SSI_INCLUDE_DIR = '/typo3temp/tx_ssiinclude/';

protected static function getContext(): Context
{
return GeneralUtility::makeInstance(Context::class);
}

public function initializeArguments(): void
{
parent::initializeArguments();
$this->registerArgument('name', 'string', 'Specifies the file name of the cache (without .html ending)', true);
}

/**
* @param array<string, mixed> $arguments
* @param \Closure $renderChildrenClosure
* @param RenderingContextInterface $renderingContext
* @return string
* @throws \Webimpress\SafeWriter\Exception\ExceptionInterface
*/
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
{
$name = static::validateName($arguments);

$filename = static::getSiteName() . '_' . static::getLangauge() . '_' . $name;
$basePath = self::SSI_INCLUDE_DIR . $filename;
$absolutePath = Environment::getPublicPath() . $basePath;
if (self::shouldRenderFile($absolutePath)) {
$html = parent::renderStatic($arguments, $renderChildrenClosure, $renderingContext);
if (self::isBackendUser()) {
return $html;
}

@mkdir(dirname($absolutePath), octdec($GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']), true);
FileWriter::writeFile($absolutePath, $html);
GeneralUtility::fixPermissions($absolutePath);
}
return '<!--# include wait="yes" virtual="' . $basePath . '?ssi_include=' . $filename . '" -->';
}

private static function shouldRenderFile(string $absolutePath): bool
{
if (!file_exists($absolutePath)) {
return true;
}
$cacheLifeTime = 5 * 60; // 5min TODO
if ((filemtime($absolutePath) + $cacheLifeTime) < time()) {
return true;
}
if (self::isBackendUser()) {
return true;
}
return false;
}

/**
* @param array<string, mixed> $arguments
* @return string
* @throws Exception
*/
private static function validateName(array $arguments): string
{
if (ctype_alnum($arguments['name'])) {
return $arguments['name'];
}
throw new Exception(sprintf('Only Alphanumeric characters allowed got: "%s"', $arguments['name']));
}

protected static function getLangauge(): int
{
return self::getContext()->getPropertyFromAspect('language', 'id');
}

protected static function isBackendUser(): bool
{
return self::getContext()->getPropertyFromAspect('backend.user', 'isLoggedIn');
}

protected static function getSiteName(): string
{
return $GLOBALS['TYPO3_REQUEST']->getAttribute('site')->getIdentifier();
}
}
14 changes: 14 additions & 0 deletions Configuration/RequestMiddlewares.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

return [
'frontend' => [
\AUS\SsiInclude\Middleware\InternalSsiRedirectMiddleware::class => [
'target' => \AUS\SsiInclude\Middleware\InternalSsiRedirectMiddleware::class,
'before' => [
'typo3/cms-core/normalized-params-attribute'
],
'after' => [
],
]
],
];
Loading

0 comments on commit c2e2c3a

Please sign in to comment.