From 060aa4e7dd4d917cd58bd026b4a0892d3416048c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Thu, 29 Feb 2024 17:31:31 +0100 Subject: [PATCH 01/16] Trim trailing equal in short --- Util/SluggerUtil.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/SluggerUtil.php b/Util/SluggerUtil.php index d88cdfd..5c84ca8 100644 --- a/Util/SluggerUtil.php +++ b/Util/SluggerUtil.php @@ -174,7 +174,7 @@ class SluggerUtil { } //Send result - return str_replace(['+','/'], ['-','_'], base64_encode($ret)); + return str_replace(['+','/','='], ['-','_',''], base64_encode($ret)); } /** -- 2.41.3 From ef9ee86cb52ee5b4e1ab70c26fd977fa2eb80586 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sat, 2 Mar 2024 23:59:48 +0100 Subject: [PATCH 02/16] Remove hardcoded range Add range to constructor argument Cleanup --- Util/SluggerUtil.php | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/Util/SluggerUtil.php b/Util/SluggerUtil.php index 5c84ca8..3b1e6b5 100644 --- a/Util/SluggerUtil.php +++ b/Util/SluggerUtil.php @@ -38,45 +38,20 @@ class SluggerUtil { /** * Construct slugger util * - * TODO: use a recipe to generate in .env.local an env variable RAPSYSPACK_SECRET="ayl[...]z9w" + * @description Run "php bin/console rapsyspack:range" to generate RAPSYSPACK_RANGE="ayl[...]z9w" range in .env.local * - * @todo Add a command to generate alpha array or generate it on first run with cache storage ? - * @todo Use Cache like in calendar controller through FilesystemAdapter + * @todo Use Cache like in calendar controller through FilesystemAdapter ? * + * @param string $range The shuffled range string * @param string $secret The secret string */ - public function __construct(protected string $secret) { + public function __construct(protected string $range, protected string $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 - * @todosee required range by json_encode result and short input (0->255 ???) + * Get pseuto-random alphabet by splitting range string + * TODO: see required range by json_encode result and short input (0->255 ???) + * XXX: The key count mismatch, count(alpha)>count(rev), resulted in a data corruption due to duplicate numeric values */ - $this->alpha = array_keys(array_flip(array_merge( - range('^', '[', -1), - range('V', 'Z'), - range('9', '7', -1), - range('L', 'O'), - range('f', 'a', -1), - range('_', '`'), - range('3', '0', -1), - range('E', 'H'), - range('v', 'r', -1), - range('+', '/'), - range('K', 'I', -1), - range('g', 'j'), - range('=', ':', -1), - range('>', '@'), - range('m', 'k', -1), - range('4', '6'), - range('*', '%', -1), - range('n', 'q'), - range('U', 'P', -1), - range(' ', '$'), - range('D', 'A', -1), - range('w', 'z'), - range('~', '!', -1) - ))); + $this->alpha = str_split($this->range); //Init rev array $this->count = count($rev = $this->rev = array_flip($this->alpha)); -- 2.41.3 From c33e232a61870982bcb859a3d8ad3d82ab9b68b4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 3 Mar 2024 00:02:28 +0100 Subject: [PATCH 03/16] Remove underscore from bundle alias Update version --- RapsysPackBundle.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/RapsysPackBundle.php b/RapsysPackBundle.php index e773042..4ad24d4 100644 --- a/RapsysPackBundle.php +++ b/RapsysPackBundle.php @@ -11,13 +11,23 @@ namespace Rapsys\PackBundle; -use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Rapsys\PackBundle\DependencyInjection\RapsysPackExtension; + /** * {@inheritdoc} */ class RapsysPackBundle extends Bundle { + /** + * {@inheritdoc} + */ + public function getContainerExtension(): ?ExtensionInterface { + //Return created container extension + return $this->createContainerExtension(); + } + /** * Return bundle alias * @@ -43,8 +53,8 @@ class RapsysPackBundle extends Bundle { $bpos = strlen(static::class) - $npos; } - //Return underscored lowercase bundle alias - return Container::underscore(substr(static::class, $npos, $bpos)); + //Return lowercase bundle alias + return strtolower(substr(static::class, $npos, $bpos)); } /** @@ -54,6 +64,6 @@ class RapsysPackBundle extends Bundle { */ public static function getVersion(): string { //Return version - return '0.2.5'; + return '0.4.0'; } } -- 2.41.3 From 762348ccbc2445dbf1f1267898ee68858e4bbd46 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 3 Mar 2024 00:04:42 +0100 Subject: [PATCH 04/16] Range command appending RAPSYSPACK_RANGE to local env config file --- Command/RangeCommand.php | 129 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 Command/RangeCommand.php diff --git a/Command/RangeCommand.php b/Command/RangeCommand.php new file mode 100644 index 0000000..e18fafa --- /dev/null +++ b/Command/RangeCommand.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Rapsys\PackBundle\Command; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +use Rapsys\PackBundle\Command; + +/** + * Shuffle printable character range + * + * {@inheritdoc} + */ +class RangeCommand extends Command { + /** + * Set description + * + * @description Shown with bin/console list + */ + protected string $description = 'Outputs a shuffled printable characters range'; + + /** + * Set help + * + * @description Shown with bin/console --help packbundle:range + */ + protected string $help = 'This command outputs a shuffled printable characters range'; + + /** + * {@inheritdoc} + */ + public function __construct(protected ?string $name = null, protected string $file = '.env.local') { + //Call parent constructor + parent::__construct($this->name); + + //Add argument + $this->addArgument('file', InputArgument::OPTIONAL, 'Environment file', $this->file); + } + + /** + * Output a shuffled printable characters range + * + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int { + //Printable character range + $ranges = range(' ', '~'); + + //Range shuffled + $shuffles = []; + + //Shuffle range array + do { + //Set start offset + $offset = rand(0, ($count = count($ranges)) - 1); + //Set length + $length = rand(1, $count - $offset < ($ceil = (int)ceil(($count+count($shuffles))/rand(5,10))) ? $count - $offset : rand(2, $ceil)); + //Splice array + $slices = array_splice($ranges, $offset, $length); + //When reverse + if (rand(0, 1)) { + //Reverse sliced array + $slices = array_reverse($slices); + } + //Append sliced array + $shuffles = array_merge($shuffles, $slices); + } while (!empty($ranges)); + + //With writeable file + if (is_file($file = $input->getArgument('file')) && is_writeable($file)) { + //Get file content + if (($content = file_get_contents($file, false)) === false) { + //Display error + error_log(sprintf('Unable to get %s content', $file), 0); + + //Return failure + return self::FAILURE; + } + + //Set string + $string = 'RAPSYSPACK_RANGE="'.strtr(implode($shuffles), ['\\' => '\\\\', '"' => '\\"', '$' => '\\$']).'"'; + + //With match + if (preg_match('/^RAPSYSPACK_RANGE=.*$/m', $content, $matches, PREG_OFFSET_CAPTURE)) { + //Replace matches + $content = preg_replace('/^(RAPSYSPACK_RANGE=.*)$/m', '#$1'."\n".strtr($string, ['\\' => '\\\\', '\\$' => '\\\\$']), $content); + //Without match + } else { + $content .= "\n".$string; + } + + //Write file content + if (file_put_contents($file, $content) === false) { + //Display error + error_log(sprintf('Unable to put %s content', $file), 0); + + //Return failure + return self::FAILURE; + } + + //Print content + echo $content; + //Without writeable file + } else { + //Print instruction + echo '# Set in '.$file."\n"; + + //Print rapsys pack range variable + echo 'RAPSYSPACK_RANGE='; + + //Print shuffled range + var_export(implode($shuffles)); + } + + //Return success + return self::SUCCESS; + } +} -- 2.41.3 From 7affe635a0275597a8ee8e4b80e1742ab183e699 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:12:59 +0100 Subject: [PATCH 05/16] Remove config key Add token key Reorder existing keys --- DependencyInjection/Configuration.php | 75 +++++++++++---------------- 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 2e57ae8..ebbdbfd 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -38,20 +38,6 @@ class Configuration implements ConfigurationInterface { //The bundle default values $defaults = [ - 'config' => [ - 'name' => 'asset_url', - 'scheme' => 'https://', - 'timeout' => (int)ini_get('default_socket_timeout'), - 'agent' => $alias.'/'.($version = RapsysPackBundle::getVersion()), - 'redirect' => 5 - ], - #TODO: migrate to public.path, public.url and router->generateUrl ? - #XXX: that would means dropping the PathPackage stuff and use static route like rapsys_pack_facebook - 'output' => [ - 'css' => '@RapsysPack/css/*.pack.css', - 'js' => '@RapsysPack/js/*.pack.js', - 'img' => '@RapsysPack/img/*.pack.jpg' - ], 'filters' => [ 'css' => [ 0 => [ @@ -62,6 +48,12 @@ class Configuration implements ConfigurationInterface { ] ] ], + 'img' => [ + 0 => [ + 'class' => 'Rapsys\PackBundle\Filter\IPackFilter', + 'args' => [] + ] + ], 'js' => [ 0 => [ 'class' => 'Rapsys\PackBundle\Filter\JPackFilter', @@ -70,15 +62,17 @@ class Configuration implements ConfigurationInterface { 'best' ] ] - ], - 'img' => [ - 0 => [ - 'class' => 'Rapsys\PackBundle\Filter\IPackFilter', - 'args' => [] - ] - ], + ] + ], + #TODO: migrate to public.path, public.url and router->generateUrl ? + #XXX: that would means dropping the PathPackage stuff and use static route like rapsys_pack_facebook + 'output' => [ + 'css' => '@RapsysPack/css/*.pack.css', + 'img' => '@RapsysPack/img/*.pack.jpg', + 'js' => '@RapsysPack/js/*.pack.js' ], 'path' => dirname(__DIR__).'/Resources/public', + 'token' => 'asset_url' ]; /** @@ -96,24 +90,6 @@ class Configuration implements ConfigurationInterface { ->getRootNode() ->addDefaultsIfNotSet() ->children() - ->arrayNode('config') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('name')->cannotBeEmpty()->defaultValue($defaults['config']['name'])->end() - ->scalarNode('scheme')->cannotBeEmpty()->defaultValue($defaults['config']['scheme'])->end() - ->integerNode('timeout')->min(0)->max(300)->defaultValue($defaults['config']['timeout'])->end() - ->scalarNode('agent')->cannotBeEmpty()->defaultValue($defaults['config']['agent'])->end() - ->integerNode('redirect')->min(1)->max(30)->defaultValue($defaults['config']['redirect'])->end() - ->end() - ->end() - ->arrayNode('output') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('css')->cannotBeEmpty()->defaultValue($defaults['output']['css'])->end() - ->scalarNode('js')->cannotBeEmpty()->defaultValue($defaults['output']['js'])->end() - ->scalarNode('img')->cannotBeEmpty()->defaultValue($defaults['output']['img'])->end() - ->end() - ->end() ->arrayNode('filters') ->addDefaultsIfNotSet() ->children() @@ -140,7 +116,7 @@ class Configuration implements ConfigurationInterface { ->end() ->end() ->end() - ->arrayNode('js') + ->arrayNode('img') /** * Undocumented * @@ -152,17 +128,17 @@ class Configuration implements ConfigurationInterface { ->scalarNode('class') ->isRequired() ->cannotBeEmpty() - ->defaultValue($defaults['filters']['js'][0]['class']) + ->defaultValue($defaults['filters']['img'][0]['class']) ->end() ->arrayNode('args') ->treatNullLike([]) - ->defaultValue($defaults['filters']['js'][0]['args']) + ->defaultValue($defaults['filters']['img'][0]['args']) ->scalarPrototype()->end() ->end() ->end() ->end() ->end() - ->arrayNode('img') + ->arrayNode('js') /** * Undocumented * @@ -174,11 +150,11 @@ class Configuration implements ConfigurationInterface { ->scalarNode('class') ->isRequired() ->cannotBeEmpty() - ->defaultValue($defaults['filters']['img'][0]['class']) + ->defaultValue($defaults['filters']['js'][0]['class']) ->end() ->arrayNode('args') ->treatNullLike([]) - ->defaultValue($defaults['filters']['img'][0]['args']) + ->defaultValue($defaults['filters']['js'][0]['args']) ->scalarPrototype()->end() ->end() ->end() @@ -186,7 +162,16 @@ class Configuration implements ConfigurationInterface { ->end() ->end() ->end() + ->arrayNode('output') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('css')->cannotBeEmpty()->defaultValue($defaults['output']['css'])->end() + ->scalarNode('img')->cannotBeEmpty()->defaultValue($defaults['output']['img'])->end() + ->scalarNode('js')->cannotBeEmpty()->defaultValue($defaults['output']['js'])->end() + ->end() + ->end() ->scalarNode('path')->cannotBeEmpty()->defaultValue($defaults['path'])->end() + ->scalarNode('token')->cannotBeEmpty()->defaultValue($defaults['token'])->end() ->end() ->end(); -- 2.41.3 From 96fd400cf3fce1bdca1a9df772d6e07096af545a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:17:31 +0100 Subject: [PATCH 06/16] Remove getAlias member function Add alias and version bundle parameter --- DependencyInjection/RapsysPackExtension.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/DependencyInjection/RapsysPackExtension.php b/DependencyInjection/RapsysPackExtension.php index 2bc7f67..435498e 100644 --- a/DependencyInjection/RapsysPackExtension.php +++ b/DependencyInjection/RapsysPackExtension.php @@ -34,23 +34,25 @@ class RapsysPackExtension extends Extension { //Process the configuration to get merged config $config = $this->processConfiguration($configuration, $configs); + //Set bundle alias + $alias = RapsysPackBundle::getAlias(); + //Detect when no user configuration is provided if ($configs === [[]]) { //Prepend default config - $container->prependExtensionConfig(self::getAlias(), $config); + $container->prependExtensionConfig($alias, $config); } //Save configuration in parameters - $container->setParameter(self::getAlias(), $config); + $container->setParameter($alias, $config); + + //Set rapsys_pack.alias key + $container->setParameter($alias.'.alias', $alias); //Set rapsys_pack.path key - $container->setParameter(self::getAlias().'.path', $config['path']); - } + $container->setParameter($alias.'.path', $config['path']); - /** - * {@inheritdoc} - */ - public function getAlias(): string { - return RapsysPackBundle::getAlias(); + //Set rapsys_pack.version key + $container->setParameter($alias.'.version', RapsysPackBundle::getVersion()); } } -- 2.41.3 From b5bfae95e2e0a3561ac9277d17bcc6450e569033 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:18:41 +0100 Subject: [PATCH 07/16] Reorder constructor arguments --- Command/RangeCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Command/RangeCommand.php b/Command/RangeCommand.php index e18fafa..f720493 100644 --- a/Command/RangeCommand.php +++ b/Command/RangeCommand.php @@ -40,7 +40,7 @@ class RangeCommand extends Command { /** * {@inheritdoc} */ - public function __construct(protected ?string $name = null, protected string $file = '.env.local') { + public function __construct(protected string $file = '.env.local', protected ?string $name = null) { //Call parent constructor parent::__construct($this->name); -- 2.41.3 From 41e15ab5df817a5178b73a08bcfb2298842cc559 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:31:49 +0100 Subject: [PATCH 08/16] Remove config array for RAPSYSPACK_AGENT, RAPSYSPACK_REDIRECT, RAPSYSPACK_SCHEME and RAPSYSPACK_TIMEOUT env variables Rename name to token Replace name, filters and output variables for member variables --- Parser/TokenParser.php | 66 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/Parser/TokenParser.php b/Parser/TokenParser.php index 02acca3..1115e0c 100644 --- a/Parser/TokenParser.php +++ b/Parser/TokenParser.php @@ -25,6 +25,8 @@ use Twig\Source; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; +use Rapsys\PackBundle\RapsysPackBundle; + class TokenParser extends AbstractTokenParser { /** * The stream context instance @@ -36,25 +38,20 @@ class TokenParser extends AbstractTokenParser { * * @param FileLocator $locator The FileLocator instance * @param PackageInterface $package The Assets Package instance - * @param array $config The config path + * @param string $token The token name * @param string $tag The tag name * @param string $output The default output string - * @param array $filters The default filters array + * @param array $filters The default filter array */ - //TODO: change config to name and get other values from RAPSYSPACK_REDIRECT, RAPSYSPACK_SCHEME, RAPSYSPACK_TIMEOUT, RAPSYSPACK_AGENT env variables ? - public function __construct(protected FileLocator $locator, protected PackageInterface $package, protected array $config, protected string $tag, protected string $output, protected array $filters) { + public function __construct(protected FileLocator $locator, protected PackageInterface $package, protected string $token, protected string $tag, protected string $output, protected array $filters) { //Set ctx $this->ctx = stream_context_create( [ 'http' => [ #'header' => ['Referer: https://www.openstreetmap.org/'], - //TODO: set as bundle env config - 'max_redirects' => $config['redirect']?:5, - //TODO: set as bundle env config - 'timeout' => $config['timeout']?:(int)ini_get('default_socket_timeout'), - #'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36', - //TODO: set as bundle env config - 'user_agent' => $config['agent']?:(string)ini_get('user_agent')?:'rapsys_pack/2.0.0', + 'max_redirects' => $_ENV['RAPSYSPACK_REDIRECT'] ?? 20, + 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (int)ini_get('default_socket_timeout') ?: 60, + 'user_agent' => $_ENV['RAPSYSPACK_AGENT'] ?? (($agent = ini_get('user_agent')) !== false && $agent !== "" ? (string)$agent : RapsysPackBundle::getAlias().'/'.RapsysPackBundle::getVersion()) ] ] ); @@ -80,14 +77,16 @@ class TokenParser extends AbstractTokenParser { * @return Node The PackNode */ public function parse(Token $token): Node { + //Get parser $parser = $this->parser; + + //Get parser stream $stream = $this->parser->getStream(); + //Set inputs array $inputs = []; - $name = $this->config['name']; - $output = $this->output; - $filters = $this->filters; + //Set content $content = ''; //Process the token block until end @@ -101,19 +100,19 @@ class TokenParser extends AbstractTokenParser { //filter='yui_js' $stream->next(); $stream->expect(Token::OPERATOR_TYPE, '='); - $filters = array_merge($filters, array_filter(array_map('trim', explode(',', $stream->expect(Token::STRING_TYPE)->getValue())))); + $this->filters = array_merge($this->filters, array_filter(array_map('trim', explode(',', $stream->expect(Token::STRING_TYPE)->getValue())))); //The output token } elseif ($stream->test(Token::NAME_TYPE, 'output')) { //output='js/packed/*.js' OR output='js/core.js' $stream->next(); $stream->expect(Token::OPERATOR_TYPE, '='); - $output = $stream->expect(Token::STRING_TYPE)->getValue(); - //The name token - } elseif ($stream->test(Token::NAME_TYPE, 'name')) { + $this->output = $stream->expect(Token::STRING_TYPE)->getValue(); + //The token name + } elseif ($stream->test(Token::NAME_TYPE, 'token')) { //name='core_js' $stream->next(); $stream->expect(Token::OPERATOR_TYPE, '='); - $name = $stream->expect(Token::STRING_TYPE)->getValue(); + $this->token = $stream->expect(Token::STRING_TYPE)->getValue(); //Unexpected token } else { $token = $stream->getCurrent(); @@ -131,9 +130,9 @@ class TokenParser extends AbstractTokenParser { $stream->expect(Token::BLOCK_END_TYPE); //Replace star with sha1 - if (($pos = strpos($output, '*')) !== false) { - //XXX: assetic use substr(sha1(serialize($inputs).serialize($filters).serialize($options)), 0, 7) - $output = substr($output, 0, $pos).sha1(serialize($inputs).serialize($filters)).substr($output, $pos + 1); + if (($pos = strpos($this->output, '*')) !== false) { + //XXX: assetic use substr(sha1(serialize($inputs).serialize($this->filters).serialize($this->output)), 0, 7) + $this->output = substr($this->output, 0, $pos).sha1(serialize($inputs).serialize($this->filters)).substr($this->output, $pos + 1); } //Process inputs @@ -141,8 +140,7 @@ class TokenParser extends AbstractTokenParser { //Deal with generic url if (strpos($inputs[$k], '//') === 0) { //Fix url - //TODO: set as bundle env config - $inputs[$k] = $this->config['scheme'].substr($inputs[$k], 2); + $inputs[$k] = ($_ENV['RAPSYSPACK_SCHEME'] ?? 'https://').substr($inputs[$k], 2); //Deal with non url path } elseif (strpos($inputs[$k], '://') === false) { //Check if we have a bundle path @@ -194,9 +192,9 @@ class TokenParser extends AbstractTokenParser { } //Check filters - if (!empty($filters)) { + if (!empty($this->filters)) { //Apply all filters - foreach($filters as $filter) { + foreach($this->filters as $filter) { //Init args $args = [$stream->getSourceContext(), $token->getLine()]; //Check if args is available @@ -221,21 +219,21 @@ class TokenParser extends AbstractTokenParser { //Retrieve asset uri //XXX: this path is the merge of services.assets.path_package.arguments[0] and rapsys_pack.output.(css,img,js) - if (($outputUrl = $this->package->getUrl($output)) === false) { - throw new Error(sprintf('Unable to get url for asset: %s', $output), $token->getLine(), $stream->getSourceContext()); + if (($outputUrl = $this->package->getUrl($this->output)) === false) { + throw new Error(sprintf('Unable to get url for asset: %s', $this->output), $token->getLine(), $stream->getSourceContext()); } //Check if we have a bundle path - if ($output[0] == '@') { + if ($this->output[0] == '@') { //Resolve it - $output = $this->getLocated($output, $token->getLine(), $stream->getSourceContext()); + $this->output = $this->getLocated($this->output, $token->getLine(), $stream->getSourceContext()); } //Get filesystem $filesystem = new Filesystem(); //Create output dir if not present - if (!is_dir($dir = dirname($output))) { + if (!is_dir($dir = dirname($this->output))) { try { //Create dir //XXX: set as 0775, symfony umask (0022) will reduce rights (0755) @@ -251,14 +249,14 @@ class TokenParser extends AbstractTokenParser { //Write content to file //XXX: this call is (maybe) atomic //XXX: see https://symfony.com/doc/current/components/filesystem.html#dumpfile - $filesystem->dumpFile($output, $content); + $filesystem->dumpFile($this->output, $content); } catch (IOExceptionInterface $e) { //Throw error - throw new Error(sprintf('Unable to write to: %s', $output), $token->getLine(), $stream->getSourceContext(), $e); + throw new Error(sprintf('Unable to write to: %s', $this->output), $token->getLine(), $stream->getSourceContext(), $e); } //Set name in context key - $ref = new AssignNameExpression($name, $token->getLine()); + $ref = new AssignNameExpression($this->token, $token->getLine()); //Set output in context value $value = new TextNode($outputUrl, $token->getLine()); -- 2.41.3 From e574f584030a65cb66c7f3ac3a48e6008ff1465c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:38:15 +0100 Subject: [PATCH 09/16] Drop getAlias function Remove config array Add token member variable string --- Extension/PackExtension.php | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/Extension/PackExtension.php b/Extension/PackExtension.php index 697f469..bbf166e 100644 --- a/Extension/PackExtension.php +++ b/Extension/PackExtension.php @@ -26,9 +26,9 @@ use Rapsys\PackBundle\Util\SluggerUtil; */ class PackExtension extends AbstractExtension { /** - * The config array + * The filters array */ - protected array $config; + protected array $filters; /** * The output array @@ -36,9 +36,9 @@ class PackExtension extends AbstractExtension { protected array $output; /** - * The filter array + * The token string */ - protected array $filters; + protected string $token; /** * @link https://twig.symfony.com/doc/2.x/advanced.html @@ -47,29 +47,29 @@ class PackExtension extends AbstractExtension { */ public function __construct(protected ContainerInterface $container, protected IntlUtil $intl, protected FileLocator $locator, protected PackageInterface $package, protected SluggerUtil $slugger) { //Retrieve bundle config - if ($parameters = $container->getParameter(self::getAlias())) { - //Set config, output and filters arrays - foreach(['config', 'output', 'filters'] as $k) { + if ($parameters = $container->getParameter(RapsysPackBundle::getAlias())) { + //Set filters, output arrays and token string + foreach(['filters', 'output', 'token'] as $k) { $this->$k = $parameters[$k]; } } } /** - * Returns a list of filters to add to the existing list. + * Returns a filter array 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']) + new TokenParser($this->locator, $this->package, $this->token, 'stylesheet', $this->output['css'], $this->filters['css']), + new TokenParser($this->locator, $this->package, $this->token, 'javascript', $this->output['js'], $this->filters['js']), + new TokenParser($this->locator, $this->package, $this->token, 'image', $this->output['img'], $this->filters['img']) ]; } /** - * Returns a list of filters to add to the existing list. + * Returns a filter array to add to the existing list. * * @return \Twig\TwigFilter[] */ @@ -89,11 +89,4 @@ class PackExtension extends AbstractExtension { new \Twig\TwigFilter('base64_decode', 'base64_decode') ]; } - - /** - * {@inheritdoc} - */ - public function getAlias(): string { - return RapsysPackBundle::getAlias(); - } } -- 2.41.3 From 687a51abbffbe68e2bb6086d1ebd466afe7e4d1e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:43:09 +0100 Subject: [PATCH 10/16] Import Command base class --- Command.php | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Command.php diff --git a/Command.php b/Command.php new file mode 100644 index 0000000..0832e2e --- /dev/null +++ b/Command.php @@ -0,0 +1,74 @@ + + * + * 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\Console\Command\Command as BaseCommand; +use Symfony\Component\DependencyInjection\Container; + +use Rapsys\PackBundle\RapsysPackBundle; + +/** + * {@inheritdoc} + */ +class Command extends BaseCommand { + /** + * {@inheritdoc} + */ + public function __construct(protected ?string $name = null) { + //Fix name + $this->name = $this->name ?? static::getName(); + + //Call parent constructor + parent::__construct($this->name); + + //With description + if (!empty($this->description)) { + //Set description + $this->setDescription($this->description); + } + + //With help + if (!empty($this->help)) { + //Set help + $this->setHelp($this->help); + } + } + + /** + * Return the command name + * + * {@inheritdoc} + */ + public function getName(): string { + //With namespace + if ($npos = strrpos(static::class, '\\')) { + //Set name pos + $npos++; + //Without namespace + } else { + $npos = 0; + } + + //With trailing command + if (substr(static::class, -strlen('Command'), strlen('Command')) === 'Command') { + //Set bundle pos + $bpos = strlen(static::class) - $npos - strlen('Command'); + //Without bundle + } else { + //Set bundle pos + $bpos = strlen(static::class) - $npos; + } + + //Return command alias + return RapsysPackBundle::getAlias().':'.strtolower(substr(static::class, $npos, $bpos)); + } +} -- 2.41.3 From 27799a6bd180315bec62053c230e16cb3fa7431a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:46:10 +0100 Subject: [PATCH 11/16] Rename routes config to match new bundle alias --- Resources/config/routes/{rapsys_pack.yaml => rapsyspack.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Resources/config/routes/{rapsys_pack.yaml => rapsyspack.yaml} (100%) diff --git a/Resources/config/routes/rapsys_pack.yaml b/Resources/config/routes/rapsyspack.yaml similarity index 100% rename from Resources/config/routes/rapsys_pack.yaml rename to Resources/config/routes/rapsyspack.yaml -- 2.41.3 From 364bd13d2171a3e02c2566d284fa56e4c148fdf6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 16:48:43 +0100 Subject: [PATCH 12/16] Add RAPSYSPACK_AGENT, RAPSYSPACK_HOSTNAME, RAPSYSPACK_RANGE, RAPSYSPACK_REDIRECT, RAPSYSPACK_SCHEME and RAPSYSPACK_TIMEOUT env variables Reorder services Add range command --- Resources/config/packages/rapsys_pack.yaml | 75 ----------------- Resources/config/packages/rapsyspack.yaml | 94 ++++++++++++++++++++++ 2 files changed, 94 insertions(+), 75 deletions(-) delete mode 100644 Resources/config/packages/rapsys_pack.yaml create mode 100644 Resources/config/packages/rapsyspack.yaml diff --git a/Resources/config/packages/rapsys_pack.yaml b/Resources/config/packages/rapsys_pack.yaml deleted file mode 100644 index 8aa8619..0000000 --- a/Resources/config/packages/rapsys_pack.yaml +++ /dev/null @@ -1,75 +0,0 @@ -#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 - rapsys_pack.path_package: - class: 'Rapsys\PackBundle\Package\PathPackage' - arguments: [ '/', '@assets.empty_version_strategy', '@assets.context' ] - public: true - #Register twig pack extension - rapsys_pack.pack_extension: - class: 'Rapsys\PackBundle\Extension\PackExtension' - arguments: [ '@service_container', '@rapsys_pack.intl_util', '@file_locator', '@rapsys_pack.path_package', '@rapsys_pack.slugger_util' ] - tags: [ 'twig.extension' ] - #Register intl util service - rapsys_pack.intl_util: - class: 'Rapsys\PackBundle\Util\IntlUtil' - public: true - #Register facebook event subscriber - Rapsys\PackBundle\Subscriber\FacebookSubscriber: - arguments: [ '@router', [] ] - tags: [ 'kernel.event_subscriber' ] - #Register intl util class alias - Rapsys\PackBundle\Util\IntlUtil: - alias: 'rapsys_pack.intl_util' - #Register facebook util service - rapsys_pack.facebook_util: - class: 'Rapsys\PackBundle\Util\FacebookUtil' - arguments: [ '@router', '%kernel.project_dir%/var/cache', '%rapsys_pack.path%' ] - public: true - #Register facebook util class alias - Rapsys\PackBundle\Util\FacebookUtil: - alias: 'rapsys_pack.facebook_util' - #Register image util service - rapsys_pack.image_util: - class: 'Rapsys\PackBundle\Util\ImageUtil' - arguments: [ '@router', '@rapsys_pack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsys_pack.path%' ] - public: true - #Register image util class alias - Rapsys\PackBundle\Util\ImageUtil: - alias: 'rapsys_pack.image_util' - #Register map util service - rapsys_pack.map_util: - class: 'Rapsys\PackBundle\Util\MapUtil' - arguments: [ '@router', '@rapsys_pack.slugger_util' ] - public: true - #Register map util class alias - Rapsys\PackBundle\Util\MapUtil: - alias: 'rapsys_pack.map_util' - #Register slugger util service - rapsys_pack.slugger_util: - class: 'Rapsys\PackBundle\Util\SluggerUtil' - arguments: [ '%kernel.secret%' ] - public: true - #Register slugger util class alias - Rapsys\PackBundle\Util\SluggerUtil: - alias: 'rapsys_pack.slugger_util' - #Register image controller - Rapsys\PackBundle\Controller\ImageController: - arguments: [ '@service_container', '@rapsys_pack.image_util', '@rapsys_pack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsys_pack.path%' ] - tags: [ 'controller.service_arguments' ] - #Register map controller - Rapsys\PackBundle\Controller\MapController: - arguments: [ '@service_container', '@rapsys_pack.map_util', '@rapsys_pack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsys_pack.path%' ] - tags: [ 'controller.service_arguments' ] - #Register captcha form type - Rapsys\PackBundle\Form\CaptchaType: - arguments: [ '@rapsys_pack.image_util', '@rapsys_pack.slugger_util', '@translator' ] - tags: [ 'form.type' ] diff --git a/Resources/config/packages/rapsyspack.yaml b/Resources/config/packages/rapsyspack.yaml new file mode 100644 index 0000000..9d63d14 --- /dev/null +++ b/Resources/config/packages/rapsyspack.yaml @@ -0,0 +1,94 @@ +# Parameters configuration +parameters: + # User agent + env(RAPSYSPACK_AGENT): "rapsyspack/Ch4ng3m3!" + # Hostname + env(RAPSYSPACK_HOSTNAME): "Ch4ng3m3!" + # Shuffled printable character range + env(RAPSYSPACK_RANGE): 'Ch4ng3m3!' + # Redirect + env(RAPSYSPACK_REDIRECT): 20 + # Scheme + env(RAPSYSPACK_SCHEME): "https://" + # Timeout + env(RAPSYSPACK_TIMEOUT): 60 + +# Services configuration +services: + # Replace assets.context definition + assets.context: + class: 'Rapsys\PackBundle\Context\RequestStackContext' + arguments: [ '@request_stack', '%asset.request_context.base_path%', '%asset.request_context.secure%' ] + # Replace assets.packages definition + assets.packages: + class: 'Symfony\Component\Asset\Packages' + arguments: [ '@rapsyspack.path_package' ] + # Register facebook util service + rapsyspack.facebook_util: + class: 'Rapsys\PackBundle\Util\FacebookUtil' + arguments: [ '@router', '%kernel.project_dir%/var/cache', '%rapsyspack.path%' ] + public: true + # Register image util service + rapsyspack.image_util: + class: 'Rapsys\PackBundle\Util\ImageUtil' + arguments: [ '@router', '@rapsyspack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsyspack.path%' ] + public: true + # Register intl util service + rapsyspack.intl_util: + class: 'Rapsys\PackBundle\Util\IntlUtil' + public: true + # Register map util service + rapsyspack.map_util: + class: 'Rapsys\PackBundle\Util\MapUtil' + arguments: [ '@router', '@rapsyspack.slugger_util' ] + public: true + # Register twig pack extension + rapsyspack.pack_extension: + class: 'Rapsys\PackBundle\Extension\PackExtension' + arguments: [ '@service_container', '@rapsyspack.intl_util', '@file_locator', '@rapsyspack.path_package', '@rapsyspack.slugger_util' ] + tags: [ 'twig.extension' ] + # Register assets pack package + rapsyspack.path_package: + class: 'Rapsys\PackBundle\Package\PathPackage' + arguments: [ '/', '@assets.empty_version_strategy', '@assets.context' ] + public: true + # Register slugger util service + rapsyspack.slugger_util: + class: 'Rapsys\PackBundle\Util\SluggerUtil' + arguments: [ '%env(string:RAPSYSPACK_RANGE)%', '%kernel.secret%' ] + public: true + # Register range command + Rapsys\PackBundle\Command\RangeCommand: + arguments: [ '%kernel.project_dir%/.env.local' ] + tags: [ 'console.command' ] + # Register image controller + Rapsys\PackBundle\Controller\ImageController: + arguments: [ '@service_container', '@rapsyspack.image_util', '@rapsyspack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsyspack.path%' ] + tags: [ 'controller.service_arguments' ] + # Register map controller + Rapsys\PackBundle\Controller\MapController: + arguments: [ '@service_container', '@rapsyspack.map_util', '@rapsyspack.slugger_util', '%kernel.project_dir%/var/cache', '%rapsyspack.path%' ] + tags: [ 'controller.service_arguments' ] + # Register captcha form type + Rapsys\PackBundle\Form\CaptchaType: + arguments: [ '@rapsyspack.image_util', '@rapsyspack.slugger_util', '@translator' ] + tags: [ 'form.type' ] + # Register facebook event subscriber + Rapsys\PackBundle\Subscriber\FacebookSubscriber: + arguments: [ '@router', [] ] + tags: [ 'kernel.event_subscriber' ] + # Register facebook util class alias + Rapsys\PackBundle\Util\FacebookUtil: + alias: 'rapsyspack.facebook_util' + # Register image util class alias + Rapsys\PackBundle\Util\ImageUtil: + alias: 'rapsyspack.image_util' + # Register intl util class alias + Rapsys\PackBundle\Util\IntlUtil: + alias: 'rapsyspack.intl_util' + # Register map util class alias + Rapsys\PackBundle\Util\MapUtil: + alias: 'rapsyspack.map_util' + # Register slugger util class alias + Rapsys\PackBundle\Util\SluggerUtil: + alias: 'rapsyspack.slugger_util' -- 2.41.3 From 884434e58dda34f2c3f780999c74f8d6a11569d5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 17:18:47 +0100 Subject: [PATCH 13/16] Use RAPSYSPACK_AGENT, RAPSYSPACK_REDIRECT and RAPSYSPACK_TIMEOUT env variables --- Controller/MapController.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Controller/MapController.php b/Controller/MapController.php index 193d336..869d5ab 100644 --- a/Controller/MapController.php +++ b/Controller/MapController.php @@ -53,12 +53,9 @@ class MapController extends AbstractController implements ServiceSubscriberInter [ 'http' => [ #'header' => ['Referer: https://www.openstreetmap.org/'], - 'max_redirects' => 5, - //TODO: set as bundle env config - 'timeout' => (int)ini_get('default_socket_timeout'), - #'user_agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36', - //TODO: set as bundle env config - 'user_agent' => (string)ini_get('user_agent')?:'rapsys_pack/2.0.0', + 'max_redirects' => $_ENV['RAPSYSPACK_REDIRECT'] ?? 20, + 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (int)ini_get('default_socket_timeout') ?: 60, + 'user_agent' => $_ENV['RAPSYSPACK_AGENT'] ?? (($agent = ini_get('user_agent')) !== false && $agent !== "" ? (string)$agent : RapsysPackBundle::getAlias().'/'.RapsysPackBundle::getVersion()) ] ] ); -- 2.41.3 From b97d9b2ac779103239b4ec1bec9dc1399b5ad9e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 17:47:33 +0100 Subject: [PATCH 14/16] Fix default_socket_timeout invalid values --- Controller/MapController.php | 2 +- Parser/TokenParser.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/MapController.php b/Controller/MapController.php index 869d5ab..255c47b 100644 --- a/Controller/MapController.php +++ b/Controller/MapController.php @@ -54,7 +54,7 @@ class MapController extends AbstractController implements ServiceSubscriberInter 'http' => [ #'header' => ['Referer: https://www.openstreetmap.org/'], 'max_redirects' => $_ENV['RAPSYSPACK_REDIRECT'] ?? 20, - 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (int)ini_get('default_socket_timeout') ?: 60, + 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (($timeout = ini_get('default_socket_timeout')) !== false && $timeout !== "" ? (float)$timeout : 60), 'user_agent' => $_ENV['RAPSYSPACK_AGENT'] ?? (($agent = ini_get('user_agent')) !== false && $agent !== "" ? (string)$agent : RapsysPackBundle::getAlias().'/'.RapsysPackBundle::getVersion()) ] ] diff --git a/Parser/TokenParser.php b/Parser/TokenParser.php index 1115e0c..07267b9 100644 --- a/Parser/TokenParser.php +++ b/Parser/TokenParser.php @@ -50,7 +50,7 @@ class TokenParser extends AbstractTokenParser { 'http' => [ #'header' => ['Referer: https://www.openstreetmap.org/'], 'max_redirects' => $_ENV['RAPSYSPACK_REDIRECT'] ?? 20, - 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (int)ini_get('default_socket_timeout') ?: 60, + 'timeout' => $_ENV['RAPSYSPACK_TIMEOUT'] ?? (($timeout = ini_get('default_socket_timeout')) !== false && $timeout !== "" ? (float)$timeout : 60), 'user_agent' => $_ENV['RAPSYSPACK_AGENT'] ?? (($agent = ini_get('user_agent')) !== false && $agent !== "" ? (string)$agent : RapsysPackBundle::getAlias().'/'.RapsysPackBundle::getVersion()) ] ] -- 2.41.3 From b69214e3aa8c18b333a58b160aa22fa2c356065f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Mon, 4 Mar 2024 17:56:01 +0100 Subject: [PATCH 15/16] Update symfony requires --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 5f9d93b..3c7f24b 100644 --- a/composer.json +++ b/composer.json @@ -13,11 +13,11 @@ } }, "require": { - "symfony/asset": "^4.0|^5.0|^6.0|^7.0", - "symfony/flex": "^1.0|^2.0", - "symfony/framework-bundle": "^4.0|^5.0|^6.0|^7.0", - "symfony/process": "^4.0|^5.0|^6.0|^7.0", - "symfony/twig-bundle": "^4.0|^5.0|^6.0|^7.0" + "symfony/asset": "^7.0", + "symfony/flex": "^2.0", + "symfony/framework-bundle": "^7.0", + "symfony/process": "^7.0", + "symfony/twig-bundle": "^7.0" }, "extra": { "branch-alias": { -- 2.41.3 From 780564d1998c2e41b4f9a145b5191a66dbaf6ed4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Thu, 7 Mar 2024 17:53:27 +0100 Subject: [PATCH 16/16] Replace filters, output and token with parameters argument --- Extension/PackExtension.php | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/Extension/PackExtension.php b/Extension/PackExtension.php index bbf166e..6b77a49 100644 --- a/Extension/PackExtension.php +++ b/Extension/PackExtension.php @@ -25,34 +25,12 @@ use Rapsys\PackBundle\Util\SluggerUtil; * {@inheritdoc} */ class PackExtension extends AbstractExtension { - /** - * The filters array - */ - protected array $filters; - - /** - * The output array - */ - protected array $output; - - /** - * The token string - */ - protected string $token; - /** * @link https://twig.symfony.com/doc/2.x/advanced.html * * {@inheritdoc} */ - public function __construct(protected ContainerInterface $container, protected IntlUtil $intl, protected FileLocator $locator, protected PackageInterface $package, protected SluggerUtil $slugger) { - //Retrieve bundle config - if ($parameters = $container->getParameter(RapsysPackBundle::getAlias())) { - //Set filters, output arrays and token string - foreach(['filters', 'output', 'token'] as $k) { - $this->$k = $parameters[$k]; - } - } + public function __construct(protected ContainerInterface $container, protected IntlUtil $intl, protected FileLocator $locator, protected PackageInterface $package, protected SluggerUtil $slugger, protected array $parameters) { } /** @@ -62,9 +40,9 @@ class PackExtension extends AbstractExtension { */ public function getTokenParsers(): array { return [ - new TokenParser($this->locator, $this->package, $this->token, 'stylesheet', $this->output['css'], $this->filters['css']), - new TokenParser($this->locator, $this->package, $this->token, 'javascript', $this->output['js'], $this->filters['js']), - new TokenParser($this->locator, $this->package, $this->token, 'image', $this->output['img'], $this->filters['img']) + new TokenParser($this->locator, $this->package, $this->parameters['token'], 'stylesheet', $this->parameters['output']['css'], $this->parameters['filters']['css']), + new TokenParser($this->locator, $this->package, $this->parameters['token'], 'javascript', $this->parameters['output']['js'], $this->parameters['filters']['js']), + new TokenParser($this->locator, $this->package, $this->parameters['token'], 'image', $this->parameters['output']['img'], $this->parameters['filters']['img']) ]; } -- 2.41.3