├── .gitattributes ├── .github └── workflows │ ├── php.yml │ ├── php8.yml │ └── phpv8.yml ├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── src └── Canducci │ └── ZipCode │ ├── Contracts │ ├── ZipCodeAddressContract.php │ ├── ZipCodeAddressInfoContract.php │ ├── ZipCodeContract.php │ ├── ZipCodeInfoContract.php │ ├── ZipCodeRequestContract.php │ └── ZipCodeResponseContract.php │ ├── Facades │ ├── ZipCode.php │ └── ZipCodeAddress.php │ ├── Providers │ ├── ZipCodeAddressServiceProvider.php │ └── ZipCodeServiceProvider.php │ ├── ZipCode.php │ ├── ZipCodeAddress.php │ ├── ZipCodeAddressHelper.php │ ├── ZipCodeAddressInfo.php │ ├── ZipCodeAddressTrait.php │ ├── ZipCodeException.php │ ├── ZipCodeHelper.php │ ├── ZipCodeInfo.php │ ├── ZipCodeItem.php │ ├── ZipCodeRequest.php │ ├── ZipCodeResponse.php │ ├── ZipCodeTrait.php │ ├── ZipCodeUf.php │ └── config │ └── simplecache.php └── tests └── ZipCodeTest.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '**' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Validate composer.json and composer.lock 17 | run: composer validate 18 | 19 | - name: Install dependencies 20 | run: composer install --ignore-platform-reqs 21 | 22 | # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" 23 | # Docs: https://getcomposer.org/doc/articles/scripts.md 24 | 25 | - name: Run test suite 26 | run: composer run-script test 27 | -------------------------------------------------------------------------------- /.github/workflows/php8.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '**' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Validate composer.json and composer.lock 17 | run: composer validate 18 | 19 | - name: Install dependencies 20 | run: composer install --ignore-platform-reqs 21 | 22 | # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" 23 | # Docs: https://getcomposer.org/doc/articles/scripts.md 24 | 25 | - name: Run test suite 26 | run: composer run-script test 27 | -------------------------------------------------------------------------------- /.github/workflows/phpv8.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '**' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Validate composer.json and composer.lock 17 | run: composer validate 18 | 19 | - name: Install dependencies 20 | run: composer install --ignore-platform-reqs 21 | 22 | # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" 23 | # Docs: https://getcomposer.org/doc/articles/scripts.md 24 | 25 | - name: Run test suite 26 | run: composer run-script test 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/tmp/* 2 | tests/tmp/* 3 | # Windows image file caches 4 | Thumbs.db 5 | ehthumbs.db 6 | 7 | # Folder config file 8 | Desktop.ini 9 | 10 | # Recycle Bin used on file shares 11 | $RECYCLE.BIN/ 12 | 13 | # Windows Installer files 14 | *.cab 15 | *.msi 16 | *.msm 17 | *.msp 18 | 19 | # Windows shortcuts 20 | *.lnk 21 | 22 | # ========================= 23 | # Operating System Files 24 | # ========================= 25 | 26 | # OSX 27 | # ========================= 28 | 29 | .DS_Store 30 | .AppleDouble 31 | .LSOverride 32 | 33 | # Thumbnails 34 | ._* 35 | 36 | # Files that might appear on external disk 37 | .Spotlight-V100 38 | .Trashes 39 | 40 | # Directories potentially created on remote AFP share 41 | .AppleDB 42 | .AppleDesktop 43 | Network Trash Folder 44 | Temporary Items 45 | .apdisk 46 | 47 | # Vendor 48 | vendor/ 49 | 50 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 51 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 52 | 53 | # User-specific stuff 54 | .idea/**/workspace.xml 55 | .idea/**/tasks.xml 56 | .idea/**/usage.statistics.xml 57 | .idea/**/dictionaries 58 | .idea/**/shelf 59 | 60 | # Generated files 61 | .idea/**/contentModel.xml 62 | 63 | # Sensitive or high-churn files 64 | .idea/**/dataSources/ 65 | .idea/**/dataSources.ids 66 | .idea/**/dataSources.local.xml 67 | .idea/**/sqlDataSources.xml 68 | .idea/**/dynamic.xml 69 | .idea/**/uiDesigner.xml 70 | .idea/**/dbnavigator.xml 71 | .idea/deployment.xml 72 | .idea/misc.xml 73 | .idea/modules.xml 74 | .idea/zipcode.iml 75 | 76 | # Gradle 77 | .idea/**/gradle.xml 78 | .idea/**/libraries 79 | 80 | # Gradle and Maven with auto-import 81 | # When using Gradle or Maven with auto-import, you should exclude module files, 82 | # since they will be recreated, and may cause churn. Uncomment if using 83 | # auto-import. 84 | # .idea/modules.xml 85 | # .idea/*.iml 86 | # .idea/modules 87 | 88 | # CMake 89 | cmake-build-*/ 90 | 91 | # Mongo Explorer plugin 92 | .idea/**/mongoSettings.xml 93 | 94 | # File-based project format 95 | *.iws 96 | 97 | # IntelliJ 98 | out/ 99 | 100 | # mpeltonen/sbt-idea plugin 101 | .idea_modules/ 102 | 103 | # JIRA plugin 104 | atlassian-ide-plugin.xml 105 | 106 | # Cursive Clojure plugin 107 | .idea/replstate.xml 108 | 109 | # Crashlytics plugin (for Android Studio and IntelliJ) 110 | com_crashlytics_export_strings.xml 111 | crashlytics.properties 112 | crashlytics-build.properties 113 | fabric.properties 114 | 115 | # Editor-based Rest Client 116 | .idea/httpRequests 117 | 118 | # Android studio 3.1+ serialized cache file 119 | .idea/caches/build_file_checksums.ser 120 | 121 | composer.phar 122 | .idea/php.xml 123 | .idea/* 124 | .idea/**/ 125 | .idea 126 | 127 | # Removing composer.lock according to recommendation: 128 | # https://blog.martinhujer.cz/17-tips-for-using-composer-efficiently/ 129 | composer.lock 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 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. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Canducci Zipcode 2 | 3 | ### Laravel pacote do Web Service [VIACEP web service](http://viacep.com.br/) - http://viacep.com.br 4 | 5 | --- 6 | 7 | [![Downloads](https://img.shields.io/packagist/dt/canducci/zipcode.svg?style=flat)](https://packagist.org/packages/canducci/zipcode) 8 | [![Version](https://img.shields.io/packagist/v/canducci/zipcode.svg?label=version)](https://packagist.org/packages/canducci/zipcode) 9 | ![PHP Composer](https://github.com/netdragoon/zipcode/workflows/PHP%20Composer/badge.svg) 10 | 11 | [See Demo](http://zipcodedemo.herokuapp.com/) 12 | 13 | ## Utilizando composer: [Composer](https://getcomposer.org/) 14 | 15 | ```sh 16 | composer require canducci/zipcode 17 | ``` 18 | 19 | Adicione as classes no final do array de `providers` no arquivo `config/app.php`: 20 | 21 | ```php 22 | 'providers' => [ 23 | // ..., 24 | Canducci\ZipCode\Providers\ZipCodeServiceProvider::class, 25 | Canducci\ZipCode\Providers\ZipCodeAddressServiceProvider::class, 26 | ], 27 | ``` 28 | 29 | e adicione os seus apelidos no array `aliases`: 30 | 31 | ```php 32 | 'aliases' => [ 33 | // ..., 34 | 'ZipCode' => Canducci\ZipCode\Facades\ZipCode::class, 35 | 'Address' => Canducci\ZipCode\Facades\ZipCodeAddress::class, 36 | ], 37 | ``` 38 | 39 | para finalizar precisa dar um: 40 | 41 | ```php 42 | php artisan vendor:publish 43 | ``` 44 | 45 | após digitar esse comando vai aparecer um menu de opções então escolha `Canducci\ZipCode\Providers\ZipCodeServiceProvider` para publicar o arquivo de configuração (`simplecache.php`) na pasta `config/` 46 | 47 | ## Como utilizar? 48 | 49 | Temos 4 caminhos para usufruir desse pacote: 50 | 51 | - [Facade](#facade) 52 | - [Helper](#helper) 53 | - [Injection](#injection) 54 | - or [Trait](#trait) 55 | 56 | ### Facade 57 | 58 | ```php 59 | use Canducci\ZipCode\Facades\ZipCode; 60 | 61 | $zipCodeInfo = ZipCode::find('01414-001'); 62 | ``` 63 | 64 | ### Helper 65 | 66 | ```php 67 | $zipCodeInfo = zipcode('01414000'); 68 | ``` 69 | 70 | ### Injection 71 | 72 | ```php 73 | use Canducci\ZipCode\Contracts\ZipCodeContract; 74 | 75 | public function index(ZipCodeContract $zipcode) 76 | { 77 | $zipCodeInfo = $zipcode->find('01414-000'); 78 | } 79 | ``` 80 | 81 | ### Trait 82 | 83 | ```php 84 | use Canducci\ZipCode\ZipCodeTrait; 85 | 86 | class WelcomeController extends Controller 87 | { 88 | use ZipCodeTrait; 89 | 90 | public function index() 91 | { 92 | $zipCodeInfo = $this->zipcode('01414000'); 93 | } 94 | } 95 | ``` 96 | 97 | Há diversas formas de chegar no mesmo resultado: 98 | 99 | ```php 100 | $zipCodeInfo = ZipCode::find('01414000'); // Facade 101 | 102 | $zipCodeInfo = $zipcode->find('01414-000'); // Contract 103 | 104 | $zipCodeInfo = zipcode('01414000'); // Helper 105 | 106 | $zipCodeInfo = $this->zipcode('01414-000'); // Trait 107 | ``` 108 | 109 | --- 110 | 111 | ### Cache renovar 112 | 113 | Pode forçar um item a renovar seu cache com o segundo parâmetro: 114 | 115 | ```php 116 | $zipCodeInfo = ZipCode::find('01414000', true); // Facade 117 | 118 | $zipCodeInfo = $zipcode->find('01414-000', true); // Contract 119 | 120 | $zipCodeInfo = zipcode('01414000', true); // Helper 121 | 122 | $zipCodeInfo = $this->zipcode('01414-000', true); // Trait 123 | ``` 124 | 125 | --- 126 | 127 | ### Tipos de retornos 128 | 129 | Por padrão o retorno é nulo ou a instância da classe `Canducci\ZipCode\ZipCodeInfo`, e com esse retorno de classe existe os tipos `array`, `object` e `json` texto: 130 | 131 | - [Array](#array) 132 | - [Json](#json) 133 | - [Object](#object) 134 | 135 | ```php 136 | if ($zipCodeInfo) // null or ZipCodeInfo 137 | { 138 | $arr = $zipCodeInfo->getArray(); // Array 139 | 140 | $json = $zipCodeInfo->getJson(); // Json 141 | 142 | $obj = $zipCodeInfo->getObject(); // Object 143 | } 144 | ``` 145 | 146 | #### Array 147 | 148 | ```php 149 | if ($zipCodeInfo) 150 | { 151 | $arr = $zipCodeInfo->getArray(); 152 | /* 153 | Array 154 | ( 155 | [cep] => 01414-001 156 | [logradouro] => Rua Haddock Lobo 157 | [bairro] => Cerqueira César 158 | [localidade] => São Paulo 159 | [uf] => SP 160 | [ibge] => 3550308, 161 | [complemento] => 162 | [gia] => 1004, 163 | [siafi] => 0 164 | [ddd] = 11, 165 | [unidade] = '', 166 | [estado] = '', 167 | [regiao] = '' 168 | ) 169 | */ 170 | } 171 | ``` 172 | 173 | #### Json 174 | 175 | ```php 176 | if ($zipCodeInfo) 177 | { 178 | $json = $zipCodeInfo->getJson(); 179 | /* 180 | { 181 | "cep": "01414-001", 182 | "logradouro": "Rua Haddock Lobo", 183 | "bairro": "Cerqueira César", 184 | "localidade": "São Paulo", 185 | "uf": "SP", 186 | "ibge": "3550308", 187 | "complemento": "" 188 | "gia": 1004, 189 | "ddd": "11", 190 | "siafi": 0, 191 | "unidade": '', 192 | "estado": '', 193 | "regiao": '' 194 | } 195 | */ 196 | } 197 | ``` 198 | 199 | #### Object 200 | 201 | ```php 202 | if ($zipCodeInfo) 203 | { 204 | $obj = $zipCodeInfo->getObject(); 205 | /* 206 | stdClass Object 207 | ( 208 | [cep] => 01414-001 209 | [logradouro] => Rua Haddock Lobo 210 | [bairro] => Cerqueira César 211 | [localidade] => São Paulo 212 | [uf] => SP 213 | [ibge] => 3550308 214 | [complemento] => 215 | [gia] => 1004 216 | [siafi] => 0 217 | [ddd] = 011, 218 | [unidade] = '', 219 | [estado] = '', 220 | [regiao] = '' 221 | ) 222 | */ 223 | } 224 | ``` 225 | 226 | --- 227 | 228 | ### Faça a buscas de varios endereços informando, `uf`, `cidade` e `endereço`: 229 | 230 | ```php 231 | public function get(Request $request) 232 | { 233 | $uf = $request->get('uf'); 234 | $city = $request->get('cidade'); 235 | $address = $request->get('endereco') 236 | $zipcodeaddressinfo = zipcodeaddress($uf, $city, $address); 237 | if ($zipcodeaddressinfo) 238 | return $zipcodeaddressinfo->getJson(); 239 | return Response::json(['error' => 1]); 240 | } 241 | ``` 242 | 243 | --- 244 | 245 | ### Lista de Unidade Federativa: 246 | 247 | ```php 248 | use Canducci\ZipCode\ZipCodeUf; 249 | 250 | $lists = ZipCodeUf::lists(); 251 | ``` 252 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "canducci/zipcode", 3 | "type": "library", 4 | "description": "ZipCode From Brazil", 5 | "keywords": [ 6 | "cep", 7 | "zip", 8 | "zipcode", 9 | "cep from brazil", 10 | "laravel" 11 | ], 12 | "homepage": "https://github.com/netdragoon/zipcode", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Fúlvio", 17 | "email": "fulviocanducci@hotmail.com", 18 | "role": "Developer" 19 | } 20 | ], 21 | "require": { 22 | "php": ">=8.3.2", 23 | "php-extended/php-simple-cache-filesystem": "^7.0", 24 | "php-extended/php-file-object": "^7.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "8.5.41", 28 | "phpspec/phpspec": "7.5.0" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "Canducci\\ZipCode\\": "src/Canducci/ZipCode/" 33 | }, 34 | "files": [ 35 | "src/Canducci/ZipCode/ZipCodeHelper.php", 36 | "src/Canducci/ZipCode/ZipCodeAddressHelper.php" 37 | ] 38 | }, 39 | "scripts": { 40 | "test": "phpunit tests/" 41 | }, 42 | "extra": { 43 | "laravel": { 44 | "providers": [ 45 | "Canducci\\ZipCode\\Providers\\ZipCodeServiceProvider", 46 | "Canducci\\ZipCode\\Providers\\ZipCodeAddressServiceProvider" 47 | ], 48 | "aliases": { 49 | "ZipCode": "Canducci\\ZipCode\\Facades\\ZipCode", 50 | "Address": "Canducci\\ZipCode\\Facades\\ZipCodeAddress" 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/Contracts/ZipCodeAddressContract.php: -------------------------------------------------------------------------------- 1 | app['Canducci\ZipCode\Contracts\ZipCodeRequestContract']) === false) { 16 | $this->app->singleton('Canducci\ZipCode\Contracts\ZipCodeRequestContract', 'Canducci\ZipCode\ZipCodeRequest'); 17 | } 18 | $this->app->singleton('Canducci\ZipCode\Contracts\ZipCodeAddressContract', function ($app) { 19 | return new ZipCodeAddress($app['Canducci\ZipCode\Contracts\ZipCodeRequestContract']); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/Providers/ZipCodeServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 13 | __DIR__ . '/../config/simplecache.php' => config_path('simplecache.php'), 14 | ], 'simplecache'); 15 | } 16 | public function register() 17 | { 18 | if (isset($this->app['PhpExtended\SimpleCache\SimpleCacheFilesystem']) === false) { 19 | $this->app->singleton( 20 | 'PhpExtended\SimpleCache\SimpleCacheFilesystem', 21 | function ($app) { 22 | $path = config('simplecache.path') ?? __DIR__; 23 | $fileSystem = new \PhpExtended\File\FileSystem($path); 24 | return new \PhpExtended\SimpleCache\SimpleCacheFilesystem($fileSystem); 25 | } 26 | ); 27 | } 28 | if (isset($this->app[\Canducci\ZipCode\Contracts\ZipCodeRequestContract::class]) === false) { 29 | $this->app->singleton(\Canducci\ZipCode\Contracts\ZipCodeRequestContract::class, \Canducci\ZipCode\ZipCodeRequest::class); 30 | } 31 | $this->app->singleton(\Canducci\ZipCode\Contracts\ZipCodeContract::class, function ($app) { 32 | return new ZipCode($app[\PhpExtended\SimpleCache\SimpleCacheFilesystem::class], $app[\Canducci\ZipCode\Contracts\ZipCodeRequestContract::class]); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCode.php: -------------------------------------------------------------------------------- 1 | value = ''; 45 | $this->renew = false; 46 | $this->cache = $cache; 47 | $this->request = $request; 48 | } 49 | 50 | /** 51 | * @param $value 52 | * @param bool $renew 53 | * @return Canducci\ZipCode\ZipCodeInfo|ZipCodeInfo|null 54 | * @throws ZipCodeException 55 | */ 56 | public function find(string $value, bool $renew = false): ?ZipCodeInfo 57 | { 58 | $message = ''; 59 | if (is_string($value)) { 60 | $value = str_replace('.', '', $value); 61 | $value = str_replace('-', '', $value); 62 | if (mb_strlen($value) === 8 && preg_match('/^(\d){8}$/', $value)) { 63 | $this->value = $value; 64 | } else { 65 | $message = 'ZipCode invalid'; 66 | } 67 | } else { 68 | $message = 'ZipCode invalid'; 69 | } 70 | if (is_bool($renew)) { 71 | $this->renew = $renew; 72 | } else { 73 | if ($message != '') { 74 | $message .= PHP_EOL; 75 | } 76 | $message .= 'ZipCode argument renew is invalid'; 77 | } 78 | if ($message === '') { 79 | $valueInfo = $this->getZipCodeInfo(); 80 | if ($valueInfo === null) { 81 | return null; 82 | } 83 | return new ZipCodeInfo($valueInfo); 84 | } 85 | throw new ZipCodeException($message); 86 | } 87 | 88 | /** 89 | * @return null|string 90 | */ 91 | private function getZipCodeInfo(): ?string 92 | { 93 | $this->renew(); 94 | if ($this->cache->has('zipcode_' . $this->value)) { 95 | $getCache = $this->cache->get('zipcode_' . $this->value); 96 | if (isset($getCache) && is_array($getCache)) { 97 | if (isset($getCache['erro']) && $getCache['erro'] == true) { 98 | return null; 99 | } 100 | return json_encode($getCache, JSON_PRETTY_PRINT); 101 | } 102 | } else { 103 | $response = $this->request->get($this->url()); 104 | if ($response && $response->getStatusCode() === 200) { 105 | $getResponse = $response->getArray(); 106 | $this->cache->set('zipcode_' . $this->value, $getResponse, 86400); 107 | if (isset($getResponse['erro']) && $getResponse['erro'] == true) { 108 | return null; 109 | } 110 | return json_encode($getResponse); 111 | } 112 | } 113 | return null; 114 | } 115 | 116 | /** 117 | * @return mixed 118 | */ 119 | private function renew(): ZipCode 120 | { 121 | if ($this->renew && (is_null($this->value) === false)) { 122 | if ($this->cache->has('zipcode_' . $this->value)) { 123 | $this->cache->delete('zipcode_' . $this->value); 124 | } 125 | $this->renew = false; 126 | } 127 | return $this; 128 | } 129 | 130 | /** 131 | * @return mixed 132 | */ 133 | private function url(): string 134 | { 135 | return str_replace('[cep]', $this->value, 'https://viacep.com.br/ws/[cep]/json/'); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeAddress.php: -------------------------------------------------------------------------------- 1 | request = $request; 26 | } 27 | 28 | /** 29 | * @param string $uf 30 | * @param string $city 31 | * @param string $address 32 | * @return ZipCodeAddressInfo 33 | * @throws ZipCodeException 34 | */ 35 | public function find(string $uf, string $city, string $address) 36 | { 37 | $message = ''; 38 | if (strlen($uf) < 2) { 39 | $message .= PHP_EOL . 'Uf invalid'; 40 | } 41 | if (strlen($city) < 3) { 42 | $message .= PHP_EOL . "City invalid"; 43 | } 44 | if (strlen($address) < 3) { 45 | $message .= PHP_EOL . 'Address invalid'; 46 | } 47 | if ($message != '') { 48 | throw new ZipCodeException($message); 49 | } 50 | try { 51 | $response = $this->request->get($this->url($uf, $city, $address, 'json')); 52 | if ($response && $response->getStatusCode() === 200) { 53 | return new ZipCodeAddressInfo($response->getJson()); 54 | } 55 | throw new ZipCodeException('Request invalid', $response->getStatusCode()); 56 | } catch (Exception $e) { 57 | throw new ZipCodeException($e->getMessage(), $e->getCode(), $e->getPrevious()); 58 | } 59 | } 60 | 61 | /** 62 | * @param $uf 63 | * @param $city 64 | * @param $address 65 | * @param $type 66 | * @return string 67 | */ 68 | protected function url($uf, $city, $address, $type) 69 | { 70 | $this->clean($uf); 71 | $this->clean($city); 72 | $this->clean($address); 73 | return sprintf( 74 | 'https://viacep.com.br/ws/%s/%s/%s/%s/', 75 | strtolower($uf), 76 | strtolower($city), 77 | strtolower($address), 78 | strtolower($type) 79 | ); 80 | } 81 | 82 | /** 83 | * @param $value 84 | * @return string 85 | */ 86 | protected function clean(&$value) 87 | { 88 | $map = array( 89 | 'á' => 'a', 90 | 'à' => 'a', 91 | 'ã' => 'a', 92 | 'â' => 'a', 93 | 'é' => 'e', 94 | 'ê' => 'e', 95 | 'í' => 'i', 96 | 'ó' => 'o', 97 | 'ô' => 'o', 98 | 'õ' => 'o', 99 | 'ú' => 'u', 100 | 'ü' => 'u', 101 | 'ç' => 'c', 102 | 'Á' => 'A', 103 | 'À' => 'A', 104 | 'Ã' => 'A', 105 | 'Â' => 'A', 106 | 'É' => 'E', 107 | 'Ê' => 'E', 108 | 'Í' => 'I', 109 | 'Ó' => 'O', 110 | 'Ô' => 'O', 111 | 'Õ' => 'O', 112 | 'Ú' => 'U', 113 | 'Ü' => 'U', 114 | 'Ç' => 'C' 115 | ); 116 | $value = strtr($value, $map); 117 | return $value; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeAddressHelper.php: -------------------------------------------------------------------------------- 1 | find($uf, $city, $address); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeAddressInfo.php: -------------------------------------------------------------------------------- 1 | value = $value; 29 | if ($this->jsonValidate() === false) { 30 | throw new ZipCodeException('Format invalid'); 31 | } 32 | } else { 33 | throw new ZipCodeException('JSON empty'); 34 | } 35 | } 36 | 37 | /** 38 | * @return Contracts\JSON|null|string 39 | */ 40 | public function getJson(): string 41 | { 42 | return $this->value; 43 | } 44 | 45 | /** 46 | * @return Contracts\Array|mixed|null 47 | */ 48 | public function getArray(): array 49 | { 50 | return json_decode($this->getJson(), true); 51 | } 52 | 53 | /** 54 | * @return mixed|null|\stdClass 55 | */ 56 | public function getObject(): array 57 | { 58 | return json_decode($this->getJson(), false); 59 | } 60 | 61 | /** 62 | * @return int 63 | */ 64 | public function count(): int 65 | { 66 | return count($this->getArray()); 67 | } 68 | 69 | /** 70 | * @return bool 71 | */ 72 | private function jsonValidate() 73 | { 74 | $ret = @json_decode($this->value, true); 75 | return json_last_error() === JSON_ERROR_NONE && is_array($ret); 76 | } 77 | 78 | /** 79 | * @return array|Contracts\Array 80 | */ 81 | public function getZipCodeItem(): array 82 | { 83 | $array = array(); 84 | foreach ($this->getArray() as $ret) { 85 | $array[] = new ZipCodeItem( 86 | $ret['cep'], 87 | $ret['logradouro'], 88 | $ret['complemento'], 89 | $ret['bairro'], 90 | $ret['localidade'], 91 | $ret['uf'], 92 | $ret['ibge'], 93 | $ret['gia'], 94 | $ret['ddd'], 95 | $ret['siafi'], 96 | $ret['unidade'], 97 | $ret['estado'], 98 | $ret['regiao'] 99 | ); 100 | } 101 | return $array; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeAddressTrait.php: -------------------------------------------------------------------------------- 1 | find($value, $renew); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeInfo.php: -------------------------------------------------------------------------------- 1 | valueJson = $valueJson; 30 | if ($this->json_validate_zipcode() === false) { 31 | throw new ZipCodeException("JSON invalid"); 32 | } 33 | } else { 34 | throw new ZipCodeException("Format invalid"); 35 | } 36 | } 37 | 38 | /** 39 | * return JSON Javascript 40 | * 41 | * @return JSON Javascript 42 | */ 43 | public function getJson(): string 44 | { 45 | if (!empty($this->valueJson)) { 46 | return $this->valueJson; 47 | } 48 | return null; 49 | } 50 | 51 | /** 52 | * return Array 53 | * 54 | * @return Array 55 | */ 56 | public function getArray(): array 57 | { 58 | if (!empty($this->valueJson)) { 59 | return json_decode($this->valueJson, true); 60 | } 61 | return null; 62 | } 63 | 64 | /** 65 | * return stdClass (Object) 66 | * 67 | * @return \stdClass 68 | */ 69 | public function getObject(): stdClass 70 | { 71 | if (!empty($this->valueJson)) { 72 | return json_decode($this->valueJson, false); 73 | } 74 | return null; 75 | } 76 | 77 | /** 78 | * validate zipcode format 79 | * 80 | * @return bool 81 | */ 82 | private function json_validate_zipcode(): bool 83 | { 84 | if (!empty($this->valueJson) && is_string($this->valueJson)) { 85 | $ret = @json_decode($this->valueJson, true); 86 | return (json_last_error() === JSON_ERROR_NONE && 87 | isset($ret['cep']) && 88 | isset($ret['logradouro']) && 89 | isset($ret['complemento']) && 90 | isset($ret['bairro']) && 91 | isset($ret['localidade']) && 92 | isset($ret['uf']) && 93 | isset($ret['ibge']) && 94 | isset($ret['gia'])) && 95 | isset($ret['ddd']) && 96 | isset($ret['siafi']); 97 | } 98 | return false; 99 | } 100 | 101 | /** 102 | * @return ZipCodeItem 103 | */ 104 | public function getZipCodeItem(): ZipCodeItem 105 | { 106 | $ret = $this->getArray(); 107 | return new ZipCodeItem( 108 | $ret['cep'], 109 | $ret['logradouro'], 110 | $ret['complemento'], 111 | $ret['bairro'], 112 | $ret['localidade'], 113 | $ret['uf'], 114 | $ret['ibge'], 115 | $ret['gia'], 116 | $ret['ddd'], 117 | $ret['siafi'] 118 | ); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeItem.php: -------------------------------------------------------------------------------- 1 | cep = $cep; 45 | $this->logradouro = $logradouro; 46 | $this->complemento = $complemento; 47 | $this->bairro = $bairro; 48 | $this->localidade = $localidade; 49 | $this->uf = $uf; 50 | $this->ibge = $ibge; 51 | $this->gia = $gia; 52 | $this->ddd = $ddd; 53 | $this->siafi = $siafi; 54 | $this->unidade = $unidade; 55 | $this->estado = $estado; 56 | $this->regiao = $regiao; 57 | } 58 | 59 | /** 60 | * @return mixed 61 | */ 62 | public function getCep(): string 63 | { 64 | return $this->cep; 65 | } 66 | 67 | /** 68 | * @return mixed 69 | */ 70 | public function getLogradouro(): string 71 | { 72 | return $this->logradouro; 73 | } 74 | 75 | /** 76 | * @return mixed 77 | */ 78 | public function getComplemento(): string 79 | { 80 | return $this->complemento; 81 | } 82 | 83 | /** 84 | * @return mixed 85 | */ 86 | public function getBairro(): string 87 | { 88 | return $this->bairro; 89 | } 90 | 91 | /** 92 | * @return mixed 93 | */ 94 | public function getLocalidade(): string 95 | { 96 | return $this->localidade; 97 | } 98 | 99 | /** 100 | * @return mixed 101 | */ 102 | public function getUf(): string 103 | { 104 | return $this->uf; 105 | } 106 | 107 | /** 108 | * @return mixed 109 | */ 110 | public function getIbge(): string 111 | { 112 | return $this->ibge; 113 | } 114 | 115 | /** 116 | * @return mixed 117 | */ 118 | public function getGia(): string 119 | { 120 | return $this->gia; 121 | } 122 | 123 | /** 124 | * @return mixed 125 | */ 126 | public function getDdd(): string 127 | { 128 | return $this->ddd; 129 | } 130 | 131 | /** 132 | * @return mixed 133 | */ 134 | public function getSiafi(): string 135 | { 136 | return $this->siafi; 137 | } 138 | 139 | /** 140 | * @return mixed 141 | */ 142 | public function getUnidade(): string 143 | { 144 | return $this->unidade; 145 | } 146 | 147 | /** 148 | * @return mixed 149 | */ 150 | public function getEstado(): string 151 | { 152 | return $this->estado; 153 | } 154 | 155 | /** 156 | * @return mixed 157 | */ 158 | public function getRegiao(): string 159 | { 160 | return $this->regiao; 161 | } 162 | 163 | /** 164 | * @param $name 165 | * @return mixed 166 | */ 167 | function __get($name) 168 | { 169 | return $this->$name; 170 | } 171 | 172 | /** 173 | * @param $name 174 | * @param $value 175 | */ 176 | function __set($name, $value) 177 | { 178 | $this->$name = $value; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeRequest.php: -------------------------------------------------------------------------------- 1 | json = $json; 19 | $this->statusCode = $statusCode; 20 | } 21 | 22 | public function getStatusCode(): int 23 | { 24 | return $this->statusCode; 25 | } 26 | 27 | public function getJson(): string 28 | { 29 | return $this->json; 30 | } 31 | 32 | public function getArray(): array 33 | { 34 | return json_decode($this->getJson(), true); 35 | } 36 | 37 | public function getObject(): stdClass 38 | { 39 | return json_decode($this->getJson(), false); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Canducci/ZipCode/ZipCodeTrait.php: -------------------------------------------------------------------------------- 1 | getConstants(); 45 | unset($rf); 46 | return $data; 47 | } 48 | } -------------------------------------------------------------------------------- /src/Canducci/ZipCode/config/simplecache.php: -------------------------------------------------------------------------------- 1 | storage_path('framework/cache') 4 | ]; -------------------------------------------------------------------------------- /tests/ZipCodeTest.php: -------------------------------------------------------------------------------- 1 | setZipCodeInstance(); 25 | $this->setZipCodeAddressInstance(); 26 | } 27 | 28 | public function setZipCodeInstance(): void 29 | { 30 | if (realpath(__DIR__ . '/tmp') === false) { 31 | mkdir(__DIR__ . '/tmp'); 32 | } 33 | $path = realpath(__DIR__ . '/tmp'); 34 | $this->zipCode = new ZipCode( 35 | new SimpleCacheFilesystem(new Filesystem($path)), 36 | new ZipCodeRequest() 37 | ); 38 | } 39 | 40 | public function setZipCodeAddressInstance(): void 41 | { 42 | $this->address = new ZipCodeAddress(new ZipCodeRequest()); 43 | } 44 | 45 | public function testZipCode(): void 46 | { 47 | $this->assertNotNull($this->zipCode); 48 | $this->assertInstanceOf(ZipCode::class, $this->zipCode); 49 | } 50 | 51 | public function testZipCodeAddress(): void 52 | { 53 | $this->assertNotNull($this->address); 54 | $this->assertInstanceOf(ZipCodeAddress::class, $this->address); 55 | } 56 | 57 | 58 | public function testZipCodeInfo(): void 59 | { 60 | $zipCodeInfo = $this->zipCode->find('01001000'); 61 | $this->assertNotNull($zipCodeInfo); 62 | $this->assertInstanceOf(ZipCodeInfo::class, $zipCodeInfo); 63 | } 64 | 65 | public function testZipCodeInfoTestMethods(): void 66 | { 67 | $zipCodeInfo = $this->zipCode->find('01001000'); 68 | $this->assertNotNull($zipCodeInfo); 69 | $this->assertIsString($zipCodeInfo->getJson()); 70 | $this->assertIsArray($zipCodeInfo->getArray()); 71 | $this->assertIsObject($zipCodeInfo->getObject()); 72 | } 73 | 74 | public function testZipCodeAddressInfo(): void 75 | { 76 | $zipCodeAddressInfo = $this->address->find('sp', 'paulo', 'ave'); 77 | $this->assertNotNull($zipCodeAddressInfo); 78 | $this->assertInstanceOf(ZipCodeAddressInfo::class, $zipCodeAddressInfo); 79 | } 80 | 81 | public function testZipCodeAddressInfoTestMethods(): void 82 | { 83 | $zipCodeAddressInfo = $this->address->find('sp', 'paulo', 'ave'); 84 | $this->assertNotNull($zipCodeAddressInfo); 85 | $this->assertIsString($zipCodeAddressInfo->getJson()); 86 | $this->assertIsArray($zipCodeAddressInfo->getArray()); 87 | $this->assertIsArray($zipCodeAddressInfo->getObject()); 88 | $this->assertIsNumeric($zipCodeAddressInfo->count()); 89 | } 90 | 91 | public function testZipCodeReturnCep(): void 92 | { 93 | $zipCodeInfo = $this->zipCode->find('01001000'); 94 | $data = $zipCodeInfo->getArray(); 95 | $this->assertIsArray($data); 96 | } 97 | 98 | 99 | public function testZipCodeAddressReturnCeps(): void 100 | { 101 | $zipCodeAddressInfo = $this->address->find('sp', 'paulo', 'ave'); 102 | $datas = $zipCodeAddressInfo->getArray(); 103 | $this->assertIsArray($datas); 104 | $this->assertEquals(50, $zipCodeAddressInfo->count()); 105 | $this->assertArrayHasKey('cep', $datas[0]); 106 | } 107 | 108 | public function testZipCodeAddressTestKeys(): void 109 | { 110 | $zipCodeAddressInfo = $this->address->find('sp', 'paulo', 'ave'); 111 | $datas = $zipCodeAddressInfo->getArray(); 112 | $this->assertArrayHasKey('cep', $datas[0]); 113 | $this->assertArrayHasKey('logradouro', $datas[0]); 114 | $this->assertArrayHasKey('complemento', $datas[0]); 115 | $this->assertArrayHasKey('bairro', $datas[0]); 116 | $this->assertArrayHasKey('localidade', $datas[0]); 117 | $this->assertArrayHasKey('uf', $datas[0]); 118 | $this->assertArrayHasKey('ddd', $datas[0]); 119 | $this->assertArrayHasKey('siafi', $datas[0]); 120 | $this->assertArrayHasKey('ibge', $datas[0]); 121 | $this->assertArrayHasKey('gia', $datas[0]); 122 | } 123 | 124 | public function testZipCodeFieldObject(): void 125 | { 126 | $zipCodeInfo = $this->zipCode->find('01001000'); 127 | $model = $zipCodeInfo->getObject(); 128 | 129 | $this->assertNotNull($model->cep); 130 | $this->assertNotNull($model->logradouro); 131 | $this->assertNotNull($model->complemento); 132 | $this->assertNotNull($model->bairro); 133 | $this->assertNotNull($model->localidade); 134 | $this->assertNotNull($model->uf); 135 | $this->assertNotNull($model->ddd); 136 | $this->assertNotNull($model->siafi); 137 | $this->assertNotNull($model->ibge); 138 | $this->assertNotNull($model->gia); 139 | } 140 | 141 | public function testZipCodeFieldArray(): void 142 | { 143 | $zipCodeInfo = $this->zipCode->find('01001000'); 144 | $model = $zipCodeInfo->getArray(); 145 | 146 | $this->assertNotNull($model['cep']); 147 | $this->assertNotNull($model['logradouro']); 148 | $this->assertNotNull($model['complemento']); 149 | $this->assertNotNull($model['bairro']); 150 | $this->assertNotNull($model['localidade']); 151 | $this->assertNotNull($model['uf']); 152 | $this->assertNotNull($model['ddd']); 153 | $this->assertNotNull($model['siafi']); 154 | $this->assertNotNull($model['ibge']); 155 | $this->assertNotNull($model['gia']); 156 | } 157 | 158 | public function testZipCodeTestValues(): void 159 | { 160 | $zipCodeInfo = $this->zipCode->find('01001000'); 161 | $model = $zipCodeInfo->getArray(); 162 | $this->assertEquals($model['cep'], '01001-000'); 163 | $this->assertEquals($model['logradouro'], 'Praça da Sé'); 164 | $this->assertEquals($model['complemento'], 'lado ímpar'); 165 | $this->assertEquals($model['bairro'], 'Sé'); 166 | $this->assertEquals($model['localidade'], 'São Paulo'); 167 | $this->assertEquals($model['uf'], 'SP'); 168 | $this->assertEquals($model['ddd'], '11'); 169 | $this->assertEquals($model['siafi'], '7107'); 170 | $this->assertEquals($model['ibge'], '3550308'); 171 | $this->assertEquals($model['gia'], '1004'); 172 | } 173 | 174 | public function testZipCodeFunctionFieldObject(): void 175 | { 176 | $zipCodeInfo = zipcode('01001000'); 177 | $model = $zipCodeInfo->getObject(); 178 | 179 | $this->assertNotNull($model->cep); 180 | $this->assertNotNull($model->logradouro); 181 | $this->assertNotNull($model->complemento); 182 | $this->assertNotNull($model->bairro); 183 | $this->assertNotNull($model->localidade); 184 | $this->assertNotNull($model->uf); 185 | $this->assertNotNull($model->ddd); 186 | $this->assertNotNull($model->siafi); 187 | $this->assertNotNull($model->ibge); 188 | $this->assertNotNull($model->gia); 189 | } 190 | 191 | public function testZipCodeFunctionFieldArray(): void 192 | { 193 | $zipCodeInfo = zipcode('01001000'); 194 | $model = $zipCodeInfo->getArray(); 195 | 196 | $this->assertNotNull($model['cep']); 197 | $this->assertNotNull($model['logradouro']); 198 | $this->assertNotNull($model['complemento']); 199 | $this->assertNotNull($model['bairro']); 200 | $this->assertNotNull($model['localidade']); 201 | $this->assertNotNull($model['uf']); 202 | $this->assertNotNull($model['ddd']); 203 | $this->assertNotNull($model['siafi']); 204 | $this->assertNotNull($model['ibge']); 205 | $this->assertNotNull($model['gia']); 206 | } 207 | 208 | public function testZipCodeFunctionTestValues(): void 209 | { 210 | $zipCodeInfo = zipcode('01001-000'); 211 | $model = $zipCodeInfo->getArray(); 212 | $this->assertEquals($model['cep'], '01001-000'); 213 | $this->assertEquals($model['logradouro'], 'Praça da Sé'); 214 | $this->assertEquals($model['complemento'], 'lado ímpar'); 215 | $this->assertEquals($model['bairro'], 'Sé'); 216 | $this->assertEquals($model['localidade'], 'São Paulo'); 217 | $this->assertEquals($model['uf'], 'SP'); 218 | $this->assertEquals($model['ddd'], '11'); 219 | $this->assertEquals($model['siafi'], '7107'); 220 | $this->assertEquals($model['ibge'], '3550308'); 221 | $this->assertEquals($model['gia'], '1004'); 222 | } 223 | } 224 | --------------------------------------------------------------------------------