GeoRoute::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 10
1
<?php
2
3
namespace LaraCrafts\GeoRoutes;
4
5
use BadMethodCallException;
6
use Illuminate\Routing\Route;
7
use LaraCrafts\GeoRoutes\Support\Facades\CallbackRegistrar;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, LaraCrafts\GeoRoutes\CallbackRegistrar. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
8
9
/**
10
 * @mixin \Illuminate\Routing\Route
11
 */
12
class GeoRoute
13
{
14
    use Concerns\HasCallback;
15
    use Concerns\ControlsAccess;
16
17
    /**
18
     * Rule is applied.
19
     *
20
     * @var bool
21
     */
22
    protected $applied;
23
24
    /**
25
     * The countries to apply the rule for.
26
     *
27
     * @var array
28
     */
29
    protected $countries;
30
31
    /**
32
     * The route.
33
     *
34
     * @var \Illuminate\Routing\Route
35
     */
36
    protected $route;
37
38
    /**
39
     * The rule's strategy.
40
     *
41
     * @var string
42
     */
43
    protected $strategy;
44
45
    /**
46
     * Create a new GeoRoute instance.
47
     *
48
     * @param  \Illuminate\Routing\Route $route
49
     * @param  array $countries
50
     * @param  string $strategy
51
     */
52 80
    public function __construct(Route $route, array $countries, string $strategy)
53
    {
54 80
        $this->applied = false;
55 80
        $this->countries = array_map('strtoupper', $countries);
56 80
        $this->route = $route;
57 80
        $this->strategy = $strategy;
58 80
    }
59
60
    /**
61
     * Dynamically call the underlying route.
62
     *
63
     * @param string $method
64
     * @param array $arguments
65
     *
66
     * @return mixed
67
     */
68
    public function __call(string $method, array $arguments)
69
    {
70
        if (method_exists($this->route, $method) || Route::hasMacro($method)) {
71
            return $this->route->$method(...$arguments);
72
        }
73
74
        if (CallbackRegistrar::hasProxy($method)) {
75
            return $this->setCallback(CallbackRegistrar::callback($method), $arguments);
76
        }
77
78
        throw new BadMethodCallException("Undefined method '$method'");
79
    }
80
81
    /**
82
     * Destruct the GeoRoute instance and apply the middleware.
83
     */
84 80
    public function __destruct()
85
    {
86 80
        $this->applyConstraint();
87 80
    }
88
89
    /**
90
     * Apply the geo-constraint to the route.
91
     */
92 80
    protected function applyConstraint()
93
    {
94 80
        if ($this->applied || !$this->countries) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->countries of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
95
            return;
96
        }
97
98 80
        $action = $this->route->getAction();
99 80
        $action['middleware'][] = 'geo';
100 80
        $action['geo'] = [
101 80
            'strategy' => $this->strategy,
102 80
            'countries' => (array)$this->countries,
103 80
            'callback' => $this->callback,
104
        ];
105
106 80
        $this->route->setAction($action);
0 ignored issues
show
Bug introduced by
It seems like $action can also be of type null; however, parameter $action of Illuminate\Routing\Route::setAction() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

106
        $this->route->setAction(/** @scrutinizer ignore-type */ $action);
Loading history...
107
108 80
        $this->applied = true;
109 80
    }
110
}
111