Completed
Push — master ( 627e0e...cd277e )
by Kamil
15s
created

DefaultContext::getAuthorizationChecker()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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
namespace Sylius\Bundle\ResourceBundle\Behat;
13
14
use Behat\Behat\Context\Context;
15
use Behat\Mink\Element\NodeElement;
16
use Behat\Mink\Exception\ElementNotFoundException;
17
use Behat\MinkExtension\Context\RawMinkContext;
18
use Behat\Symfony2Extension\Context\KernelAwareContext;
19
use Doctrine\Common\Collections\ArrayCollection;
20
use Doctrine\Common\Persistence\ObjectManager;
21
use Faker\Factory as FakerFactory;
22
use Faker\Generator;
23
use Sylius\Component\Resource\Factory\FactoryInterface;
24
use Sylius\Component\Resource\Repository\RepositoryInterface;
25
use Symfony\Component\DependencyInjection\ContainerInterface;
26
use Symfony\Component\HttpKernel\KernelInterface;
27
use Symfony\Component\Intl\Intl;
28
use Symfony\Component\Routing\RouterInterface;
29
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
30
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
31
use Symfony\Component\Security\Core\User\UserInterface;
32
33
abstract class DefaultContext extends RawMinkContext implements Context, KernelAwareContext
34
{
35
    /**
36
     * @var string
37
     */
38
    protected $applicationName = 'sylius';
39
40
    /**
41
     * @var Generator
42
     */
43
    protected $faker;
44
45
    /**
46
     * @var array
47
     */
48
    protected $actions = [
49
        'viewing' => 'show',
50
        'creation' => 'create',
51
        'editing' => 'update',
52
        'building' => 'build',
53
        'customization' => 'customize',
54
    ];
55
56
    /**
57
     * @var KernelInterface
58
     */
59
    private $kernel;
60
61
    /**
62
     * @var KernelInterface
63
     */
64
    private static $sharedKernel;
65
66
    public function __construct($applicationName = null)
67
    {
68
        \Locale::setDefault('en');
69
70
        $this->faker = FakerFactory::create();
71
72
        if (null !== $applicationName) {
73
            $this->applicationName = $applicationName;
74
        }
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function setKernel(KernelInterface $kernel)
81
    {
82
        $this->kernel = $kernel;
83
84
        if (null === self::$sharedKernel) {
85
            self::$sharedKernel = clone $kernel;
86
            self::$sharedKernel->boot();
87
        }
88
    }
89
90
    /**
91
     * @param string $type
92
     * @param string $name
93
     *
94
     * @return object
95
     */
96
    protected function findOneByName($type, $name)
97
    {
98
        $resource = $this->getRepository($type)->findOneByName(trim($name));
0 ignored issues
show
Bug introduced by
The method findOneByName() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
99
100
        if (null === $resource) {
101
            throw new \InvalidArgumentException(
102
                sprintf('%s with name "%s" was not found.', str_replace('_', ' ', ucfirst($type)), $name)
103
            );
104
        }
105
106
        return $resource;
107
    }
108
109
    /**
110
     * @param string $type
111
     * @param array  $criteria
112
     *
113
     * @return object
114
     *
115
     * @throws \InvalidArgumentException
116
     */
117
    protected function findOneBy($type, array $criteria)
118
    {
119
        $resource = $this
120
            ->getRepository($type)
121
            ->findOneBy($criteria)
122
        ;
123
124
        if (null === $resource) {
125
            throw new \InvalidArgumentException(
126
                sprintf('%s for criteria "%s" was not found.', str_replace('_', ' ', ucfirst($type)), serialize($criteria))
127
            );
128
        }
129
130
        return $resource;
131
    }
132
133
    /**
134
     * @param string $resourceName
135
     *
136
     * @return RepositoryInterface
137
     */
138
    protected function getRepository($resourceName)
139
    {
140
        return $this->getService($this->applicationName.'.repository.'.$resourceName);
141
    }
142
143
    /**
144
     * @param string $resourceName
145
     *
146
     * @return FactoryInterface
147
     */
148
    protected function getFactory($resourceName)
149
    {
150
        return $this->getService($this->applicationName.'.factory.'.$resourceName);
151
    }
152
153
    /**
154
     * @return ObjectManager
155
     */
156
    protected function getEntityManager()
157
    {
158
        return $this->getService('doctrine')->getManager();
159
    }
160
161
    /**
162
     * @return ContainerInterface
163
     */
164
    protected function getContainer()
165
    {
166
        return $this->kernel->getContainer();
167
    }
168
169
    /**
170
     * @param string $id
171
     *
172
     * @return object
173
     */
174
    protected function getService($id)
175
    {
176
        return $this->getContainer()->get($id);
177
    }
178
179
    /**
180
     * Configuration converter.
181
     *
182
     * @param string $configurationString
183
     *
184
     * @return array
185
     */
186
    protected function getConfiguration($configurationString)
187
    {
188
        $configuration = [];
189
        $list = explode(',', $configurationString);
190
191
        foreach ($list as $parameter) {
192
            list($key, $value) = explode(':', $parameter, 2);
193
            $key = strtolower(trim(str_replace(' ', '_', $key)));
194
195
            switch ($key) {
196
                case 'country':
197
                    $countryCode = $this->getCountryCodeByEnglishCountryName(trim($value));
198
199
                    $configuration[$key] = $this->getRepository('country')->findOneBy(['code' => $countryCode])->getId();
200
                    break;
201
202
                case 'taxons':
203
                    $configuration[$key] = [$this->getRepository('taxon')->findOneByName(trim($value))->getCode()];
0 ignored issues
show
Bug introduced by
The method findOneByName() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
204
                    break;
205
206
                case 'variant':
207
                    $configuration[$key] = $this->getRepository('product')->findOneByName($value)->getMasterVariant()->getId();
0 ignored issues
show
Bug introduced by
The method findOneByName() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
208
                    break;
209
210
                case 'amount':
211
                    $configuration[$key] = (int) $value;
212
                    break;
213
214
                default:
215
                    $configuration[$key] = trim($value);
216
                    break;
217
            }
218
        }
219
220
        return $configuration;
221
    }
222
223
    /**
224
     * Generate page url.
225
     * This method uses simple convention where page argument is prefixed
226
     * with the application name and used as route name passed to router generate method.
227
     *
228
     * @param object|string $page
229
     * @param array         $parameters
230
     *
231
     * @return string
232
     */
233
    protected function generatePageUrl($page, array $parameters = [])
234
    {
235
        if (is_object($page)) {
236
            return $this->generateUrl($page, $parameters);
0 ignored issues
show
Documentation introduced by
$page is of type object, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
237
        }
238
239
        $route = str_replace(' ', '_', trim($page));
240
        $routes = $this->getRouter()->getRouteCollection();
241
242
        if (null === $routes->get($route)) {
243
            $route = $this->applicationName.'_'.$route;
244
        }
245
246
        if (null === $routes->get($route)) {
247
            $route = str_replace($this->applicationName.'_', $this->applicationName.'_backend_', $route);
248
        }
249
250
        $route = str_replace(array_keys($this->actions), array_values($this->actions), $route);
251
        $route = str_replace(' ', '_', $route);
252
253
        return $this->generateUrl($route, $parameters);
254
    }
255
256
    /**
257
     * Get current user instance.
258
     *
259
     * @return UserInterface|null
260
     *
261
     * @throws \Exception
262
     */
263
    protected function getUser()
264
    {
265
        $token = $this->getTokenStorage()->getToken();
266
267
        if (null === $token) {
268
            throw new \Exception('No token found in security context.');
269
        }
270
271
        return $token->getUser();
272
    }
273
274
    /**
275
     * @return TokenStorageInterface
276
     */
277
    protected function getTokenStorage()
278
    {
279
        return $this->getContainer()->get('security.token_storage');
280
    }
281
282
    /**
283
     * @return AuthorizationCheckerInterface
284
     */
285
    protected function getAuthorizationChecker()
286
    {
287
        return $this->getContainer()->get('security.authorization_checker');
288
    }
289
290
    /**
291
     * @param string  $route
292
     * @param array   $parameters
293
     * @param bool $absolute
294
     *
295
     * @return string
296
     */
297
    protected function generateUrl($route, array $parameters = [], $absolute = false)
298
    {
299
        return $this->locatePath($this->getRouter()->generate($route, $parameters, $absolute));
300
    }
301
302
    /**
303
     * Presses button with specified id|name|title|alt|value.
304
     *
305
     * @param string $button
306
     *
307
     * @throws ElementNotFoundException
308
     */
309
    protected function pressButton($button)
310
    {
311
        $this->getSession()->getPage()->pressButton($this->fixStepArgument($button));
312
    }
313
314
    /**
315
     * Clicks link with specified id|title|alt|text.
316
     *
317
     * @param string $link
318
     *
319
     * @throws ElementNotFoundException
320
     */
321
    protected function clickLink($link)
322
    {
323
        $this->getSession()->getPage()->clickLink($this->fixStepArgument($link));
324
    }
325
326
    /**
327
     * Fills in form field with specified id|name|label|value.
328
     *
329
     * @param string $field
330
     * @param string $value
331
     *
332
     * @throws ElementNotFoundException
333
     */
334
    protected function fillField($field, $value)
335
    {
336
        $this->getSession()->getPage()->fillField(
337
            $this->fixStepArgument($field),
338
            $this->fixStepArgument($value)
339
        );
340
    }
341
342
    /**
343
     * Selects option in select field with specified id|name|label|value.
344
     *
345
     * @param string $select
346
     * @param string $option
347
     *
348
     * @throws ElementNotFoundException
349
     */
350
    protected function selectOption($select, $option)
351
    {
352
        $this->getSession()->getPage()->selectFieldOption(
353
            $this->fixStepArgument($select),
354
            $this->fixStepArgument($option)
355
        );
356
    }
357
358
    /**
359
     * Returns fixed step argument (with \\" replaced back to ").
360
     *
361
     * @param string $argument
362
     *
363
     * @return string
364
     */
365
    protected function fixStepArgument($argument)
366
    {
367
        return str_replace('\\"', '"', $argument);
368
    }
369
370
    /**
371
     * @param NodeElement $table
372
     * @param string $columnName
373
     *
374
     * @return int
375
     *
376
     * @throws \Exception If column was not found
377
     */
378
    protected function getColumnIndex(NodeElement $table, $columnName)
379
    {
380
        $rows = $table->findAll('css', 'tr');
381
382
        if (!isset($rows[0])) {
383
            throw new \Exception('There are no rows!');
384
        }
385
386
        /** @var NodeElement $firstRow */
387
        $firstRow = $rows[0];
388
        $columns = $firstRow->findAll('css', 'th,td');
389
        foreach ($columns as $index => $column) {
390
            /** @var NodeElement $column */
391
            if (0 === stripos($column->getText(), $columnName)) {
392
                return $index;
393
            }
394
        }
395
396
        throw new \Exception(sprintf('Column with name "%s" not found!', $columnName));
397
    }
398
399
    /**
400
     * @param NodeElement $table
401
     * @param array $fields
402
     *
403
     * @return NodeElement|null
404
     *
405
     * @throws \Exception If column was not found
406
     */
407
    protected function getRowWithFields(NodeElement $table, array $fields)
408
    {
409
        $foundRows = $this->getRowsWithFields($table, $fields, true);
410
411
        if (empty($foundRows)) {
412
            return null;
413
        }
414
415
        return current($foundRows);
416
    }
417
418
    /**
419
     * @param NodeElement $table
420
     * @param array $fields
421
     * @param bool $onlyFirstOccurence
422
     *
423
     * @return NodeElement[]
424
     *
425
     * @throws \Exception If columns or rows were not found
426
     */
427
    protected function getRowsWithFields(NodeElement $table, array $fields, $onlyFirstOccurence = false)
428
    {
429
        $rows = $table->findAll('css', 'tr');
430
431
        if (!isset($rows[0])) {
432
            throw new \Exception('There are no rows!');
433
        }
434
435
        $fields = $this->replaceColumnNamesWithColumnIds($table, $fields);
436
437
        $foundRows = [];
438
439
        /** @var NodeElement[] $rows */
440
        $rows = $table->findAll('css', 'tr');
441
        foreach ($rows as $row) {
442
            $found = true;
443
444
            /** @var NodeElement[] $columns */
445
            $columns = $row->findAll('css', 'th,td');
446
            foreach ($fields as $index => $searchedValue) {
447
                if (!isset($columns[$index])) {
448
                    throw new \InvalidArgumentException(sprintf('There is no column with index %d', $index));
449
                }
450
451
                $containing = false;
452
                $searchedValue = trim($searchedValue);
453
                if (0 === strpos($searchedValue, '%') && (strlen($searchedValue) - 1) === strrpos($searchedValue, '%')) {
454
                    $searchedValue = substr($searchedValue, 1, strlen($searchedValue) - 2);
455
                    $containing = true;
456
                }
457
458
                $position = stripos(trim($columns[$index]->getText()), $searchedValue);
459
                if (($containing && false === $position) || (!$containing && 0 !== $position)) {
460
                    $found = false;
461
462
                    break;
463
                }
464
            }
465
466
            if ($found) {
467
                $foundRows[] = $row;
468
469
                if ($onlyFirstOccurence) {
470
                    break;
471
                }
472
            }
473
        }
474
475
        return $foundRows;
476
    }
477
478
    /**
479
     * @param NodeElement $table
480
     * @param string[] $fields
481
     *
482
     * @return string[]
483
     *
484
     * @throws \Exception
485
     */
486
    protected function replaceColumnNamesWithColumnIds(NodeElement $table, array $fields)
487
    {
488
        $replacedFields = [];
489
        foreach ($fields as $columnName => $expectedValue) {
490
            $columnIndex = $this->getColumnIndex($table, $columnName);
491
492
            $replacedFields[$columnIndex] = $expectedValue;
493
        }
494
495
        return $replacedFields;
496
    }
497
498
    /**
499
     * @param callable $callback
500
     * @param int $limit
501
     * @param int $delay In miliseconds
502
     *
503
     * @return mixed
504
     *
505
     * @throws \RuntimeException If timeout was reached
506
     */
507
    protected function waitFor(callable $callback, $limit = 30, $delay = 100)
508
    {
509
        for ($i = 0; $i < $limit; ++$i) {
510
            $payload = $callback();
511
512
            if (!empty($payload)) {
513
                return $payload;
514
            }
515
516
            usleep($delay * 1000);
517
        }
518
519
        throw new \RuntimeException(sprintf('Timeout reached (%f seconds)!', round($limit * $delay / 1000, 1)));
520
    }
521
522
    /**
523
     * @param string $name
524
     *
525
     * @return string
526
     *
527
     * @throws \InvalidArgumentException If name is not found in country code registry.
528
     */
529
    protected function getCountryCodeByEnglishCountryName($name)
530
    {
531
        $names = Intl::getRegionBundle()->getCountryNames('en');
532
        $countryCode = array_search(trim($name), $names);
533
534
        if (null === $countryCode) {
535
            throw new \InvalidArgumentException(sprintf(
536
                'Country "%s" not found! Available names: %s.', $name, implode(', ', $names)
537
            ));
538
        }
539
540
        return $countryCode;
541
    }
542
543
    /**
544
     * @param string $name
545
     *
546
     * @return string
547
     *
548
     * @throws \InvalidArgumentException If name is not found in locale code registry.
549
     */
550
    protected function getLocaleCodeByEnglishLocaleName($name)
551
    {
552
        $localeNameConverter = $this->getService('sylius.converter.locale_name');
553
554
        return $localeNameConverter->convertToCode($name);
555
    }
556
557
    /**
558
     * @return RouterInterface
559
     */
560
    protected function getRouter()
561
    {
562
        return $this->getSharedService('router');
563
    }
564
565
    /**
566
     * @return KernelInterface
567
     */
568
    protected function getKernel()
569
    {
570
        return $this->kernel;
571
    }
572
573
    /**
574
     * @return KernelInterface
575
     */
576
    protected function getSharedKernel()
577
    {
578
        return self::$sharedKernel;
579
    }
580
581
    /**
582
     * @param string $id
583
     *
584
     * @return object
585
     */
586
    protected function getSharedService($id)
587
    {
588
        return self::$sharedKernel->getContainer()->get($id);
589
    }
590
}
591