Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split big sitemaps & generate proper index (closes #79, #106) #128

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion UPGRADE-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
## New features

* Generation of sitemaps is done via the CLI, schedule them in a cronjob:
* Sitemap Index: `bin/console sylius:sitemap:generate-index`
* Sitemap Index: `bin/console sylius:sitemap:generate`
* Sitemap URLs now support adding images. The default providers do this where possible. It can be disabled using the `images` configuration key.
* Sitemaps are split automatically per 50.000 URL's. This can be adjusted by providing `--limit={int}` to the CLI command.

## Removed features

Expand Down
17 changes: 16 additions & 1 deletion src/Builder/SitemapIndexBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ final class SitemapIndexBuilder implements SitemapIndexBuilderInterface
/** @var array */
private $indexProviders = [];

/** @var array */
private $paths = [];

public function __construct(SitemapIndexFactoryInterface $sitemapIndexFactory)
{
$this->sitemapIndexFactory = $sitemapIndexFactory;
Expand All @@ -41,6 +44,18 @@ public function addIndexProvider(IndexUrlProviderInterface $provider): void
$this->indexProviders[] = $provider;
}

/**
* {@inheritdoc}
*/
public function addPath(UrlProviderInterface $provider, string $path): void
{
if (!array_key_exists($provider->getName(), $this->paths)) {
$this->paths[$provider->getName()] = [];
}

$this->paths[$provider->getName()][] = $path;
}

/**
* {@inheritdoc}
*/
Expand All @@ -53,7 +68,7 @@ public function build(): SitemapInterface
foreach ($this->indexProviders as $indexProvider) {
/** @var UrlProviderInterface $provider */
foreach ($this->providers as $provider) {
$indexProvider->addProvider($provider);
$indexProvider->addProvider($provider, $this->paths[$provider->getName()]);
}

$urls[] = $indexProvider->generate();
Expand Down
37 changes: 22 additions & 15 deletions src/Command/GenerateSitemapCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,43 +56,50 @@ public function __construct(
protected function configure(): void
{
$this->addOption('channel', 'c', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Channel codes to generate. If none supplied, all channels will generated.');
$this->addOption('limit', 'l', InputOption::VALUE_OPTIONAL, 'Limit amount of URLs per sitemap', 50000);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
foreach ($this->channels($input) as $channel) {
$this->executeChannel($channel, $output);
$this->executeChannel($channel, $input, $output);
}
}

private function executeChannel(ChannelInterface $channel, OutputInterface $output)
private function executeChannel(ChannelInterface $channel, InputInterface $input, OutputInterface $output)
{
// TODO make sure providers are every time emptied (reset call or smth?)
foreach ($this->sitemapBuilder->getProviders() as $provider) {
$output->writeln(\sprintf('Start generating sitemap "%s" for channel "%s"', $provider->getName(), $channel->getCode()));

$sitemap = $this->sitemapBuilder->build($provider, $channel); // TODO use provider instance, not the name
$xml = $this->sitemapRenderer->render($sitemap);
$path = $path = $this->path($channel, \sprintf('%s.xml', $provider->getName()));
$xml = $this->sitemapRenderer->render($sitemap, (int)$input->getOption('limit'));
foreach($xml as $index => $data) {
$path = $path = $this->path($channel, \sprintf('%s_%d.xml', $provider->getName(), $index));

$this->writer->write(
$path,
$xml
);
$this->writer->write(
$path,
$data
);

$output->writeln(\sprintf('Finished generating sitemap "%s" for channel "%s" at path "%s"', $provider->getName(), $channel->getCode(), $path));
$output->writeln(\sprintf('Finished generating sitemap "%s" (%d) for channel "%s" at path "%s"', $provider->getName(), $index, $channel->getCode(), $path));

$this->sitemapIndexBuilder->addPath($provider, $path);
}
}

$output->writeln(\sprintf('Start generating sitemap index for channel "%s"', $channel->getCode()));

$sitemap = $this->sitemapIndexBuilder->build();
$xml = $this->sitemapIndexRenderer->render($sitemap);
$path = $this->path($channel, 'sitemap_index.xml');

$this->writer->write(
$path,
$xml
);
foreach($xml as $index => $data) {
$path = $this->path($channel, 'sitemap_index.xml');

$this->writer->write(
$path,
$data
);
}

$output->writeln(\sprintf('Finished generating sitemap index for channel "%s" at path "%s"', $channel->getCode(), $path));
}
Expand Down
4 changes: 2 additions & 2 deletions src/Controller/SitemapController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public function __construct(
parent::__construct($reader);
}

public function showAction(string $name): Response
public function showAction(string $name, int $index): Response
{
$path = \sprintf('%s/%s', $this->channelContext->getChannel()->getCode(), \sprintf('%s.xml', $name));
$path = \sprintf('%s/%s', $this->channelContext->getChannel()->getCode(), \sprintf('%s_%d.xml', $name, $index));

return $this->createResponse($path);
}
Expand Down
16 changes: 13 additions & 3 deletions src/Provider/IndexUrlProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ final class IndexUrlProvider implements IndexUrlProviderInterface
/** @var array */
private $urls = [];

/** @var array */
private $paths = [];

public function __construct(
RouterInterface $router,
IndexUrlFactoryInterface $sitemapIndexUrlFactory
Expand All @@ -29,17 +32,24 @@ public function __construct(
$this->sitemapIndexUrlFactory = $sitemapIndexUrlFactory;
}

public function addProvider(UrlProviderInterface $provider): void
public function addProvider(UrlProviderInterface $provider, array $paths = []): void
{
$this->providers[] = $provider;
$this->paths[$provider->getName()] = $paths;
}

public function generate(): iterable
{
foreach ($this->providers as $provider) {
$location = $this->router->generate('sylius_sitemap_' . $provider->getName());
$pathCount = count($this->paths[$provider->getName()]);

for ($i = 0; $i < $pathCount; $i++) {
$params = ['index' => $i];

$location = $this->router->generate('sylius_sitemap_'.$provider->getName(), $params);

$this->urls[] = $this->sitemapIndexUrlFactory->createNew($location);
$this->urls[] = $this->sitemapIndexUrlFactory->createNew($location);
}
}

return $this->urls;
Expand Down
2 changes: 1 addition & 1 deletion src/Provider/IndexUrlProviderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ interface IndexUrlProviderInterface
*/
public function generate(): iterable;

public function addProvider(UrlProviderInterface $provider): void;
public function addProvider(UrlProviderInterface $provider, array $paths = []): void;
}
15 changes: 13 additions & 2 deletions src/Renderer/SitemapRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,19 @@ public function __construct(RendererAdapterInterface $adapter)
/**
* {@inheritdoc}
*/
public function render(SitemapInterface $sitemap): string
public function render(SitemapInterface $sitemap, ?int $limit = null): iterable
{
return $this->adapter->render($sitemap);
$urls = $sitemap->getUrls();
$total = count($urls);

if (null === $limit || $limit < 0) {
$limit = $total;
}

foreach(array_chunk($urls, $limit) as $slice) {
$sitemap->setUrls($slice);

yield $this->adapter->render($sitemap);
}
}
}
6 changes: 5 additions & 1 deletion src/Renderer/SitemapRendererInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@

interface SitemapRendererInterface
{
public function render(SitemapInterface $sitemap): string;

/**
* @return string[]
*/
public function render(SitemapInterface $sitemap, ?int $limit = null): iterable;
}
8 changes: 5 additions & 3 deletions src/Routing/SitemapLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function __construct(SitemapBuilderInterface $sitemapBuilder)
public function load($resource, $type = null): RouteCollection
{
$routes = new RouteCollection();

if (true === $this->loaded) {
return $routes;
}
Expand All @@ -50,12 +50,14 @@ public function load($resource, $type = null): RouteCollection
$routes->add(
$name,
new Route(
'/sitemap/' . $provider->getName() . '.xml',
'/sitemap/' . $provider->getName() . '/{index}.xml',
[
'_controller' => 'sylius.controller.sitemap:showAction',
'name' => $provider->getName(),
],
[],
[
'index' => '\d+',
],
[],
'',
[],
Expand Down