Skip to content
Open
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
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"symfony/security-core": "^6.4 || ^7.1",
"symfony/security-http": "^6.4 || ^7.1",
"symfony/serializer": "^6.4 || ^7.1",
"symfony/string": "^6.4 || ^7.1",
"symfony/validator": "^6.4 || ^7.1",
"twig/string-extra": "^3.0",
"twig/twig": "^3.0"
Expand Down
68 changes: 27 additions & 41 deletions src/Entity/PageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
use Sonata\PageBundle\Model\PageInterface;
use Sonata\PageBundle\Model\PageManagerInterface;
use Sonata\PageBundle\Model\SiteInterface;
use Sonata\PageBundle\Service\Contract\PageFixerInterface;
use Sonata\PageBundle\Service\PageFixerService;
use Symfony\Component\String\Slugger\AsciiSlugger;

/**
* @extends BaseEntityManager<PageInterface>
Expand All @@ -35,10 +38,19 @@ final class PageManager extends BaseEntityManager implements PageManagerInterfac
public function __construct(
string $class,
ManagerRegistry $registry,
private SlugifyInterface $slugify,
private SlugifyInterface|PageFixerInterface $pageFixer,
private array $defaults = [],
private array $pageDefaults = [],
) {
// NEXT_MAJOR: Remove the if block bellow and "cocur/slugify" dependecy.
if ($this->pageFixer instanceof SlugifyInterface) {
@trigger_error(\sprintf(
'Inject %s in %s is deprecated since version 4.10.0 and will be removed in 5.0, use %s instead of.',
SlugifyInterface::class,
self::class,
PageFixerInterface::class,
), \E_USER_DEPRECATED);
}
parent::__construct($class, $registry);
}

Expand Down Expand Up @@ -71,50 +83,24 @@ public function createWithDefaults(array $defaults = []): PageInterface
return $page;
}

/**
* NEXT_MAJOR: keep only $this->fixPageUrl->fixUrl$page) in this method.
*/
public function fixUrl(PageInterface $page): void
{
if ($page->isInternal()) {
$page->setUrl(null); // internal routes do not have any url ...

return;
}

// hybrid page cannot be altered
if (!$page->isHybrid()) {
$parent = $page->getParent();

if (null !== $parent) {
$slug = $page->getSlug();

if (null === $slug) {
$slug = $this->slugify->slugify($page->getName() ?? '');

$page->setSlug($slug);
}

$parentUrl = $parent->getUrl();

if ('/' === $parentUrl) {
$base = '/';
} elseif (!str_ends_with($parentUrl ?? '', '/')) {
$base = $parentUrl.'/';
} else {
$base = $parentUrl;
}

$url = $page->getCustomUrl() ?? $slug;
$page->setUrl('/'.ltrim($base.$url, '/'));
} else {
$page->setSlug(null);

$url = $page->getCustomUrl() ?? '';
$page->setUrl('/'.ltrim($url, '/'));
}
$pageFixer = $this->pageFixer;

if ($pageFixer instanceof SlugifyInterface) {
@trigger_error(\sprintf(
'Inject %s in %s is deprecated since version 4.10.0 and will be removed in 5.0, use %s instead of.',
SlugifyInterface::class,
self::class,
PageFixerInterface::class,
), \E_USER_DEPRECATED);
$pageFixer = new PageFixerService(new AsciiSlugger());
}

foreach ($page->getChildren() as $child) {
$this->fixUrl($child);
}
$pageFixer->fixUrl($page);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Resources/config/orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Sonata\PageBundle\Model\SnapshotPageProxyFactory;
use Sonata\PageBundle\Serializer\BlockTypeExtractor;
use Sonata\PageBundle\Serializer\InterfaceTypeExtractor;
use Sonata\PageBundle\Service\Contract\PageFixerInterface;

return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->services()
Expand All @@ -42,7 +43,7 @@
->args([
param('sonata.page.page.class'),
service('doctrine'),
service('sonata.page.slugify.cocur'),
service(PageFixerInterface::class),
abstract_arg('defaults'),
abstract_arg('page defaults'),
])
Expand Down
9 changes: 8 additions & 1 deletion src/Resources/config/service.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Sonata\PageBundle\Service\CleanupSnapshotService;
use Sonata\PageBundle\Service\Contract\PageFixerInterface;
use Sonata\PageBundle\Service\CreateSnapshotService;
use Sonata\PageBundle\Service\PageFixerService;

return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->services()
Expand All @@ -34,5 +36,10 @@
service('sonata.page.manager.page'),
])

->alias(CreateSnapshotService::class, 'sonata.page.service.create_snapshot');
->alias(CreateSnapshotService::class, 'sonata.page.service.create_snapshot')

->set(PageFixerService::class)
->autowire()

->alias(PageFixerInterface::class, PageFixerService::class);
};
21 changes: 21 additions & 0 deletions src/Service/Contract/PageFixerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\PageBundle\Service\Contract;

use Sonata\PageBundle\Model\PageInterface;

interface PageFixerInterface
{
public function fixUrl(PageInterface $page): void;
}
74 changes: 74 additions & 0 deletions src/Service/PageFixerService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sonata\PageBundle\Service;

use Sonata\PageBundle\Model\PageInterface;
use Sonata\PageBundle\Service\Contract\PageFixerInterface;
use Symfony\Component\String\Slugger\SluggerInterface;

final class PageFixerService implements PageFixerInterface
{
public function __construct(private SluggerInterface $slugger)
{
}

public function fixUrl(PageInterface $page): void
{
if ($page->isInternal()) {
$page->setUrl(null); // internal routes do not have any url ...

return;
}

// hybrid page cannot be altered
if (!$page->isHybrid()) {
$parent = $page->getParent();

if (null !== $parent) {
$slug = $page->getSlug();

if (null === $slug) {
$slug = $this->slugger
->slug($page->getName() ?? '')
->lower()
->toString();

$page->setSlug(\sprintf('%s', $slug));
}

$parentUrl = $parent->getUrl();

if ('/' === $parentUrl) {
$base = '/';
} elseif (!str_ends_with($parentUrl ?? '', '/')) {
$base = $parentUrl.'/';
} else {
$base = $parentUrl;
}

$url = $page->getCustomUrl() ?? $slug;
$page->setUrl('/'.ltrim($base.$url, '/'));
} else {
$page->setSlug(null);

$url = $page->getCustomUrl() ?? '';
$page->setUrl('/'.ltrim($url, '/'));
}
}

foreach ($page->getChildren() as $child) {
$this->fixUrl($child);
}
}
}
31 changes: 25 additions & 6 deletions tests/Entity/PageManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,36 @@
namespace Sonata\PageBundle\Tests\Entity;

use Cocur\Slugify\Slugify;
use Cocur\Slugify\SlugifyInterface;
use Doctrine\Persistence\ManagerRegistry;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Sonata\PageBundle\Entity\PageManager;
use Sonata\PageBundle\Service\Contract\PageFixerInterface;
use Sonata\PageBundle\Service\PageFixerService;
use Sonata\PageBundle\Tests\Model\Page;
use Symfony\Component\String\Slugger\AsciiSlugger;

final class PageManagerTest extends TestCase
{
public function testFixUrl(): void
/**
* NEXT_MAJOR: Remove this data provider and keep only "PageFixerService" in tests that is using it.
*
* @return iterable<array<SlugifyInterface|PageFixerInterface>>
**/
public static function provideFixUrlCases(): iterable
{
yield [new Slugify()];
yield [new PageFixerService(new AsciiSlugger())];
}

#[DataProvider('provideFixUrlCases')]
public function testFixUrl(SlugifyInterface|PageFixerInterface $pageFixer): void
{
$manager = new PageManager(
Page::class,
static::createStub(ManagerRegistry::class),
new Slugify()
$pageFixer,
);

$page1 = new Page();
Expand Down Expand Up @@ -65,12 +82,13 @@ public function testFixUrl(): void
static::assertSame('/', $page1->getUrl());
}

public function testWithSlashAtTheEnd(): void
#[DataProvider('provideFixUrlCases')]
public function testWithSlashAtTheEnd(SlugifyInterface|PageFixerInterface $pageFixer): void
{
$manager = new PageManager(
Page::class,
$this->createMock(ManagerRegistry::class),
new Slugify()
$pageFixer,
);

$homepage = new Page();
Expand All @@ -92,12 +110,13 @@ public function testWithSlashAtTheEnd(): void
static::assertSame('/bundles/foobar', $child->getUrl());
}

public function testCreateWithGlobalDefaults(): void
#[DataProvider('provideFixUrlCases')]
public function testCreateWithGlobalDefaults(SlugifyInterface|PageFixerInterface $pageFixer): void
{
$manager = new PageManager(
Page::class,
$this->createMock(ManagerRegistry::class),
new Slugify(),
$pageFixer,
[],
['my_route' => ['decorate' => false, 'name' => 'Salut!']]
);
Expand Down