From 69a6039f2beabcaed32d64951a071870b3c5d9ff Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz <1921950+norberttech@users.noreply.github.com> Date: Sat, 7 Sep 2024 20:50:21 +0200 Subject: [PATCH] Added auto generated sitemap to website (#1216) Added auto generated sitemap to website page --- web/landing/.gitignore | 1 + web/landing/composer.json | 7 +- web/landing/composer.lock | 70 +++++++++- web/landing/config/bundles.php | 1 + .../config/packages/presta_sitemap.yaml | 3 + web/landing/config/routes.yaml | 14 +- web/landing/public/robots.txt | 13 ++ .../Website/Controller/BlogController.php | 2 +- .../Controller/DocumentationController.php | 6 +- .../Website/Controller/ExamplesController.php | 4 +- .../Website/Controller/FlowController.php | 2 +- .../Website/Controller/HomeController.php | 2 +- .../EventListener/SitemapSubscriber.php | 124 ++++++++++++++++++ 13 files changed, 236 insertions(+), 13 deletions(-) create mode 100644 web/landing/config/packages/presta_sitemap.yaml create mode 100644 web/landing/public/robots.txt create mode 100644 web/landing/src/Flow/Website/EventListener/SitemapSubscriber.php diff --git a/web/landing/.gitignore b/web/landing/.gitignore index 03de6899e..abdbdb451 100644 --- a/web/landing/.gitignore +++ b/web/landing/.gitignore @@ -4,3 +4,4 @@ build/ vendor/ var/ public/assets +public/*.xml diff --git a/web/landing/composer.json b/web/landing/composer.json index afb35eb83..478eb44af 100644 --- a/web/landing/composer.json +++ b/web/landing/composer.json @@ -26,7 +26,8 @@ "twig/markdown-extra": "^3.11", "twig/extra-bundle": "^3.8", "league/commonmark": "^2.4", - "cocur/slugify": "^4.5" + "cocur/slugify": "^4.5", + "presta/sitemap-bundle": "^4.1" }, "require-dev": { "symfony/web-profiler-bundle": "^6.4", @@ -58,8 +59,7 @@ ], "post-update-cmd": [ "@importmap:install", - "@build:tailwind", - "@tools:update" + "@build:tailwind" ], "tools:install": [ "composer install --working-dir=./tools/phpunit" @@ -88,6 +88,7 @@ "APP_ENV=prod bin/console importmap:install", "APP_ENV=prod bin/console tailwind:build --minify", "APP_ENV=prod bin/console asset-map:compile", + "APP_ENV=prod bin/console presta:sitemaps:dump", "APP_ENV=prod bin/console static-content-generator:generate:routes --clean", "APP_ENV=prod bin/console static-content-generator:copy:assets -d public" ] diff --git a/web/landing/composer.lock b/web/landing/composer.lock index 6f8e25ee5..0eac029a4 100644 --- a/web/landing/composer.lock +++ b/web/landing/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "61474211e42935fbc7058ff05897c378", + "content-hash": "e9a772b9ab46ed5c8f4bc7f8c9af24fd", "packages": [ { "name": "aeon-php/calendar", @@ -1569,6 +1569,74 @@ }, "time": "2024-03-15T13:55:21+00:00" }, + { + "name": "presta/sitemap-bundle", + "version": "v4.1.1", + "source": { + "type": "git", + "url": "https://github.com/prestaconcept/PrestaSitemapBundle.git", + "reference": "28f6c146d600258099bfae959c2f04d94c71b26d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/prestaconcept/PrestaSitemapBundle/zipball/28f6c146d600258099bfae959c2f04d94c71b26d", + "reference": "28f6c146d600258099bfae959c2f04d94c71b26d", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "php": ">=7.2.5|>=8.0.2", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "doctrine/annotations": "^1.0", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^7.5|^8.0", + "squizlabs/php_codesniffer": "^3.5", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "4.x": "4.x-dev", + "3.x": "3.x-dev", + "2.x": "2.x-dev", + "1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Presta\\SitemapBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Prestaconcept", + "homepage": "http://www.prestaconcept.net/" + } + ], + "description": "A Symfony bundle that provides tools to build your application sitemap.", + "keywords": [ + "Sitemap", + "bundle", + "prestaconcept", + "symfony", + "xml" + ], + "support": { + "issues": "https://github.com/prestaconcept/PrestaSitemapBundle/issues", + "source": "https://github.com/prestaconcept/PrestaSitemapBundle/tree/v4.1.1" + }, + "time": "2024-03-19T15:38:28+00:00" + }, { "name": "psr/cache", "version": "3.0.0", diff --git a/web/landing/config/bundles.php b/web/landing/config/bundles.php index 83a107df5..860aa432f 100644 --- a/web/landing/config/bundles.php +++ b/web/landing/config/bundles.php @@ -9,4 +9,5 @@ Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], \Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], + \Presta\SitemapBundle\PrestaSitemapBundle::class => ['all' => true], ]; diff --git a/web/landing/config/packages/presta_sitemap.yaml b/web/landing/config/packages/presta_sitemap.yaml new file mode 100644 index 000000000..a3d67c513 --- /dev/null +++ b/web/landing/config/packages/presta_sitemap.yaml @@ -0,0 +1,3 @@ +presta_sitemap: + defaults: + priority: 1 \ No newline at end of file diff --git a/web/landing/config/routes.yaml b/web/landing/config/routes.yaml index 930a8c1df..65561306d 100644 --- a/web/landing/config/routes.yaml +++ b/web/landing/config/routes.yaml @@ -2,4 +2,16 @@ controllers: resource: path: ../src/Flow/Website/Controller/ namespace: Flow\Website\Controller - type: attribute \ No newline at end of file + type: attribute + +PrestaSitemapBundle_index: + path: "/%presta_sitemap.sitemap_file_prefix%.{_format}" + defaults: { _controller: Presta\SitemapBundle\Controller\SitemapController::indexAction } + requirements: + _format: xml + +PrestaSitemapBundle_section: + path: "/%presta_sitemap.sitemap_file_prefix%.{name}.{_format}" + defaults: { _controller: Presta\SitemapBundle\Controller\SitemapController::sectionAction } + requirements: + _format: xml \ No newline at end of file diff --git a/web/landing/public/robots.txt b/web/landing/public/robots.txt new file mode 100644 index 000000000..6e9de640e --- /dev/null +++ b/web/landing/public/robots.txt @@ -0,0 +1,13 @@ +# robots.txt for https://flow-php.com + +# Allow all web crawlers to index the site +User-agent: * +Disallow: + +# Allow assets required for rendering the page, such as JavaScript and CSS +Allow: /assets/controllers/ +Allow: /assets/styles/ +Allow: /assets/images/ + +# Sitemap location +Sitemap: https://flow-php.com/sitemap.xml \ No newline at end of file diff --git a/web/landing/src/Flow/Website/Controller/BlogController.php b/web/landing/src/Flow/Website/Controller/BlogController.php index bc5689cec..3c20c22b1 100644 --- a/web/landing/src/Flow/Website/Controller/BlogController.php +++ b/web/landing/src/Flow/Website/Controller/BlogController.php @@ -20,7 +20,7 @@ public function post(string $date, string $slug) : Response ]); } - #[Route('/blog', name: 'blog', priority: 100)] + #[Route('/blog', name: 'blog', options: ['sitemap' => true])] public function posts() : Response { return $this->render('blog/posts.html.twig', [ diff --git a/web/landing/src/Flow/Website/Controller/DocumentationController.php b/web/landing/src/Flow/Website/Controller/DocumentationController.php index 5aed7fa78..1e48e890c 100644 --- a/web/landing/src/Flow/Website/Controller/DocumentationController.php +++ b/web/landing/src/Flow/Website/Controller/DocumentationController.php @@ -19,7 +19,7 @@ public function __construct( ) { } - #[Route('/documentation/dsl', name: 'documentation', priority: 100)] + #[Route('/documentation/dsl', name: 'documentation', options: ['sitemap' => true])] public function dsl() : Response { $modules = $this->dslDefinitions->modules(); @@ -32,7 +32,7 @@ public function dsl() : Response ]); } - #[Route('/documentation/dsl/{module}/{function}', name: 'documentation_dsl_function', priority: 100)] + #[Route('/documentation/dsl/{module}/{function}', name: 'documentation_dsl_function')] public function dslFunction(string $module, string $function) : Response { $modules = $this->dslDefinitions->modules(); @@ -57,7 +57,7 @@ public function dslFunction(string $module, string $function) : Response ]); } - #[Route('/documentation/dsl/{module}', name: 'documentation_dsl', priority: 100)] + #[Route('/documentation/dsl/{module}', name: 'documentation_dsl')] public function dslModule(string $module = 'core') : Response { $modules = $this->dslDefinitions->modules(); diff --git a/web/landing/src/Flow/Website/Controller/ExamplesController.php b/web/landing/src/Flow/Website/Controller/ExamplesController.php index 7dd5c99fc..d44773960 100644 --- a/web/landing/src/Flow/Website/Controller/ExamplesController.php +++ b/web/landing/src/Flow/Website/Controller/ExamplesController.php @@ -16,7 +16,7 @@ public function __construct( ) { } - #[Route('/{topic}/{example}/', name: 'example')] + #[Route('/{topic}/{example}/', name: 'example', priority: -2)] public function example(string $topic, string $example) : Response { $topics = $this->examples->topics(); @@ -36,7 +36,7 @@ public function example(string $topic, string $example) : Response ]); } - #[Route('/{topic}/', name: 'topic', priority: 10)] + #[Route('/{topic}/', name: 'topic', priority: -1)] public function topic(string $topic) : Response { $topics = $this->examples->topics(); diff --git a/web/landing/src/Flow/Website/Controller/FlowController.php b/web/landing/src/Flow/Website/Controller/FlowController.php index 61abf7513..8b577aef9 100644 --- a/web/landing/src/Flow/Website/Controller/FlowController.php +++ b/web/landing/src/Flow/Website/Controller/FlowController.php @@ -14,7 +14,7 @@ public function __construct() { } - #[Route('/changelog', name: 'changelog', priority: 100)] + #[Route('/changelog', name: 'changelog', options: ['sitemap' => true])] public function main() : Response { return $this->render('main/changelog.html.twig', [ diff --git a/web/landing/src/Flow/Website/Controller/HomeController.php b/web/landing/src/Flow/Website/Controller/HomeController.php index 269cf4ecb..ea4720e50 100644 --- a/web/landing/src/Flow/Website/Controller/HomeController.php +++ b/web/landing/src/Flow/Website/Controller/HomeController.php @@ -16,7 +16,7 @@ public function __construct( ) { } - #[Route('/', name: 'home')] + #[Route('/', name: 'home', options: ['sitemap' => true])] public function home() : Response { return $this->render('main/index.html.twig', [ diff --git a/web/landing/src/Flow/Website/EventListener/SitemapSubscriber.php b/web/landing/src/Flow/Website/EventListener/SitemapSubscriber.php new file mode 100644 index 000000000..69a7f50d6 --- /dev/null +++ b/web/landing/src/Flow/Website/EventListener/SitemapSubscriber.php @@ -0,0 +1,124 @@ + 'populate', + ]; + } + + public function populate(SitemapPopulateEvent $event) : void + { + $this->populateExamples($event); + $this->populateBlogPosts($event); + $this->populateDocumentation($event); + } + + private function populateBlogPosts(SitemapPopulateEvent $event) : void + { + $posts = $this->posts->all(); + + foreach ($posts as $post) { + $event->getUrlContainer()->addUrl( + new UrlConcrete( + $event->getUrlGenerator()->generate( + 'blog_post', + ['date' => $post->date->format('Y-m-d'), 'slug' => $post->slug], + UrlGeneratorInterface::ABSOLUTE_URL + ), + changefreq: 'weekly' + ), + 'blog' + ); + } + } + + private function populateDocumentation(SitemapPopulateEvent $event) : void + { + $modules = $this->dslDefinitions->modules(); + + foreach ($modules as $module) { + $event->getUrlContainer()->addUrl( + new UrlConcrete( + $event->getUrlGenerator()->generate( + 'documentation_dsl', + ['module' => \mb_strtolower($module->name)], + UrlGeneratorInterface::ABSOLUTE_URL + ), + changefreq: 'weekly' + ), + 'documentation' + ); + + foreach ($this->dslDefinitions->fromModule($module)->all() as $definition) { + $event->getUrlContainer()->addUrl( + new UrlConcrete( + $event->getUrlGenerator()->generate( + 'documentation_dsl_function', + ['module' => \mb_strtolower($module->name), 'function' => $definition->slug()], + UrlGeneratorInterface::ABSOLUTE_URL + ), + changefreq: 'weekly' + ), + 'documentation' + ); + } + } + } + + private function populateExamples(SitemapPopulateEvent $event) : void + { + $topics = $this->examples->topics(); + + foreach ($topics as $topic) { + $event->getUrlContainer()->addUrl( + new UrlConcrete( + $event->getUrlGenerator()->generate( + 'topic', + ['topic' => $topic], + UrlGeneratorInterface::ABSOLUTE_URL + ), + changefreq: 'weekly' + ), + 'examples' + ); + + $examples = $this->examples->examples($topic); + + foreach ($examples as $example) { + $event->getUrlContainer()->addUrl( + new UrlConcrete( + $event->getUrlGenerator()->generate( + 'example', + ['topic' => $topic, 'example' => $example], + UrlGeneratorInterface::ABSOLUTE_URL + ), + changefreq: 'weekly' + ), + 'examples' + ); + } + } + } +}