Passed
Push — master ( 779d84...3d5507 )
by Vincent
05:31
created

PhoneElement::toPhp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Bdf\Form\Phone;
4
5
use Bdf\Form\Leaf\LeafElement;
6
use Bdf\Form\Transformer\TransformerInterface;
7
use Bdf\Form\Validator\ValueValidatorInterface;
8
use libphonenumber\NumberParseException;
9
use libphonenumber\PhoneNumber;
10
use libphonenumber\PhoneNumberFormat;
11
use libphonenumber\PhoneNumberUtil;
12
13
/**
14
 * Element for handle phone number input
15
 *
16
 * The package "giggsey/libphonenumber-for-php" is required for use this element
17
 * The PHP value of this element is a PhoneNumber instance. Constraints and hydrated entities should support this type.
18
 *
19
 * @method PhoneNumber value()
20
 * @extends LeafElement<PhoneNumber>
21
 */
22
final class PhoneElement extends LeafElement
23
{
24
    /**
25
     * @var callable(PhoneElement):string
26
     */
27
    private $regionResolver;
28
29
    /**
30
     * @var PhoneNumberUtil
31
     */
32
    private $formatter;
33
34
35
    /**
36
     * PhoneElement constructor.
37
     *
38
     * @param ValueValidatorInterface|null $validator
39
     * @param TransformerInterface|null $transformer
40
     * @param callable|null $regionResolver Resolve the region / country code. Takes as parameter the element, and must return the country code as string
41
     * @param PhoneNumberUtil|null $formatter The phone number formatter
42
     */
43 63
    public function __construct(?ValueValidatorInterface $validator = null, ?TransformerInterface $transformer = null, ?callable $regionResolver = null, ?PhoneNumberUtil $formatter = null)
44
    {
45 63
        parent::__construct($validator, $transformer);
46
47 63
        $this->regionResolver = $regionResolver;
48 63
        $this->formatter = $formatter ?? PhoneNumberUtil::getInstance();
49 63
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 39
    protected function toPhp($httpValue)
55
    {
56 39
        if (empty($httpValue)) {
57 10
            return null;
58
        }
59
60 33
        return $this->parseValue($httpValue);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->parseValue($httpValue) returns the type libphonenumber\PhoneNumber which is incompatible with the return type mandated by Bdf\Form\Leaf\LeafElement::toPhp() of Bdf\Form\Leaf\T|null.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 17
    protected function toHttp($phpValue)
67
    {
68 17
        if (!$phpValue) {
69 4
            return null;
70
        }
71
72 15
        return $phpValue->getRawInput() ?: $this->formatter->format($phpValue, PhoneNumberFormat::E164);
73
    }
74
75
    /**
76
     * Get the resolved region string
77
     *
78
     * @return string
79
     */
80 36
    private function resolveRegion(): string
81
    {
82 36
        if (!$this->regionResolver) {
83 24
            return PhoneNumberUtil::UNKNOWN_REGION;
84
        }
85
86 12
        return strtoupper(($this->regionResolver)($this));
87
    }
88
89
    /**
90
     * @internal
91
     */
92 17
    public function getFormatter(): PhoneNumberUtil
93
    {
94 17
        return $this->formatter;
95
    }
96
97
    /**
98
     * Parse a phone number string
99
     *
100
     * @param string $rawPhoneNumber The string value of the phone number
101
     * @return PhoneNumber The parsed instance
102
     *
103
     * @internal
104
     */
105 36
    public function parseValue(string $rawPhoneNumber): PhoneNumber
106
    {
107
        try {
108 36
            return $this->formatter->parse($rawPhoneNumber, $this->resolveRegion(), null, true);
109 11
        } catch (NumberParseException $e) {
110 11
            return (new PhoneNumber())->setRawInput($rawPhoneNumber);
111
        }
112
    }
113
}
114