I have been asked to write a cli script that takes a list of phone numbers to validate from a file and as an option in the command line.
It will then produce a CSV file with three columns “phone number”, “carrier”, “status”.
The status column should indicate if the phone number is valid or not valid. The carrier field should contain the carrier name if the phone number is valid.
I am using libphonenumber-for-php
They want me to show knowledge in PHP programming using the latest techniques and open source technologies available. Can anybody see obvious improvements where I am not doing this?
So far I have come up with the following:
<?php
/**
* Created by PhpStorm.
* User: Andy
* Date: 20/05/2019
* Time: 23:38
*/
require 'vendor/autoload.php';
require_once "class/validator.php";
$options = getopt('f:l:n:');
if(!isset($options['f']) && !isset($options['n'])){
echo "No files or number have been specified \n";
exit();
}
if(isset($options['f'])){
if(!is_array($options['f'])){
$files[] = $options['f'];
}
else {
$files = $options['f'];
}
foreach ($files as $file){
if(!file_exists($file)) {
echo "File not found ".$file. "\n";
exit();
}
}
}
if(isset($options['n'])){
$numbers = explode(',', $options['n']);
}
$logResults = false;
if(isset($options['l']) && $options['l'] == 'true')
$logResults = true;
//Uk, Guernsey, Jersey and Isle of Man
$regionCodes = array('GB', 'GG', 'JE', 'IM');
echo "Validation Process Starting \r\n";
$validator = new validator($files, $numbers, $regionCodes, $logResults);
$results = $validator->getResults();
// Open a file to write to
$fp = fopen('output/phone_numbers_'. date('d-M-Y-H-i').'.csv' , 'wb');
$headerRow = array ('Phone Number', 'Carrier', 'Status');
$i = 0;
// Loop the array of objects
foreach( $results as $fields )
{
if( $i === 0 )
{
fputcsv($fp, $headerRow ); // First write the headers
}
fputcsv($fp, $fields); // Then write the fields
$i++;
}
fclose($fp);
The class:
<?php
/**
* Used to validate uk mobile numbers including the channel islands
* Created by PhpStorm.
* User: Andy
*/
class validator
{
private $files;
private $manualNumbers;
private $logResults;
private $phoneNumbers;
private $regionCodes;
private const VALID = 'Valid';
private const INVALID = 'Invalid';
function __construct($files = null, $manualNumbers = null, $regionCodes, $logResults)
{
$this->files = $files;
$this->manualNumbers = $manualNumbers;
$this->logResults = $logResults;
$this->regionCodes = $regionCodes;
//parse passed in files
if(!is_null($files)) $this->parseFiles();
//parse numbers passed in as an option
if(!is_null($manualNumbers)) $this->parseNumbers();
}
/**
* Loops through the supplied txt files and extracts the phone numbers.
* Phone numbers are validated as uk mobile numbers (including the channel islands).
* Phone numbers should be separated by new lines.
*/
public function parseFiles(){
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$carrierMapper = \libphonenumber\PhoneNumberToCarrierMapper::getInstance();
foreach ($this->files as $file) {
$phoneNumbers = file($file);
foreach ($phoneNumbers as $phoneNumber) {
$number = trim($phoneNumber);
try {
$phoneNumberObject = $phoneUtil->parse($number, 'GB');
}
catch (\libphonenumber\NumberParseException $e) {
$this->phoneNumbers[] = array($number,'', self::INVALID);
$this->log($number.' '.$e);
error_log($e);
continue;
}
$regionCode = $phoneUtil->getRegionCodeForNumber($phoneNumberObject);
$valid = false;
if(in_array($regionCode, $this->regionCodes)){
$valid = $phoneUtil->isValidNumber($phoneNumberObject);
}
$type = $phoneUtil->getNumberType($phoneNumberObject);
$carrier = '';
$validMobile = self::INVALID;
if ($valid && $type === 1) {
//if it is a valid mobile number but carrier is unknown
$carrier = ($carrierMapper->getNameForNumber($phoneNumberObject, 'en') === '' ? 'unknown': $carrierMapper->getNameForNumber($phoneNumberObject, 'en')) ;
$validMobile = self::VALID;
}
$this->phoneNumbers[] = array($number,$carrier, $validMobile);
if($this->logResults){
$this->log($number.' carrier:'.$carrier.' status:'.$validMobile);
}
}
}
}
/**
* Loops through the phone numbers supplied as an option .
* Phone numbers are validated as uk mobile numbers (including the channel islands).
* Phone numbers should be separated by new lines.
*/
public function parseNumbers(){
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$carrierMapper = \libphonenumber\PhoneNumberToCarrierMapper::getInstance();
foreach ($this->manualNumbers as $phoneNumber){
$number = trim($phoneNumber);
try {
$phoneNumberObject = $phoneUtil->parse($number, 'GB');
}
catch (\libphonenumber\NumberParseException $e) {
$this->phoneNumbers[] = array($number,'', self::INVALID);
$this->log($number.' '.$e);
error_log($e);
continue;
}
$regionCode = $phoneUtil->getRegionCodeForNumber($phoneNumberObject);
$valid = false;
if(in_array($regionCode, $this->regionCodes)){
$valid = $phoneUtil->isValidNumber($phoneNumberObject);
}
$type = $phoneUtil->getNumberType($phoneNumberObject);
$carrier = '';
$validMobile = self::INVALID;
if ($valid && $type === 1) {
//if it is a valid mobile number but carrier is unknown
$carrier = ($carrierMapper->getNameForNumber($phoneNumberObject, 'en') === '' ? 'unknown': $carrierMapper->getNameForNumber($phoneNumberObject, 'en')) ;
$validMobile = self::VALID;
}
$this->phoneNumbers[] = array($number,$carrier, $validMobile);
if($this->logResults){
$this->log($number.' carrier:'.$carrier.' status:'.$validMobile);
}
}
}
/**
* Writes to custom log file
*/
public function log($log_msg)
{
$log_filename = "logs";
if (!file_exists($log_filename))
{
// create directory/folder uploads.
mkdir($log_filename, 0777, true);
}
$log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
file_put_contents($log_file_data, '['.date("Y-m-d H:i:s").'] '.$log_msg . "\n", FILE_APPEND);
}
/**
* Returns validated results.
* @return array
*/
public function getResults(){
return $this->phoneNumbers;
}
}