Passed
Push — master ( afef6b...b42680 )
by Marc
03:21
created

SocialContext::validateFullTwitterOpenGraphData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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