├── .editorconfig ├── .github └── workflows │ └── php.yml ├── LICENSE.md ├── README.md ├── composer.json └── src ├── Exceptions └── InvalidMsisdnException.php ├── Msisdn.php └── prefixes ├── dito.json ├── globe.json ├── gomo.json ├── smart.json └── sun.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.blade.php] 12 | indent_size = 2 13 | 14 | [*.js] 15 | indent_size = 2 16 | 17 | [*.scss] 18 | indent_size = 2 19 | 20 | [*.css] 21 | indent_size = 2 22 | 23 | [*.vue] 24 | indent_size = 2 25 | 26 | [*.md] 27 | trim_trailing_whitespace = false 28 | 29 | [*.yml] 30 | indent_size = 2 31 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | 13 | - name: Validate composer.json and composer.lock 14 | run: composer validate 15 | 16 | - name: Install dependencies 17 | run: composer install --prefer-dist --no-progress --no-suggest 18 | 19 | - name: Run test suite 20 | run: composer run-script test 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 CoreProc, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MsisdnPH - PHP 2 | ===================== 3 | 4 | [![Latest Version on Packagist][ico-version]][link-packagist] 5 | [![Software License][ico-license]](LICENSE.md) 6 | [![Build Status][ico-travis]][link-travis] 7 | [![Coverage Status][ico-scrutinizer]][link-scrutinizer] 8 | [![Quality Score][ico-code-quality]][link-code-quality] 9 | [![Total Downloads][ico-downloads]][link-downloads] 10 | 11 | Easily validate and manipulate Philippine mobile numbers. 12 | 13 | ## Table of contents 14 | 15 | * [Install](#install) 16 | * [Usage](#usage) 17 | * [Validate the mobile number](#validate-the-mobile-number) 18 | * [Instantiate an MSISDN object](#instantiate-an-msisdn-object) 19 | * [Return a standardized format of your mobile number](#return-a-standardized-format-of-your-mobile-number) 20 | * [Get the telco operator of a mobile number](#get-the-telco-operator-of-a-mobile-number) 21 | * [Get the prefix of a mobile number](#get-the-prefix-of-a-mobile-number) 22 | * [Validating mobile numbers using Laravel 5.1](#validating-mobile-numbers-using-laravel-51) 23 | * [Credits](#credits) 24 | * [License](#license) 25 | 26 | ## Install 27 | 28 | Run the following command at the root of your project (assuming you have Composer and a composer.json file already) 29 | 30 | ```bash 31 | composer require coreproc/msisdn-ph "^1.0" 32 | ``` 33 | 34 | ## Usage 35 | 36 | ### Validate the mobile number 37 | 38 | ```php 39 | $mobileNumber = '09171231234'; 40 | 41 | if (Msisdn::validate($mobileNumber)) { 42 | echo 'Valid mobile number'; 43 | } else { 44 | echo 'Invalid mobile number'; 45 | } 46 | ``` 47 | 48 | The `validate` method cleans the given mobile number and validates it so even if the mobile number is malformed or has other characters within it, it will still return true as long as the number is really valid: 49 | 50 | ```php 51 | $validMobileNumber = '+639171231234'; 52 | $validMobileNumber = '+63-917-123-1234'; 53 | $validMobileNumber = '0917-123-1234'; 54 | $validMobileNumber = '0917.123.1234'; 55 | $validMobileNumber = '63 917 123 12 34 '; 56 | ``` 57 | 58 | ### Instantiate an MSISDN object 59 | 60 | You can instantiate an MSISDN object and get a standardized format of your mobile number and even get the telco attached to the mobile number using this object. 61 | 62 | ```php 63 | $mobileNumber = '09171231234'; 64 | 65 | $msisdn = new Msisdn($mobileNumber); 66 | ``` 67 | 68 | The MSISDN object will throw an `InvalidMsisdnException` if you give it an invalid mobile number, so it's best to either catch the exception OR validate it before creating an MSISDN object. 69 | 70 | ```php 71 | $invalidMobileNumber = '0917-123-123'; 72 | 73 | try { 74 | $msisdn = new Msisdn($invalidMobileNumber); 75 | } catch (InvalidMsisdnException $e) { 76 | echo 'The number is invalid'; 77 | return; 78 | } 79 | ``` 80 | 81 | OR 82 | 83 | ```php 84 | $invalidMobileNumber = '0917-123-123'; 85 | 86 | if (Msisdn::validate($invalidMobileNumber)) { 87 | $msisdn = new Msisdn($invalidMobileNumber); 88 | } else { 89 | echo 'Invalid mobile number'; 90 | return; 91 | } 92 | ``` 93 | 94 | 95 | ### Return a standardized format of your mobile number 96 | 97 | When you've instantiated an `Msisdn` object, you can return the mobile number in any format you want. 98 | 99 | ```php 100 | $mobileNumber = '09171231234'; 101 | 102 | $msisdn = new Msisdn($mobileNumber); 103 | 104 | echo $msisdn->get(); // will return 09171231234 105 | 106 | echo $msisdn->get(true); // will return +639171231234 107 | 108 | echo $msisdn->get(false, '-'); // will return 0917-123-1234 109 | 110 | echo $msisdn->get(true, '-'); // will return +63-917-123-1234 111 | 112 | echo $msisdn->get(true, '.'); // will return +63.917.123.1234 113 | ``` 114 | 115 | ### Get the telco operator of a mobile number 116 | 117 | You can also get the telco operator of the given mobile number - this is based on the included prefixes we have gathered from the telcos. 118 | 119 | We cannot guarantee that this list is updated so use with a grain of salt. 120 | 121 | If you want to add to the prefixes, you can find the list inside the `src/prefixes` directory. 122 | 123 | ```php 124 | $mobileNumber = '09171231234'; 125 | 126 | $msisdn = new Msisdn($mobileNumber); 127 | 128 | echo $msisdn->getOperator(); // will return Globe 129 | ``` 130 | 131 | ### Get the prefix of a mobile number 132 | 133 | You might just want to get the prefix of a mobile number. 134 | 135 | ```php 136 | $mobileNumber = '09171231234'; 137 | 138 | $msisdn = new Msisdn($mobileNumber); 139 | 140 | echo $msisdn->getPrefix(); // will return 917 141 | ``` 142 | 143 | ### Validating mobile numbers using Laravel 5.1 144 | 145 | You can easily integrate this into Laravel's validator class by adding the line below to the default `AppServiceProvider` located in the `app/Providers` directory. 146 | 147 | Inside the `boot()` method, add the following line: 148 | 149 | ```php 150 | Validator::extend('msisdn', function ($attribute, $value, $parameters) { 151 | return Coreproc\MsisdnPh\Msisdn::validate($value); 152 | }); 153 | ``` 154 | 155 | ## Credits 156 | 157 | - [Chris Bautista][link-author] 158 | - [All Contributors][link-contributors] 159 | 160 | ## About CoreProc 161 | 162 | CoreProc is a software development company that provides software development services to startups, digital/ad agencies, and enterprises. 163 | 164 | Learn more about us on our [website](https://coreproc.com). 165 | 166 | ## License 167 | 168 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 169 | 170 | [ico-version]: https://img.shields.io/packagist/v/coreproc/msisdn-ph.svg?style=flat-square 171 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square 172 | [ico-travis]: https://img.shields.io/travis/CoreProc/msisdn-ph-php/master.svg?style=flat-square 173 | [ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/CoreProc/msisdn-ph-php.svg?style=flat-square 174 | [ico-code-quality]: https://img.shields.io/scrutinizer/g/CoreProc/msisdn-ph-php.svg?style=flat-square 175 | [ico-downloads]: https://img.shields.io/packagist/dt/coreproc/msisdn-ph.svg?style=flat-square 176 | 177 | [link-packagist]: https://packagist.org/packages/coreproc/msisdn-ph 178 | [link-travis]: https://travis-ci.org/CoreProc/msisdn-ph-php 179 | [link-scrutinizer]: https://scrutinizer-ci.com/g/CoreProc/msisdn-ph-php/code-structure 180 | [link-code-quality]: https://scrutinizer-ci.com/g/CoreProc/msisdn-ph-php 181 | [link-downloads]: https://packagist.org/packages/coreproc/msisdn-ph 182 | [link-author]: https://github.com/chrisbjr 183 | [link-contributors]: ../../contributors 184 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coreproc/msisdn-ph", 3 | "type": "library", 4 | "description": "An MSISDN identification and cleaner library for Philippine telco subscribers", 5 | "keywords": ["msisdn", "msisdn philippines", "globe", "smart", "sun", "mobile number"], 6 | "homepage": "http://github.com/coreproc/msisdn-ph-php", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Chris Bautista", 11 | "email": "chris.bautista@coreproc.ph", 12 | "homepage": "https://coreproc.com", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.4", 18 | "ext-json": "*" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "4.*", 22 | "scrutinizer/ocular": "~1.1" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Coreproc\\MsisdnPh\\": "src" 27 | } 28 | }, 29 | "scripts": { 30 | "test": "vendor/bin/phpunit", 31 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidMsisdnException.php: -------------------------------------------------------------------------------- 1 | msisdn = self::clean($msisdn); 45 | } 46 | 47 | /** 48 | * Returns a formatted mobile number 49 | * 50 | * @param bool|false $hasCountryCode 51 | * @param string $separator 52 | * @return mixed|string 53 | */ 54 | function get($hasCountryCode = false, $separator = '') 55 | { 56 | if (! $hasCountryCode) { 57 | $formattedNumber = '0' . $this->msisdn; 58 | 59 | if (! empty($separator)) { 60 | $formattedNumber = substr_replace($formattedNumber, $separator, 4, 0); 61 | $formattedNumber = substr_replace($formattedNumber, $separator, 8, 0); 62 | } 63 | } else { 64 | $formattedNumber = $this->countryPrefix . $this->msisdn; 65 | 66 | if (! empty($separator)) { 67 | $formattedNumber = substr_replace($formattedNumber, $separator, strlen($this->countryPrefix), 0); 68 | $formattedNumber = substr_replace($formattedNumber, $separator, 7, 0); 69 | $formattedNumber = substr_replace($formattedNumber, $separator, 11, 0); 70 | } 71 | } 72 | 73 | return $formattedNumber; 74 | } 75 | 76 | /** 77 | * Returns the prefix of the MSISDN number. 78 | * 79 | * @return string The prefix of the MSISDN number 80 | */ 81 | public function getPrefix() 82 | { 83 | if ($this->prefix == null) { 84 | $this->prefix = substr($this->msisdn, 0, 3); 85 | } 86 | 87 | return $this->prefix; 88 | } 89 | 90 | /** 91 | * Determines the operator of this number 92 | * 93 | * @return string The operator of this number 94 | */ 95 | public function getOperator() 96 | { 97 | $this->setPrefixes(); 98 | 99 | if (! empty($this->operator)) { 100 | return $this->operator; 101 | } 102 | 103 | foreach ($this->globePrefixes as $globePrefix) { 104 | $prefix = substr($this->msisdn, 0, strlen($globePrefix)); 105 | 106 | if (in_array($prefix, $this->globePrefixes)) { 107 | $this->operator = 'GLOBE'; 108 | 109 | return $this->operator; 110 | } 111 | } 112 | 113 | foreach ($this->smartPrefixes as $smartPrefix) { 114 | $prefix = substr($this->msisdn, 0, strlen($smartPrefix)); 115 | 116 | if (in_array($prefix, $this->smartPrefixes)) { 117 | $this->operator = 'SMART'; 118 | 119 | return $this->operator; 120 | } 121 | } 122 | 123 | foreach ($this->sunPrefixes as $sunPrefix) { 124 | $prefix = substr($this->msisdn, 0, strlen($sunPrefix)); 125 | 126 | if (in_array($prefix, $this->sunPrefixes)) { 127 | $this->operator = 'SUN'; 128 | 129 | return $this->operator; 130 | } 131 | } 132 | 133 | foreach ($this->ditoPrefixes as $ditoPrefix) { 134 | $prefix = substr($this->msisdn, 0, strlen($ditoPrefix)); 135 | 136 | if (in_array($prefix, $this->ditoPrefixes)) { 137 | $this->operator = 'DITO'; 138 | 139 | return $this->operator; 140 | } 141 | } 142 | 143 | foreach ($this->gomoPrefixes as $gomoPrefix) { 144 | $prefix = substr($this->msisdn, 0, strlen($gomoPrefix)); 145 | 146 | if (in_array($prefix, $this->gomoPrefixes)) { 147 | $this->operator = 'GOMO'; 148 | 149 | return $this->operator; 150 | } 151 | } 152 | 153 | $this->operator = 'UNKNOWN'; 154 | 155 | return $this->operator; 156 | } 157 | 158 | private function setPrefixes() 159 | { 160 | if (empty($this->smartPrefixes)) { 161 | $this->smartPrefixes = json_decode(file_get_contents(__DIR__ . '/prefixes/smart.json')); 162 | } 163 | 164 | if (empty($this->globePrefixes)) { 165 | $this->globePrefixes = json_decode(file_get_contents(__DIR__ . '/prefixes/globe.json')); 166 | } 167 | 168 | if (empty($this->sunPrefixes)) { 169 | $this->sunPrefixes = json_decode(file_get_contents(__DIR__ . '/prefixes/sun.json')); 170 | } 171 | 172 | if (empty($this->ditoPrefixes)) { 173 | $this->ditoPrefixes = json_decode(file_get_contents(__DIR__ . '/prefixes/dito.json')); 174 | } 175 | 176 | if (empty($this->gomoPrefixes)) { 177 | $this->gomoPrefixes = json_decode(file_get_contents(__DIR__ . '/prefixes/gomo.json')); 178 | } 179 | } 180 | 181 | /** 182 | * Validate a given mobile number 183 | * 184 | * @param string $mobileNumber 185 | * @return bool 186 | */ 187 | public static function validate($mobileNumber) 188 | { 189 | $mobileNumber = Msisdn::clean($mobileNumber); 190 | 191 | return ! empty($mobileNumber) && 192 | strlen($mobileNumber) === 10 && 193 | is_numeric($mobileNumber); 194 | } 195 | 196 | /** 197 | * Cleans the string 198 | * 199 | * @param string $msisdn 200 | * @return string The clean MSISDN 201 | */ 202 | private static function clean($msisdn) 203 | { 204 | $msisdn = preg_replace("/[^0-9]/", "", $msisdn); 205 | 206 | // We remove the 0 or 63 from the number 207 | if (substr($msisdn, 0, 1) === '0') { 208 | $msisdn = substr($msisdn, 1, strlen($msisdn)); 209 | } else { 210 | if (substr($msisdn, 0, 2) === '63') { 211 | $msisdn = substr($msisdn, 2, strlen($msisdn)); 212 | } 213 | } 214 | 215 | return $msisdn; 216 | } 217 | 218 | /** 219 | * Sets the country prefix - this defaults to +63 220 | * 221 | * @param $countryPrefix 222 | */ 223 | public function setCountryPrefix($countryPrefix) 224 | { 225 | $this->countryPrefix = $countryPrefix; 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/prefixes/dito.json: -------------------------------------------------------------------------------- 1 | [ 2 | "991", 3 | "992", 4 | "993", 5 | "994", 6 | "895", 7 | "896", 8 | "897", 9 | "898" 10 | ] 11 | -------------------------------------------------------------------------------- /src/prefixes/globe.json: -------------------------------------------------------------------------------- 1 | [ 2 | "817", 3 | "904", 4 | "905", 5 | "906", 6 | "915", 7 | "916", 8 | "917", 9 | "926", 10 | "927", 11 | "935", 12 | "936", 13 | "937", 14 | "945", 15 | "954", 16 | "955", 17 | "956", 18 | "965", 19 | "966", 20 | "967", 21 | "975", 22 | "977", 23 | "978", 24 | "979", 25 | "995", 26 | "996", 27 | "997", 28 | "9253", 29 | "9255", 30 | "9256", 31 | "9257", 32 | "9258" 33 | ] 34 | -------------------------------------------------------------------------------- /src/prefixes/gomo.json: -------------------------------------------------------------------------------- 1 | [ 2 | "976" 3 | ] 4 | -------------------------------------------------------------------------------- /src/prefixes/smart.json: -------------------------------------------------------------------------------- 1 | [ 2 | "813", 3 | "907", 4 | "908", 5 | "909", 6 | "910", 7 | "911", 8 | "912", 9 | "913", 10 | "914", 11 | "918", 12 | "919", 13 | "920", 14 | "921", 15 | "928", 16 | "929", 17 | "930", 18 | "939", 19 | "938", 20 | "946", 21 | "947", 22 | "948", 23 | "949", 24 | "950", 25 | "951", 26 | "961", 27 | "970", 28 | "981", 29 | "989", 30 | "998", 31 | "999" 32 | ] 33 | -------------------------------------------------------------------------------- /src/prefixes/sun.json: -------------------------------------------------------------------------------- 1 | [ 2 | "922", 3 | "923", 4 | "924", 5 | "925", 6 | "931", 7 | "932", 8 | "933", 9 | "934", 10 | "940", 11 | "941", 12 | "942", 13 | "943", 14 | "944", 15 | "973", 16 | "974" 17 | 18 | ] 19 | --------------------------------------------------------------------------------