├── LICENSE.md ├── README.md ├── composer.json ├── phpunit.xml └── src ├── Config └── addressval.php ├── Examples └── google-output.png ├── Lib ├── Checker.php ├── Contract.php └── drivers │ └── GeoogleGeocode.php └── ValidatorServiceProvider.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gustavo Ocanto 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 13 | > all 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 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Places Validation 2 | 3 | Total Downloads 4 | Build Status 5 | Latest Stable Version 6 | 7 | 8 | Places validation is a ***laravel*** library that will help you out to handle your user addresses. Its aim is making sure the addresses submitted by users are valid through 3rd party services, as google. 9 | 10 | # Installation 11 | 12 | Begin by installing the package through Composer. Run the following command in your terminal: 13 | 14 | ```bash 15 | composer require gocanto/places-validation 16 | ``` 17 | 18 | Once composer is done, add the package service provider in the providers array in `config/app.php`: 19 | 20 | ```php 21 | Gocanto\AddressValidation\ValidatorServiceProvider::class 22 | ``` 23 | 24 | 25 | # Client Side 26 | 27 | ```Vuejs``` component which implements the google autocomplete library: 28 | 29 | * Repository: https://github.com/gocanto/google-autocomplete 30 | * Demo: https://gocanto.github.io/google-autocomplete/ 31 | 32 | 33 | # Settings 34 | 35 | You will be able to set the validator driver into ```config/addressval.php``` file. At the moment, the package just has the ability to work with google, but others services are planned ahead. 36 | 37 | 38 | The array driver looks like this: 39 | ```php 40 | 'driver' => [ 41 | 42 | //api key if required 43 | 'key' => '', 44 | 45 | //driver object 46 | 'name' => 'GeoogleGeocode', 47 | 48 | //api url 49 | 'api' => 'http://maps.google.com/maps/api/geocode/json' 50 | ], 51 | ``` 52 | 53 | if you do not set the driver within this file, the default one will be used. 54 | 55 | 56 | # Validate user address using the Laravel validator object 57 | 58 | Now you will be able to use this package to validate the user address information within your validations rules. This is how it would look like: 59 | 60 | ```php 61 | $rules = [ 62 | 'address' => 'valid_place' 63 | ]; 64 | 65 | $data = [ 66 | 'address' => 'Guacara, Carabobo, Venezuela' 67 | ]; 68 | 69 | $v = \Validator::make($data, $rules); 70 | ``` 71 | 72 | You will be able to see the implementation on ManagerTest 73 | 74 | 75 | # Use out of the Laravel object 76 | 77 | To implement the validation within your project, you have to include the Checker object as so: 78 | ```php 79 | use Gocanto\AddressValidation\Lib\Checker; 80 | ``` 81 | 82 | 83 | then, you can let laravel to handle the dependency injection for you, as so: 84 | ```php 85 | public function index(Checker $places) 86 | { 87 | 88 | if ( ! $v = $places->validate('Guacara, Carabobo, Venezuela')) { 89 | //the place is not valid. 90 | } 91 | 92 | //retrieve the place information. 93 | dd($v->retrieve(), $v->location()); 94 | } 95 | ``` 96 | 97 | 98 | ***Output Illustration*** 99 | 100 | ![example](https://github.com/gocanto/places-validation/blob/dev/src/Examples/google-output.png) 101 | 102 | 103 | # Inspiration 104 | 105 | The inspiration came from a needed of using the validation within a form request object. I used [Prosper Otemuyiwa](https://github.com/unicodeveloper/laravel-password) package to have a scope of what I had to do. 106 | 107 | 108 | # Contributing 109 | 110 | Please feel free to fork this package and contribute by submitting a pull request to enhance the functionalities. 111 | 112 | 113 | # License 114 | 115 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 116 | 117 | 118 | # How can I thank you? 119 | Why not star the github repo? Why not share the link for this repository on Twitter? Spread the word! 120 | 121 | 122 | Don't forget to [follow me on twitter](https://twitter.com/gocanto)! 123 | 124 | Thanks! 125 | 126 | Gustavo Ocanto. 127 | gustavoocanto@gmail.com 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gocanto/places-validation", 3 | "description": "validate users addresses through services like google place", 4 | "keywords": ["validate", "users", "addresses", "places", "validation"], 5 | "homepage": "https://github.com/gocanto/places-validation", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Gustavo Ocanto", 10 | "email": "gustavoocanto@gmail.com", 11 | "homepage": "http://g-ocanto.com", 12 | "role": "Web Developer" 13 | } 14 | ], 15 | "require": { 16 | "php" : "^7.1.3", 17 | "illuminate/support": "5.6.*" 18 | }, 19 | "require-dev": { 20 | "phpunit/phpunit" : "~7.0", 21 | "orchestra/testbench": "3.6.*", 22 | "mockery/mockery": "~1.0", 23 | "sebastian/diff": "^3.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Gocanto\\AddressValidation\\": "src" 28 | } 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "Gocanto\\AddressValidation\\Tests\\": "tests" 33 | }, 34 | "classmap": [ 35 | "tests/TestCase.php" 36 | ] 37 | }, 38 | "scripts": { 39 | "test": "./vendor/bin/phpunit" 40 | }, 41 | "extra": { 42 | "laravel": { 43 | "providers": [ 44 | "Gocanto\\AddressValidation\\ValidatorServiceProvider" 45 | ] 46 | } 47 | }, 48 | "config": { 49 | "sort-packages": true 50 | }, 51 | "prefer-stable": true 52 | } 53 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | tests/ 17 | 18 | 19 | 20 | 21 | src/ 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Config/addressval.php: -------------------------------------------------------------------------------- 1 | [ 14 | 15 | //api key if required 16 | 'key' => '', 17 | 18 | //driver object 19 | 'name' => 'GeoogleGeocode', 20 | 21 | //api url 22 | 'api' => 'http://maps.google.com/maps/api/geocode/json' 23 | ], 24 | ]; -------------------------------------------------------------------------------- /src/Examples/google-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gocanto/places-validation/48f5e176e5282ffa1fab12e9c8c32dfb393f445a/src/Examples/google-output.png -------------------------------------------------------------------------------- /src/Lib/Checker.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Gocanto\AddressValidation\Lib; 12 | 13 | class Checker 14 | { 15 | /** 16 | * Default driver. 17 | * @var string 18 | */ 19 | private $default = 'GeoogleGeocode'; 20 | 21 | /** 22 | * Drivers map. 23 | * @var array 24 | */ 25 | private $drivers = [ 26 | 'GeoogleGeocode' => \Gocanto\AddressValidation\Lib\drivers\GeoogleGeocode::class 27 | ]; 28 | 29 | /** 30 | * Validation driver object. 31 | * @var object 32 | */ 33 | private $driver = null; 34 | 35 | /** 36 | * Driver configuration info. 37 | * @var array 38 | */ 39 | private $config = null; 40 | 41 | /** 42 | * Create a new instance. 43 | */ 44 | public function __construct() 45 | { 46 | $this->config = $this->resolveConfig(); 47 | $this->driver = $this->resolveDriver(); 48 | } 49 | 50 | /** 51 | * Resolve the driver config info 52 | * @return array 53 | */ 54 | private function resolveConfig() 55 | { 56 | $config = config('addressval.driver'); 57 | 58 | if ($config) { 59 | return $config; 60 | } 61 | 62 | return $this->defaultDriver(); 63 | } 64 | 65 | /** 66 | * Returns the default driver. 67 | * @return array 68 | */ 69 | private function defaultDriver() 70 | { 71 | return [ 72 | 'key' => '', 73 | 'name' => 'GeoogleGeocode', 74 | 'api' => 'http://maps.google.com/maps/api/geocode/json' 75 | ]; 76 | } 77 | 78 | /** 79 | * Return a new driver instance. 80 | * @param array $driver 81 | * @return driver 82 | */ 83 | private function resolveDriver() 84 | { 85 | if ($this->isDrivable()) { 86 | return $this->createInstanceFor($this->config["name"]); 87 | } 88 | 89 | return $this->createInstanceFor($this->default); 90 | } 91 | 92 | /** 93 | * Check whether the driver given is valid. 94 | * @return boolean 95 | */ 96 | private function isDrivable() 97 | { 98 | $driver = $this->config["name"]; 99 | 100 | return isset($this->drivers[$driver]); 101 | } 102 | 103 | /** 104 | * Create a new instance for a given driver. 105 | * @param string $driver 106 | * @return driver 107 | */ 108 | private function createInstanceFor(string $driver) 109 | { 110 | return new $this->drivers[$driver]($this->config); 111 | } 112 | 113 | /** 114 | * Call methods for a given driver. 115 | * @param String $method 116 | * @param Array $arguments 117 | * @return Driver|Exception 118 | */ 119 | public function __call($method, $arguments) 120 | { 121 | $arguments = (string) implode(', ', $arguments); 122 | 123 | if (method_exists($this->driver, $method)) { 124 | return $this->driver->$method($arguments); 125 | } 126 | 127 | throw new \Exception('The method "'.$method.'" does not exist in the class: ' . get_class($this->driver)); 128 | } 129 | } -------------------------------------------------------------------------------- /src/Lib/Contract.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Gocanto\AddressValidation\Lib; 12 | 13 | interface Contract 14 | { 15 | /** 16 | * Validate whether a given address is valid. 17 | * @param string $address 18 | * @return Mixed 19 | */ 20 | public function validate(string $address); 21 | 22 | /** 23 | * Retrieve the place information. 24 | * @return collection 25 | */ 26 | public function retrieve(); 27 | 28 | /** 29 | * Retrieve the 'lat' and 'lng' for a given place. 30 | * @return array 31 | */ 32 | public function location(); 33 | } 34 | -------------------------------------------------------------------------------- /src/Lib/drivers/GeoogleGeocode.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Gocanto\AddressValidation\Lib\drivers; 12 | 13 | use Gocanto\AddressValidation\Lib\Contract; 14 | 15 | class GeoogleGeocode implements Contract 16 | { 17 | /** 18 | * Indicates when there was no results from google. 19 | */ 20 | const ZERO_RESULTS = 'ZERO_RESULTS'; 21 | 22 | /** 23 | * Google place object. 24 | * @var null 25 | */ 26 | private $place = null; 27 | 28 | /** 29 | * Driver configuration info. 30 | * @var array 31 | */ 32 | private $config = null; 33 | 34 | /** 35 | * Create a new instance. 36 | */ 37 | public function __construct($config = []) 38 | { 39 | $this->config = $config; 40 | } 41 | 42 | /** 43 | * fetch an address from google geocode api. 44 | * @param string $address 45 | * @return array 46 | */ 47 | private function fetchAddress(string $address) 48 | { 49 | return json_decode( 50 | file_get_contents($this->resolveUrl($address)), 51 | true 52 | ); 53 | } 54 | 55 | /** 56 | * Build the google request url for a given address. 57 | * @param string $address 58 | * @return string 59 | */ 60 | private function resolveUrl(string $address) 61 | { 62 | return $this->config['api'] .'?address='. urlencode($address); 63 | } 64 | 65 | /** 66 | * Validate whether a given address is valid. 67 | * @param string $address 68 | * @return Mixed 69 | */ 70 | public function validate(string $address) 71 | { 72 | $this->place = $this->fetchAddress($address); 73 | 74 | if ($this->placeDoesntExist()) { 75 | return false; 76 | } 77 | 78 | return $this; 79 | } 80 | 81 | /** 82 | * Check whether the address exists. 83 | * @return [type] [description] 84 | */ 85 | private function placeDoesntExist() 86 | { 87 | return $this->place['status'] == self::ZERO_RESULTS; 88 | } 89 | 90 | /** 91 | * Retrieve the place information. 92 | * @return collection 93 | */ 94 | public function retrieve() 95 | { 96 | $place = collect($this->place['results'])->collapse(); 97 | 98 | return $this->getAddressComponents($place)->merge( 99 | [ 100 | 'geometry' => $place->get('geometry'), 101 | 'place_id' => $place->get('place_id') 102 | ] 103 | ); 104 | } 105 | 106 | /** 107 | * Builds the address components collection. 108 | * @param Collection $place 109 | * @return Collection 110 | */ 111 | private function getAddressComponents($place) 112 | { 113 | $components = $place->get('address_components'); 114 | 115 | return collect($components)->map(function($item) 116 | { 117 | return [ 118 | $item["types"][0] => [ 119 | 'long_name' => $item['long_name'], 120 | 'short_name' => $item['short_name'] 121 | ] 122 | ]; 123 | })->collapse(); 124 | } 125 | 126 | /** 127 | * Retrieve the 'lat' and 'lng' for a given place. 128 | * @return array 129 | */ 130 | public function location() 131 | { 132 | return $this->retrieve()['geometry']['location']; 133 | } 134 | } -------------------------------------------------------------------------------- /src/ValidatorServiceProvider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Gocanto\AddressValidation; 12 | 13 | use Illuminate\Support\ServiceProvider; 14 | use Gocanto\AddressValidation\Lib\Checker; 15 | 16 | class ValidatorServiceProvider extends ServiceProvider 17 | { 18 | /* 19 | * Indicates if loading of the provider is deferred. 20 | * @var bool 21 | */ 22 | protected $defer = false; 23 | 24 | /** 25 | * Validation rule message 26 | * @var string 27 | */ 28 | protected $validPlaceMessage = 'The address given is not valid. Please try another!'; 29 | 30 | /** 31 | * Perform post-registration booting of services. 32 | * 33 | * @param Checker $place 34 | * @return void 35 | */ 36 | public function boot(Checker $place) 37 | { 38 | $this->populateSettings(); 39 | 40 | //We extend from the Validator object and add "valid_place", so you will be able 41 | //to use it as a rule within your validations. 42 | $this->app['validator']->extend('valid_place', function($attribute, $value, $parameters, $validator) use ($place) { 43 | 44 | //Evaluating validation for a given address. 45 | return $place->validate($value); 46 | 47 | }, $this->validPlaceMessage); 48 | } 49 | 50 | /** 51 | * publishes the setting files into the user app. 52 | * @return void 53 | */ 54 | protected function populateSettings() 55 | { 56 | $this->publishes([ 57 | __DIR__.'/Config/addressval.php' => config_path('addressval.php') 58 | ]); 59 | } 60 | 61 | /** 62 | * Register bindings in the container. 63 | * @return void 64 | */ 65 | public function register() 66 | { 67 | // 68 | } 69 | 70 | /** 71 | * Get the services provided by the provider. 72 | * @return array 73 | */ 74 | public function provides() 75 | { 76 | return ['address-validation']; 77 | } 78 | } --------------------------------------------------------------------------------