├── CHANGELOG.md
├── i18n
├── de_DE.csv
├── en_GB.csv
├── en_US.csv
└── fr_FR.csv
├── registration.php
├── etc
├── adminhtml
│ ├── events.xml
│ ├── routes.xml
│ └── system.xml
├── module.xml
├── di.xml
├── routes.xml
├── config.xml
├── acl.xml
└── fieldset.xml
├── view
├── frontend
│ ├── requirejs-config.js
│ ├── layout
│ │ ├── customer_account_edit.xml
│ │ ├── customer_account_forgotpassword.xml
│ │ ├── customer_account_create.xml
│ │ └── customer_account_login.xml
│ ├── templates
│ │ ├── widget
│ │ │ └── username.phtml
│ │ └── form
│ │ │ ├── forgotpassword.phtml
│ │ │ ├── login.phtml
│ │ │ ├── edit.phtml
│ │ │ └── register.phtml
│ └── web
│ │ ├── template
│ │ ├── form
│ │ │ └── element
│ │ │ │ └── email.html
│ │ └── authentication.html
│ │ └── js
│ │ └── view
│ │ └── form
│ │ └── element
│ │ └── email.js
└── adminhtml
│ └── templates
│ └── config
│ └── generate.phtml
├── composer.json
├── Model
├── Config
│ ├── Source
│ │ └── Inputvalidation.php
│ └── Share.php
├── Generate
│ └── Flag.php
└── Event
│ ├── AddToCollection.php
│ └── ChangeEavAttribute.php
├── Controller
├── Adminhtml
│ ├── Sync.php
│ └── Sync
│ │ ├── Status.php
│ │ └── Generate.php
└── Account
│ └── ForgotPasswordPost.php
├── Setup
├── Uninstall.php
├── InstallData.php
├── UpgradeData.php
└── InstallSchema.php
├── phpunit.xml.dist
├── README.md
├── Block
├── Config
│ └── Form
│ │ └── Field
│ │ └── Generate.php
└── Widget
│ └── Username.php
├── Test
└── Helper
│ └── CustomerTest.php
├── Helper
└── Customer.php
├── Plugin
└── Model
│ └── ResourceModel
│ └── CustomerRepositoryPlugin.php
└── LICENSE.txt
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### Changelog
2 |
--------------------------------------------------------------------------------
/i18n/de_DE.csv:
--------------------------------------------------------------------------------
1 | "This account is disabled.","Dieses Benutzerkonto ist deaktiviert."
2 | "Username","Benutzername"
3 | "Email Address/Username","E-Mail-Adresse/Benutzername"
4 | "Email/Username:","E-Mail-Adresse/Benutzername:"
--------------------------------------------------------------------------------
/i18n/en_GB.csv:
--------------------------------------------------------------------------------
1 | "This account is disabled.","This account is disabled."
2 | "Username","Username"
3 | "Email Address/Username", "Email Address/Username"
4 | "'Email/Username:'","'Email/Username:'"
5 | "Username already exists","Username already exists"
--------------------------------------------------------------------------------
/i18n/en_US.csv:
--------------------------------------------------------------------------------
1 | "This account is disabled.","This account is disabled."
2 | "Username","Username"
3 | "Email Address/Username", "Email Address/Username"
4 | "'Email/Username:'","'Email/Username:'"
5 | "Username already exists","Username already exists"
6 | "Change Email & Username"
--------------------------------------------------------------------------------
/i18n/fr_FR.csv:
--------------------------------------------------------------------------------
1 | "This account is disabled.","Ce compte est désactivé"
2 | "Username","Nom d'utilisateur"
3 | "Email Address/Username", "Adresse email / Nom d'utilisateur"
4 | "'Email/Username:'","'Adresse Email / Nom d\utilisateur:'"
5 | "Username already exists","Ce nom d'utilisateur existe déjà"
--------------------------------------------------------------------------------
/registration.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/view/frontend/requirejs-config.js:
--------------------------------------------------------------------------------
1 | var config = {
2 | map: {
3 | '*': {
4 | 'Magento_Checkout/template/authentication.html':
5 | 'Diglin_Username/template/authentication.html'
6 | //'Magento_Checkout/form/element/email':
7 | // 'Diglin_Username/form/element/email',
8 | //'Magento_Checkout/form/element/email.html':
9 | // 'Diglin_Username/form/element/email.html'
10 | }
11 | }
12 | };
--------------------------------------------------------------------------------
/etc/adminhtml/routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/etc/routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/etc/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 | 1
13 | 0
14 | 30
15 | 6
16 | default
17 | 1
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/view/frontend/layout/customer_account_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | Diglin_Username::form/edit.phtml
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/view/frontend/layout/customer_account_forgotpassword.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | Diglin_Username::form/forgotpassword.phtml
16 |
17 |
18 |
--------------------------------------------------------------------------------
/etc/acl.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "diglin/module-username",
3 | "description": "Real Username support for Magento 2",
4 | "require": {
5 | "php": "~5.5.0|~5.6.0|~7.0.0|~7.1.0",
6 | "magento/framework": "100.0.*|100.1.*",
7 | "magento/module-backend": "100.0.*|100.1.*",
8 | "magento/module-checkout": "100.0.*|100.1.*",
9 | "magento/module-config": "100.0.*|100.1.*",
10 | "magento/module-customer": "100.0.*|100.1.*",
11 | "magento/module-eav": "100.0.*|100.1.*",
12 | "magento/module-quote": "100.0.*|100.1.*",
13 | "magento/module-sales": "100.0.*|100.1.*",
14 | "magento/module-store": "100.0.*|100.1.*",
15 | "magento/module-theme": "100.0.*|100.1.*",
16 |
17 | "hoa/regex": "~1.0"
18 | },
19 | "type": "magento2-module",
20 | "version": "2.0.0-beta",
21 | "license": [
22 | "OSL-3.0",
23 | "AFL-3.0"
24 | ],
25 | "autoload": {
26 | "files": [
27 | "registration.php"
28 | ],
29 | "psr-4": {
30 | "Diglin\\Username\\": ""
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Model/Config/Source/Inputvalidation.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_Username
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Model\Config\Source;
12 |
13 | class Inputvalidation implements \Magento\Framework\Option\ArrayInterface
14 | {
15 | /**
16 | * Options getter
17 | *
18 | * @deprecated
19 | * @return array
20 | */
21 | public function toOptionArray()
22 | {
23 | return [
24 | ['value'=>'default', 'label'=> __('Default (letters, digits and _- characters)')],
25 | ['value'=>'alphanumeric', 'label'=> __('Letters and digits')],
26 | ['value'=>'alpha', 'label'=> __('Letters only')],
27 | ['value'=>'numeric', 'label'=> __('Digits only')],
28 | ['value'=>'custom', 'label'=> __('Custom (PCRE Regex)')]
29 | ];
30 | }
31 | }
--------------------------------------------------------------------------------
/view/frontend/layout/customer_account_create.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | Diglin_Username::form/register.phtml
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/view/frontend/layout/customer_account_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | Diglin_Username::form/login.phtml
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Model/Generate/Flag.php:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2008-2015 Diglin GmbH - Switzerland (http://www.diglin.com)
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10 | */
11 |
12 | namespace Diglin\Username\Model\Generate;
13 |
14 | /**
15 | * Class Flag
16 | * @package Diglin\Username\Model\Generate
17 | */
18 | class Flag extends \Magento\Framework\Flag
19 | {
20 | /**
21 | * There was no generation
22 | */
23 | const STATE_INACTIVE = 0;
24 | /**
25 | * Generation process is active
26 | */
27 | const STATE_RUNNING = 1;
28 | /**
29 | * Generation is finished
30 | */
31 | const STATE_FINISHED = 2;
32 | /**
33 | * Generation finished and notify message was formed
34 | */
35 | const STATE_NOTIFIED = 3;
36 |
37 | /**
38 | * Generation flag code
39 | *
40 | * @var string
41 | */
42 | protected $_flagCode = 'username_generate';
43 | }
44 |
--------------------------------------------------------------------------------
/etc/fieldset.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
14 |
15 |
22 |
27 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Sync.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Controller\Adminhtml;
12 |
13 | abstract class Sync extends \Magento\Backend\App\Action
14 | {
15 | /**
16 | * Authorization level of a basic admin session
17 | */
18 | const ADMIN_USERNAME_RESOURCE = 'Diglin_Username::config_username';
19 |
20 | /**
21 | * Return file storage singleton
22 | *
23 | * @return \Diglin\Username\Model\Generate\Flag
24 | */
25 | protected function _getSyncSingleton()
26 | {
27 | return $this->_objectManager->get('Diglin\Username\Model\Generate\Flag');
28 | }
29 |
30 | /**
31 | * Return synchronize process status flag
32 | *
33 | * @return \Diglin\Username\Model\Generate\Flag
34 | */
35 | protected function _getSyncFlag()
36 | {
37 | return $this->_getSyncSingleton()->loadSelf();
38 | }
39 |
40 | /**
41 | * @return bool
42 | */
43 | protected function _isAllowed()
44 | {
45 | return $this->_authorization->isAllowed(static::ADMIN_USERNAME_RESOURCE);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Setup/Uninstall.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_Username
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Setup;
12 |
13 | use Magento\Customer\Model\Customer;
14 | use Magento\Framework\Setup\ModuleContextInterface;
15 | use Magento\Framework\Setup\SchemaSetupInterface;
16 | use Magento\Eav\Setup\EavSetup;
17 |
18 | /**
19 | * Class Uninstall
20 | */
21 | class Uninstall implements \Magento\Framework\Setup\UninstallInterface
22 | {
23 | /**
24 | * @var EavSetup
25 | */
26 | private $eavSetup;
27 |
28 | /**
29 | * InstallSchema constructor.
30 | */
31 | public function __construct(
32 | EavSetup $eavSetup
33 | ){
34 | $this->eavSetup = $eavSetup;
35 | }
36 |
37 | /**
38 | * @param SchemaSetupInterface $setup
39 | * @param ModuleContextInterface $context
40 | */
41 | public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context)
42 | {
43 | $setup->startSetup();
44 |
45 | $this->eavSetup->removeAttribute(Customer::ENTITY, 'username');
46 |
47 | $setup->getConnection()->dropColumn($setup->getTable('customer_grid_flat'), 'username');
48 | $setup->getConnection()->dropColumn($setup->getTable('quote'), 'customer_username');
49 | $setup->getConnection()->dropColumn($setup->getTable('sales_order'), 'customer_username');
50 |
51 | $setup->endSetup();
52 | }
53 | }
--------------------------------------------------------------------------------
/Model/Event/AddToCollection.php:
--------------------------------------------------------------------------------
1 | getEvent()->getCollection();
41 | $entity = $collection->getEntity();
42 | if (!empty($entity) && $entity->getType() == 'customer') {
43 | $collection->addAttributeToSelect('username');
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | tests/Framework
10 | tests/Extensions
11 | tests/Runner
12 | tests/Util
13 |
14 |
15 |
16 | tests/TextUI
17 | tests/Regression
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | src
31 |
32 | src/Framework/Assert/Functions.php
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/view/frontend/templates/widget/username.phtml:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | // @codingStandardsIgnoreFile
12 |
13 | /* @var $block Diglin\Username\Block\Widget\Username */
14 |
15 | $username = $block->getUsername();
16 | ?>
17 |
18 | isEditable() || !$block->isEditable() && !empty($username)): ?>
19 |
20 |
21 |
22 | isEditable()): ?>
23 | getFieldParams() ?> getAttributeValidationClass('username') == 'required-entry') echo ' data-validate="{required:true}"' ?>>
28 |
29 | escapeHtml($username); ?>
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Model/Config/Share.php:
--------------------------------------------------------------------------------
1 | getValue();
39 | if ($value == self::SHARE_GLOBAL) {
40 | if ($this->_customerResource->findUsernameDuplicates()) { // @todo - see how to implement the method findUsernameDuplicates with overwrite or similar (plugin)
41 | //@codingStandardsIgnoreStart
42 | throw new \Magento\Framework\Exception\LocalizedException(
43 | __('Cannot share customer accounts globally because some customer accounts with the same username exist on multiple websites and cannot be merged.')
44 | );
45 | }
46 | }
47 | return $this;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/view/frontend/templates/form/forgotpassword.phtml:
--------------------------------------------------------------------------------
1 | helper('\Diglin\Username\Helper\Customer')->isEnabled()) {
16 | $usernameLabel = __('Email/Username');
17 | $usernameInputType = 'text';
18 | $usernameInputValidation = "";
19 | }
20 |
21 | ?>
22 |
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Diglin\Username module for Magento 2 - BETA #
2 |
3 | Magento module which allows your customers to use a username and not only the email address as identifier
4 |
5 | **IMPORTANT**
6 | It's a BETA. Lots of things have not been yet implemented or is a work in progress. See the issues https://github.com/diglin/Diglin_Username2/issues/created_by/diglin. For example checkout account creation with username doesn't work.
7 |
8 | ## Features
9 |
10 | - Compatible and tested with Magento version 2.0 & 2.1
11 | - Login with a username or email, it can be done from frontend during checkout or to get access to the customer account
12 | - Save a username from frontend (register account or checkout process) or from backend by editing a customer account
13 | - Prevent duplicate username
14 | - The default templates override some customer and checkout views to adapt display for login pages, checkout process and account edition in frontend. If you have a customized template, update your template with the content of the one of this module.
15 | - Configurable options to define what kind of username to support: only letters, only digits, both or default (digits, letters and special characters '-_') or even custom regex
16 | - Configurable options to set the maximum and minimum string length
17 | - Display Username of each customer in the Customer Management Grid
18 | - Allow or not the customer to edit the username in My Account in frontend
19 | - Support username when a customer wants to retrieve his forgotten password thanks to the "Forgotten Password" form
20 | - Generate usernames for customer account who don't have one, can be triggered from configuration page. Generated usernames will use current saved configuration (letters, digits, both or custom regex).
21 |
22 | ## Installation
23 |
24 | ```
25 | cd path/to/my/magento/project
26 | composer.phar require 'diglin/module-username'
27 | bin/magento module:enable Diglin_Username
28 | bin/magento setup:upgrade
29 | bin/magento setup:di:compile
30 | ```
31 |
32 | ## Uninstall
33 |
34 | ```
35 | cd path/to/my/magento/project
36 | bin/magento module:uninstall -r Diglin_Username
37 | ```
38 |
39 | ## Author
40 |
41 | * Sylvain Rayé
42 | * http://www.diglin.com/
43 | * [@diglin_](https://twitter.com/diglin_)
44 | * [Follow me on github!](https://github.com/diglin)
45 |
--------------------------------------------------------------------------------
/Setup/InstallData.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Training\CustomerComment\Setup
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Setup;
12 |
13 | use Magento\Customer\Model\Customer;
14 | use Magento\Customer\Setup\CustomerSetup;
15 | use Magento\Framework\Setup\InstallDataInterface;
16 | use Magento\Framework\Setup\ModuleContextInterface;
17 | use Magento\Framework\Setup\ModuleDataSetupInterface;
18 | use Magento\Customer\Setup\CustomerSetupFactory;
19 |
20 | /**
21 | * @codeCoverageIgnore
22 | */
23 | class InstallData implements InstallDataInterface
24 | {
25 | /**
26 | * Customer setup factory
27 | *
28 | * @var CustomerSetupFactory
29 | */
30 | private $customerSetupFactory;
31 |
32 | /**
33 | * Init
34 | *
35 | * @param CustomerSetupFactory $customerSetupFactory
36 | */
37 | public function __construct(CustomerSetupFactory $customerSetupFactory)
38 | {
39 | $this->customerSetupFactory = $customerSetupFactory;
40 | }
41 |
42 | /**
43 | * {@inheritdoc}
44 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
45 | */
46 | public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
47 | {
48 | /** @var CustomerSetup $customerSetup */
49 | $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
50 |
51 | $setup->startSetup();
52 |
53 | $attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'username');
54 |
55 | $data = [];
56 | $usedInForms = [
57 | 'adminhtml_customer',
58 | 'adminhtml_checkout',
59 | 'customer_account_edit',
60 | 'customer_account_create',
61 | 'checkout_register'
62 | ];
63 |
64 | foreach ($usedInForms as $formCode) {
65 | $data[] = ['form_code' => $formCode, 'attribute_id' => $attribute->getId()];
66 | }
67 |
68 | if ($data) {
69 | $setup->getConnection()
70 | ->insertMultiple($setup->getTable('customer_form_attribute'), $data);
71 | }
72 |
73 | $setup->endSetup();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Setup/UpgradeData.php:
--------------------------------------------------------------------------------
1 | fieldDataConverterFactory = $fieldDataConverterFactory;
33 | }
34 |
35 | /**
36 | * {@inheritdoc}
37 | */
38 | public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
39 | {
40 | if (version_compare($context->getVersion(), "2.0.1", '<')) {
41 | $this->convertSerializedDataToJson($setup);
42 | }
43 | }
44 |
45 | /**
46 | * Convert data for the customer_eav_attribute.username from serialized to JSON format
47 | *
48 | * @param ModuleDataSetupInterface $setup
49 | *
50 | * @return void
51 | */
52 | protected function convertSerializedDataToJson(ModuleDataSetupInterface $setup)
53 | {
54 | $tableName = 'customer_eav_attribute';
55 | $identifierFieldName = 'attribute_id';
56 | $serializedFieldName = 'validate_rules';
57 |
58 | /** @var \Magento\Framework\DB\FieldDataConverter $fieldDataConverter */
59 | $fieldDataConverter = $this->fieldDataConverterFactory->create(SerializedToJson::class);
60 | try {
61 |
62 | $fieldDataConverter->convert(
63 | $setup->getConnection(),
64 | $setup->getTable($tableName),
65 | $identifierFieldName,
66 | $serializedFieldName
67 | );
68 | } catch (\Magento\Framework\DB\FieldDataConversionException $e) {
69 | //TODO add exception handler
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/Block/Config/Form/Field/Generate.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_Username
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Block\Config\Form\Field;
12 |
13 | use Magento\Config\Block\System\Config\Form\Field;
14 |
15 | /**
16 | * Class Generate
17 | * @package Diglin\Username\Block\Config\Form\Field
18 | */
19 | class Generate extends Field
20 | {
21 | /**
22 | * @var string
23 | */
24 | protected $_template = 'Diglin_Username::config/generate.phtml';
25 |
26 | /**
27 | * Remove scope label
28 | *
29 | * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
30 | * @return string
31 | */
32 | public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element)
33 | {
34 | $element
35 | ->unsScope()
36 | ->unsCanUseWebsiteValue()
37 | ->unsCanUseDefaultValue();
38 |
39 | return parent::render($element);
40 | }
41 |
42 | /**
43 | * Return element html
44 | *
45 | * @param \Magento\Framework\Data\Form\Element\AbstractElement $element
46 | * @return string
47 | *
48 | * @SuppressWarnings(PHPMD.UnusedFormalParameter)
49 | */
50 | protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element)
51 | {
52 | return $this->_toHtml();
53 | }
54 |
55 | /**
56 | * Return ajax url for synchronize button
57 | *
58 | * @return string
59 | */
60 | public function getAjaxSyncUrl()
61 | {
62 | return $this->getUrl('username/sync/generate');
63 | }
64 |
65 | /**
66 | * Return ajax url for synchronize button
67 | *
68 | * @return string
69 | */
70 | public function getAjaxStatusUpdateUrl()
71 | {
72 | return $this->getUrl('username/sync/status');
73 | }
74 |
75 | /**
76 | * Generate generate button html
77 | *
78 | * @return string
79 | */
80 | public function getButtonHtml()
81 | {
82 | /* @var $button \Magento\Backend\Block\Widget\Button */
83 | $button = $this
84 | ->getLayout()
85 | ->createBlock('Magento\Backend\Block\Widget\Button')
86 | ->setData(array(
87 | 'id' => 'generate_button',
88 | 'label' => __('Generate'),
89 | ));
90 |
91 | return $button->toHtml();
92 | }
93 | }
--------------------------------------------------------------------------------
/Controller/Adminhtml/Sync/Status.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Controller\Adminhtml\Sync;
12 |
13 |
14 | use Diglin\Username\Controller\Adminhtml\Sync;
15 | use Diglin\Username\Model\Generate\Flag;
16 | use Magento\Backend\App\Action\Context;
17 | use Magento\Framework\Json\Helper\Data;
18 |
19 | /**
20 | * Class Status
21 | * @package Diglin\Username\Controller\Adminhtml\Username\Sync
22 | */
23 | class Status extends Sync
24 | {
25 | /**
26 | * @var Data
27 | */
28 | private $jsonHelper;
29 |
30 | /**
31 | * Status constructor.
32 | */
33 | public function __construct(
34 | Context $context,
35 | Data $jsonHelper
36 | ) {
37 | $this->jsonHelper = $jsonHelper;
38 | parent::__construct($context);
39 | }
40 |
41 | public function execute()
42 | {
43 | $flag = $this->_getSyncFlag();
44 | if ($flag) {
45 | $state = $flag->getState();
46 | $flagData = $flag->getFlagData();
47 |
48 | switch ($state) {
49 | case Flag::STATE_RUNNING:
50 | if ($flagData['total_items'] > 0) {
51 | $percent = (int)($flagData['total_items_done'] * 100 / $flagData['total_items']) . '%';
52 | $result['message'] = __('Generating username: %s done.', $percent);
53 | } else {
54 | $result ['message'] = __('Generating...');
55 | }
56 | break;
57 | case Flag::STATE_FINISHED:
58 | $result ['message'] = __('Generation finished');
59 |
60 | if ($flag->getHasErrors()) {
61 | $result ['message'] .= __('Errors occurred while running. Please, check the log if enabled.');
62 | $result ['has_errors'] = true;
63 | }
64 | $state = Flag::STATE_NOTIFIED;
65 | break;
66 | case Flag::STATE_NOTIFIED:
67 | break;
68 | default:
69 | $state = Flag::STATE_INACTIVE;
70 | break;
71 | }
72 | } else {
73 | $state = Flag::STATE_INACTIVE;
74 | }
75 | $result['state'] = $state;
76 |
77 | $this->getResponse()->setBody($this->jsonHelper->jsonEncode($result));
78 | }
79 | }
--------------------------------------------------------------------------------
/Controller/Account/ForgotPasswordPost.php:
--------------------------------------------------------------------------------
1 | resultRedirectFactory->create();
26 | $email = (string)$this->getRequest()->getPost('email');
27 | if ($email) {
28 |
29 | // Diglin - Commented as not needed
30 | // if (!\Zend_Validate::is($email, 'EmailAddress')) {
31 | // $this->session->setForgottenEmail($email);
32 | // $this->messageManager->addErrorMessage(__('Please correct the email address.'));
33 | // return $resultRedirect->setPath('*/*/forgotpassword');
34 | // }
35 |
36 | try {
37 | $this->customerAccountManagement->initiatePasswordReset(
38 | $email,
39 | AccountManagement::EMAIL_RESET
40 | );
41 | } catch (NoSuchEntityException $exception) {
42 | // Do nothing, we don't want anyone to use this action to determine which email accounts are registered.
43 | } catch (SecurityViolationException $exception) {
44 | $this->messageManager->addErrorMessage($exception->getMessage());
45 | return $resultRedirect->setPath('*/*/forgotpassword');
46 | } catch (\Exception $exception) {
47 | $this->messageManager->addExceptionMessage(
48 | $exception,
49 | __('We\'re unable to send the password reset email.')
50 | );
51 | return $resultRedirect->setPath('*/*/forgotpassword');
52 | }
53 | $this->messageManager->addSuccessMessage($this->getSuccessMessage($email));
54 | return $resultRedirect->setPath('*/*/');
55 | } else {
56 | $this->messageManager->addErrorMessage(__('Please enter your email.'));
57 | return $resultRedirect->setPath('*/*/forgotpassword');
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/view/frontend/web/template/form/element/email.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
69 |
70 |
--------------------------------------------------------------------------------
/Model/Event/ChangeEavAttribute.php:
--------------------------------------------------------------------------------
1 | config = $config;
45 | $this->attributeFactory = $attributeFactory;
46 | }
47 |
48 | /**
49 | * Change the attribute of username after the configuration
50 | * has been changed
51 | *
52 | * Event: admin_system_config_changed_section_username
53 | *
54 | * @param \Magento\Framework\Event\Observer $observer Observer
55 | * @throws \Exception
56 | */
57 | public function execute(\Magento\Framework\Event\Observer $observer)
58 | {
59 | $minLength = $this->config->getValue('username/general/min_length');
60 | $maxLength = $this->config->getValue('username/general/max_length');
61 | $inputValidation = $this->config->getValue('username/general/input_validation');
62 |
63 | if ($minLength > $maxLength) {
64 | throw new \Exception (
65 | __('Sorry but you cannot set a minimum length value %s bigger than the maximum length value %s. Please, change the values.',
66 | $minLength,
67 | $maxLength)
68 | );
69 | }
70 |
71 | /* @var $attributeUsernameModel \Magento\Customer\Model\Attribute */
72 | $attributeUsernameModel = $this->attributeFactory->create();
73 | $attributeUsernameModel->loadByCode('customer', 'username');
74 |
75 | if ($attributeUsernameModel->getId()) {
76 | $rules = $attributeUsernameModel->getValidateRules();
77 | $rules['max_text_length'] = $maxLength;
78 | $rules['min_text_length'] = $minLength;
79 |
80 | if ($inputValidation != 'default' && $inputValidation != 'custom') {
81 | $rules['input_validation'] = $inputValidation;
82 | } else {
83 | $rules['input_validation'] = ''; // validation is done at save level of the customer model
84 | }
85 |
86 | $usedInGrid = $this->config->getValue('username/general/grid');
87 | $attributeUsernameModel->setData('is_used_in_grid', $usedInGrid);
88 |
89 | $attributeUsernameModel->setValidateRules($rules);
90 | $attributeUsernameModel->save();
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/view/frontend/templates/form/login.phtml:
--------------------------------------------------------------------------------
1 |
11 | helper('\Diglin\Username\Helper\Customer')->isEnabled()) {
24 | $usernameLabel = __('Email/Username');
25 | $usernameInputType = 'text';
26 | $usernameInputValidation = "";
27 | }
28 |
29 | ?>
30 |
64 |
--------------------------------------------------------------------------------
/Test/Helper/CustomerTest.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Test\Helper;
12 |
13 | /**
14 | * Class CustomerTest
15 | * @package Diglin\Username\Test\Helper
16 | */
17 | class CustomerTest extends \PHPUnit_Framework_TestCase
18 | {
19 | /**
20 | * @var array
21 | */
22 | private static $flattenedFixture = [
23 | 'configData1' => [
24 | 'input_validation' => 'default',
25 | 'custom_validation' => '',
26 | 'min_length' => '6',
27 | 'max_length' => '30'
28 | ],
29 | 'configData2' => [
30 | 'input_validation' => 'default',
31 | 'custom_validation' => '',
32 | 'min_length' => '3',
33 | 'max_length' => '50'
34 | ],
35 | 'configData3' => [
36 | 'input_validation' => 'alpha',
37 | 'custom_validation' => '',
38 | 'min_length' => '6',
39 | 'max_length' => '30'
40 | ],
41 | 'configData4' => [
42 | 'input_validation' => 'numeric',
43 | 'custom_validation' => '',
44 | 'min_length' => '6',
45 | 'max_length' => '30'
46 | ],
47 | 'configData5' => [
48 | 'input_validation' => 'alphanumeric',
49 | 'custom_validation' => '',
50 | 'min_length' => '6',
51 | 'max_length' => '30'
52 | ],
53 | 'configData6' => [
54 | 'input_validation' => 'custom',
55 | 'custom_validation' => '^[\d]{4}\-[\d]{4}\-[\w]{4}$',
56 | 'min_length' => '6',
57 | 'max_length' => '30'
58 | ],
59 | ];
60 |
61 | public function testGenerateCustomer()
62 | {
63 | foreach (self::$flattenedFixture as $config) {
64 | $inputValidation = $config['input_validation'];
65 | $minLength = $config['min_length'];
66 | $maxLength = $config['max_length'];
67 | $customValidation = $config['custom_validation'];
68 |
69 | switch ($inputValidation) {
70 | case 'alpha': // letters
71 | $regex = '^[a-zA-Z]{%d,%d}$';
72 | break;
73 | case 'numeric': // digits
74 | $regex = '^[\d]{%d,%d}$';
75 | break;
76 | case 'alphanumeric': // letters & digits
77 | $regex = '^[\d\w]{%d,%d}$';
78 | break;
79 | case 'custom':
80 | $regex = $customValidation;
81 | break;
82 | case 'default': // letters, digits and _- characters
83 | default:
84 | $regex = '^[\w]{%d,%d}$';
85 | break;
86 | }
87 |
88 | $regex = sprintf($regex, $minLength, $maxLength);
89 |
90 | // 1. Read the grammar.
91 | $grammar = new \Hoa\File\Read('hoa://Library/Regex/Grammar.pp');
92 |
93 | // 2. Load the compiler.
94 | $compiler = \Hoa\Compiler\Llk\Llk::load($grammar);
95 |
96 | // 3. Lex, parse and produce the AST.
97 | $ast = $compiler->parse($regex);
98 |
99 | $generator = new \Hoa\Regex\Visitor\Isotropic(new \Hoa\Math\Sampler\Random());
100 | $username = $generator->visit($ast);
101 |
102 | echo sprintf('Username %s with the following regex has been tested %s', $username, $regex) . PHP_EOL;
103 |
104 | $this->assertRegExp('@'.$regex.'@', $username, 'Username does not comply to the regex ' . $regex);
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/view/adminhtml/templates/config/generate.phtml:
--------------------------------------------------------------------------------
1 |
8 | * @copyright Copyright (c) 2008-2015 Diglin GmbH - Switzerland (http://www.diglin.com)
9 | * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10 | */
11 | use Diglin\Username\Model\Generate\Flag;
12 |
13 | /* @var $block Diglin\Username\Block\Config\Form\Field\Generate.php */
14 | ?>
15 |
95 |
96 | getButtonHtml(); ?>
97 |
--------------------------------------------------------------------------------
/Setup/InstallSchema.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Training\CustomerComment\Setup
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Setup;
12 |
13 | use Magento\Customer\Model\Customer;
14 | use Magento\Eav\Model\Config;
15 | use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
16 | use Magento\Eav\Setup\EavSetup;
17 | use Magento\Framework\Setup\ModuleContextInterface;
18 | use Magento\Framework\Setup\SchemaSetupInterface;
19 | use Magento\Framework\Setup\InstallSchemaInterface;
20 |
21 | /**
22 | * @codeCoverageIgnore
23 | */
24 | class InstallSchema implements InstallSchemaInterface
25 | {
26 | /**
27 | * @var Config
28 | */
29 | private $eavConfig;
30 | /**
31 | * @var AttributeSetFactory
32 | */
33 | private $attributeSet;
34 | /**
35 | * @var EavSetup
36 | */
37 | private $eavSetup;
38 |
39 | /**
40 | * InstallSchema constructor.
41 | */
42 | public function __construct(
43 | AttributeSetFactory $attributeSet,
44 | Config $eavConfig,
45 | EavSetup $eavSetup
46 | )
47 | {
48 | $this->attributeSet = $attributeSet;
49 | $this->eavConfig = $eavConfig;
50 | $this->eavSetup = $eavSetup;
51 | }
52 |
53 | /**
54 | * {@inheritdoc}
55 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
56 | */
57 | public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
58 | {
59 | $setup->startSetup();
60 |
61 | $entityType = $this->eavConfig->getEntityType(Customer::ENTITY);
62 | $attributeSet = $this->attributeSet->create();
63 | $groupId = $attributeSet->getDefaultGroupId($entityType->getDefaultAttributeSetId());
64 |
65 | $this->eavSetup->addAttribute(Customer::ENTITY, 'username',
66 | [
67 | 'label' => 'Username',
68 | 'input' => 'text',
69 | 'required' => 0,
70 | 'user_defined' => 1,
71 | 'unique' => 0,
72 | 'system' => 0,
73 | 'group' => $groupId,
74 | 'is_used_in_grid' => 1,
75 | 'is_visible_in_grid' => 1,
76 | 'is_filterable_in_grid' => 1,
77 | 'is_searchable_in_grid' => 1,
78 | 'validate_rules' => serialize([
79 | 'max_text_length' => 30,
80 | 'min_text_length' => 6
81 | ])
82 | ]
83 | );
84 |
85 | $setup->getConnection()
86 | ->addColumn(
87 | $setup->getTable('customer_grid_flat'),
88 | 'username',
89 | [
90 | 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
91 | 'default' => '',
92 | 'comment' => 'Customer Username'
93 | ]
94 | );
95 |
96 | $setup->getConnection()
97 | ->addColumn(
98 | $setup->getTable('quote'), 'customer_username',
99 | [
100 | 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
101 | 'length' => '255',
102 | 'nullable' => true,
103 | 'comment' => 'Customer Username',
104 | 'after' => 'customer_taxvat'
105 | ]
106 | );
107 |
108 | $setup->getConnection()
109 | ->addColumn(
110 | $setup->getTable('sales_order'), 'customer_username',
111 | [
112 | 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
113 | 'length' => '255',
114 | 'nullable' => true,
115 | 'comment' => 'Customer Username',
116 | 'after' => 'customer_taxvat'
117 | ]
118 | );
119 |
120 | $setup->endSetup();
121 | }
122 | }
--------------------------------------------------------------------------------
/Block/Widget/Username.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Block\Widget;
12 |
13 | use Diglin\Username\Helper\Customer;
14 | use Magento\Customer\Api\CustomerMetadataInterface;
15 | use Magento\Customer\Api\CustomerRepositoryInterface;
16 | use Magento\Customer\Api\Data\CustomerInterface;
17 | use Magento\Customer\Block\Widget\AbstractWidget;
18 |
19 | /**
20 | * Class Username
21 | *
22 | * @method CustomerInterface getObject()
23 | * @method Username setObject(CustomerInterface $customer)
24 | *
25 | * @package Diglin\Username\Block\Widget
26 | */
27 | class Username extends AbstractWidget
28 | {
29 | /**
30 | * @var \Magento\Customer\Model\Session
31 | */
32 | protected $_customerSession;
33 |
34 | /**
35 | * @var CustomerRepositoryInterface
36 | */
37 | protected $customerRepository;
38 | /**
39 | * @var Customer
40 | */
41 | private $usernameHelper;
42 |
43 |
44 | /**
45 | * Create an instance of the Username widget
46 | *
47 | * @param \Magento\Framework\View\Element\Template\Context $context
48 | * @param \Magento\Customer\Helper\Address $addressHelper
49 | * @param CustomerMetadataInterface $customerMetadata
50 | * @param CustomerRepositoryInterface $customerRepository
51 | * @param \Magento\Customer\Model\Session $customerSession
52 | * @param Customer $usernameHelper
53 | * @param array $data
54 | */
55 | public function __construct(
56 | \Magento\Framework\View\Element\Template\Context $context,
57 | \Magento\Customer\Helper\Address $addressHelper,
58 | CustomerMetadataInterface $customerMetadata,
59 | CustomerRepositoryInterface $customerRepository,
60 | \Magento\Customer\Model\Session $customerSession,
61 | Customer $usernameHelper,
62 | array $data = []
63 | ) {
64 | $this->_customerSession = $customerSession;
65 | $this->customerRepository = $customerRepository;
66 | parent::__construct($context, $addressHelper, $customerMetadata, $data);
67 | $this->_isScopePrivate = true;
68 | $this->usernameHelper = $usernameHelper;
69 | }
70 |
71 | /**
72 | * Initialize block
73 | *
74 | * @return void
75 | */
76 | public function _construct()
77 | {
78 | parent::_construct();
79 | $this->setTemplate('widget/username.phtml');
80 | }
81 |
82 | /**
83 | * Check if username attribute enabled in system
84 | * @return bool
85 | */
86 | public function isEnabled()
87 | {
88 | return $this->usernameHelper->isEnabled() && ($this->_getAttribute('username') ? (bool)$this->_getAttribute('username')->isVisible() : false);
89 | }
90 |
91 | /**
92 | * Check if username attribute marked as required
93 | * @return bool
94 | */
95 | public function isRequired()
96 | {
97 | return $this->_getAttribute('username') ? (bool)$this->_getAttribute('username')->isRequired() : false;
98 | }
99 |
100 | /**
101 | * Get current customer from session
102 | *
103 | * @return CustomerInterface
104 | */
105 | public function getCustomer()
106 | {
107 | return $this->customerRepository->getById($this->_customerSession->getCustomerId());
108 | }
109 |
110 | /**
111 | * @return bool
112 | */
113 | public function isEditable()
114 | {
115 | return $this->usernameHelper->isEditableOnFrontend() || $this->getData('is_editable');
116 | }
117 |
118 | /**
119 | * @return mixed
120 | */
121 | public function getUsername()
122 | {
123 | if (!$this->getData('username')) {
124 | if ($this->getObject()->getCustomAttribute('username') instanceof \Magento\Framework\Api\AttributeInterface) {
125 | $this->setData('username', $this->getObject()->getCustomAttribute('username')->getValue());
126 | }
127 | }
128 |
129 | return $this->getData('username');
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/view/frontend/web/template/authentication.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
14 |
28 |
29 |
30 |
31 |
33 |
34 |
38 |
39 |
40 |
41 |
42 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Sync/Generate.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Controller\Adminhtml\Sync;
12 |
13 | use Diglin\Username\Controller\Adminhtml\Sync;
14 | use Diglin\Username\Model\Generate\Flag;
15 | use Magento\Backend\App\Action\Context;
16 | use Magento\Framework\App\Config as AppConfig;
17 | use Magento\Eav\Model\Config;
18 | use Magento\Framework\App\ResourceConnection;
19 | use Magento\Framework\DB\LoggerInterface;
20 | use Diglin\Username\Helper\Customer as CustomerHelper;
21 |
22 | /**
23 | * Class Generate
24 | * @package Diglin\Username\Controller\Adminhtml\Username\Sync
25 | */
26 | class Generate extends Sync
27 | {
28 | /**
29 | * @var LoggerInterface
30 | */
31 | private $logger;
32 | /**
33 | * @var Config
34 | */
35 | private $eavConfig;
36 |
37 | /**
38 | * @var \Magento\Framework\DB\Adapter\AdapterInterface
39 | */
40 | private $connection;
41 |
42 | /**
43 | * @var ResourceConnection
44 | */
45 | private $resource;
46 |
47 | /**
48 | * @var AppConfig
49 | */
50 | private $config;
51 |
52 | /**
53 | * @var CustomerHelper
54 | */
55 | private $helper;
56 |
57 | public function __construct(
58 | Context $context,
59 | LoggerInterface $logger,
60 | Config $eavConfig,
61 | ResourceConnection $resource,
62 | AppConfig $config,
63 | CustomerHelper $helper
64 | )
65 | {
66 | parent::__construct($context);
67 |
68 | $this->logger = $logger;
69 | $this->eavConfig = $eavConfig;
70 | $this->config = $config;
71 | $this->resource = $resource;
72 | $this->connection = $resource->getConnection('core_read');
73 | $this->helper = $helper;
74 | }
75 |
76 | public function execute()
77 | {
78 | session_write_close();
79 |
80 | $flag = $this->_getSyncFlag();
81 | $flag
82 | ->setState(Flag::STATE_RUNNING)
83 | ->save();
84 |
85 | $flag->setFlagData(array());
86 |
87 | try {
88 | $usernameAttribute = $this->eavConfig->getAttribute('customer', 'username');
89 |
90 | /**
91 | * Get customer entity_ids having a username
92 | */
93 | $select = $this->connection
94 | ->select()
95 | ->from($this->resource->getTableName('customer_entity_varchar'), 'entity_id')
96 | ->where('attribute_id = ?', $usernameAttribute->getId())
97 | ->where('value IS NOT NULL');
98 |
99 | $ids = $this->connection->fetchCol($select);
100 |
101 | /**
102 | * Get additional data from customers who doesn't have a username
103 | */
104 | $select = $this->connection
105 | ->select()
106 | ->from(array('c' => $this->resource->getTableName('customer_entity')), array('email', 'entity_id'))
107 | ->group('c.entity_id');
108 |
109 | if (!empty($ids)) {
110 | $select->where('c.entity_id NOT IN (' . implode(',', $ids) . ')');
111 | }
112 |
113 | // @todo - add support for Customer Website Share option (check that the username doesn't already exist in other websites)
114 |
115 | // Create username for old customers to prevent problem when creating an order as a guest
116 | $customers = $this->connection->fetchAll($select);
117 | $totalItemsDone = 0;
118 |
119 | $flagData['total_items'] = count($customers);
120 |
121 | $flag
122 | ->setFlagData($flagData)
123 | ->save();
124 |
125 | foreach ($customers as $customer) {
126 |
127 | $customer['value'] = $this->helper->generateUsername();
128 | $customer['attribute_id'] = $usernameAttribute->getId();
129 |
130 | unset($customer['email']);
131 | unset($customer['value_id']);
132 |
133 | $this->connection->insert($this->connection->getTableName('customer_entity_varchar'), $customer);
134 |
135 | $flagData['total_items_done'] = $totalItemsDone;
136 | $flag
137 | ->setFlagData($flagData)
138 | ->save();
139 | }
140 |
141 | } catch (\Exception $e) {
142 | $this->logger->critical($e);
143 | $flag->setHasErrors(true);
144 | }
145 | $flag->setState(Flag::STATE_FINISHED)->save();
146 | }
147 | }
--------------------------------------------------------------------------------
/etc/adminhtml/system.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 | separator-top
16 |
17 | customer
18 | Diglin_Username::config_username
19 |
20 |
21 |
22 |
23 | Magento\Config\Model\Config\Source\Yesno
24 |
25 |
26 |
27 |
28 | Magento\Config\Model\Config\Source\Yesno
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Diglin\Username\Model\Config\Source\Inputvalidation
45 |
46 |
47 |
48 |
49 |
50 | /^[\w-]*$/. More info at PHP Manual]]>
51 |
52 | custom
53 |
54 |
55 |
56 |
57 |
58 | ]]>
59 |
60 | custom
61 |
62 |
63 |
64 |
65 |
66 | Magento\Config\Model\Config\Source\Yesno
67 |
68 |
69 |
70 |
71 |
72 |
73 | Diglin\Username\Block\Config\Form\Field\Generate
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/view/frontend/web/js/view/form/element/email.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright © 2016 Magento. All rights reserved.
3 | * See COPYING.txt for license details.
4 | */
5 | /*browser:true*/
6 | /*global define*/
7 | define([
8 | 'jquery',
9 | 'uiComponent',
10 | 'ko',
11 | 'Magento_Customer/js/model/customer',
12 | 'Magento_Customer/js/action/check-email-availability',
13 | 'Magento_Customer/js/action/login',
14 | 'Magento_Checkout/js/model/quote',
15 | 'Magento_Checkout/js/checkout-data',
16 | 'Magento_Checkout/js/model/full-screen-loader',
17 | 'mage/validation'
18 | ], function ($, Component, ko, customer, checkEmailAvailability, loginAction, quote, checkoutData, fullScreenLoader) {
19 | 'use strict';
20 |
21 | var validatedEmail = checkoutData.getValidatedEmailValue();
22 |
23 | if (validatedEmail && !customer.isLoggedIn()) {
24 | quote.guestEmail = validatedEmail;
25 | }
26 |
27 | return Component.extend({
28 | defaults: {
29 | template: 'Diglin_Username/form/element/email',
30 | email: checkoutData.getInputFieldEmailValue(),
31 | emailFocused: false,
32 | isLoading: false,
33 | isPasswordVisible: false,
34 | listens: {
35 | email: 'emailHasChanged',
36 | emailFocused: 'validateEmail'
37 | }
38 | },
39 | checkDelay: 2000,
40 | checkRequest: null,
41 | isEmailCheckComplete: null,
42 | isCustomerLoggedIn: customer.isLoggedIn,
43 | forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl,
44 | emailCheckTimeout: 0,
45 |
46 | /**
47 | * Initializes observable properties of instance
48 | *
49 | * @returns {Object} Chainable.
50 | */
51 | initObservable: function () {
52 | this._super()
53 | .observe(['email', 'emailFocused', 'isLoading', 'isPasswordVisible']);
54 |
55 | return this;
56 | },
57 |
58 | /**
59 | * Callback on changing email property
60 | */
61 | emailHasChanged: function () {
62 | var self = this;
63 |
64 | clearTimeout(this.emailCheckTimeout);
65 |
66 | if (self.validateEmail()) {
67 | quote.guestEmail = self.email();
68 | checkoutData.setValidatedEmailValue(self.email());
69 | }
70 | this.emailCheckTimeout = setTimeout(function () {
71 | if (self.validateEmail()) {
72 | self.checkEmailAvailability();
73 | } else {
74 | self.isPasswordVisible(false);
75 | }
76 | }, self.checkDelay);
77 |
78 | checkoutData.setInputFieldEmailValue(self.email());
79 | },
80 |
81 | /**
82 | * Check email existing.
83 | */
84 | checkEmailAvailability: function () {
85 | var self = this;
86 | this.validateRequest();
87 | this.isEmailCheckComplete = $.Deferred();
88 | this.isLoading(true);
89 | this.checkRequest = checkEmailAvailability(this.isEmailCheckComplete, this.email());
90 |
91 | $.when(this.isEmailCheckComplete).done(function () {
92 | self.isPasswordVisible(false);
93 | }).fail(function () {
94 | self.isPasswordVisible(true);
95 | }).always(function () {
96 | self.isLoading(false);
97 | });
98 | },
99 |
100 | /**
101 | * If request has been sent -> abort it.
102 | * ReadyStates for request aborting:
103 | * 1 - The request has been set up
104 | * 2 - The request has been sent
105 | * 3 - The request is in process
106 | */
107 | validateRequest: function () {
108 | if (this.checkRequest != null && $.inArray(this.checkRequest.readyState, [1, 2, 3])) {
109 | this.checkRequest.abort();
110 | this.checkRequest = null;
111 | }
112 | },
113 |
114 | /**
115 | * Local email validation.
116 | *
117 | * @param {Boolean} focused - input focus.
118 | * @returns {Boolean} - validation result.
119 | */
120 | validateEmail: function (focused) {
121 | var loginFormSelector = 'form[data-role=email-with-possible-login]',
122 | usernameSelector = loginFormSelector + ' input[name=username]',
123 | loginForm = $(loginFormSelector),
124 | validator;
125 |
126 | loginForm.validation();
127 |
128 | if (focused === false && !!this.email()) {
129 | return !!$(usernameSelector).valid();
130 | }
131 |
132 | validator = loginForm.validate();
133 |
134 | return validator.check(usernameSelector);
135 | },
136 |
137 | /**
138 | * Log in form submitting callback.
139 | *
140 | * @param {HTMLElement} loginForm - form element.
141 | */
142 | login: function (loginForm) {
143 | var loginData = {},
144 | formDataArray = $(loginForm).serializeArray();
145 |
146 | formDataArray.forEach(function (entry) {
147 | loginData[entry.name] = entry.value;
148 | });
149 |
150 | if (this.isPasswordVisible() && $(loginForm).validation() && $(loginForm).validation('isValid')) {
151 | fullScreenLoader.startLoader();
152 | loginAction(loginData).always(function() {
153 | fullScreenLoader.stopLoader();
154 | });
155 | }
156 | }
157 | });
158 | });
159 |
--------------------------------------------------------------------------------
/Helper/Customer.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Helper;
12 |
13 | use Magento\Framework\App\Config;
14 | use Magento\Customer\Model\ResourceModel\CustomerRepository;
15 | use Magento\Framework\Api\SearchCriteriaBuilder;
16 | use Magento\Framework\App\Helper\Context;
17 |
18 | /**
19 | * Class Customer
20 | * @package Diglin\Username\Helper
21 | */
22 | class Customer extends \Magento\Framework\App\Helper\AbstractHelper
23 | {
24 | const CFG_ENABLED = 'username/general/enabled';
25 | const CFG_FRONTEND = 'username/general/frontend';
26 | const CFG_INPUT_VALIDATION = 'username/general/input_validation';
27 | const CFG_CASE_SENSITIVE = 'username/general/case_sensitive';
28 | const CFG_INPUT_VALIDATION_CUSTOM = 'username/general/input_validation_custom';
29 | const CFG_INPUT_VALIDATION_CUSTOM_MESSAGE = 'username/general/input_validation_custom_message';
30 | const CFG_INPUT_MAXLENGTH = 'username/general/max_length';
31 | const CFG_INPUT_MINLENGTH = 'username/general/min_length';
32 |
33 | /**
34 | * @var CustomerRepository
35 | */
36 | private $customerRepository;
37 | /**
38 | * @var SearchCriteriaBuilder
39 | */
40 | private $searchCriteriaBuilder;
41 | /**
42 | * @var Config
43 | */
44 | private $config;
45 |
46 | /**
47 | * Customer constructor.
48 | * @param Context $context
49 | * @param CustomerRepository $customerRepository
50 | * @param SearchCriteriaBuilder $searchCriteriaBuilder
51 | */
52 | public function __construct(
53 | Context $context,
54 | CustomerRepository $customerRepository,
55 | SearchCriteriaBuilder $searchCriteriaBuilder,
56 | Config $config
57 | ){
58 | $this->customerRepository = $customerRepository;
59 |
60 | parent::__construct($context);
61 | $this->searchCriteriaBuilder = $searchCriteriaBuilder;
62 | $this->config = $config;
63 | }
64 |
65 | /**
66 | * @param $username
67 | * @param null $websiteId
68 | * @return bool|\Magento\Customer\Api\Data\CustomerInterface
69 | */
70 | public function customerUsernameExists($username, $websiteId = null)
71 | {
72 | return $this->loadByUsername($username, $websiteId);
73 | }
74 |
75 | /**
76 | * @param $username
77 | * @param null $websiteId
78 | * @return bool|\Magento\Customer\Api\Data\CustomerInterface
79 | */
80 | public function loadByUsername($username, $websiteId = null)
81 | {
82 | $this->searchCriteriaBuilder->addFilter('username', $username, 'like');
83 |
84 | if (!is_null($websiteId)) {
85 | $this->searchCriteriaBuilder->addFilter('website_id', $websiteId, 'eq');
86 | }
87 |
88 | $searchCriteria = $this->searchCriteriaBuilder->create();
89 | $list = $this->customerRepository->getList($searchCriteria);
90 |
91 | if ($list->getTotalCount() > 0) {
92 | foreach ($list->getItems() as $item) {
93 |
94 | if ($this->isCaseSensitive() && $username != $item->getCustomAttribute('username')->getValue()) {
95 | return false;
96 | }
97 |
98 | return $item;
99 | }
100 | }
101 |
102 | return false;
103 | }
104 |
105 | /**
106 | * Is Username editable on frontend
107 | *
108 | * @return bool
109 | */
110 | public function isEditableOnFrontend()
111 | {
112 | return $this->config->isSetFlag(self::CFG_FRONTEND);
113 | }
114 |
115 | /**
116 | * @return bool
117 | */
118 | public function isEnabled()
119 | {
120 | return $this->config->isSetFlag(self::CFG_ENABLED);
121 | }
122 |
123 | /**
124 | * @return bool
125 | */
126 | public function isCaseSensitive()
127 | {
128 | return $this->config->isSetFlag(self::CFG_CASE_SENSITIVE);
129 | }
130 |
131 | /**
132 | * @return mixed
133 | * @throws \Hoa\Compiler\Exception
134 | * @throws \Hoa\Compiler\Exception\UnexpectedToken
135 | * @throws \Hoa\Regex\Exception
136 | */
137 | public function generateUsername()
138 | {
139 | $inputValidation = $this->config->getValue(self::CFG_INPUT_VALIDATION);
140 | $customValidation = $this->config->getValue(self::CFG_INPUT_VALIDATION_CUSTOM);
141 | $maxLength = (int) $this->config->getValue(self::CFG_INPUT_MAXLENGTH);
142 | $minLength = (int) $this->config->getValue(self::CFG_INPUT_MINLENGTH);
143 |
144 | switch ($inputValidation) {
145 | case 'alpha': // letters
146 | $regex = '^[a-zA-Z]{%d,%d}$';
147 | break;
148 | case 'numeric': // digits
149 | $regex = '^[\d]{%d,%d}$';
150 | break;
151 | case 'alphanumeric': // letters & digits
152 | $regex = '^[\d\w]{%d,%d}$';
153 | break;
154 | case 'custom':
155 |
156 | // Remove potential delimiter for Hoa\Regex class
157 | $delimiter = substr($customValidation, 0, 1);
158 | $endDelimiter = -1;
159 | if ($delimiter != substr($customValidation, $endDelimiter)) {
160 | $endDelimiter = -2;
161 | }
162 |
163 | if ($delimiter == substr($customValidation, $endDelimiter)) {
164 | $regex = substr($customValidation, 1, $endDelimiter);
165 | } else {
166 | $regex = $customValidation;
167 | }
168 |
169 | break;
170 | case 'default': // letters, digits and _- characters
171 | default:
172 | $regex = '^[\w]{%d,%d}$';
173 | break;
174 | }
175 |
176 | $regex = sprintf($regex, $minLength, $maxLength);
177 |
178 | // 1. Read the grammar.
179 | $grammar = new \Hoa\File\Read('hoa://Library/Regex/Grammar.pp');
180 |
181 | // 2. Load the compiler.
182 | $compiler = \Hoa\Compiler\Llk\Llk::load($grammar);
183 |
184 | // 3. Lex, parse and produce the AST.
185 | $ast = $compiler->parse($regex);
186 |
187 | $generator = new \Hoa\Regex\Visitor\Isotropic(new \Hoa\Math\Sampler\Random());
188 | $username = $generator->visit($ast);
189 |
190 | if (!$this->isCaseSensitive()) {
191 | $username = strtolower($username);
192 | }
193 |
194 | if ($this->customerUsernameExists($username)) {
195 | $username = $this->generateUsername();
196 | }
197 |
198 | return $username;
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/view/frontend/templates/form/edit.phtml:
--------------------------------------------------------------------------------
1 |
11 |
93 |
123 |
134 |
--------------------------------------------------------------------------------
/Plugin/Model/ResourceModel/CustomerRepositoryPlugin.php:
--------------------------------------------------------------------------------
1 |
6 | * @category Diglin
7 | * @package Diglin_
8 | * @copyright Copyright (c) 2011-2016 Diglin (http://www.diglin.com)
9 | */
10 |
11 | namespace Diglin\Username\Plugin\Model\ResourceModel;
12 |
13 | use Diglin\Username\Helper\Customer as CustomerHelper;
14 | use Diglin\Username\Helper\Customer;
15 | use Magento\Checkout\Helper\Data;
16 | use Magento\Config\Model\Config\Backend\Admin\Custom;
17 | use Magento\Customer\Model\Metadata\CustomerMetadata;
18 | use Magento\Framework\Api\SearchCriteriaBuilder;
19 | use Magento\Framework\App\Config;
20 | use Magento\Framework\App\State;
21 | use Magento\Framework\Exception\InputException;
22 | use Magento\Framework\Exception\NoSuchEntityException;
23 | use Magento\Framework\ObjectManagerInterface;
24 |
25 | /**
26 | * Class CustomerRepositoryPlugin
27 | * @package Diglin\Username\Plugin\Model\ResourceModel
28 | */
29 | class CustomerRepositoryPlugin
30 | {
31 | /**
32 | * @var SearchCriteriaBuilder
33 | */
34 | private $searchCriteriaBuilder;
35 | /**
36 | * @var CustomerMetadata
37 | */
38 | private $customerMetadata;
39 | /**
40 | * @var Config
41 | */
42 | private $config;
43 | /**
44 | * @var State
45 | */
46 | private $state;
47 | /**
48 | * @var CustomerHelper
49 | */
50 | private $customerHelper;
51 | /**
52 | * @var Data
53 | */
54 | private $checkoutHelper;
55 | /**
56 | * @var ObjectManagerInterface
57 | */
58 | private $objectManager;
59 |
60 | /**
61 | * CustomerRepositoryPlugin constructor.
62 | * @param SearchCriteriaBuilder $searchCriteriaBuilder
63 | * @param CustomerMetadata $customerMetadata
64 | * @param Config $config
65 | * @param State $state
66 | * @param CustomerHelper $customerHelper
67 | * @param Data $checkoutHelper
68 | * @param ObjectManagerInterface $objectManager
69 | */
70 | public function __construct(
71 | SearchCriteriaBuilder $searchCriteriaBuilder,
72 | CustomerMetadata $customerMetadata,
73 | Config $config,
74 | State $state,
75 | CustomerHelper $customerHelper,
76 | Data $checkoutHelper,
77 | ObjectManagerInterface $objectManager
78 | )
79 | {
80 | $this->searchCriteriaBuilder = $searchCriteriaBuilder;
81 | $this->customerMetadata = $customerMetadata;
82 | $this->config = $config;
83 | $this->state = $state;
84 | $this->customerHelper = $customerHelper;
85 | $this->checkoutHelper = $checkoutHelper;
86 | $this->objectManager = $objectManager;
87 | }
88 |
89 | /**
90 | * @param \Magento\Customer\Model\ResourceModel\CustomerRepository $subject
91 | * @param $username
92 | * @param null $websiteId
93 | * @return array
94 | */
95 | public function beforeGet(\Magento\Customer\Model\ResourceModel\CustomerRepository $subject, $username, $websiteId = null)
96 | {
97 | if (strpos($username, '@') === false) {
98 | $customerFound = $this->customerHelper->loadByUsername($username, $websiteId);
99 | if ($customerFound) {
100 | $username = $customerFound->getEmail();
101 | }
102 | }
103 |
104 | return [$username, $websiteId];
105 | }
106 |
107 | /**
108 | * @param \Magento\Customer\Model\ResourceModel\CustomerRepository $subject
109 | * @param \Magento\Customer\Api\Data\CustomerInterface $customer
110 | * @param null $passwordHash
111 | * @return array
112 | * @throws InputException
113 | * @throws \Magento\Framework\Exception\LocalizedException
114 | */
115 | public function beforeSave(\Magento\Customer\Model\ResourceModel\CustomerRepository $subject, \Magento\Customer\Api\Data\CustomerInterface $customer, $passwordHash = null)
116 | {
117 | $exception = new InputException();
118 | $customerDataOriginal = $usernameOriginal = null;
119 |
120 | $usernameAttribute = $customer->getCustomAttribute('username');
121 |
122 | if (is_null($usernameAttribute)) {
123 | return [$customer, $passwordHash];
124 | }
125 |
126 | $username = $usernameAttribute->getValue();
127 |
128 | if ($customer->getId()) {
129 | $customerDataOriginal = $subject->getById($customer->getId());
130 | $originalUsernameAttribute = $customerDataOriginal->getCustomAttribute('username');
131 | if ($originalUsernameAttribute) {
132 | $usernameOriginal = $originalUsernameAttribute->getValue();
133 | }
134 | }
135 |
136 | if (!is_null($usernameOriginal) && $usernameOriginal != $username) {
137 |
138 | // @todo return true even in none checkout process which is not expected
139 | // $guestMethod = $this->checkoutHelper->isAllowedGuestCheckout($this->checkoutHelper->getQuote());
140 | $guestMethod = false;
141 |
142 | /**
143 | * Validate Username
144 | * - No duplicate must exist
145 | * - Must respect format of the username
146 | * - check if required or not
147 | * - Do not allow frontend edition if configuration is enabled
148 | * - Do not check for guest
149 | */
150 |
151 | if ($this->state->getAreaCode() == 'frontend' && !$this->customerHelper->isEditableOnFrontend()) {
152 | $exception->addError(__('Username cannot be edited on frontend.'));
153 | $customer->setCustomAttribute('username', $customerDataOriginal->getCustomAttribute('username')->getValue());
154 | } else if ($guestMethod != \Magento\Checkout\Model\Type\Onepage::METHOD_GUEST) {
155 | $this->validate($customer, $exception);
156 | }
157 | } else if (!$customer->getId()) {
158 | $this->validate($customer, $exception);
159 | }
160 |
161 | if ($exception->wasErrorAdded()) {
162 | throw $exception;
163 | }
164 |
165 | return [$customer, $passwordHash];
166 | }
167 |
168 | /**
169 | * Get attribute metadata.
170 | *
171 | * @param string $attributeCode
172 | * @return \Magento\Customer\Api\Data\AttributeMetadataInterface|null
173 | */
174 | private function getAttributeMetadata($attributeCode)
175 | {
176 | try {
177 | return $this->customerMetadata->getAttributeMetadata($attributeCode);
178 | } catch (NoSuchEntityException $e) {
179 | return null;
180 | }
181 | }
182 |
183 | /**
184 | * @param \Magento\Customer\Api\Data\CustomerInterface $customer
185 | * @param InputException $exception
186 | * @return $this
187 | * @throws InputException
188 | */
189 | private function validate(\Magento\Customer\Api\Data\CustomerInterface $customer, InputException $exception)
190 | {
191 | $username = $customer->getCustomAttribute('username')->getValue();
192 | $websiteId = ($customer->getWebsiteId()) ? $customer->getWebsiteId() : null;
193 |
194 | $usernameAttribute = $this->getAttributeMetadata('username');
195 | if ($usernameAttribute !== null && $usernameAttribute->isRequired() && '' == trim($username)) {
196 | throw InputException::requiredField('username');
197 | }
198 |
199 | // Other rules are validated by the parent class because they are basic rules provided by Magento Core
200 | $inputValidation = $this->config->getValue(CustomerHelper::CFG_INPUT_VALIDATION);
201 | $useInputValidation = ($inputValidation == 'default' || $inputValidation == 'custom') ? true : false;
202 |
203 | if ($useInputValidation) {
204 | $validate = '/^*$/';
205 | switch ($inputValidation) {
206 | case 'default':
207 | $validate = '/^[\w-]*$/';
208 | break;
209 | case 'custom':
210 | $validate = $this->config->getValue(CustomerHelper::CFG_INPUT_VALIDATION_CUSTOM);
211 | break;
212 | }
213 |
214 | // if (!$this->config->isSetFlag('username/general/case_sensitive')) {
215 | // $validate .= 'i';
216 | // }
217 |
218 | $validate = new \Zend_Validate_Regex($validate);
219 |
220 | if (!$validate->isValid($username)) {
221 | if ($inputValidation == 'custom') {
222 | $message = new \Magento\Framework\Phrase($this->config->getValue(Customer::CFG_INPUT_VALIDATION_CUSTOM_MESSAGE));
223 | } else {
224 | $message = __('Username is invalid! Only letters, digits and \'_-\' values are accepted.');
225 | }
226 | $exception->addError($message);
227 | }
228 | }
229 |
230 | $customerFound = $this->customerHelper->customerUsernameExists($username, $websiteId);
231 | if ($customerFound && $customerFound->getId() != $customer->getId()) {
232 | $message = __('Username already exists');
233 | $exception->addError($message);
234 | }
235 |
236 | return $this;
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Open Software License ("OSL") v. 3.0
3 |
4 | This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work:
5 |
6 | Licensed under the Open Software License version 3.0
7 |
8 | 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following:
9 |
10 | 1. to reproduce the Original Work in copies, either alone or as part of a collective work;
11 |
12 | 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work;
13 |
14 | 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License;
15 |
16 | 4. to perform the Original Work publicly; and
17 |
18 | 5. to display the Original Work publicly.
19 |
20 | 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works.
21 |
22 | 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work.
23 |
24 | 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license.
25 |
26 | 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c).
27 |
28 | 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
29 |
30 | 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer.
31 |
32 | 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation.
33 |
34 | 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c).
35 |
36 | 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
37 |
38 | 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License.
39 |
40 | 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
41 |
42 | 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
43 |
44 | 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
45 |
46 | 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
47 |
48 | 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process.
--------------------------------------------------------------------------------
/view/frontend/templates/form/register.phtml:
--------------------------------------------------------------------------------
1 |
10 |
17 | getChildHtml('form_fields_before')?>
18 |
19 | getChildHtml('customer.form.register.extra')?>
20 |
182 |
213 | getShowAddressFields()): ?>
214 |
230 |
231 |
--------------------------------------------------------------------------------