Completed
Push — theme-bundle ( aad440...af4cdd )
by Kamil
15:45
created

DefaultContext::getTokenStorage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
dl 0
loc 4
rs 10
c 1
b 1
f 0
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\MinkExtension\Context\RawMinkContext;
16
use Behat\Mink\Element\NodeElement;
17
use Behat\Mink\Exception\ElementNotFoundException;
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 = array(
49
        'viewing'  => 'show',
50
        'creation' => 'create',
51
        'editing'  => 'update',
52
        'building' => 'build',
53
    );
54
55
    /**
56
     * @var KernelInterface
57
     */
58
    private $kernel;
59
60
    /**
61
     * @var KernelInterface
62
     */
63
    private static $sharedKernel;
64
65
    public function __construct($applicationName = null)
66
    {
67
        \Locale::setDefault('en');
68
69
        $this->faker = FakerFactory::create();
70
71
        if (null !== $applicationName) {
72
            $this->applicationName = $applicationName;
73
        }
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function setKernel(KernelInterface $kernel)
80
    {
81
        $this->kernel = $kernel;
82
83
        if (null === self::$sharedKernel) {
84
            self::$sharedKernel = clone $kernel;
85
            self::$sharedKernel->boot();
86
        }
87
    }
88
89
    /**
90
     * @param string $type
91
     * @param string $name
92
     *
93
     * @return object
94
     */
95
    protected function findOneByName($type, $name)
96
    {
97
        return $this->findOneBy($type, array('name' => trim($name)));
98
    }
99
100
    /**
101
     * @param string $type
102
     * @param array  $criteria
103
     *
104
     * @return object
105
     *
106
     * @throws \InvalidArgumentException
107
     */
108
    protected function findOneBy($type, array $criteria)
109
    {
110
        $resource = $this
111
            ->getRepository($type)
112
            ->findOneBy($criteria)
113
        ;
114
115
        if (null === $resource) {
116
            throw new \InvalidArgumentException(
117
                sprintf('%s for criteria "%s" was not found.', str_replace('_', ' ', ucfirst($type)), serialize($criteria))
118
            );
119
        }
120
121
        return $resource;
122
    }
123
124
    /**
125
     * @param string $resourceName
126
     *
127
     * @return RepositoryInterface
128
     */
129
    protected function getRepository($resourceName)
130
    {
131
        return $this->getService($this->applicationName.'.repository.'.$resourceName);
132
    }
133
134
    /**
135
     * @param string $resourceName
136
     *
137
     * @return FactoryInterface
138
     */
139
    protected function getFactory($resourceName)
140
    {
141
        return $this->getService($this->applicationName.'.factory.'.$resourceName);
142
    }
143
144
    /**
145
     * @return ObjectManager
146
     */
147
    protected function getEntityManager()
148
    {
149
        return $this->getService('doctrine')->getManager();
150
    }
151
152
    /**
153
     * @return ContainerInterface
154
     */
155
    protected function getContainer()
156
    {
157
        return $this->kernel->getContainer();
158
    }
159
160
    /**
161
     * @param string $id
162
     *
163
     * @return object
164
     */
165
    protected function getService($id)
166
    {
167
        return $this->getContainer()->get($id);
168
    }
169
170
    /**
171
     * Configuration converter.
172
     *
173
     * @param string $configurationString
174
     *
175
     * @return array
176
     */
177
    protected function getConfiguration($configurationString)
178
    {
179
        $configuration = array();
180
        $list = explode(',', $configurationString);
181
182
        foreach ($list as $parameter) {
183
            list($key, $value) = explode(':', $parameter, 2);
184
            $key = strtolower(trim(str_replace(' ', '_', $key)));
185
186
            switch ($key) {
187
                case 'country':
188
                    $isoName = $this->getCountryCodeByEnglishCountryName(trim($value));
189
190
                    $configuration[$key] = $this->getRepository('country')->findOneBy(array('isoName' => $isoName))->getId();
191
                    break;
192
193
                case 'taxons':
194
                    $configuration[$key] = new ArrayCollection(array($this->getRepository('taxon')->findOneBy(array('name' => trim($value)))->getId()));
195
                    break;
196
197
                case 'variant':
198
                    $configuration[$key] = $this->getRepository('product')->findOneBy(array('name' => trim($value)))->getMasterVariant()->getId();
199
                    break;
200
201
                case 'amount':
202
                    $configuration[$key] = (int) $value;
203
                    break;
204
205
                default:
206
                    $configuration[$key] = trim($value);
207
                    break;
208
            }
209
        }
210
211
        return $configuration;
212
    }
213
214
    /**
215
     * Generate page url.
216
     * This method uses simple convention where page argument is prefixed
217
     * with the application name and used as route name passed to router generate method.
218
     *
219
     * @param object|string $page
220
     * @param array         $parameters
221
     *
222
     * @return string
223
     */
224
    protected function generatePageUrl($page, array $parameters = array())
225
    {
226
        if (is_object($page)) {
227
            return $this->generateUrl($page, $parameters);
228
        }
229
230
        $route  = str_replace(' ', '_', trim($page));
231
        $routes = $this->getRouter()->getRouteCollection();
232
233
        if (null === $routes->get($route)) {
234
            $route = $this->applicationName.'_'.$route;
235
        }
236
237
        if (null === $routes->get($route)) {
238
            $route = str_replace($this->applicationName.'_', $this->applicationName.'_backend_', $route);
239
        }
240
241
        $route = str_replace(array_keys($this->actions), array_values($this->actions), $route);
242
        $route = str_replace(' ', '_', $route);
243
244
        return $this->generateUrl($route, $parameters);
245
    }
246
247
    /**
248
     * Get current user instance.
249
     *
250
     * @return UserInterface|null
251
     *
252
     * @throws \Exception
253
     */
254
    protected function getUser()
255
    {
256
        $token = $this->getTokenStorage()->getToken();
257
258
        if (null === $token) {
259
            throw new \Exception('No token found in security context.');
260
        }
261
262
        return $token->getUser();
263
    }
264
265
    /**
266
     * @return TokenStorageInterface
267
     */
268
    protected function getTokenStorage()
269
    {
270
        return $this->getContainer()->get('security.token_storage');
271
    }
272
273
    /**
274
     * @return AuthorizationCheckerInterface
275
     */
276
    protected function getAuthorizationChecker()
277
    {
278
        return $this->getContainer()->get('security.authorization_checker');
279
    }
280
281
    /**
282
     * @param string  $route
283
     * @param array   $parameters
284
     * @param Boolean $absolute
285
     *
286
     * @return string
287
     */
288
    protected function generateUrl($route, array $parameters = array(), $absolute = false)
289
    {
290
        return $this->locatePath($this->getRouter()->generate($route, $parameters, $absolute));
291
    }
292
293
    /**
294
     * Presses button with specified id|name|title|alt|value.
295
     *
296
     * @param string $button
297
     *
298
     * @throws ElementNotFoundException
299
     */
300
    protected function pressButton($button)
301
    {
302
        $this->getSession()->getPage()->pressButton($this->fixStepArgument($button));
303
    }
304
305
    /**
306
     * Clicks link with specified id|title|alt|text.
307
     *
308
     * @param string $link
309
     *
310
     * @throws ElementNotFoundException
311
     */
312
    protected function clickLink($link)
313
    {
314
        $this->getSession()->getPage()->clickLink($this->fixStepArgument($link));
315
    }
316
317
    /**
318
     * Fills in form field with specified id|name|label|value.
319
     *
320
     * @param string $field
321
     * @param string $value
322
     *
323
     * @throws ElementNotFoundException
324
     */
325
    protected function fillField($field, $value)
326
    {
327
        $this->getSession()->getPage()->fillField(
328
            $this->fixStepArgument($field),
329
            $this->fixStepArgument($value)
330
        );
331
    }
332
333
    /**
334
     * Selects option in select field with specified id|name|label|value.
335
     *
336
     * @param string $select
337
     * @param string $option
338
     *
339
     * @throws ElementNotFoundException
340
     */
341
    protected function selectOption($select, $option)
342
    {
343
        $this->getSession()->getPage()->selectFieldOption(
344
            $this->fixStepArgument($select),
345
            $this->fixStepArgument($option)
346
        );
347
    }
348
349
    /**
350
     * Returns fixed step argument (with \\" replaced back to ").
351
     *
352
     * @param string $argument
353
     *
354
     * @return string
355
     */
356
    protected function fixStepArgument($argument)
357
    {
358
        return str_replace('\\"', '"', $argument);
359
    }
360
361
    /**
362
     * @param NodeElement $table
363
     * @param string $columnName
364
     *
365
     * @return integer
366
     *
367
     * @throws \Exception If column was not found
368
     */
369
    protected function getColumnIndex(NodeElement $table, $columnName)
370
    {
371
        $rows = $table->findAll('css', 'tr');
372
373
        if (!isset($rows[0])) {
374
            throw new \Exception("There are no rows!");
375
        }
376
377
        /** @var NodeElement $firstRow */
378
        $firstRow = $rows[0];
379
        $columns = $firstRow->findAll('css', 'th,td');
380
        foreach ($columns as $index => $column) {
381
            /** @var NodeElement $column */
382
            if (0 === stripos($column->getText(), $columnName)) {
383
                return $index;
384
            }
385
        }
386
387
        throw new \Exception(sprintf('Column with name "%s" not found!', $columnName));
388
    }
389
390
    /**
391
     * @param NodeElement $table
392
     * @param array $fields
393
     *
394
     * @return NodeElement|null
395
     *
396
     * @throws \Exception If column was not found
397
     */
398
    protected function getRowWithFields(NodeElement $table, array $fields)
399
    {
400
        $foundRows = $this->getRowsWithFields($table, $fields, true);
401
402
        if (empty($foundRows)) {
403
            return null;
404
        }
405
406
        return current($foundRows);
407
    }
408
409
    /**
410
     * @param NodeElement $table
411
     * @param array $fields
412
     * @param boolean $onlyFirstOccurence
413
     *
414
     * @return NodeElement[]
415
     *
416
     * @throws \Exception If columns or rows were not found
417
     */
418
    protected function getRowsWithFields(NodeElement $table, array $fields, $onlyFirstOccurence = false)
419
    {
420
        $rows = $table->findAll('css', 'tr');
421
422
        if (!isset($rows[0])) {
423
            throw new \Exception("There are no rows!");
424
        }
425
426
        $fields = $this->replaceColumnNamesWithColumnIds($table, $fields);
427
428
        $foundRows = array();
429
430
        /** @var NodeElement[] $rows */
431
        $rows = $table->findAll('css', 'tr');
432
        foreach ($rows as $row) {
433
            $found = true;
434
435
            /** @var NodeElement[] $columns */
436
            $columns = $row->findAll('css', 'th,td');
437
            foreach ($fields as $index => $searchedValue) {
438
                if (!isset($columns[$index])) {
439
                    throw new \InvalidArgumentException(sprintf('There is no column with index %d', $index));
440
                }
441
442
                $containing = false;
443
                $searchedValue = trim($searchedValue);
444
                if (0 === strpos($searchedValue, '%') && (strlen($searchedValue) - 1) === strrpos($searchedValue, '%')) {
445
                    $searchedValue = substr($searchedValue, 1, strlen($searchedValue) - 2);
446
                    $containing = true;
447
                }
448
449
                $position = stripos(trim($columns[$index]->getText()), $searchedValue);
450
                if (($containing && false === $position) || (!$containing && 0 !== $position)) {
451
                    $found = false;
452
453
                    break;
454
                }
455
            }
456
457
            if ($found) {
458
                $foundRows[] = $row;
459
460
                if ($onlyFirstOccurence) {
461
                    break;
462
                }
463
            }
464
        }
465
466
        return $foundRows;
467
    }
468
469
    /**
470
     * @param NodeElement $table
471
     * @param string[] $fields
472
     *
473
     * @return string[]
474
     *
475
     * @throws \Exception
476
     */
477
    protected function replaceColumnNamesWithColumnIds(NodeElement $table, array $fields)
478
    {
479
        $replacedFields = array();
480
        foreach ($fields as $columnName => $expectedValue) {
481
            $columnIndex = $this->getColumnIndex($table, $columnName);
482
483
            $replacedFields[$columnIndex] = $expectedValue;
484
        }
485
486
        return $replacedFields;
487
    }
488
489
    /**
490
     * @param callable $callback
491
     * @param int $limit
492
     * @param int $delay In miliseconds
493
     *
494
     * @return mixed
495
     *
496
     * @throws \RuntimeException If timeout was reached
497
     */
498
    protected function waitFor(callable $callback, $limit = 30, $delay = 100)
499
    {
500
        for ($i = 0; $i < $limit; ++$i) {
501
            $payload = $callback();
502
503
            if (!empty($payload)) {
504
                return $payload;
505
            }
506
507
            usleep($delay * 1000);
508
        }
509
510
        throw new \RuntimeException(sprintf('Timeout reached (%f seconds)!', round($limit * $delay / 1000, 1)));
511
    }
512
513
    /**
514
     * @param string $name
515
     *
516
     * @return string
517
     *
518
     * @throws \InvalidArgumentException If name is not found in country code registry.
519
     */
520
    protected function getCountryCodeByEnglishCountryName($name)
521
    {
522
        $names = Intl::getRegionBundle()->getCountryNames('en');
523
        $isoName = array_search(trim($name), $names);
524
525
        if (null === $isoName) {
526
            throw new \InvalidArgumentException(sprintf(
527
                'Country "%s" not found! Available names: %s.', $name, join(', ', $names)
528
            ));
529
        }
530
531
        return $isoName;
532
    }
533
534
    /**
535
     * @param string $name
536
     *
537
     * @return string
538
     *
539
     * @throws \InvalidArgumentException If name is not found in locale code registry.
540
     */
541
    protected function getLocaleCodeByEnglishLocaleName($name)
542
    {
543
        $names = Intl::getLocaleBundle()->getLocaleNames('en');
544
        $code = array_search(trim($name), $names);
545
546
        if (null === $code) {
547
            throw new \InvalidArgumentException(sprintf(
548
                'Locale "%s" not found! Available names: %s.', $name, join(', ', $names)
549
            ));
550
        }
551
552
        return $code;
553
    }
554
555
    /**
556
     * @return RouterInterface
557
     */
558
    protected function getRouter()
559
    {
560
        return $this->getSharedService('router');
561
    }
562
563
    /**
564
     * @return KernelInterface
565
     */
566
    protected function getKernel()
567
    {
568
        return $this->kernel;
569
    }
570
571
    /**
572
     * @return KernelInterface
573
     */
574
    protected function getSharedKernel()
575
    {
576
        return self::$sharedKernel;
577
    }
578
579
    /**
580
     * @param string $id
581
     *
582
     * @return object
583
     */
584
    protected function getSharedService($id)
585
    {
586
        return self::$sharedKernel->getContainer()->get($id);
587
    }
588
}
589