From 482e4bd6f7308147b1f0cdcb3c291a167fba78e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:22:01 +0200 Subject: [PATCH 01/16] Add strict types Improve documentation --- RapsysPackBundle.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/RapsysPackBundle.php b/RapsysPackBundle.php index d1fd290..260ce22 100644 --- a/RapsysPackBundle.php +++ b/RapsysPackBundle.php @@ -1,7 +1,19 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Rapsys\PackBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; +/** + * {@inheritdoc} + */ class RapsysPackBundle extends Bundle {} -- 2.41.1 From a3d21dc7b3d01a8e02af3e88cd263adc259f909d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:22:58 +0200 Subject: [PATCH 02/16] New tree layout Add strict types Improve documentation Cleanup --- Parser/TokenParser.php | 65 +++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/Parser/TokenParser.php b/Parser/TokenParser.php index 9f2bf14..7749ad2 100644 --- a/Parser/TokenParser.php +++ b/Parser/TokenParser.php @@ -1,11 +1,12 @@ locator = $locator; @@ -66,30 +67,21 @@ class PackTokenParser extends AbstractTokenParser { * * @return string This tag name */ - public function getTag() { + public function getTag(): string { return $this->tag; } /** * Parse the token * - * @param Token token The \Twig\Token instance + * @xxx Skip filter when debug mode is enabled is not possible + * @xxx This code is only run once when twig cache is enabled + * @xxx Twig cache value is not avaible in container parameters, maybe in twig env ? * + * @param Token $token The \Twig\Token instance * @return Node The PackNode - * - * @todo see if we can't add a debug mode behaviour - * - * If twig.debug or env=dev (or rapsys_pack.config.debug?) is set, it should be possible to loop on each input - * and process the captured body without applying requested filter. - * - * @todo list: - * - detect debug mode - * - retrieve fixe link from input s%@(Name)Bundle/Resources/public(/somewhere/file.ext)%/bundles/\L\1\E\2% - * - for each inputs: - * - generate a set asset_url=x - * - generate a body */ - public function parse(Token $token) { + public function parse(Token $token): Node { $parser = $this->parser; $stream = $this->parser->getStream(); @@ -140,8 +132,6 @@ class PackTokenParser extends AbstractTokenParser { //Process end block $stream->expect(Token::BLOCK_END_TYPE); - //TODO: debug mode should be inserted here before the output variable is rewritten - //Replace star with sha1 if (($pos = strpos($output, '*')) !== false) { //XXX: assetic use substr(sha1(serialize($inputs).serialize($filters).serialize($options)), 0, 7) @@ -261,7 +251,7 @@ class PackTokenParser extends AbstractTokenParser { try { //Create dir //XXX: set as 0775, symfony umask (0022) will reduce rights (0755) - $filesystem->mkdir($dir, 0775); + $filesystem->mkdir($dir, 0775); } catch (IOExceptionInterface $e) { //Throw error throw new Error(sprintf('Output directory "%s" do not exists and unable to create it', $dir), $token->getLine(), $stream->getSourceContext(), $e); @@ -297,28 +287,25 @@ class PackTokenParser extends AbstractTokenParser { /** * Test for tag end * - * @param Token token The \Twig\Token instance - * - * @return bool + * @param Token $token The \Twig\Token instance + * @return bool The token end test result */ - public function testEndTag(Token $token) { + public function testEndTag(Token $token): bool { return $token->test(['end'.$this->getTag()]); } /** * Get path from bundled file * - * @param string file The bundled file path - * @param int lineno The template line where the error occurred - * @param Source source The source context where the error occurred - * @param \Exception prev The previous exception + * @see https://symfony.com/doc/current/bundles.html#overridding-the-bundle-directory-structure * + * @param string $file The bundled file path + * @param int $lineno The template line where the error occurred + * @param Source $source The source context where the error occurred + * @param Exception $prev The previous exception * @return string The resolved file path - * - * @todo Try retrive public dir from the member function BundleNameBundle::getPublicDir() return value ? - * @xxx see https://symfony.com/doc/current/bundles.html#overridding-the-bundle-directory-structure */ - public function getLocated($file, int $lineno = 0, Source $source = null, \Exception $prev = null) { + public function getLocated(string $file, int $lineno = 0, Source $source = null, \Exception $prev = null): string { /*TODO: add a @jquery magic feature ? if ($file == '@jquery') { #header('Content-Type: text/plain'); -- 2.41.1 From b365fc709c3a552386ee3c03d26aa7c5a3c285fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:28:34 +0200 Subject: [PATCH 03/16] Add getAbsoluteUrl feature New tree layout Add strict types Improve documentation Cleanup --- Package/PathPackage.php | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/Package/PathPackage.php b/Package/PathPackage.php index 50c6172..4746fe9 100644 --- a/Package/PathPackage.php +++ b/Package/PathPackage.php @@ -1,41 +1,75 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Rapsys\PackBundle\Package; use Symfony\Component\Asset\Context\ContextInterface; use Symfony\Component\Asset\Package; use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface; +use Rapsys\PackBundle\Context\NullContext; + /** - * (@inheritdoc) + * {@inheritdoc} */ class PathPackage extends Package { //The base path protected $basePath; + //The base url + protected $baseUrl; + /** * {@inheritdoc} */ public function __construct(string $basePath, VersionStrategyInterface $versionStrategy, ContextInterface $context = null) { + //Without context use a null context + $context = $context ?? new NullContext(); + + //Call parent constructor parent::__construct($versionStrategy, $context); - if (!$basePath) { + //Without base path + if (empty($basePath)) { + //Set base path $this->basePath = '/'; + //With base path } else { + //With relative base path if ('/' != $basePath[0]) { + //Set base path as absolute $basePath = '/'.$basePath; } + //Set base path $this->basePath = rtrim($basePath, '/').'/'; } + + //Set base url + $this->baseUrl = $context->getBaseUrl(); } /** - * @todo Try retrive public dir from the member function BundleNameBundle::getPublicDir() return value ? - * @xxx see https://symfony.com/doc/current/bundles.html#overridding-the-bundle-directory-structure + * Returns an absolute or root-relative public path + * + * Transform @BundleBundle to bundle and remove /Resources/public fragment from path + * This bundle name conversion and bundle prefix are the same as in asset:install command + * + * @link https://symfony.com/doc/current/bundles.html#overridding-the-bundle-directory-structure + * @see vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php +113 + * @see vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php +141 + * * {@inheritdoc} */ - public function getUrl($path) { + public function getUrl(string $path): string { //Match url starting with a bundle name if (preg_match('%^@([A-Z][a-zA-Z]*?)(?:Bundle/Resources/public)?/(.*)$%', $path, $matches)) { //Handle empty or without replacement pattern basePath @@ -53,4 +87,15 @@ class PathPackage extends Package { //Return parent getUrl result return parent::getUrl($path); } + + /** + * Returns an absolute public path. + * + * @param string $path A path + * @return string The absolute public path + */ + public function getAbsoluteUrl(string $path): string { + //Return concated base url and url from path + return $this->baseUrl.self::getUrl($path); + } } -- 2.41.1 From 0d6adabf6050f4496f683fab894e0da5ac42d57b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:29:27 +0200 Subject: [PATCH 04/16] Add hash, short and unshort twig filter New tree layout Add strict types Improve documentation Cleanup --- Extension/PackExtension.php | 66 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/Extension/PackExtension.php b/Extension/PackExtension.php index 91a7a89..118de0c 100644 --- a/Extension/PackExtension.php +++ b/Extension/PackExtension.php @@ -1,12 +1,27 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Rapsys\PackBundle\Extension; -use Symfony\Component\HttpKernel\Config\FileLocator; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Asset\PackageInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpKernel\Config\FileLocator; use Twig\Extension\AbstractExtension; +use Rapsys\PackBundle\Util\SluggerUtil; +use Rapsys\PackBundle\Parser\TokenParser; + +/** + * {@inheritdoc} + */ class PackExtension extends AbstractExtension { //The config private $config; @@ -20,13 +35,24 @@ class PackExtension extends AbstractExtension { //The file locator protected $locator; + //The slugger instance + protected $slugger; + //The assets package protected $package; - public function __construct(FileLocator $locator, ContainerInterface $container, PackageInterface $package) { + /** + * @link https://twig.symfony.com/doc/2.x/advanced.html + * + * {@inheritdoc} + */ + public function __construct(FileLocator $locator, ContainerInterface $container, PackageInterface $package, SluggerUtil $slugger) { //Set file locator $this->locator = $locator; + //Set slugger + $this->slugger = $slugger; + //Set assets packages $this->package = $package; @@ -39,18 +65,36 @@ class PackExtension extends AbstractExtension { } } - public function getTokenParsers() { + /** + * Returns a list of filters to add to the existing list. + * + * @return \Twig\TwigFilter[] + */ + public function getTokenParsers(): array { + return [ + new TokenParser($this->locator, $this->package, $this->config, 'stylesheet', $this->output['css'], $this->filters['css']), + new TokenParser($this->locator, $this->package, $this->config, 'javascript', $this->output['js'], $this->filters['js']), + new TokenParser($this->locator, $this->package, $this->config, 'image', $this->output['img'], $this->filters['img']) + ]; + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return \Twig\TwigFilter[] + */ + public function getFilters(): array { return [ - new PackTokenParser($this->locator, $this->package, $this->config, 'stylesheet', $this->output['css'], $this->filters['css']), - new PackTokenParser($this->locator, $this->package, $this->config, 'javascript', $this->output['js'], $this->filters['js']), - new PackTokenParser($this->locator, $this->package, $this->config, 'image', $this->output['img'], $this->filters['img']) + new \Twig\TwigFilter('hash', [$this->slugger, 'hash']), + new \Twig\TwigFilter('unshort', [$this->slugger, 'unshort']), + new \Twig\TwigFilter('short', [$this->slugger, 'short']) ]; } /** * {@inheritdoc} */ - public function getAlias() { + public function getAlias(): string { return 'rapsys_pack'; } } -- 2.41.1 From b8f0779faee6db6d4c4fe71fc417415968966e8f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:32:32 +0200 Subject: [PATCH 05/16] New tree layout Add strict types Improve documentation Cleanup --- Filter/FilterInterface.php | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Filter/FilterInterface.php b/Filter/FilterInterface.php index 2dc2b6f..f3b2987 100644 --- a/Filter/FilterInterface.php +++ b/Filter/FilterInterface.php @@ -1,9 +1,27 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Rapsys\PackBundle\Filter; + +/** + * Filter interface definition + * + * @todo do we need something else ? (like a constructor that read parameters or else) + */ interface FilterInterface { - //TODO: see if we need something else (like a constructor that read parameters or something else ?) - public function process($content); + /** + * Process function + * + * @param string $content The content to process + * @return string The processed content + */ + public function process(string $content): string; } -- 2.41.1 From 3f45db7aa4f5ff402e28842ae6efdef5044333ae Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:33:41 +0200 Subject: [PATCH 06/16] New tree layout Add strict types Improve documentation Cleanup --- Filter/JPackFilter.php | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Filter/JPackFilter.php b/Filter/JPackFilter.php index ca4555d..6715596 100644 --- a/Filter/JPackFilter.php +++ b/Filter/JPackFilter.php @@ -1,10 +1,22 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Rapsys\PackBundle\Filter; -use Rapsys\PackBundle\Twig\Filter\FilterInterface; use Twig\Error\Error; +use Twig\Source; +/** + * {@inheritdoc} + */ class JPackFilter implements FilterInterface { //Default bin private $bin; @@ -18,9 +30,12 @@ class JPackFilter implements FilterInterface { //Twig template line private $line; - //Configure the object - //XXX: can be clean, shrink, obfuscate or best - public function __construct($fileName, $line, $bin = 'jpack', $compress = 'best') { + /** + * Setup jpack filter + * + * @xxx compress can be clean, shrink, obfuscate or best + */ + public function __construct(Source $fileName, int $line, string $bin = 'jpack', string $compress = 'best') { //Set fileName $this->fileName = $fileName; @@ -53,7 +68,10 @@ class JPackFilter implements FilterInterface { } } - public function process($content) { + /** + * {@inheritdoc} + */ + public function process(string $content): string { //Create descriptors $descriptorSpec = array( 0 => array('pipe', 'r'), @@ -64,7 +82,7 @@ class JPackFilter implements FilterInterface { //Open process if (is_resource($proc = proc_open($this->bin, $descriptorSpec, $pipes))) { //Set stderr as non blocking - stream_set_blocking($pipes[2], 0); + stream_set_blocking($pipes[2], false); //Send content to stdin fwrite($pipes[0], $content); -- 2.41.1 From a89acd005990aa42339d4f90fb5c5c5520edc906 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:34:37 +0200 Subject: [PATCH 07/16] New tree layout Add strict types Improve documentation Cleanup --- Filter/CPackFilter.php | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Filter/CPackFilter.php b/Filter/CPackFilter.php index ca38c3b..853e94a 100644 --- a/Filter/CPackFilter.php +++ b/Filter/CPackFilter.php @@ -1,10 +1,22 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Rapsys\PackBundle\Filter; -use Rapsys\PackBundle\Twig\Filter\FilterInterface; use Twig\Error\Error; +use Twig\Source; +/** + * {@inheritdoc} + */ class CPackFilter implements FilterInterface { //Default bin private $bin; @@ -18,9 +30,12 @@ class CPackFilter implements FilterInterface { //Twig template line private $line; - //Configure the object - //XXX: compress can be minify or pretty - public function __construct($fileName, $line, $bin = 'cpack', $compress = 'minify') { + /** + * Setup cpack filter + * + * @xxx compress can be minify or pretty + */ + public function __construct(Source $fileName, int $line, string $bin = 'cpack', string $compress = 'minify') { //Set fileName $this->fileName = $fileName; @@ -47,7 +62,10 @@ class CPackFilter implements FilterInterface { } } - public function process($content) { + /** + * {@inheritdoc} + */ + public function process(string $content): string { //Create descriptors $descriptorSpec = array( 0 => array('pipe', 'r'), @@ -58,7 +76,7 @@ class CPackFilter implements FilterInterface { //Open process if (is_resource($proc = proc_open($this->bin, $descriptorSpec, $pipes))) { //Set stderr as non blocking - stream_set_blocking($pipes[2], 0); + stream_set_blocking($pipes[2], false); //Send content to stdin fwrite($pipes[0], $content); -- 2.41.1 From 83f10fd131e8d4fad68cc77480aa7c49512c505a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:35:09 +0200 Subject: [PATCH 08/16] New tree layout Add strict types Improve documentation Cleanup --- README.md | 60 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 3f3ab87..b50ca2d 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,14 @@ Add bundle custom repository to your project's `composer.json` file: "psr-4": { "Rapsys\\PackBundle\\": "" } + }, + "require": { + "symfony/asset": "^4.4", + "symfony/flex": "^1.5", + "symfony/framework-bundle": "^4.4", + "symfony/process": "^4.4", + "symfony/twig-bundle": "^4.4", + "twig/extensions": "^1.5" } } } @@ -82,32 +90,46 @@ class AppKernel extends Kernel ### Step 3: Configure the Bundle -Verify that you have the configuration file `config/packages/rapsys_pack.yaml` -with the following content: +Setup configuration file `config/packages/rapsys_pack.yaml` with the following +content available in `Resources/config/packages/rapsys_pack.yaml`: ```yaml #Services configuration services: + #Replace assets.packages definition + assets.packages: + class: 'Symfony\Component\Asset\Packages' + arguments: [ '@rapsys_pack.path_package' ] + #Replace assets.context definition + assets.context: + class: 'Rapsys\PackBundle\Context\RequestStackContext' + arguments: [ '@request_stack', '%asset.request_context.base_path%', '%asset.request_context.secure%' ] #Register assets pack package - assets.pack_package: - class: Rapsys\PackBundle\Asset\PathPackage + rapsys_pack.path_package: + class: 'Rapsys\PackBundle\Package\PathPackage' arguments: [ '/', '@assets.empty_version_strategy', '@assets.context' ] + public: true #Register twig pack extension - rapsys_pack.twig.pack_extension: - class: Rapsys\PackBundle\Twig\PackExtension - arguments: [ '@file_locator', '@service_container', '@assets.pack_package' ] - tags: [ twig.extension ] + rapsys_pack.pack_extension: + class: 'Rapsys\PackBundle\Extension\PackExtension' + arguments: [ '@file_locator', '@service_container', '@rapsys_pack.path_package', '@rapsys_pack.slugger_util' ] + tags: [ 'twig.extension' ] + #Register slugger utils service + rapsys_pack.slugger_util: + class: 'Rapsys\PackBundle\Util\SluggerUtil' + arguments: [ '%env(APP_SECRET)%' ] + public: true ``` -Open a command console, enter your project directory and execute the -following command to see default bundle configuration: +Open a command console, enter your project directory and execute the following +command to see default bundle configuration: ```console $ php bin/console config:dump-reference RapsysPackBundle ``` -Open a command console, enter your project directory and execute the -following command to see current bundle configuration: +Open a command console, enter your project directory and execute the following +command to see current bundle configuration: ```console $ php bin/console debug:config RapsysPackBundle @@ -115,7 +137,8 @@ $ php bin/console debug:config RapsysPackBundle ### Step 4: Use the twig extension in your Template -You can use a template like this to generate your first `rapsys_pack` enabled template: +You can use a template like this to generate your first `rapsys_pack` enabled +template: ```twig @@ -169,15 +192,14 @@ You can create you own mypackfilter class which call a mypack binary: ```php fileName = $fileName; @@ -200,7 +222,7 @@ class MyPackFilter implements FilterInterface { } //Pass merge of all inputs in content - public function process($content) { + public function process(string $content): string { //Create descriptors $descriptorSpec = array( 0 => array('pipe', 'r'), @@ -211,7 +233,7 @@ class MyPackFilter implements FilterInterface { //Open process if (is_resource($proc = proc_open($this->bin, $descriptorSpec, $pipes))) { //Set stderr as non blocking - stream_set_blocking($pipes[2], 0); + stream_set_blocking($pipes[2], false); //Send content to stdin fwrite($pipes[0], $content); @@ -247,4 +269,4 @@ class MyPackFilter implements FilterInterface { } ``` -The class is required to get it's arguments through constructor and have a process method. +The class must implements FilterInterface and get it's arguments through constructor. -- 2.41.1 From 54aa1b26da12d7d0aedf04eca87277255a98ba9d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 14:46:36 +0200 Subject: [PATCH 09/16] Update mail address Update composer requires --- composer.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 0d6f49d..404bfa5 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "type": "symfony-bundle", "authors": [{ "name": "Raphaël Gertz", - "email": "packbundle@rapsys.eu" + "email": "symfony@rapsys.eu" }], "autoload": { "psr-4": { @@ -13,11 +13,12 @@ } }, "require": { - "php": "*", - "symfony/config": "*", - "symfony/dependency-injection": "*", - "symfony/asset": "*", - "twig/extensions": "*" + "symfony/asset": "^4.4", + "symfony/flex": "^1.5", + "symfony/framework-bundle": "^4.4", + "symfony/process": "^4.4", + "symfony/twig-bundle": "^4.4", + "twig/extensions": "^1.5" }, "extra": { "branch-alias": { -- 2.41.1 From 438757217861be80e99c8648b3f4e57d207f4198 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 15:40:18 +0200 Subject: [PATCH 10/16] Remove mixed strict type for data as it may be array or string Improve doc --- Util/SluggerUtil.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Util/SluggerUtil.php b/Util/SluggerUtil.php index 14a128d..0d8f346 100644 --- a/Util/SluggerUtil.php +++ b/Util/SluggerUtil.php @@ -84,14 +84,14 @@ class SluggerUtil { /** * Flatten recursively an array * - * @param array $data The data tree + * @param array|string $data The data tree * @param string|null $current The current prefix * @param string $sep The key separator * @param string $prefix The key prefix * @param string $suffix The key suffix * @return array The flattened data */ - public function flatten(array $data, mixed $current = null, string $sep = '.', string $prefix = '', string $suffix = ''): array { + public function flatten($data, ?string $current = null, string $sep = '.', string $prefix = '', string $suffix = ''): array { //Init result $ret = []; -- 2.41.1 From e228b33bad82184f989a081b162e127c1a949f10 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 15:41:32 +0200 Subject: [PATCH 11/16] Remove strict type for path to conform to parent definition --- Package/PathPackage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package/PathPackage.php b/Package/PathPackage.php index 4746fe9..8b53136 100644 --- a/Package/PathPackage.php +++ b/Package/PathPackage.php @@ -69,7 +69,7 @@ class PathPackage extends Package { * * {@inheritdoc} */ - public function getUrl(string $path): string { + public function getUrl($path): string { //Match url starting with a bundle name if (preg_match('%^@([A-Z][a-zA-Z]*?)(?:Bundle/Resources/public)?/(.*)$%', $path, $matches)) { //Handle empty or without replacement pattern basePath -- 2.41.1 From 617c8ffd029b19af880da209ec7d3f0ddb20d28d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 8 Aug 2021 15:42:34 +0200 Subject: [PATCH 12/16] Add SluggerUtil class alias --- Resources/config/packages/rapsys_pack.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Resources/config/packages/rapsys_pack.yaml b/Resources/config/packages/rapsys_pack.yaml index 3f93ff4..b9a1645 100644 --- a/Resources/config/packages/rapsys_pack.yaml +++ b/Resources/config/packages/rapsys_pack.yaml @@ -18,8 +18,11 @@ services: class: 'Rapsys\PackBundle\Extension\PackExtension' arguments: [ '@file_locator', '@service_container', '@rapsys_pack.path_package', '@rapsys_pack.slugger_util' ] tags: [ 'twig.extension' ] - #Register slugger utils service + #Register slugger util service rapsys_pack.slugger_util: class: 'Rapsys\PackBundle\Util\SluggerUtil' arguments: [ '%env(APP_SECRET)%' ] public: true + #Register slugger util class alias + Rapsys\PackBundle\Util\SluggerUtil: + alias: 'rapsys_pack.slugger_util' -- 2.41.1 From 9f79688919cb4245f6a971c7eb47fbea1e437bb6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Wed, 11 Aug 2021 20:23:22 +0200 Subject: [PATCH 13/16] Switch to kernel.secret like documented in symfony example --- Resources/config/packages/rapsys_pack.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/config/packages/rapsys_pack.yaml b/Resources/config/packages/rapsys_pack.yaml index b9a1645..26e957b 100644 --- a/Resources/config/packages/rapsys_pack.yaml +++ b/Resources/config/packages/rapsys_pack.yaml @@ -21,7 +21,7 @@ services: #Register slugger util service rapsys_pack.slugger_util: class: 'Rapsys\PackBundle\Util\SluggerUtil' - arguments: [ '%env(APP_SECRET)%' ] + arguments: [ '%kernel.secret%' ] public: true #Register slugger util class alias Rapsys\PackBundle\Util\SluggerUtil: -- 2.41.1 From ff3c3d6005d4b6263ab27b6541390a9d95d7d822 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Wed, 11 Aug 2021 20:24:30 +0200 Subject: [PATCH 14/16] Skip short empty data Throw exception on unknown character in short to avoid silent corruption Switch to json_encode to prevent utf-8 character in encoded string Cleanup --- Util/SluggerUtil.php | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Util/SluggerUtil.php b/Util/SluggerUtil.php index 0d8f346..5b05958 100644 --- a/Util/SluggerUtil.php +++ b/Util/SluggerUtil.php @@ -42,9 +42,12 @@ class SluggerUtil { //Set secret $this->secret = $secret; - //Pseudo-random alphabet - //XXX: use array flip and keys to workaround php "smart" that cast range('0', '9') as int instead of string - //XXX: The key count mismatch, count(alpha)>count(rev), resulted in a data corruption due to duplicate numeric values + /** + * Pseudo-random alphabet + * @xxx use array flip and keys to workaround php "smart" that cast range('0', '9') as int instead of string + * @xxx The key count mismatch, count(alpha)>count(rev), resulted in a data corruption due to duplicate numeric values + * @todosee required range by json_encode result and short input (0->255 ???) + */ $this->alpha = array_keys(array_flip(array_merge( range('^', '[', -1), range('V', 'Z'), @@ -133,7 +136,8 @@ class SluggerUtil { */ public function serialize(array $data): string { //Return shorted serialized data - return $this->short(serialize($data)); + //XXX: dropped serialize use to prevent short function from dropping utf-8 characters + return $this->short(json_encode($data)); } /** @@ -146,11 +150,16 @@ class SluggerUtil { //Return string $ret = ''; - //Iterate on each character - foreach(str_split($data) as $k => $c) { - if (isset($this->rev[$c]) && isset($this->alpha[($this->rev[$c]+$this->offset)%$this->count])) { - //XXX: Remap char to an other one - $ret .= chr(($this->rev[$c] - $this->offset + $this->count) % $this->count); + //With data + if (!empty($data)) { + //Iterate on each character + foreach(str_split($data) as $k => $c) { + if (isset($this->rev[$c]) && isset($this->alpha[($this->rev[$c]+$this->offset)%$this->count])) { + //XXX: Remap char to an other one + $ret .= chr(($this->rev[$c] - $this->offset + $this->count) % $this->count); + } else { + throw new \RuntimeException(sprintf('Unable to retrieve character: %c', $c)); + } } } @@ -184,7 +193,7 @@ class SluggerUtil { */ public function unserialize(string $data): array { //Return unshorted unserialized string - return unserialize($this->unshort($data)); + return json_decode($this->unshort($data), true); } /** -- 2.41.1 From ce4ef48d51a312fa5f854e91f3825a699d9325e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Wed, 11 Aug 2021 20:33:30 +0200 Subject: [PATCH 15/16] Move alias generation in RapsysPackBundle::getAlias --- DependencyInjection/Configuration.php | 4 ++- DependencyInjection/RapsysPackExtension.php | 4 ++- Extension/PackExtension.php | 5 ++-- RapsysPackBundle.php | 32 ++++++++++++++++++++- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 0265db3..7217e98 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -15,6 +15,8 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Process\ExecutableFinder; +use Rapsys\PackBundle\RapsysPackBundle; + /** * This is the class that validates and merges configuration from your app/config files. * @@ -28,7 +30,7 @@ class Configuration implements ConfigurationInterface { */ public function getConfigTreeBuilder(): TreeBuilder { //Get TreeBuilder object - $treeBuilder = new TreeBuilder('rapsys_pack'); + $treeBuilder = new TreeBuilder(RapsysPackBundle::getAlias()); //Get ExecutableFinder object $finder = new ExecutableFinder(); diff --git a/DependencyInjection/RapsysPackExtension.php b/DependencyInjection/RapsysPackExtension.php index 5bf3008..94b9fad 100644 --- a/DependencyInjection/RapsysPackExtension.php +++ b/DependencyInjection/RapsysPackExtension.php @@ -14,6 +14,8 @@ namespace Rapsys\PackBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; +use Rapsys\PackBundle\RapsysPackBundle; + /** * This is the class that loads and manages your bundle configuration. * @@ -46,6 +48,6 @@ class RapsysPackExtension extends Extension { * {@inheritdoc} */ public function getAlias(): string { - return 'rapsys_pack'; + return RapsysPackBundle::getAlias(); } } diff --git a/Extension/PackExtension.php b/Extension/PackExtension.php index 118de0c..48f93cd 100644 --- a/Extension/PackExtension.php +++ b/Extension/PackExtension.php @@ -16,8 +16,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Config\FileLocator; use Twig\Extension\AbstractExtension; -use Rapsys\PackBundle\Util\SluggerUtil; use Rapsys\PackBundle\Parser\TokenParser; +use Rapsys\PackBundle\RapsysPackBundle; +use Rapsys\PackBundle\Util\SluggerUtil; /** * {@inheritdoc} @@ -95,6 +96,6 @@ class PackExtension extends AbstractExtension { * {@inheritdoc} */ public function getAlias(): string { - return 'rapsys_pack'; + return RapsysPackBundle::getAlias(); } } diff --git a/RapsysPackBundle.php b/RapsysPackBundle.php index 260ce22..ca879af 100644 --- a/RapsysPackBundle.php +++ b/RapsysPackBundle.php @@ -11,9 +11,39 @@ namespace Rapsys\PackBundle; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpKernel\Bundle\Bundle; /** * {@inheritdoc} */ -class RapsysPackBundle extends Bundle {} +class RapsysPackBundle extends Bundle { + /** + * Return bundle alias + * + * @return string The bundle alias + */ + public function getAlias(): string { + //With namespace + if ($npos = strrpos(static::class, '\\')) { + //Set name pos + $npos++; + //Without namespace + } else { + $npos = 0; + } + + //With trailing bundle + if (substr(static::class, -strlen('Bundle'), strlen('Bundle')) === 'Bundle') { + //Set bundle pos + $bpos = strlen(static::class) - $npos - strlen('Bundle'); + //Without bundle + } else { + //Set bundle pos + $bpos = strlen(static::class) - $npos; + } + + //Return underscored lowercase bundle alias + return Container::underscore(substr(static::class, $npos, $bpos)); + } +} -- 2.41.1 From 44ea2f60a6d17b6c9475a6e87a1f520200c7d036 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Wed, 11 Aug 2021 20:46:13 +0200 Subject: [PATCH 16/16] Call self::getAlias --- DependencyInjection/RapsysPackExtension.php | 4 ++-- Extension/PackExtension.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DependencyInjection/RapsysPackExtension.php b/DependencyInjection/RapsysPackExtension.php index 94b9fad..c73e90c 100644 --- a/DependencyInjection/RapsysPackExtension.php +++ b/DependencyInjection/RapsysPackExtension.php @@ -37,11 +37,11 @@ class RapsysPackExtension extends Extension { //Detect when no user configuration is provided if ($configs === [[]]) { //Prepend default config - $container->prependExtensionConfig($this->getAlias(), $config); + $container->prependExtensionConfig(self::getAlias(), $config); } //Save configuration in parameters - $container->setParameter($this->getAlias(), $config); + $container->setParameter(self::getAlias(), $config); } /** diff --git a/Extension/PackExtension.php b/Extension/PackExtension.php index 48f93cd..40863e9 100644 --- a/Extension/PackExtension.php +++ b/Extension/PackExtension.php @@ -58,7 +58,7 @@ class PackExtension extends AbstractExtension { $this->package = $package; //Retrieve bundle config - if ($parameters = $container->getParameter($this->getAlias())) { + if ($parameters = $container->getParameter(self::getAlias())) { //Set config, output and filters arrays foreach(['config', 'output', 'filters'] as $k) { $this->$k = $parameters[$k]; -- 2.41.1