Phone   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 121
ccs 37
cts 37
cp 1
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 7

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C validate() 0 53 13
A extractParameters() 0 30 5
1
<?php namespace Propaganistas\LaravelPhone\Validation;
2
3
use Illuminate\Support\Arr;
4
use Illuminate\Support\Collection;
5
use libphonenumber\PhoneNumberUtil;
6
use Propaganistas\LaravelPhone\Exceptions\InvalidParameterException;
7
use libphonenumber\NumberParseException;
8
use Propaganistas\LaravelPhone\PhoneNumber;
9
use Propaganistas\LaravelPhone\Traits\ParsesCountries;
10
use Propaganistas\LaravelPhone\Traits\ParsesTypes;
11
12
class Phone
13
{
14
    use ParsesCountries,
15
        ParsesTypes;
16
17
    /**
18
     * @var \libphonenumber\PhoneNumberUtil
19
     */
20
    protected $lib;
21
22
    /**
23
     * Phone constructor.
24
     */
25 51
    public function __construct()
26
    {
27 51
        $this->lib = PhoneNumberUtil::getInstance();
28 51
    }
29
30
    /**
31
     * Validates a phone number.
32
     *
33
     * @param  string $attribute
34
     * @param  mixed  $value
35
     * @param  array  $parameters
36
     * @param  object $validator
37
     * @return bool
38
     */
39 51
    public function validate($attribute, $value, array $parameters, $validator)
40
    {
41 51
        $data = $validator->getData();
42
43
        list(
44
            $countries,
45
            $types,
46
            $detect,
47 51
            $lenient) = $this->extractParameters($attribute, $parameters, $data);
48
49
        // A "null" country is prepended:
50
        // 1. In case of auto-detection to have the validation run first without supplying a country.
51
        // 2. In case of lenient validation without provided countries; we still might have some luck...
52 48
        if ($detect || ($lenient && empty($countries))) {
53 12
            array_unshift($countries, null);
54
        }
55
56 48
        foreach ($countries as $country) {
57
            try {
58
                // Parsing the phone number also validates the country, so no need to do this explicitly.
59
                // It'll throw a PhoneCountryException upon failure.
60 42
                $phoneNumber = PhoneNumber::make($value, $country);
61
62
                // Type validation.
63 42
                if (! empty($types) && ! $phoneNumber->isOfType($types)) {
64 18
                    continue;
65
                }
66
67 39
                $lenientPhoneNumber = $phoneNumber->lenient()->getPhoneNumberInstance();
68
69
                // Lenient validation.
70 39
                if ($lenient && $this->lib->isPossibleNumber($lenientPhoneNumber, $country)) {
71 3
                    return true;
72
                }
73
74 39
                $phoneNumberInstance = $phoneNumber->getPhoneNumberInstance();
75
76
                // Country detection.
77 39
                if ($detect && $this->lib->isValidNumber($phoneNumberInstance)) {
78 9
                    return true;
79
                }
80
81
                // Default number+country validation.
82 39
                if ($this->lib->isValidNumberForRegion($phoneNumberInstance, $country)) {
83 39
                    return true;
84
                }
85 24
            } catch (NumberParseException $e) {
86 24
                continue;
87
            }
88
        }
89
90 45
        return false;
91
    }
92
93
    /**
94
     * Parse and extract parameters in the appropriate validation arguments.
95
     *
96
     * @param string $attribute
97
     * @param array  $parameters
98
     * @param array  $data
99
     * @return array
100
     * @throws \Propaganistas\LaravelPhone\Exceptions\InvalidParameterException
101
     */
102 51
    protected function extractParameters($attribute, array $parameters, array $data)
103
    {
104
        // Discover if an input field was provided. If not, guess the field's name.
105 51
        $inputField = Collection::make($parameters)
106 51
                                ->intersect(array_keys(Arr::dot($data)))
0 ignored issues
show
Documentation introduced by
$data is of type array, but the function expects a object<Illuminate\Support\iterable>.

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...
107 51
                                ->first() ?: "${attribute}_country";
108
109
        // Attempt to retrieve the field's value.
110 51
        if ($inputCountry = Arr::get($data, $inputField)) {
111
112 30
            if (static::isValidType($inputField)) {
113 3
                throw InvalidParameterException::ambiguous($inputField);
114
            }
115
116
            // Invalid country field values should just validate to false.
117
            // This will also prevent parameter hijacking through the country field.
118 27
            if (static::isValidCountryCode($inputCountry)) {
119 21
                $parameters[] = $inputCountry;
120
            }
121
        }
122
        
123 48
        $parameters = array_map('strtolower', $parameters);
124
125
        return [
126 48
            static::parseCountries($parameters),
127 48
            static::parseTypes($parameters),
128 48
            in_array('auto', $parameters),
129 48
            in_array('lenient', $parameters)
130
        ];
131
    }
132
}
133