Completed
Push — develop ( e72854...0832ef )
by Daniel
06:46
created

RouteFactory::getRoutePrefix()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Silverback\ApiComponentBundle\Factory;
6
7
use ApiPlatform\Core\Validator\ValidatorInterface;
8
use Cocur\Slugify\SlugifyInterface;
9
use Doctrine\Common\Collections\ArrayCollection;
10
use Doctrine\Common\Persistence\ObjectManager;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Silverback\ApiComponentBundle\Entity\Content\AbstractContent;
13
use Silverback\ApiComponentBundle\Entity\Route\Route;
14
use Silverback\ApiComponentBundle\Entity\Route\RouteAwareInterface;
15
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
16
17
final class RouteFactory
18
{
19
    private $slugify;
20
    private $manager;
21
    private $validator;
22
23
    public function __construct(
24
        ObjectManager $manager,
25
        SlugifyInterface $slugify,
26
        ValidatorInterface $validator
27
    ) {
28
        $this->slugify = $slugify;
29
        $this->manager = $manager;
30
        $this->validator = $validator;
31
    }
32
33
    /**
34
     * @param RouteAwareInterface $entity
35
     * @param int|null $postfix
36
     * @return Route
37
     */
38
    public function createFromRouteAwareEntity(RouteAwareInterface $entity, int $postfix = 0): Route
39
    {
40
        $pageRoute = $this->slugify->slugify($entity->getDefaultRoute() ?: '');
41
        $routePrefix = $this->getRoutePrefix($entity);
42
        $fullRoute = $routePrefix . $pageRoute;
43
        if ($postfix > 0) {
44
            $fullRoute .= '-' . $postfix;
45
        }
46
47
        $repository = $this->manager->getRepository(Route::class);
48
        $existing = $repository->findOneBy(['route' => $fullRoute]);
49
        if ($existing) {
50
            return $this->createFromRouteAwareEntity($entity, $postfix + 1);
51
        }
52
53
        $converter = new CamelCaseToSnakeCaseNameConverter();
54
        $generatedName = $converter->normalize(str_replace(' ', '', $entity->getDefaultRouteName()));
55
        $name = $generatedName;
56
        $counter = 0;
57
        while ($repository->findOneBy(['name' => $name])) {
58
            $counter++;
59
            $name = sprintf('%s-%s', $generatedName, $counter);
60
        }
61
62
        $route = new Route();
63
        $route->setName($name)->setRoute($fullRoute);
64
        if ($entity instanceof AbstractContent) {
65
            $route->setContent($entity);
66
        }
67
68
        $entity->addRoute($route);
69
        return $route;
70
    }
71
72
    public function createRedirectFromOldRoute(Route $oldRoute, Route $newRoute): Route
73
    {
74
        $oldRoute
75
            ->setName($oldRoute->getName() . '_redirect')
76
            ->setContent(null)
77
            ->setRedirect($newRoute)
78
        ;
79
        return $oldRoute;
80
    }
81
82
    /**
83
     * @param RouteAwareInterface $entity
84
     * @param EntityManagerInterface|null $entityManager
85
     * @return null|ArrayCollection|Route[]
86
     */
87
    public function createPageRoute(RouteAwareInterface $entity, ?EntityManagerInterface $entityManager = null): ?ArrayCollection
88
    {
89
        $em = $entityManager ?: $this->manager;
90
91
        $entityRoutes = $entity->getRoutes();
92
        if (($routeCount = $entityRoutes->count()) === 0 || $entity->getRegenerateRoute()) {
93
            $newRoutes = new ArrayCollection();
94
            $entity->setRegenerateRoute(false);
95
96
            $newRoute = $this->createFromRouteAwareEntity($entity);
97
            $this->validator->validate($newRoute);
98
            $em->persist($newRoute);
99
100
            if ($routeCount > 0 && ($defaultRoute = $entityRoutes->first())) {
101
                $this->createRedirectFromOldRoute($defaultRoute, $newRoute);
102
                $newRoutes->add($defaultRoute);
103
                $entity->removeRoute($defaultRoute);
104
            }
105
106
            $newRoutes->add($newRoute);
107
            return $newRoutes;
108
        }
109
        return null;
110
    }
111
112
    /**
113
     * @param RouteAwareInterface $entity
114
     * @return string
115
     */
116
    private function getRoutePrefix(RouteAwareInterface $entity): string
117
    {
118
        $parent = $entity->getParentRoute();
119
        if ($parent) {
120
            return $parent->getRoute() . '/';
121
        }
122
        return '/';
123
    }
124
}
125