Issues (1)

src/HumanDirect/Socially/Parser.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace HumanDirect\Socially;
4
5
use HumanDirect\Socially\Normalizer\DefaultNormalizer;
6
use HumanDirect\Socially\Normalizer\NormalizerInterface;
7
8
/**
9
 * Class Parser.
10
 */
11
class Parser implements ParserInterface
12
{
13
    /**
14
     * @var NormalizerInterface[]
15
     */
16
    private $normalizers;
17
18
    /**
19
     * {@inheritdoc}
20
     */
21
    public function parse(string $url): ResultInterface
22
    {
23
        if (!$this->isSocialMediaProfile($url)) {
24
            throw new NotSupportedException('Supplied URL is not a social media profile URL.');
25
        }
26
27
        return Result::createFromUrl($url);
28
    }
29
30
    /**
31
     * {@inheritdoc}
32
     */
33
    public function normalize(string $url): string
34
    {
35
        if (null === $this->normalizers) {
36
            $this->loadNormalizers();
37
        }
38
39
        try {
40
            $platform = $this->identifyPlatform($url);
41
        } catch (NotSupportedException | \Exception $e) {
42
            return $url;
43
        }
44
45
        $normalizer = $this->getNormalizer($platform);
46
47
        return $normalizer->normalize($url);
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function isSocialMediaProfile(string $url): bool
54
    {
55
        if (!Util::isValidUrl($url)) {
56
            return false;
57
        }
58
59
        try {
60
            $this->identifyPlatform($url);
61
        } catch (NotSupportedException | \Exception $e) {
62
            return false;
63
        }
64
65
        return true;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function identifyPlatform(string $url): string
72
    {
73
        foreach (self::SOCIAL_MEDIA_PATTERNS as $platform => $regex) {
74
            foreach ($regex as $prefix => $pattern) {
75
                if (preg_match('#' . $pattern . '#i', rawurldecode($url))) {
76
                    return \is_string($prefix) ? sprintf('%s.%s', $platform, $prefix) : $platform;
77
                }
78
            }
79
        }
80
81
        throw new NotSupportedException('Could not identify platform for URL.');
82
    }
83
84
    /**
85
     * Load normalizers.
86
     */
87
    private function loadNormalizers(): void
88
    {
89
        $normalizerNS = '\\HumanDirect\\Socially\\Normalizer\\';
90
        $directory = new \RecursiveDirectoryIterator(
91
            __DIR__ . '/Normalizer',
92
            \RecursiveDirectoryIterator::SKIP_DOTS
93
        );
94
        $files = new \RecursiveCallbackFilterIterator($directory, function ($current, $key, $iterator) use ($normalizerNS) {
0 ignored issues
show
function(...) { /* ... */ } of type callable is incompatible with the type string expected by parameter $callback of RecursiveCallbackFilterIterator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
        $files = new \RecursiveCallbackFilterIterator($directory, /** @scrutinizer ignore-type */ function ($current, $key, $iterator) use ($normalizerNS) {
Loading history...
95
            $className = str_replace('.php', '', $current->getFilename());
96
            $isNormalizer = 'Normalizer' === substr($className, -10);
97
98
            if (!$isNormalizer || $current->isDir() || $iterator->hasChildren()) {
99
                return false;
100
            }
101
102
            $r = new \ReflectionClass($normalizerNS . $className);
103
104
            return $r->isInstantiable();
105
        });
106
107
        foreach ($files as $file) {
108
            $className = $normalizerNS . str_replace('.php', '', $file->getFilename());
109
            $this->normalizers[] = new $className();
110
        }
111
    }
112
113
    /**
114
     * Get a normalizer for a specific platform or a default normalizer.
115
     *
116
     * @param string $platform
117
     *
118
     * @return NormalizerInterface
119
     */
120
    private function getNormalizer(string $platform): NormalizerInterface
121
    {
122
        foreach ($this->normalizers as $normalizer) {
123
            if ($normalizer->supports($platform)) {
124
                return $normalizer;
125
            }
126
        }
127
128
        return new DefaultNormalizer();
129
    }
130
}
131