diff --git a/README.md b/README.md index 4892ac3..a2babb3 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ n98-magerun2 varnish:tuned # Get active themes n98-magerun2 dev:theme:active + +# Generate nginx maps for URL redirects +n98-magerun2 hypernode:maps-generate ``` ## Commands available @@ -92,6 +95,33 @@ improves performance. There is no output on success. It is suitable to be set up into a `@monthly` cron, e.g.: @monthly n98-magerun2 db:maintain:search-query --root-dir=/path/to/magento2 + +### `n98-magerun2 hypernode:maps-generate` + +Generates nginx map files for URL redirects from Magento 2's url_rewrite table. This is useful for +creating efficient nginx redirect configurations instead of relying on Magento to handle redirects. + +Example output: + +```nginx +# Nginx map for URL redirects +# Generated by n98-magerun2 hypernode:maps-generate + +# 301 redirects +map $request_uri $redirect_uri { + default ""; + "/old-product.html" "/new-product.html"; + "/old-category.html" "/new-category.html"; +} +``` + +Options: +- `--store=` - Generate maps for a specific store ID only +- `--type=<301|302>` - Filter by redirect type (301 for permanent, 302 for temporary) + +You can save the output to a file and include it in your nginx configuration: + + n98-magerun2 hypernode:maps-generate > /etc/nginx/maps/magento-redirects.conf ### TODO diff --git a/n98-magerun2.yaml b/n98-magerun2.yaml index 8b7bb08..a08e0ef 100644 --- a/n98-magerun2.yaml +++ b/n98-magerun2.yaml @@ -7,3 +7,4 @@ commands: - GetPageSpeed\DeployLocaleActiveCommand - GetPageSpeed\DevModuleListCommand - GetPageSpeed\DbMaintainSearchQuery + - GetPageSpeed\MapsGenerateCommand diff --git a/src/GetPageSpeed/MapsGenerateCommand.php b/src/GetPageSpeed/MapsGenerateCommand.php new file mode 100644 index 0000000..46380bf --- /dev/null +++ b/src/GetPageSpeed/MapsGenerateCommand.php @@ -0,0 +1,122 @@ +setName('hypernode:maps-generate') + ->setDescription('Generate nginx map files for URL redirects') + ->addOption( + 'store', + null, + InputOption::VALUE_OPTIONAL, + 'Store ID (default: all stores)' + ) + ->addOption( + 'type', + null, + InputOption::VALUE_OPTIONAL, + 'Redirect type (301 or 302, default: both)' + ) + ; + } + + /** + * @param \Symfony\Component\Console\Input\InputInterface $input + * @param \Symfony\Component\Console\Output\OutputInterface $output + * @return int|void + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->detectMagento($output); + if ($this->initMagento()) { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $resource = $objectManager->get('Magento\Framework\App\ResourceConnection'); + $connection = $resource->getConnection(); + + $tableName = $resource->getTableName('url_rewrite'); + + // Build WHERE clause + $whereConditions = ['redirect_type IN (301, 302)']; + + $storeId = $input->getOption('store'); + if ($storeId !== null) { + $whereConditions[] = sprintf('store_id = %d', (int)$storeId); + } + + $redirectType = $input->getOption('type'); + if ($redirectType !== null && in_array($redirectType, ['301', '302'])) { + $whereConditions = [sprintf('redirect_type = %d', (int)$redirectType)]; + if ($storeId !== null) { + $whereConditions[] = sprintf('store_id = %d', (int)$storeId); + } + } + + $where = implode(' AND ', $whereConditions); + + $sql = sprintf( + "SELECT request_path, target_path, redirect_type, store_id FROM `%s` WHERE %s ORDER BY store_id, redirect_type", + $tableName, + $where + ); + + $redirects = $connection->fetchAll($sql); + + if (empty($redirects)) { + $output->writeln('No redirects found.'); + return Command::SUCCESS; + } + + // Generate nginx map format + $output->writeln('# Nginx map for URL redirects'); + $output->writeln('# Generated by n98-magerun2 hypernode:maps-generate'); + $output->writeln(''); + + // Group by redirect type + $redirectsByType = []; + foreach ($redirects as $redirect) { + $type = $redirect['redirect_type']; + if (!isset($redirectsByType[$type])) { + $redirectsByType[$type] = []; + } + $redirectsByType[$type][] = $redirect; + } + + foreach ($redirectsByType as $type => $typeRedirects) { + $output->writeln(sprintf('# %d redirects', $type)); + $output->writeln('map $request_uri $redirect_uri {'); + $output->writeln(' default "";'); + + foreach ($typeRedirects as $redirect) { + $requestPath = '/' . ltrim($redirect['request_path'], '/'); + $targetPath = '/' . ltrim($redirect['target_path'], '/'); + + // Escape special characters if needed + $requestPath = addslashes($requestPath); + $targetPath = addslashes($targetPath); + + $output->writeln(sprintf(' "%s" "%s";', $requestPath, $targetPath)); + } + + $output->writeln('}'); + $output->writeln(''); + } + + return Command::SUCCESS; + } else { + return Command::FAILURE; + } + } +}