1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Sylius package. |
5
|
|
|
* |
6
|
|
|
* (c) Paweł Jędrzejewski |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
declare(strict_types=1); |
13
|
|
|
|
14
|
|
|
namespace Sylius\Behat\Page\Admin\Taxon; |
15
|
|
|
|
16
|
|
|
use Behat\Mink\Driver\Selenium2Driver; |
17
|
|
|
use Behat\Mink\Element\NodeElement; |
18
|
|
|
use Behat\Mink\Exception\ElementNotFoundException; |
19
|
|
|
use DMore\ChromeDriver\ChromeDriver; |
20
|
|
|
use Sylius\Behat\Behaviour\ChecksCodeImmutability; |
21
|
|
|
use Sylius\Behat\Page\Admin\Crud\UpdatePage as BaseUpdatePage; |
22
|
|
|
use Sylius\Behat\Service\AutocompleteHelper; |
23
|
|
|
use Sylius\Behat\Service\SlugGenerationHelper; |
24
|
|
|
use Sylius\Component\Core\Model\TaxonInterface; |
25
|
|
|
use Webmozart\Assert\Assert; |
26
|
|
|
|
27
|
|
|
class UpdatePage extends BaseUpdatePage implements UpdatePageInterface |
28
|
|
|
{ |
29
|
|
|
use ChecksCodeImmutability; |
30
|
|
|
|
31
|
|
|
/** @var array */ |
32
|
|
|
private $imageUrls = []; |
33
|
|
|
|
34
|
|
|
public function chooseParent(TaxonInterface $taxon): void |
35
|
|
|
{ |
36
|
|
|
AutocompleteHelper::chooseValue($this->getSession(), $this->getElement('parent')->getParent(), $taxon->getName()); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
public function describeItAs(string $description, string $languageCode): void |
40
|
|
|
{ |
41
|
|
|
$this->getDocument()->fillField(sprintf('sylius_taxon_translations_%s_description', $languageCode), $description); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
public function nameIt(string $name, string $languageCode): void |
45
|
|
|
{ |
46
|
|
|
$this->activateLanguageTab($languageCode); |
47
|
|
|
$this->getDocument()->fillField(sprintf('sylius_taxon_translations_%s_name', $languageCode), $name); |
48
|
|
|
|
49
|
|
|
if ($this->getDriver() instanceof Selenium2Driver || $this->getDriver() instanceof ChromeDriver) { |
|
|
|
|
50
|
|
|
SlugGenerationHelper::waitForSlugGeneration( |
51
|
|
|
$this->getSession(), |
52
|
|
|
$this->getElement('slug', ['%language%' => $languageCode]) |
53
|
|
|
); |
54
|
|
|
} |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
public function specifySlug(string $slug, string $languageCode): void |
58
|
|
|
{ |
59
|
|
|
$this->getDocument()->fillField(sprintf('sylius_taxon_translations_%s_slug', $languageCode), $slug); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
public function attachImage(string $path, string $type = null): void |
63
|
|
|
{ |
64
|
|
|
$filesPath = $this->getParameter('files_path'); |
65
|
|
|
|
66
|
|
|
$this->getDocument()->find('css', '[data-form-collection="add"]')->click(); |
67
|
|
|
|
68
|
|
|
$imageForm = $this->getLastImageElement(); |
69
|
|
|
if (null !== $type) { |
70
|
|
|
$imageForm->fillField('Type', $type); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$imageForm->find('css', 'input[type="file"]')->attachFile($filesPath . $path); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
public function isImageWithTypeDisplayed(string $type): bool |
77
|
|
|
{ |
78
|
|
|
$imageElement = $this->getImageElementByType($type); |
79
|
|
|
|
80
|
|
|
$imageUrl = $imageElement ? $imageElement->find('css', 'img')->getAttribute('src') : $this->provideImageUrlForType($type); |
81
|
|
|
if (null === $imageElement && null === $imageUrl) { |
82
|
|
|
return false; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
$this->getDriver()->visit($imageUrl); |
86
|
|
|
$pageText = $this->getDocument()->getText(); |
87
|
|
|
$this->getDriver()->back(); |
88
|
|
|
|
89
|
|
|
return false === stripos($pageText, '404 Not Found'); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
public function isSlugReadonly(string $languageCode = 'en_US'): bool |
93
|
|
|
{ |
94
|
|
|
return SlugGenerationHelper::isSlugReadonly( |
95
|
|
|
$this->getSession(), |
96
|
|
|
$this->getElement('slug', ['%language%' => $languageCode]) |
97
|
|
|
); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function removeImageWithType(string $type): void |
101
|
|
|
{ |
102
|
|
|
$imageElement = $this->getImageElementByType($type); |
103
|
|
|
$imageSourceElement = $imageElement->find('css', 'img'); |
104
|
|
|
if (null !== $imageSourceElement) { |
105
|
|
|
$this->saveImageUrlForType($type, $imageSourceElement->getAttribute('src')); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$imageElement->clickLink('Delete'); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
public function removeFirstImage(): void |
112
|
|
|
{ |
113
|
|
|
$imageElement = $this->getFirstImageElement(); |
114
|
|
|
$imageTypeElement = $imageElement->find('css', 'input[type=text]'); |
115
|
|
|
$imageSourceElement = $imageElement->find('css', 'img'); |
116
|
|
|
|
117
|
|
|
if (null !== $imageTypeElement && null !== $imageSourceElement) { |
118
|
|
|
$this->saveImageUrlForType( |
119
|
|
|
$imageTypeElement->getValue(), |
120
|
|
|
$imageSourceElement->getAttribute('src') |
121
|
|
|
); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
$imageElement->clickLink('Delete'); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
public function enableSlugModification(string $languageCode = 'en_US'): void |
128
|
|
|
{ |
129
|
|
|
SlugGenerationHelper::enableSlugModification( |
130
|
|
|
$this->getSession(), |
131
|
|
|
$this->getElement('toggle_taxon_slug_modification_button', ['%locale%' => $languageCode]) |
132
|
|
|
); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
public function countImages(): int |
136
|
|
|
{ |
137
|
|
|
$imageElements = $this->getImageElements(); |
138
|
|
|
|
139
|
|
|
return count($imageElements); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
public function changeImageWithType(string $type, string $path): void |
143
|
|
|
{ |
144
|
|
|
$filesPath = $this->getParameter('files_path'); |
145
|
|
|
|
146
|
|
|
$imageForm = $this->getImageElementByType($type); |
147
|
|
|
$imageForm->find('css', 'input[type="file"]')->attachFile($filesPath . $path); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
public function modifyFirstImageType(string $type): void |
151
|
|
|
{ |
152
|
|
|
$firstImage = $this->getFirstImageElement(); |
153
|
|
|
|
154
|
|
|
$typeField = $firstImage->findField('Type'); |
155
|
|
|
$typeField->setValue($type); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function getParent(): string |
159
|
|
|
{ |
160
|
|
|
return $this->getElement('parent')->getValue(); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
public function getSlug(string $languageCode = 'en_US'): string |
164
|
|
|
{ |
165
|
|
|
return $this->getElement('slug', ['%language%' => $languageCode])->getValue(); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
public function getValidationMessageForImage(): string |
169
|
|
|
{ |
170
|
|
|
$lastImageElement = $this->getLastImageElement(); |
171
|
|
|
|
172
|
|
|
$foundElement = $lastImageElement->find('css', '.sylius-validation-error'); |
173
|
|
|
if (null === $foundElement) { |
174
|
|
|
throw new ElementNotFoundException($this->getSession(), 'Tag', 'css', '.sylius-validation-error'); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return $foundElement->getText(); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
public function getValidationMessageForImageAtPlace(int $place): string |
181
|
|
|
{ |
182
|
|
|
$images = $this->getImageElements(); |
183
|
|
|
|
184
|
|
|
$foundElement = $images[$place]->find('css', '.sylius-validation-error'); |
185
|
|
|
if (null === $foundElement) { |
186
|
|
|
throw new ElementNotFoundException($this->getSession(), 'Tag', 'css', '.sylius-validation-error'); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return $foundElement->getText(); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
public function activateLanguageTab(string $locale): void |
193
|
|
|
{ |
194
|
|
|
if (!$this->getDriver() instanceof Selenium2Driver && !$this->getDriver() instanceof ChromeDriver) { |
|
|
|
|
195
|
|
|
return; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
$languageTabTitle = $this->getElement('language_tab', ['%locale%' => $locale]); |
199
|
|
|
if (!$languageTabTitle->hasClass('active')) { |
200
|
|
|
$languageTabTitle->click(); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
$this->getDocument()->waitFor(10, function () use ($languageTabTitle) { |
204
|
|
|
return $languageTabTitle->hasClass('active'); |
205
|
|
|
}); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
protected function getElement(string $name, array $parameters = []): NodeElement |
209
|
|
|
{ |
210
|
|
|
if (!isset($parameters['%language%'])) { |
211
|
|
|
$parameters['%language%'] = 'en_US'; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
return parent::getElement($name, $parameters); |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
protected function getCodeElement(): NodeElement |
218
|
|
|
{ |
219
|
|
|
return $this->getElement('code'); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
protected function getDefinedElements(): array |
223
|
|
|
{ |
224
|
|
|
return array_merge(parent::getDefinedElements(), [ |
225
|
|
|
'code' => '#sylius_taxon_code', |
226
|
|
|
'description' => '#sylius_taxon_translations_en_US_description', |
227
|
|
|
'images' => '#sylius_taxon_images', |
228
|
|
|
'language_tab' => '[data-locale="%locale%"] .title', |
229
|
|
|
'name' => '#sylius_taxon_translations_en_US_name', |
230
|
|
|
'parent' => '#sylius_taxon_parent', |
231
|
|
|
'slug' => '#sylius_taxon_translations_%language%_slug', |
232
|
|
|
'toggle_taxon_slug_modification_button' => '[data-locale="%locale%"] .toggle-taxon-slug-modification', |
233
|
|
|
]); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
private function getLastImageElement(): NodeElement |
237
|
|
|
{ |
238
|
|
|
$imageElements = $this->getImageElements(); |
239
|
|
|
|
240
|
|
|
Assert::notEmpty($imageElements); |
241
|
|
|
|
242
|
|
|
return end($imageElements); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
private function getFirstImageElement(): NodeElement |
246
|
|
|
{ |
247
|
|
|
$imageElements = $this->getImageElements(); |
248
|
|
|
|
249
|
|
|
Assert::notEmpty($imageElements); |
250
|
|
|
|
251
|
|
|
return reset($imageElements); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* @return NodeElement[] |
256
|
|
|
*/ |
257
|
|
|
private function getImageElements(): array |
258
|
|
|
{ |
259
|
|
|
$images = $this->getElement('images'); |
260
|
|
|
|
261
|
|
|
return $images->findAll('css', 'div[data-form-collection="item"]'); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
private function getImageElementByType(string $type): ?NodeElement |
|
|
|
|
265
|
|
|
{ |
266
|
|
|
$images = $this->getElement('images'); |
267
|
|
|
$typeInput = $images->find('css', 'input[value="' . $type . '"]'); |
268
|
|
|
|
269
|
|
|
if (null === $typeInput) { |
270
|
|
|
return null; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
return $typeInput->getParent()->getParent()->getParent(); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
private function provideImageUrlForType(string $type): ?string |
|
|
|
|
277
|
|
|
{ |
278
|
|
|
return $this->imageUrls[$type] ?? null; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
private function saveImageUrlForType(string $type, string $imageUrl): void |
282
|
|
|
{ |
283
|
|
|
if (false !== strpos($imageUrl, 'data:image/jpeg')) { |
284
|
|
|
return; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
$this->imageUrls[$type] = $imageUrl; |
288
|
|
|
} |
289
|
|
|
} |
290
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.