Passed
Push — master ( 0cbadc...76f984 )
by Marc
02:27
created

theOpenGraphDataShouldSatisfyFullRequirements()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 10
c 1
b 1
f 0
nc 3
nop 1
dl 0
loc 14
rs 9.9332
1
<?php declare(strict_types=1);
2
3
namespace MOrtola\BehatSEOContexts\Context;
4
5
use InvalidArgumentException;
6
use Webmozart\Assert\Assert;
7
8
class SocialContext extends BaseContext
9
{
10
    /**
11
     * @Then /^the (Twitter|Facebook) Open Graph data should not satisfy (minimum|full) requirements$/
12
     */
13
    public function theOpenGraphDataShouldNotSatisfyRequirements(
14
        string $socialNetworkName,
15
        string $requirementsType
16
    ): void {
17
        $this->assertInverse(
18
            function () use ($socialNetworkName, $requirementsType) {
19
                $this->theOpenGraphDataShouldSatisfyRequirements($socialNetworkName, $requirementsType);
0 ignored issues
show
Unused Code introduced by
The call to MOrtola\BehatSEOContexts...ldSatisfyRequirements() has too many arguments starting with $requirementsType. ( Ignorable by Annotation )

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

19
                $this->/** @scrutinizer ignore-call */ 
20
                       theOpenGraphDataShouldSatisfyRequirements($socialNetworkName, $requirementsType);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
20
            },
21
            sprintf('The %s OG Data satisfies %s requirements.', $socialNetworkName, $requirementsType)
22
        );
23
    }
24
25
    /**
26
     * @Then /^the (Twitter|Facebook) Open Graph data should satisfy minimum requirements$/
27
     */
28
    public function theOpenGraphDataShouldSatisfyRequirements(string $socialNetworkName): void
29
    {
30
        switch ($socialNetworkName) {
31
            case 'Twitter':
32
                $this->validateTwitterOpenGraphData();
33
34
                break;
35
            case 'Facebook':
36
                $this->validateFacebookOpenGraphData();
37
38
                break;
39
            default:
40
                throw new InvalidArgumentException(
41
                    sprintf('%s open graph simple validation is not allowed.', $socialNetworkName)
42
                );
43
        }
44
    }
45
46
    /**
47
     * @Then /^the (Twitter|Facebook) Open Graph data should satisfy full requirements$/
48
     */
49
    public function theOpenGraphDataShouldSatisfyFullRequirements(string $socialNetworkName): void
50
    {
51
        switch ($socialNetworkName) {
52
            case 'Twitter':
53
                $this->validateFullTwitterOpenGraphData();
54
55
                break;
56
            case 'Facebook':
57
                $this->validateFullFacebookOpenGraphData();
58
59
                break;
60
            default:
61
                throw new InvalidArgumentException(
62
                    sprintf('%s open graph full validation is not allowed.', $socialNetworkName)
63
                );
64
        }
65
    }
66
67
    private function validateTwitterOpenGraphData(): void
68
    {
69
        Assert::oneOf(
70
            $this->getOGMetaContent('twitter:card'),
71
            ['summary', 'summary_large_image', 'app', 'player'],
72
            'OG meta twitter:card contains invalid content'
73
        );
74
75
        $this->getOGMetaContent('twitter:title');
76
    }
77
78
    private function validateFullTwitterOpenGraphData(): void
79
    {
80
        $this->validateTwitterOpenGraphData();
81
82
        Assert::notEmpty(
83
            filter_var($this->getOGMetaContent('twitter:image'), FILTER_VALIDATE_URL)
84
        );
85
86
        $pathInfo = pathinfo($this->getOGMetaContent('twitter:image'));
87
88
        Assert::keyExists($pathInfo, 'extension');
89
90
        if (isset($pathInfo['extension'])) {
91
            Assert::oneOf(
92
                $pathInfo['extension'],
93
                ['jpg', 'jpeg', 'webp', 'png', 'gif'],
94
                'OG meta twitter:image has valid extension. Allowed are: jpg/jpeg, png, webp, gif'
95
            );
96
        }
97
98
        $this->getOGMetaContent('twitter:description');
99
    }
100
101
    private function getOGMetaContent(string $property): string
102
    {
103
        $ogMeta = $this->getSession()->getPage()->find(
104
            'xpath',
105
            sprintf('//head/meta[@property="%1$s" or @name="%1$s"]', $property)
106
        );
107
108
        Assert::notNull(
109
            $ogMeta,
110
            sprintf('Open Graph meta %s does not exist', $property)
111
        );
112
113
        Assert::notEmpty(
114
            $ogMeta->getAttribute('content'),
115
            sprintf('Open Graph meta %s should not be empty', $property)
116
        );
117
118
        return $ogMeta->getAttribute('content') ?? '';
119
    }
120
121
    private function validateFacebookOpenGraphData(): void
122
    {
123
        Assert::notEmpty(
124
            filter_var($this->getOGMetaContent('og:url'), FILTER_VALIDATE_URL)
125
        );
126
127
        Assert::eq(
128
            $this->getOGMetaContent('og:url'),
129
            $this->getCurrentUrl(),
130
            'OG meta og:url does not match expected url'
131
        );
132
133
        $this->getOGMetaContent('og:title');
134
        $this->getOGMetaContent('og:description');
135
136
        Assert::notEmpty(
137
            filter_var($this->getOGMetaContent('og:image'), FILTER_VALIDATE_URL)
138
        );
139
140
        $pathInfo = pathinfo($this->getOGMetaContent('og:image'));
141
142
        Assert::keyExists($pathInfo, 'extension');
143
144
        if (isset($pathInfo['extension'])) {
145
            Assert::oneOf(
146
                $pathInfo['extension'],
147
                ['jpg', 'jpeg', 'png', 'gif'],
148
                'OG meta og:image has valid extension. Allowed are: jpg/jpeg, png, gif'
149
            );
150
        }
151
    }
152
153
    private function validateFullFacebookOpenGraphData(): void
154
    {
155
        $this->validateFacebookOpenGraphData();
156
157
        Assert::oneOf(
158
            $this->getOGMetaContent('og:type'),
159
            [
160
                'article',
161
                'book',
162
                'books.author',
163
                'books.book',
164
                'books.genre',
165
                'business.business',
166
                'fitness.course',
167
                'game.achievement',
168
                'music.album',
169
                'music.playlist',
170
                'music.radio_station',
171
                'music.song',
172
                'place',
173
                'product',
174
                'product.group',
175
                'product.item',
176
                'profile',
177
                'restaurant.menu',
178
                'restaurant.menu_item',
179
                'restaurant.menu_section',
180
                'restaurant.restaurant',
181
                'video.episode',
182
                'video.movie',
183
                'video.other',
184
                'video.tv_show',
185
            ],
186
            'OG meta og:type contains invalid content.'
187
        );
188
189
        Assert::regex(
190
            $this->getOGMetaContent('og:locale'),
191
            '/^[a-z]{2}_[A-Z]{2}$/',
192
            'OG meta og:locale does not follow the right format az_AZ.'
193
        );
194
    }
195
}
196