Skip to content

38325 make city field optional in address #38470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: 2.4-develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->
<div if="isAddressDetailsVisible() && currentBillingAddress()" class="billing-address-details">
Expand All @@ -12,7 +12,11 @@
<text args="currentBillingAddress().company"></text><br>
</if>
<text args="_.values(_.compact(currentBillingAddress().street)).join(', ')"></text><br>
<text args="currentBillingAddress().city "></text>, <span text="currentBillingAddress().region"></span>

<if args="currentBillingAddress().city">
<text args="currentBillingAddress().city "></text>,
</if>
<span text="currentBillingAddress().region"></span>
<text args="currentBillingAddress().postcode"></text><br>
<text args="getCountryName(currentBillingAddress().countryId)"></text><br>
<a if="currentBillingAddress().telephone" attr="'href': 'tel:' + currentBillingAddress().telephone" text="currentBillingAddress().telephone"></a><br>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->
<div class="shipping-address-item" css="'selected-item' : isSelected() , 'not-selected-item':!isSelected()">
Expand All @@ -11,7 +11,10 @@
<text args="address().company"></text><br>
</if>
<text args="_.values(_.compact(address().street)).join(', ')"></text><br>
<text args="address().city "></text>, <span text="address().region"></span> <text args="address().postcode"></text><br>
<if args="address().city">
<text args="address().city "></text>,
</if>
<span text="address().region"></span> <text args="address().postcode"></text><br>
<text args="getCountryName(address().countryId)"></text><br>
<a if="address().telephone" attr="'href': 'tel:' + address().telephone" text="address().telephone"></a><br>
<if args="address().vatId">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->
<if args="visible()">
Expand All @@ -11,7 +11,10 @@
<text args="address().company"></text><br>
</if>
<text args="_.values(_.compact(address().street)).join(', ')"></text><br>
<text args="address().city "></text>, <span text="address().region"></span> <text args="address().postcode"></text><br>
<if args="address().city">
<text args="address().city "></text>,
</if>
<span text="address().region"></span> <text args="address().postcode"></text><br>
<text args="getCountryName(address().countryId)"></text><br>
<a if="address().telephone" attr="'href': 'tel:' + address().telephone" text="address().telephone"></a><br>
<if args="address().vatId">
Expand Down
182 changes: 182 additions & 0 deletions app/code/Magento/Customer/Block/Widget/City.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<?php
/**
* Copyright 2024 Adobe.
* All Rights Reserved.
*/

declare(strict_types=1);

namespace Magento\Customer\Block\Widget;

use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Customer\Api\Data\AttributeMetadataInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Helper\Address as AddressHelper;
use Magento\Customer\Model\Options;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Element\Template\Context;

/**
* Widget for showing customer city.
*
* @method CustomerInterface getObject()
* @method Name setObject(CustomerInterface $customer)
*
* @SuppressWarnings(PHPMD.DepthOfInheritance)
*/
class City extends AbstractWidget
{

/**
* the attribute code
*/
public const ATTRIBUTE_CODE = 'city';

/**
* @var AddressMetadataInterface
*/
private $addressMetadata;

/**
* @var Options
*/
private $options;

/**
* @param Context $context
* @param AddressHelper $addressHelper
* @param CustomerMetadataInterface $customerMetadata
* @param Options $options
* @param AddressMetadataInterface $addressMetadata
* @param array $data
*/
public function __construct(
Context $context,
AddressHelper $addressHelper,
CustomerMetadataInterface $customerMetadata,
Options $options,
AddressMetadataInterface $addressMetadata,
array $data = []
) {
$this->options = $options;
parent::__construct($context, $addressHelper, $customerMetadata, $data);
$this->addressMetadata = $addressMetadata;
$this->_isScopePrivate = true;
}

/**
* @inheritdoc
*/
public function _construct()
{
parent::_construct();

// default city location
$this->setTemplate('Magento_Customer::widget/city.phtml');
}

/**
* Can show prefix
*
* @return bool
*/
public function showCity()
{
return $this->isAttributeVisible(self::ATTRIBUTE_CODE);
}

/**
* Retrieve customer attribute instance
*
* @param string $attributeCode
*
* @return AttributeMetadataInterface|null
* @throws LocalizedException
*/
//@codingStandardsIgnoreStart
protected function _getAttribute($attributeCode)
{
//@codingStandardsIgnoreEnd
if ($this->getForceUseCustomerAttributes() || $this->getObject() instanceof CustomerInterface) {
return parent::_getAttribute($attributeCode);
}

try {
$attribute = $this->addressMetadata->getAttributeMetadata($attributeCode);
} catch (NoSuchEntityException $e) {
return null;
}

if ($this->getForceUseCustomerRequiredAttributes() && $attribute && !$attribute->isRequired()) {
$customerAttribute = parent::_getAttribute($attributeCode);
if ($customerAttribute && $customerAttribute->isRequired()) {
$attribute = $customerAttribute;
}
}

return $attribute;
}

/**
* Retrieve store attribute label
*
* @param string $attributeCode
*
* @return string
*/
public function getStoreLabel(string $attributeCode)
{
$attribute = $this->_getAttribute($attributeCode);
return $attribute ? __($attribute->getStoreLabel()) : '';
}

/**
* Get string with frontend validation classes for attribute
*
* @param string $attributeCode
*
* @return string
* @throws LocalizedException
*/
public function getAttributeValidationClass(string $attributeCode)
{
return $this->_addressHelper->getAttributeValidationClass($attributeCode);
}

/**
* Checks is attribute visible
*
* @param string $attributeCode
*
* @return bool
*/
private function isAttributeVisible(string $attributeCode)
{
$attributeMetadata = $this->_getAttribute($attributeCode);
return $attributeMetadata ? (bool)$attributeMetadata->isVisible() : false;
}

/**
* Check if city attribute enabled in system
*
* @return bool
*/
public function isEnabled()
{
return $this->_getAttribute(self::ATTRIBUTE_CODE)
? (bool)$this->_getAttribute(self::ATTRIBUTE_CODE)->isVisible() : false;
}

/**
* Check if city attribute marked as required
*
* @return bool
*/
public function isRequired(): bool
{
return $this->_getAttribute(self::ATTRIBUTE_CODE)
? (bool)$this->_getAttribute(self::ATTRIBUTE_CODE)->isRequired() : false;
}
}
27 changes: 21 additions & 6 deletions app/code/Magento/Customer/Model/Address/Validator/General.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
namespace Magento\Customer\Model\Address\Validator;

Expand Down Expand Up @@ -75,10 +75,6 @@ private function checkRequiredFields(AbstractAddress $address)
$errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'street']);
}

if (!ValidatorChain::is($address->getCity(), NotEmpty::class)) {
$errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'city']);
}

return $errors;
}

Expand All @@ -88,6 +84,8 @@ private function checkRequiredFields(AbstractAddress $address)
* @param AbstractAddress $address
* @return array
* @throws LocalizedException|ValidateException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
private function checkOptionalFields(AbstractAddress $address)
{
Expand All @@ -111,6 +109,12 @@ private function checkOptionalFields(AbstractAddress $address)
$errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'company']);
}

if ($this->isCityRequired()
&& !ValidatorChain::is($address->getCity(), NotEmpty::class)
) {
$errors[] = __('"%fieldName" is required. Enter and try again.', ['fieldName' => 'city']);
}

$havingOptionalZip = $this->directoryData->getCountriesWithOptionalZip();
if (!in_array($address->getCountryId(), $havingOptionalZip)
&& !ValidatorChain::is($address->getPostcode(), NotEmpty::class)
Expand Down Expand Up @@ -154,6 +158,17 @@ private function isFaxRequired()
return $this->eavConfig->getAttribute('customer_address', 'fax')->getIsRequired();
}

/**
* Check if city field required in configuration.
*
* @return bool
* @throws LocalizedException
*/
private function isCityRequired()
{
return $this->eavConfig->getAttribute('customer_address', 'city')->getIsRequired();
}

/**
* Reload address attributes for the certain store
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->

<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
<actionGroup name="AdminCustomerShowCityActionGroup">
<annotations>
<description>Goes to the customer configuration. Set "Show City" with provided value.</description>
</annotations>
<arguments>
<argument name="value" type="string" defaultValue="{{ShowCity.optional}}"/>
</arguments>
<amOnPage url="{{AdminCustomerConfigPage.url('#customer_address-link')}}" stepKey="openCustomerConfigPage"/>
<waitForPageLoad stepKey="waitCustomerConfigPage"/>
<scrollTo selector="{{AdminCustomerConfigSection.showCity}}" x="0" y="-100" stepKey="scrollToShowCity"/>
<uncheckOption selector="{{AdminCustomerConfigSection.showCityInherit}}" stepKey="uncheckUseSystem"/>
<selectOption selector="{{AdminCustomerConfigSection.showCity}}" userInput="{{value}}" stepKey="fillShowCity"/>
<click selector="{{AdminMainActionsSection.save}}" stepKey="clickSave"/>
<seeElement selector="{{AdminMessagesSection.success}}" stepKey="seeSuccessMessage"/>
</actionGroup>
</actionGroups>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
<data key="optional">Optional</data>
<data key="required">Required</data>
</entity>
<entity name="ShowCity">
<data key="no">No</data>
<data key="optional">Optional</data>
<data key="required">Required</data>
</entity>
<entity name="ShowCompany">
<data key="no">No</data>
<data key="optional">Optional</data>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2024 Adobe
* All Rights Reserved.
*/
-->
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
Expand All @@ -17,6 +17,7 @@
<element name="showTelephoneInherit" type="checkbox" selector="#customer_address_telephone_show_inherit"/>
<element name="showCompany" type="select" selector="#customer_address_company_show"/>
<element name="showCompanyInherit" type="select" selector="#customer_address_company_show_inherit"/>
<element name="showCity" type="select" selector="#customer_address_city_show"/>
<element name="passwordOptions" type="select" selector="#customer_password-head"/>
<element name="passwordResetProtectionType" type="select" selector="#customer_password_password_reset_protection_type"/>
<element name="passwordResetProtectionTypeOptions" type="select" selector="#customer_password_password_reset_protection_type option:nth-child({{option}})" parameterized="true"/>
Expand Down
Loading