Test Failed
Push — release/4.x ( d1eb98...528038 )
by
unknown
04:34
created

lBundle/Url/ShortUrlManager.php$0   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 7
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 10
wmc 1
1
<?php
2
declare(strict_types=1);
3
/**
4
 * @copyright Zicht Online <http://zicht.nl>
5
 */
6
7
namespace Zicht\Bundle\UrlBundle\Url;
8
9
use Zicht\Bundle\UrlBundle\Aliasing\Aliasing;
10
use Zicht\Bundle\UrlBundle\Entity\UrlAlias;
11
12
// phpcs:disable Zicht.NamingConventions.Functions.NestedDefinition
13
14
class ShortUrlManager
15
{
16
    /**
17
     * @var ShortUrlHashGeneratorInterface
18
     */
19
    private $shortUrlHashGenerator;
20
21
    /**
22
     * @var Aliasing
23
     */
24
    private $aliasing;
25
26
    /**
27
     * @param Aliasing $aliasing
28
     * @param ShortUrlHashGeneratorInterface|null $shortUrlHashGenerator
29
     */
30
    public function __construct(Aliasing $aliasing, ShortUrlHashGeneratorInterface $shortUrlHashGenerator = null)
31
    {
32
        $this->aliasing = $aliasing;
33
        $this->shortUrlHashGenerator = $shortUrlHashGenerator ?: new class() implements ShortUrlHashGeneratorInterface {
34
            /**
35
             * {@inheritDoc}
36
             */
37
            public function generate($url, $length)
38
            {
39
                return substr(hash('sha1', $url), 0, $length);
40
            }
41
        };
42
    }
43
44
    /**
45
     * @param string $url
46
     * @param string|null $prefix
47
     * @param int $minLength
48
     * @param int $mode
49
     * @return UrlAlias
50
     */
51
    public function getAlias($url, $prefix = null, $minLength = 8, $mode = UrlAlias::MOVE)
52
    {
53
        if ($prefix && false === strpos($prefix, '/')) {
54
            $prefix = sprintf('/%s', $prefix);
55
        }
56
57
        do {
58
            // the hash will function as our public url
59
            $hash = $this->shortUrlHashGenerator->generate($url, $minLength);
60
            $publicUrl = $prefix ? sprintf('%s/%s', $prefix, $hash) : $hash;
61
            $exists = $this->aliasing->getRepository()->findOneByPublicUrl($publicUrl, $mode);
62
            if ($exists && $exists->getInternalUrl() === $url) {
63
                return $exists;
64
            }
65
            $minLength++;
66
            // sanely (sha256 consists of 64 chars) fail if we have a collision after numerous attempts. Something might be wronly implemented.
67
            if ($minLength >= 65) {
68
                throw new \LogicException(sprintf('Found a collision for a hash with %d chars. Something is not right.', $minLength));
69
            }
70
        } while ($exists);
71
72
        $this->aliasing->addAlias($publicUrl, $url, $mode);
73
        return $this->aliasing->findAlias($publicUrl, $url);
74
    }
75
}
76