Passed
Push — master ( 432fe2...c3ceb1 )
by Misha
41s queued 10s
created

PhoneNumber::__clone()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 4
c 1
b 0
f 1
dl 0
loc 6
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Communibase\Entity;
6
7
use Communibase\DataBag;
8
use libphonenumber\NumberParseException;
9
use libphonenumber\PhoneNumberUtil;
10
11
/**
12
 * @author Kingsquare ([email protected])
13
 * @copyright Copyright (c) Kingsquare BV (http://www.kingsquare.nl)
14
 */
15
class PhoneNumber
16
{
17
    /**
18
     * @var DataBag
19
     */
20
    protected $dataBag;
21
22
    private static $phoneNumberUtil;
23
24
    protected function __construct(array $phoneNumberData = [])
25
    {
26
        $this->dataBag = DataBag::create();
27
        if (empty($phoneNumberData['type'])) {
28
            $phoneNumberData['type'] = 'private';
29
        }
30
        $this->dataBag->addEntityData('phone', $phoneNumberData);
31
        self::$phoneNumberUtil = self::$phoneNumberUtil ?? PhoneNumberUtil::getInstance();
32
    }
33
34
    /**
35
     * @return static
36
     */
37
    public static function create()
38
    {
39
        return new static();
40
    }
41
42
    /**
43
     * @return static
44
     */
45
    public static function fromPhoneNumberData(array $phoneNumberData = null)
46
    {
47
        return new static($phoneNumberData ?? []);
48
    }
49
50
    /**
51
     * @return static
52
     */
53
    public static function fromString(string $phoneNumberString)
54
    {
55
        $phoneNumber = static::create();
56
        $phoneNumber->setPhoneNumber($phoneNumberString);
57
        return $phoneNumber;
58
    }
59
60
    /**
61
     * @param string|null $format defaults to 'c(a)s'
62
     * The following characters are recognized in the format parameter string:
63
     * <table><tr>
64
     * <td>Character&nbsp;</td><td>Description</td>
65
     * </tr><tr>
66
     * <td>c</td><td>countryCode</td>
67
     * </tr><tr>
68
     * <td>a</td><td>areaCode</td>
69
     * </tr><tr>
70
     * <td>s</td><td>subscriberNumber</td>
71
     * </tr>
72
     */
73
    public function toString(?string $format = 'c (a) s'): string
74
    {
75
        if ($format === null) {
76
            $format = 'c (a) s';
77
        }
78
        $countryCode = $this->dataBag->get('phone.countryCode');
79
        $areaCode = $this->dataBag->get('phone.areaCode');
80
        $subscriberNumber = $this->dataBag->get('phone.subscriberNumber');
81
        if (!empty($countryCode) && \strpos($countryCode, '+') !== 0) {
82
            $countryCode = '+' . $countryCode;
83
        }
84
85
        if (empty($areaCode) && empty($subscriberNumber)) {
86
            return '';
87
        }
88
        if (empty($areaCode)) {
89
            $areaCode = ''; // remove '0' values
90
            $format = (string)\preg_replace('/\(\s?a\s?\)\s?/', '', $format);
91
        }
92
        if (!empty($countryCode) && \strpos($format, 'c') !== false) {
93
            $areaCode = \ltrim($areaCode, '0');
94
        }
95
        if (strpos($areaCode, '0') !== 0 && (empty($countryCode) || \strpos($format, 'c') === false)) {
96
            $areaCode = '0' . $areaCode;
97
        }
98
        return trim(
99
            (string)\preg_replace_callback(
100
                '![cas]!',
101
                static function (array $matches) use ($countryCode, $areaCode, $subscriberNumber) {
102
                    switch ($matches[0]) {
103
                        case 'c':
104
                            return $countryCode;
105
                        case 'a':
106
                            return $areaCode;
107
                        case 's':
108
                            return $subscriberNumber;
109
                    }
110
                    return '';
111
                },
112
                $format
113
            )
114
        );
115
    }
116
117
    public function __toString(): string
118
    {
119
        return $this->toString();
120
    }
121
122
    public function setPhoneNumber(string $value): void
123
    {
124
        try {
125
            /** @var \libphonenumber\PhoneNumber $phoneNumber */
126
            $phoneNumber = self::$phoneNumberUtil->parse($value, 'NL');
127
            $countryCode = (string)($phoneNumber->getCountryCode() ?? 0);
128
            $nationalNumber = (string)$phoneNumber->getNationalNumber();
129
            $split = \preg_match('/^(1[035]|2[0346]|3[03568]|4[03568]|5[0358]|7\d)/', $nationalNumber) === 1 ? 2 : 3;
130
            if (\strpos($nationalNumber, '6') === 0) {
131
                $split = 1;
132
            }
133
            $areaCode = \substr($nationalNumber, 0, $split);
134
            $subscriberNumber = \substr($nationalNumber, $split);
135
        } catch (NumberParseException $e) {
136
            $countryCode = '';
137
            $areaCode = '';
138
            $subscriberNumber = '';
139
        }
140
        $this->dataBag->set('phone.countryCode', $countryCode);
141
        $this->dataBag->set('phone.areaCode', $areaCode);
142
        $this->dataBag->set('phone.subscriberNumber', $subscriberNumber);
143
    }
144
145
    public function __clone()
146
    {
147
        $state = $this->getState();
148
        if ($state !== null) {
149
            unset($state['_id']);
150
            $this->dataBag->addEntityData('phone', $state);
151
        }
152
    }
153
154
    public function getState(): ?array
155
    {
156
        if (!array_filter([$this->dataBag->get('phone.areaCode'), $this->dataBag->get('phone.subscriberNumber')])) {
157
            return null;
158
        }
159
        return $this->dataBag->getState('phone');
160
    }
161
}
162