Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
27 / 27
RecipientValidator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
6 / 6
17
100.00% covered (success)
100.00%
27 / 27
 validateAll
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
11 / 11
 validate
100.00% covered (success)
100.00%
1 / 1
6
100.00% covered (success)
100.00%
10 / 10
 rewriteNigerianNumberOrReturnDefault
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 isShortNigerianNumber
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 isInvalidNigerianNumber
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 isInvalidMobileNumberLength
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
1<?php
2
3namespace CeculaSyncApiClient;
4
5use JetBrains\PhpStorm\Pure;
6
7class RecipientValidator
8{
9    protected static int $lengthNigerianMobileNumberWithCountryCode = 13;
10    protected static int $lengthNigerianMobileNumberWithoutCountryCode = 11;
11    protected static int $minLengthMobileNumber = 7;
12    protected static int $maxLengthMobileNumber = 15;
13
14    /**
15     * @param string $commaSeperatedNumbers
16     * @return bool
17     * @throws \Exception
18     */
19    public function validateAll(string $commaSeperatedNumbers): bool
20    {
21        if (empty($commaSeperatedNumbers))
22        {
23            throw new \Exception("Receivers not submitted", 404);
24        }
25
26        $numbersList = explode(",", $commaSeperatedNumbers);
27        $invalidNumbers = [];
28
29        foreach ($numbersList as $recipient)
30        {
31            try {
32                $x = $this->validate($recipient);
33            } catch (\Exception $e)
34            {
35                array_push($invalidNumbers, $recipient);
36            }
37        }
38
39        if (count($invalidNumbers) > 0)
40        {
41            throw new \Exception(sprintf("The following numbers are invalid: %s", implode(",", $invalidNumbers)), 100);
42        }
43        return true;
44    }
45
46    /**
47     * @param $receiver
48     * @return bool
49     * @throws \Exception
50     */
51    public function validate($receiver): bool
52    {
53        if (empty($receiver))
54        {
55            throw new \Exception("Receiver not submitted", 404);
56        }
57
58        if (!is_numeric($receiver))
59        {
60            throw new \Exception(sprintf("%s in not a valid recipient", $receiver), 100);
61        }
62
63        //  Finally, Check that number matches internation number requirement
64        if ($this->isInvalidMobileNumberLength($receiver))
65        {
66            throw new \Exception(sprintf("%s in not a valid mobile Number. Number length: %d", $receiver, strlen($receiver)), 100);
67        }
68
69        // Rewrite Nigerian Numbers that begin with zero
70        $receiver = $this->rewriteNigerianNumberOrReturnDefault($receiver);
71
72        // If number is a Nigerian number, check that it is valid
73        if (str_starts_with($receiver, '234') && $this->isInvalidNigerianNumber($receiver))
74        {
75            throw new \Exception(sprintf("%s in not a valid Nigerian Number", $receiver), 100);
76        }
77
78        return true;
79    }
80
81
82    /**
83     * @param string $suppliedNumber
84     * @return string
85     */
86    #[Pure] public function rewriteNigerianNumberOrReturnDefault(string $suppliedNumber): string
87    {
88        $suppliedNumber = str_replace([' ', '-', '.'], '', $suppliedNumber);
89        return $this->isShortNigerianNumber($suppliedNumber) ? "234".substr($suppliedNumber, 1) : $suppliedNumber;
90    }
91
92
93    /**
94     * @param string $suppliedNumber
95     * @return bool
96     */
97    private function isShortNigerianNumber(string $suppliedNumber): bool
98    {
99        return in_array(substr($suppliedNumber, 0, 2), ['07', '08', '09']) &&
100            strlen($suppliedNumber) === self::$lengthNigerianMobileNumberWithoutCountryCode;
101    }
102
103
104    /**
105     * @param string $suppliedNumber
106     * @return bool
107     */
108    #[Pure] public function isInvalidNigerianNumber(string $suppliedNumber): bool
109    {
110        return strlen($this->rewriteNigerianNumberOrReturnDefault($suppliedNumber)) != self::$lengthNigerianMobileNumberWithCountryCode;
111    }
112
113    /**
114     *
115     */
116    public function isInvalidMobileNumberLength(string $suppliedNumber): bool
117    {
118        return !in_array(strlen($suppliedNumber), range(self::$minLengthMobileNumber, self::$maxLengthMobileNumber));
119    }
120}