-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit of the google-address-lookup module
- Loading branch information
1 parent
ec3b3ee
commit d2f8abe
Showing
67 changed files
with
4,329 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
.project | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
/** | ||
* @package CtiDigital\GoogleAddressLookup | ||
* @author Bartosz Herba <[email protected]> | ||
* @copyright 2017 CtiDigital Sp. z o.o. | ||
*/ | ||
|
||
namespace CtiDigital\GoogleAddressLookup\Api; | ||
|
||
/** | ||
* Interface AutocompleteConfigResolverInterface | ||
*/ | ||
interface AutocompleteConfigResolverInterface | ||
{ | ||
/** | ||
* Configuration paths | ||
*/ | ||
const PATH_IS_ENABLED = 'ctidigital_sales/autocomplete/enable'; | ||
const PATH_API_KEY = 'ctidigital_sales/autocomplete/api_key'; | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function getIsEnabled(): bool; | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getApiKey(): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
<?php | ||
/** | ||
* @package CtiDigital\GoogleAddressLookup | ||
* @author Bartosz Herba <[email protected]> | ||
* @copyright 2017 CtiDigital Sp. z o.o. | ||
*/ | ||
|
||
namespace CtiDigital\GoogleAddressLookup\Block\Checkout; | ||
|
||
use CtiDigital\GoogleAddressLookup\Api\AutocompleteConfigResolverInterface; | ||
use Magento\Checkout\Block\Checkout\LayoutProcessorInterface; | ||
|
||
/** | ||
* Class LayoutProcessor | ||
*/ | ||
class LayoutProcessor implements LayoutProcessorInterface | ||
{ | ||
/** | ||
* @var AutocompleteConfigResolverInterface | ||
*/ | ||
protected $configResolver; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $paymentsList; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $addressFields = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $fieldsConfig; | ||
|
||
/** | ||
* LayoutProcessor constructor. | ||
* | ||
* @param AutocompleteConfigResolverInterface $configResolver | ||
* @param array $fieldsConfig | ||
*/ | ||
public function __construct(AutocompleteConfigResolverInterface $configResolver, $fieldsConfig = []) | ||
{ | ||
$this->configResolver = $configResolver; | ||
$this->fieldsConfig = $fieldsConfig; | ||
} | ||
|
||
/** | ||
* Process js Layout of block | ||
* | ||
* @param array $jsLayout | ||
* | ||
* @return array | ||
*/ | ||
public function process($jsLayout) | ||
{ | ||
if (false === $this->configResolver->getIsEnabled()) { | ||
return $jsLayout; | ||
} | ||
|
||
$this->addressFields = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']; | ||
$this->paymentsList = &$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['children']['payments-list']['children']; | ||
|
||
$this->processShippingAddress(); | ||
$this->processBillingAddress(); | ||
|
||
return $jsLayout; | ||
} | ||
|
||
/** | ||
* Processing shipping address layout | ||
* | ||
* @return void | ||
*/ | ||
protected function processShippingAddress() | ||
{ | ||
$this->updateStreetFields($this->addressFields['children']['street'], 'shippingAddress'); | ||
|
||
// region_id field is no longer required | ||
unset($this->addressFields['children']['region']['filterBy']); | ||
unset($this->addressFields['children']['region_id']); | ||
|
||
foreach ($this->fieldsConfig as $fieldName => $config) { | ||
$field = &$this->addressFields['children'][$fieldName]; | ||
$this->configureField($field, 'shippingAddress', $config); | ||
} | ||
} | ||
|
||
/** | ||
* Processing billing address layout | ||
* | ||
* @return void | ||
*/ | ||
protected function processBillingAddress() | ||
{ | ||
|
||
// Unlike in shipping address, on billing address there is a lot of different billing forms. | ||
// Each of these forms must be processed. | ||
foreach ($this->paymentsList as &$payment) { | ||
foreach ($this->fieldsConfig as $fieldName => $config) { | ||
if (!isset($payment['children']['form-fields'])) { | ||
continue; | ||
} | ||
|
||
if ('region' === $fieldName) { | ||
$payment = $this->copyRegionLayoutFromShippingAddress($payment, $fieldName); | ||
} | ||
|
||
$field = &$payment['children']['form-fields']['children'][$fieldName]; | ||
$this->configureField($field, 'billingAddress', $config); | ||
|
||
if ('street' === $fieldName) { | ||
$this->updateStreetFields($field, 'billingAddress'); | ||
} | ||
} | ||
unset($payment['children']['form-fields']['children']['region_id']); | ||
} | ||
} | ||
|
||
/** | ||
* @param array $streetField | ||
* @param string $scope | ||
* | ||
* @return void | ||
*/ | ||
protected function updateStreetFields(array &$streetField, string $scope) | ||
{ | ||
foreach ($streetField['children'] as &$input) { | ||
$input['component'] = 'CtiDigital_GoogleAddressLookup/js/form/element/input'; | ||
$input['autocomplete_id'] = $scope; | ||
} | ||
|
||
/** | ||
* There is a bug in Magento with inconsistency in validation of streets | ||
* in address modal and first address form. | ||
* In address form all street fields[$i > 0] are required but on modal only the first one. | ||
* This solution fix this gap. | ||
*/ | ||
$streetCount = count($streetField['children']); | ||
|
||
for ($i = 1; $i <= $streetCount; $i++) { | ||
$streetField['children'][$i]['validation']['min_text_length'] = 0; | ||
} | ||
} | ||
|
||
/** | ||
* @param mixed $field | ||
* @param string $scope | ||
* @param array $config | ||
* | ||
* @return $this | ||
*/ | ||
protected function configureField(&$field, string $scope, array $config = []) | ||
{ | ||
$field = is_array($field) ? $field : []; | ||
$field = array_merge($field, $config); | ||
$field['autocomplete_id'] = $scope; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* @param array $payment | ||
* @param string$fieldName | ||
* | ||
* @return array | ||
*/ | ||
protected function copyRegionLayoutFromShippingAddress(array $payment, string $fieldName): array | ||
{ | ||
$region = $this->addressFields['children']['region']; | ||
$payment['children']['form-fields']['children'][$fieldName] = $region; | ||
|
||
return $payment; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
/** | ||
* @package CtiDigital\GoogleAddressLookup | ||
* @author Bartosz Herba <[email protected]> | ||
* @copyright 2017 CtiDigital Sp. z o.o. | ||
*/ | ||
|
||
namespace CtiDigital\GoogleAddressLookup\Block\Js; | ||
|
||
use CtiDigital\GoogleAddressLookup\Api\AutocompleteConfigResolverInterface; | ||
use Magento\Framework\View\Element\Template; | ||
|
||
/** | ||
* Class GoogleApi | ||
*/ | ||
class GoogleApi extends Template | ||
{ | ||
/** | ||
* @var array | ||
*/ | ||
private $fieldsMap; | ||
|
||
/** | ||
* @var AutocompleteConfigResolverInterface | ||
*/ | ||
private $configResolver; | ||
|
||
/** | ||
* GoogleApi constructor. | ||
* | ||
* @param Template\Context $context | ||
* @param AutocompleteConfigResolverInterface $configResolver | ||
* @param array $fieldsMap | ||
* @param array $data | ||
*/ | ||
public function __construct( | ||
Template\Context $context, | ||
AutocompleteConfigResolverInterface $configResolver, | ||
$fieldsMap = [], | ||
array $data = [] | ||
) { | ||
parent::__construct($context, $data); | ||
|
||
$this->fieldsMap = $fieldsMap; | ||
$this->configResolver = $configResolver; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function getFieldsMap() | ||
{ | ||
return $this->fieldsMap; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getApiKey() | ||
{ | ||
return $this->configResolver->getApiKey(); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function isEnabled() | ||
{ | ||
return $this->configResolver->getIsEnabled(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,41 @@ | ||
# magento2-google-address-lookup | ||
Provides an address lookup service on a Magento 2 store powered by the Google Places API | ||
## Google Address Lookup for Magento 2 | ||
The Google Address Lookup module makes use of the Google Places API Web Service to provide the following functionality to your Magento 2 store. | ||
|
||
1. Minimise address input errors by providing a post-code lookup service. | ||
2. Reduce the number of visible input fields on the checkout by hiding city, state, street 1, street 2 and post-code fields. | ||
3. Provide a manual address input override which will display the hidden fields. | ||
|
||
**Note**: The Google Places API offers 150,000 FREE daily lookup requests for users that validate their account and add billing information. If you require more than 150,000 lookup requests daily then you can register to a paid plan. [See Usage Tiers & Pricing](https://developers.google.com/places/web-service/usage#verify_your_identity_by_enabling_billing) | ||
|
||
## Configuration | ||
After installing the module you will need to enable the module and generate a Key for the Google Places API Web Service in the [Google Console](https://console.developers.google.com) (see further reading). | ||
|
||
##### Enabling the Module: | ||
Store->Configuration->CtiDigital->Google Autocomplete | ||
|
||
| Config Value | Notes | | ||
| ------------- |-------------| | ||
| Enable/Disable| if module is enabled then checkout configuration will be overridden and Google API is attached | | ||
| API Key | Enter your Google Places API Web Service key (see further reading) | | ||
|
||
##### Address Lookup | ||
Once enabled, the post-code lookup service will be used on: | ||
|
||
* Guest Checkout | ||
* Registered Customer Checkout (if they are adding a new address) | ||
* My Account Address Management | ||
|
||
## Further Reading | ||
[Google Places API](https://developers.google.com/maps/documentation/javascript/places-autocomplete#address_forms) | ||
[Google Places API Examples](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform) | ||
|
||
## Implementation Details | ||
* Configuration of checkout fields is in etc/frontend/di.xml This configuration is processed in CtiDigital/GoogleAddressLookup/Block/Checkout/LayoutProcessor.php | ||
* Google Address fields are mapped in etc/frontend/di.xml and processed in CtiDigital/GoogleAddressLookup/Block/Js/GoogleApi.php. It will allow for easy third-party customizations like adding custom fields that should be also autocompleted. | ||
* Javascript modules are written in es6 and compiled with gulp using babel. Src and dist files are in CtiDigital/GoogleAddressLookup/view | ||
|
||
## Screenshots | ||
![Configuration](./README/system-configuration.png) | ||
![Configuration](./README/guest-checkout.png) | ||
![Configuration](./README/non-guest-checkout.png) | ||
![Configuration](./README/account-management.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
/** | ||
* @package CtiDigital\GoogleAddressLookup | ||
* @author Bartosz Herba <[email protected]> | ||
*/ | ||
|
||
namespace CtiDigital\GoogleAddressLookup\System; | ||
|
||
use CtiDigital\GoogleAddressLookup\Api\AutocompleteConfigResolverInterface; | ||
use Magento\Framework\App\Config\ScopeConfigInterface; | ||
|
||
/** | ||
* Class ConfigResolver | ||
*/ | ||
class AutocompleteConfigResolver implements AutocompleteConfigResolverInterface | ||
{ | ||
/** | ||
* @var ScopeConfigInterface | ||
*/ | ||
private $scopeConfig; | ||
|
||
/** | ||
* ConfigResolver constructor. | ||
* | ||
* @param ScopeConfigInterface $scopeConfig | ||
*/ | ||
public function __construct(ScopeConfigInterface $scopeConfig) | ||
{ | ||
$this->scopeConfig = $scopeConfig; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function getIsEnabled(): bool | ||
{ | ||
return $this->scopeConfig->getValue(self::PATH_IS_ENABLED); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getApiKey(): string | ||
{ | ||
return $this->scopeConfig->getValue(self::PATH_API_KEY); | ||
} | ||
} |
Oops, something went wrong.