extractLabels()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 7
c 2
b 1
f 0
dl 0
loc 14
rs 10
cc 2
nc 2
nop 0
1
<?php
2
/**
3
 * Utility script to extract supported countries for the showphone
4
 * command, meant to be opened in a browser.
5
 *
6
 * @package Mailcode
7
 * @subpackage Tools
8
 * @author Sebastian Mordziol <[email protected]>
9
 *
10
 * @see https://countrycode.org/countryCode/downloadCountryCodes
11
 */
12
13
declare(strict_types=1);
14
15
use AppUtils\ConvertHelper\JSONConverter;use AppUtils\CSVHelper;
16
use AppUtils\CSVHelper_Exception;use AppUtils\FileHelper;
17
use AppUtils\FileHelper_Exception;use libphonenumber\PhoneNumberFormat;
18
use libphonenumber\PhoneNumberUtil;use Mailcode\Mailcode;use function AppLocalize\pts;
19
20
require_once 'prepend.php';
21
22
$outputFile = '../src/Mailcode/Commands/Command/ShowPhone/numbers.json';
23
$countries = generateList();
24
25
FileHelper::saveAsJSON($countries, $outputFile, true);
26
27
?><!DOCTYPE html>
28
<html lang="en">
29
    <head>
30
        <meta charset="utf-8">
31
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
32
        <meta name="viewport" content="width=device-width, initial-scale=1">
33
        <title><?php pts('Phone countries extractor') ?> - <?php echo Mailcode::getName(); ?></title>
34
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
35
        <style>
36
            BODY{
37
                padding:2em 0;
38
            }
39
            TEXTAREA{
40
                font-family: monospace;
41
            }
42
        </style>
43
    </head>
44
    <body>
45
        <div class="container">
46
            <p>
47
                <a href="./">&laquo; <?php pts('Back to overview'); ?></a>
48
            </p>
49
            <h1>Phone number countries extraction</h1>
50
            <p>
51
                This uses Google's <a href="https://github.com/google/libphonenumber">libphonenumber</a>
52
                library (via its PHP port
53
                <a href="https://github.com/giggsey/libphonenumber-for-php">giggsey/libphonenumber-for-php</a>).
54
                It generates a list of all supported countries for use in the <code>{showphone}</code>
55
                command class, to validate the source country phone format parameter.
56
            </p>
57
            <p>
58
                As the library does not contain human-readable country names, a separate CSV file
59
                is used to map the ISO codes to the country names.
60
                This file is based on the
61
                <a href="https://countrycode.org">countrycode.org</a>
62
                download.
63
            </p>
64
            <p>
65
                Target class: <code>Mailcode_Commands_Command_ShowPhone</code><br>
66
                Target data file: <code><?php echo str_replace('../', '/', $outputFile) ?></code>
67
            </p>
68
            <p>
69
                The command reads the file to access the countries.
70
            </p>
71
            <p>
72
                <label for="json_source"><strong>Extracted JSON data:</strong></label>
73
            </p>
74
            <textarea id="json_source" rows="20" class="form-control"><?php echo JSONConverter::var2json($countries, JSON_PRETTY_PRINT) ?></textarea>
75
        </div>
76
    </body>
77
</html>
78
79
<?php
80
81
/**
82
 * @return array<string,array{label:string,local:string,international:string}>
83
 */
84
function generateList() : array
85
{
86
    $labels = extractLabels();
87
    $phoneNumberUtil = PhoneNumberUtil::getInstance();
88
    $regions = $phoneNumberUtil->getSupportedRegions();
89
90
    $data = array();
91
    foreach ($regions as $code)
92
    {
93
        $code = (string)$code;
94
95
        $meta = $phoneNumberUtil->getMetadataForRegion($code);
96
        if (!$meta) {
97
            die('No metadata for ' . $code);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
98
        }
99
100
        $exampleNumber = $phoneNumberUtil->getExampleNumber($code);
101
102
        // PHPStan complains about this, but the method can return null - it's not documented correctly.
103
        if($exampleNumber === null) {
104
            die('No example number for ' . $code);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
105
        }
106
107
        $local = $phoneNumberUtil->formatInOriginalFormat($exampleNumber, $code);
108
        $international = $phoneNumberUtil->format($exampleNumber, PhoneNumberFormat::INTERNATIONAL);
109
110
        $data[$code] = array(
111
            'label' => $labels[$code] ?? $code,
112
            'local' => $local,
113
            'international' => $international
114
        );
115
    }
116
117
    ksort($data);
118
119
    return $data;
120
}
121
122
/**
123
 * @return array<string,string>
124
 * @throws CSVHelper_Exception
125
 * @throws FileHelper_Exception
126
 */
127
function extractLabels() : array
128
{
129
    $lines = CSVHelper::parseFile('countrycodes.csv');
130
131
    $isoIdx = 1;
132
    $nameIdx = 0;
133
134
    $result = array();
135
136
    foreach ($lines as $line) {
137
        $result[$line[$isoIdx]] = $line[$nameIdx];
138
    }
139
140
    return $result;
141
}
142