0

I want to prevent customers from changing their first and last name once they're registered but I want to allow them to change the password in a customer account.

I added disabled = "disabled" to first and last name input field:

app/design/frontend/Vendor/Magento_Customer/templates/widget/name.phtml

<div class="field field-name-firstname required">
            <label class="label" for="<?= $block->escapeHtmlAttr($block->getFieldId('firstname')) ?>"><span><?= $block->escapeHtml($block->getStoreLabel('firstname')) ?></span></label>
            <div class="control">
                <input type="text" id="<?= $block->escapeHtmlAttr($block->getFieldId('firstname')) ?>"
                       name="<?= $block->escapeHtmlAttr($block->getFieldName('firstname')) ?>"
                       value="<?= $block->escapeHtmlAttr($block->getObject()->getFirstname()) ?>"
                       disabled="disabled"
                       title="<?= $block->escapeHtmlAttr($block->getStoreLabel('firstname')) ?>"
                       class="input-text <?= $block->escapeHtmlAttr($block->getAttributeValidationClass('firstname')) ?>" <?php if ($block->getAttributeValidationClass('firstname') == 'required-entry') echo ' data-validate="{required:true}"' ?>>
            </div>
        </div>

Now, my input fields are greyed out but when I change my password I get

"First name is required. Last name is required"

I created a before plugin for vendor/magento/module-customer/Controller/Account/EditPost.php so I can inject EXISTING first and last name before POST executes so I can prevent this error from appearing and make sure the customer's existing first and the last name is not changed.

app/code/Vendor/Customer/etc/frontend/di.xml

<type name="Magento\Customer\Controller\Account\EditPost">
     <plugin name="disableCustomerFields" type="Vendor\Customer\Plugin\Controller\Account\DisableCustomerPost" />
</type>

PLUGIN: app/code/Vendor/Customer/Plugin/Controller/Account/DisableCustomerPost.php

<?php

namespace Vendor\Customer\Plugin\Controller\Account;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Controller\Account\EditPost;
use Magento\Customer\Model\CustomerExtractor;
use Magento\Customer\Model\Session;
use Magento\Framework\App\Action\AbstractAction;
use Magento\Customer\Model\Customer\Mapper;
use Magento\Framework\App\RequestInterface;

class DisableCustomerPost
{
    /**
     * @var CustomerRepositoryInterface
     */
    protected $customerRepository;

    /**
     * @var Session
     */
    protected $session;

    /**
     * @var Mapper
     */
    protected $extensibleDataObjectConverter;

    /**
     * @var CustomerExtractor
     */
    protected $customerExtractor;

    /**
     * Form code for data extractor
     */
    const FORM_DATA_EXTRACTOR_CODE = 'customer_account_edit';

    /**
     * @var EditPost
     */
    protected $editPost;

    /**
     * EditPost constructor.
     *
     * @param CustomerRepositoryInterface $customerRepository ,
     * @param Session $customerSession ,
     * @param EditPost $editPost
     */
    public function __construct(
        CustomerRepositoryInterface $customerRepository,
        Session                     $customerSession,
        Mapper                      $extensibleDataObjectConverter,
        CustomerExtractor           $customerExtractor,
        EditPost                    $editPost
    )
    {
        $this->customerRepository = $customerRepository;
        $this->session = $customerSession;
        $this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
        $this->customerExtractor = $customerExtractor;
        $this->editPost = $editPost;
    }

    /**
     * Get customer data object
     *
     * @param int $customerId
     *
     * @return CustomerInterface
     */
    private function getCustomerDataObject($customerId): CustomerInterface
    {
        return $this->customerRepository->getById($customerId);
    }

    /**
     * Populate customer data with existing full name
     * @param RequestInterface $request
     * @param CustomerInterface $currentCustomerData
     * @return array
     */
    private function addExistingFirstandLastname(
        RequestInterface $request,
        CustomerInterface $currentCustomerData
    ): array
    {
        /** @var Mapper $extensibleDataObjectConverter */
        $attributeValues = $this->extensibleDataObjectConverter->toFlatArray($currentCustomerData);
        $customerDto = $this->customerExtractor->extract(
            self::FORM_DATA_EXTRACTOR_CODE,
            $request,
            $attributeValues
        );
        $customerDto->setId($currentCustomerData->getId());
        if (!$customerDto->getFirstname()) {
            $customerDto->setFirstname($currentCustomerData->getFirstname());
        }
        if (!$customerDto->getLastname()) {
            $customerDto->setLastname($currentCustomerData->getLastname());
        }
        return $customerDto;
    }

    /**
     * @param \Magento\Customer\Controller\Account\EditPost $subject
     * @return mixed
     */
    public function beforeExecute(EditPost $subject)
    {
        $post = $subject->getRequest()->getPostValue();
//            /** @var RequestInterface $request */
            $currentCustomerDataObject = $this->getCustomerDataObject($this->session->getCustomerId());
            $customerCandidateDataObject = $this->addExistingFirstandLastname($post, $currentCustomerDataObject);
            return $this->session->setCustomerFormData($customerCandidateDataObject);
    }
}

but I'm getting different errors such as:

Fatal error: Uncaught TypeError: Argument 1 passed to Vendor\Customer\Plugin\Controller\Account\DisableCustomerPost::addExistingFirstandLastname() must implement interface Magento\Framework\App\RequestInterface, array given, called in /app/app/code/Vendor/Customer/Plugin/Controller/Account/DisableCustomerPost.php on line 117 and defined in /app/app/code/Vendor/Customer/Plugin/Controller/Account/DisableCustomerPost.php:86 Stack trace: #0

I know my function for getting the current customer name and setting the current customer name is not written properly and then sending that data to the POST controller but I don't have an idea of how to make it work.

1 Answer 1

0

It's been a few months but I'm adding a solution to this if anyone needs it in the future.

How to get and edit post parameters for customer account in Magento - the plugin should look like this:

<?php

namespace Vendor\CustomerB2B\Plugin\Controller\Account;

use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Controller\Account\EditPost;

/**
 * Class AccountEditPost
 *
 * @package Vendor\CustomerB2B\Plugin\Controller\Account
 */
class AccountEditPost
{
    /**
     * @var EditPost
     */
    private $subject;

    /**
     * @var CustomerInterface
     */
    private $customerData;

    public function __construct(
        EditPost                     $subject,
        CustomerInterface            $customerData
    )
    {
        $this->subject = $subject;
        $this->customerData = $customerData;
    }

    public function beforeExecute(\Magento\Customer\Controller\Account\EditPost $subject)
    {
        $getExistingFirstName = $this->customerData->getFirstname();
        $getExistingMiddleName = $this->customerData->getMiddlename();
        $getExistingLastName = $this->customerData->getLastname();

        $subject->getRequest()->setParam('firstname', $getExistingFirstName)
            ->setParam('middlename', $getExistingMiddleName)
            ->setParam('lastname', $getExistingLastName);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.