Les extensions attributes

Ajouter notre attribut dans le fichier etc/extension_attributes.xml :

<?xml version="1.0" encoding="UTF-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Customer\Api\Data\AddressInterface">
        <attribute code="mobile" type="string" />
    </extension_attributes>
</config>

Déclarer les deux plugins dans le fichier etc/di.xml :

<?xml version="1.0" encoding="UTF-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Adexos\Formation\Api\AddressExtensionAttributeRepositoryInterface" type="Adexos\Formation\Model\AddressExtensionAttributeRepository" />
    <preference for="Adexos\Formation\Api\Data\AddressExtensionAttributeInterface" type="Adexos\Formation\Model\AddressExtensionAttribute" />

    <type name="Magento\Customer\Api\AddressRepositoryInterface">
        <plugin name="adexos_formation_customer_address_save" type="Adexos\Formation\Plugin\Customer\Address\Save"/>
        <plugin name="adexos_formation_customer_address_get" type="Adexos\Formation\Plugin\Customer\Address\Get"/>
    </type>
</config>

Plugin Get.

<?php
namespace Adexos\Formation\Plugin\Customer\Address;

use Adexos\Formation\Api\Data\AddressExtensionAttributeInterface;
use Adexos\Formation\Api\AddressExtensionAttributeRepositoryInterface;
use Magento\Customer\Api\Data\AddressExtensionFactory;
use Adexos\Formation\Model\AddressExtensionAttributeFactory;

class Get
{
    /**
     * @var AddressExtensionAttributeRepositoryInterface
     */
    private $addressExtensionAttributeRepository;

    /**
     * @var AddressExtensionFactory
     */
    private $addressExtensionFactory;

    /**
     * @var AddressExtensionAttributeFactory
     */
    private $addressExtensionAttributeFactory;

    /**
     * Get constructor.
     * @param AddressExtensionAttributeRepositoryInterface $addressExtensionAttributeRepository
     * @param AddressExtensionFactory $addressExtensionFactory
     * @param AddressExtensionAttributeFactory $addressExtensionAttributeFactory
     */
    public function __construct(
        AddressExtensionAttributeRepositoryInterface $addressExtensionAttributeRepository,
        AddressExtensionFactory $addressExtensionFactory,
        AddressExtensionAttributeFactory $addressExtensionAttributeFactory
    ) {
        $this->addressExtensionAttributeRepository    = $addressExtensionAttributeRepository;
        $this->addressExtensionFactory                = $addressExtensionFactory;
        $this->addressExtensionAttributeFactory       = $addressExtensionAttributeFactory;
    }

    /**
     * @param \Magento\Customer\Api\AddressRepositoryInterface $subject
     * @param \Magento\Customer\Api\Data\AddressInterface $resultAddress
     * @return \Magento\Customer\Api\Data\AddressInterface
     */
    public function afterGetById(
        \Magento\Customer\Api\AddressRepositoryInterface $subject,
        \Magento\Customer\Api\Data\AddressInterface $resultAddress
    ) {
        $resultAddress = $this->getMobile($resultAddress);

        return $resultAddress;
    }

    /**
     * @param \Magento\Customer\Api\Data\AddressInterface $order
     * @return \Magento\Customer\Api\Data\AddressInterface
     */
    private function getMobile(\Magento\Customer\Api\Data\AddressInterface $address)
    {
        $mobile = $this->addressExtensionAttributeRepository->get('mobile', $address->getId());

        $extensionAttributes = $address->getExtensionAttributes();
        $addressExtension = $extensionAttributes ? $extensionAttributes : $this->addressExtensionFactory->create();

        /** @var AddressExtensionAttributeInterface $mobileAttribute */
        $mobileAttribute = $this->addressExtensionAttributeFactory->create();
        $mobileAttribute->setValue($mobile);

        $addressExtension->setMobile($mobileAttribute);
        $address->setExtensionAttributes($addressExtension);

        return $address;
    }
}

Plugin Save

<?php
namespace Adexos\Formation\Plugin\Customer\Address;

use Adexos\Formation\Api\AddressExtensionAttributeRepositoryInterface;
use Magento\Framework\Exception\CouldNotSaveException;

class Save
{
    /**
     * @var AddressExtensionAttributeRepositoryInterface
     */
    private $addressExtensionAttributeRepository;

    /**
     * Save constructor.
     * @param AddressExtensionAttributeRepositoryInterface $addressExtensionAttributeRepository
     */
    public function __construct(
        AddressExtensionAttributeRepositoryInterface $addressExtensionAttributeRepository
    ) {
        $this->addressExtensionAttributeRepository = $addressExtensionAttributeRepository;
    }

    /**
     * @param \Magento\Customer\Api\AddressRepositoryInterface $subject
     * @param \Magento\Customer\Api\Data\AddressInterface $resultAddress
     * @return \Magento\Customer\Api\Data\AddressInterface
     * @throws CouldNotSaveException
     */
    public function afterSave(
        \Magento\Customer\Api\AddressRepositoryInterface $subject,
        \Magento\Customer\Api\Data\AddressInterface $resultAddress
    ) {
        $resultAddress = $this->saveAttributes($resultAddress);

        return $resultAddress;
    }

    /**
     * @param \Magento\Customer\Api\Data\AddressInterface $address
     * @return \Magento\Customer\Api\Data\AddressInterface
     * @throws CouldNotSaveException
     */
    private function saveAttributes(\Magento\Customer\Api\Data\AddressInterface $address)
    {
        $extensionAttributes = $address->getExtensionAttributes();
        if (null !== $extensionAttributes && null !== $extensionAttributes->getMobile()) {
            $mobile = is_object($extensionAttributes->getMobile()) ? $extensionAttributes->getMobile()->getValue() : $extensionAttributes->getMobile();

            try {
                $this->addressExtensionAttributeRepository->save($address->getId(), $mobile);
            } catch (\Exception $e) {
                throw new CouldNotSaveException(
                    __('Could not add attribute to address: "%1"', $e->getMessage()),
                    $e
                );
            }
        }
        return $address;
    }
}

Les interfaces AddressExtensionAttributeRepositoryInterface

<?php
namespace Adexos\Formation\Api;

interface AddressExtensionAttributeRepositoryInterface
{
    /**
     * @param int $addressId
     * @param $mobile
     * @return mixed
     */
    public function save(int $addressId, $mobile);

    /**
     * @param $code
     * @param int $addressId
     * @return mixed
     */
    public function get($code, int $addressId);
}

AddressExtensionAttributeInterface

<?php
namespace Adexos\Formation\Api\Data;

interface AddressExtensionAttributeInterface
{
    const VALUE = 'value';

    /**
     * @return string
     */
    public function getValue();

    /**
     * @param $value
     * @return AddressExtensionAttributeInterface
     */
    public function setValue($value);
}
<?php
namespace Adexos\Formation\Model;

use Adexos\Formation\Api\AddressExtensionAttributeRepositoryInterface;
use Magento\Framework\App\ResourceConnection;

/**
 * Class OrderItemExtensionAttributeRepository
 * @package Autobernard\Sales\Model
 */
class AddressExtensionAttributeRepository implements AddressExtensionAttributeRepositoryInterface
{
    /**
     * @var ResourceConnection
     */
    private $resource;

    /**
     * OrderItemExtensionAttributeRepository constructor.
     * @param ResourceConnection $resource
     */
    public function __construct(
        ResourceConnection $resource
    ) {
        $this->resource = $resource;
    }

    /**
     * @param int $addressId
     * @param $mobile
     * @return $this|mixed
     */
    public function save(int $addressId, $mobile)
    {
        $connection = $this->getConnection();
        $select = $connection->select(
        )->from(
            $this->getMainTable()
        )->where(
            'entity_id = ?',
            $addressId
        );

        $row = $connection->fetchRow($select);

        $newData = ['mobile' => $mobile, 'entity_id' => $addressId];

        if ($row) {
            $whereCondition = [$this->getIdFieldName() . '=?' => $row[$this->getIdFieldName()]];
            $connection->update($this->getMainTable(), $newData, $whereCondition);
        } else {
            $connection->insert($this->getMainTable(), $newData);
        }

        return $this;
    }

    /**
     * @param $code
     * @param int $addressId
     * @return string
     */
    public function get($code, int $addressId)
    {
        $condition = $this->getConnection()->quoteInto($this->getEntityIdFieldName() . '=?', $addressId);
        $select = $this->getConnection()->select()
                    ->from($this->getMainTable(), [$code])
                    ->where($condition);
        $result = $this->getConnection()->fetchCol($select);

        if (count($result)) {
            return $result[0];
        }

        return '';
    }

    /**
     * @return \Magento\Framework\DB\Adapter\AdapterInterface
     */
    private function getConnection()
    {
        return $this->resource->getConnection();
    }

    /**
     * @return string
     */
    private function getMainTable()
    {
        return $this->resource->getTableName('adexos_address_extension_attribute');
    }

    /**
     * @return string
     */
    private function getIdFieldName()
    {
        return 'value_id';
    }

    /**
     * @return string
     */
    private function getEntityIdFieldName()
    {
        return 'entity_id';
    }
}

AddressExtensionAttribute

<?php
namespace Adexos\Formation\Model;

use Adexos\Formation\Api\Data\AddressExtensionAttributeInterface;
use Magento\Framework\App\ResourceConnection;

/**
 * Class AddressExtensionAttribute
 * @package Adexos\Formation\Model
 */
class AddressExtensionAttribute extends \Magento\Framework\DataObject implements AddressExtensionAttributeInterface
{
    /**
     * @var ResourceConnection
     */
    private $resource;

    /**
     * OrderItemExtensionAttribute constructor.
     * @param ResourceConnection $resource
     * @param array $data
     */
    public function __construct(
        ResourceConnection $resource,
        array $data = []
    ) {
        $this->resource = $resource;

        parent::__construct($data);
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->getData(self::VALUE);
    }

    /**
     * @param $value
     * @return AddressExtensionAttributeInterface
     */
    public function setValue($value)
    {
        return $this->setData(self::VALUE, $value);
    }
}