1
0
mirror of synced 2025-03-27 10:33:53 +03:00
woocommerce-module/src/include/components/class-wc-retailcrm-customer-switcher.php
2022-09-30 17:50:15 +03:00

326 lines
9.4 KiB
PHP

<?php
/**
* PHP version 7.0
*
* Class WC_Retailcrm_Customer_Switcher - This component provides builder-like interface in order to make it easier to
* change customer & customer data in the order via retailCRM history.
*
* @category Integration
* @author RetailCRM <integration@retailcrm.ru>
* @license http://retailcrm.ru Proprietary
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
class WC_Retailcrm_Customer_Switcher implements WC_Retailcrm_Builder_Interface
{
/**
* @var \WC_Retailcrm_Customer_Switcher_State $data
*/
private $data;
/**
* @var \WC_Retailcrm_Customer_Switcher_Result|null $result
*/
private $result;
/**
* WC_Retailcrm_Customer_Data_Replacer constructor.
*/
public function __construct()
{
$this->reset();
}
/**
* In fact, this will execute customer change in provided order.
* This will not produce any new entities.
*
* @return $this|\WC_Retailcrm_Builder_Interface
* @throws \WC_Data_Exception
*/
public function build()
{
$this->data->validate();
WC_Retailcrm_Logger::debug(__METHOD__, array('state', $this->data));
$newCustomer = $this->data->getNewCustomer();
$newContact = $this->data->getNewContact();
$newCompany = $this->data->getNewCompanyName();
$companyAddress = $this->data->getCompanyAddress();
if (!empty($newCustomer)) {
WC_Retailcrm_Logger::debug(
__METHOD__,
array(
'Changing to individual customer for order',
$this->data->getWcOrder()->get_id()
)
);
$this->processChangeToRegular($this->data->getWcOrder(), $newCustomer, false);
$this->data->getWcOrder()->set_billing_company('');
} else {
if (!empty($newContact)) {
WC_Retailcrm_Logger::debug(
__METHOD__,
array(
'Changing to contact person customer for order',
$this->data->getWcOrder()->get_id()
)
);
$this->processChangeToRegular($this->data->getWcOrder(), $newContact, true);
}
if (!empty($newCompany)) {
WC_Retailcrm_Logger::debug(
__METHOD__,
array(sprintf(
'Replacing old order id=`%d` company `%s` with new company `%s`',
$this->data->getWcOrder()->get_id(),
$this->data->getWcOrder()->get_billing_company(),
$newCompany
))
);
$this->processCompanyChange();
}
if (!empty($companyAddress)) {
$this->processCompanyAddress();
}
}
return $this;
}
/**
* Change order customer to regular one
*
* @param \WC_Order $wcOrder
* @param array $newCustomer
* @param bool $isContact
*
* @throws \WC_Data_Exception
*/
public function processChangeToRegular($wcOrder, $newCustomer, $isContact)
{
$wcCustomer = null;
WC_Retailcrm_Logger::debug(
__METHOD__,
array(
'Switching in order',
$wcOrder->get_id(),
'to',
$newCustomer
)
);
if (isset($newCustomer['externalId'])) {
$wcCustomer = new WC_Customer($newCustomer['externalId']);
if (!empty($wcCustomer)) {
$wcOrder->set_customer_id($wcCustomer->get_id());
WC_Retailcrm_Logger::debug(
__METHOD__,
array(
'Set customer to',
$wcCustomer->get_id(),
'in order',
$wcOrder->get_id()
)
);
}
} else {
$wcOrder->set_customer_id(0);
WC_Retailcrm_Logger::debug(
__METHOD__,
array(
'Set customer to 0 (guest) in order',
$wcOrder->get_id()
)
);
}
$fields = array(
'billing_first_name' => self::arrayValue($newCustomer, 'firstName'),
'billing_last_name' => self::arrayValue($newCustomer, 'lastName'),
'billing_email' => self::arrayValue($newCustomer, 'email')
);
foreach ($fields as $field => $value) {
$wcOrder->{'set_' . $field}($value);
}
$address = self::arrayValue($newCustomer, 'address', array());
if ($isContact) {
self::setShippingAddressToOrder($wcOrder, $address);
} else {
self::setBillingAddressToOrder($wcOrder, $address);
self::setShippingAddressToOrder($wcOrder, $address);
}
$wcOrder->set_billing_phone(self::singleCustomerPhone($newCustomer));
$this->result = new WC_Retailcrm_Customer_Switcher_Result($wcCustomer, $wcOrder);
}
/**
* Process company address.
*
* @throws \WC_Data_Exception
*/
protected function processCompanyAddress()
{
$wcOrder = $this->data->getWcOrder();
$companyAddress = $this->data->getCompanyAddress();
if (!empty($companyAddress)) {
self::setBillingAddressToOrder($wcOrder, $companyAddress);
}
if (empty($this->result)) {
$this->result = new WC_Retailcrm_Customer_Switcher_Result(null, $wcOrder);
}
}
/**
* This will update company field in order and create result if it's not set (happens when only company was changed).
*
* @throws \WC_Data_Exception
*/
public function processCompanyChange()
{
$this->data->getWcOrder()->set_billing_company($this->data->getNewCompanyName());
if (empty($this->result)) {
$this->result = new WC_Retailcrm_Customer_Switcher_Result(null, $this->data->getWcOrder());
}
}
/**
* @return $this|\WC_Retailcrm_Builder_Interface
*/
public function reset()
{
$this->data = new WC_Retailcrm_Customer_Switcher_State();
$this->result = null;
return $this;
}
/**
* Set initial state into component
*
* @param \WC_Retailcrm_Customer_Switcher_State $data
*
* @return $this|\WC_Retailcrm_Builder_Interface
*/
public function setData($data)
{
if (!($data instanceof WC_Retailcrm_Customer_Switcher_State)) {
throw new \InvalidArgumentException('Invalid data type');
}
$this->data = $data;
return $this;
}
/**
* @return \WC_Retailcrm_Customer_Switcher_Result|null
*/
public function getResult()
{
return $this->result;
}
/**
* @return \WC_Retailcrm_Customer_Switcher_State
*/
public function getData()
{
return $this->data;
}
/**
* Sets billing address properties in order
*
* @param \WC_Order $wcOrder
* @param array $address
*
* @throws \WC_Data_Exception
*/
private static function setBillingAddressToOrder($wcOrder, $address)
{
$wcOrder->set_billing_state(self::arrayValue($address, 'region', ''));
$wcOrder->set_billing_postcode(self::arrayValue($address, 'index', ''));
$wcOrder->set_billing_country(self::arrayValue($address, 'country', ''));
$wcOrder->set_billing_city(self::arrayValue($address, 'city', ''));
$wcOrder->set_billing_address_1(self::arrayValue($address, 'text', ''));
}
/**
* Sets shipping address properties in order
*
* @param \WC_Order $wcOrder
* @param array $address
*
* @throws \WC_Data_Exception
*/
private static function setShippingAddressToOrder($wcOrder, $address)
{
$wcOrder->set_shipping_state(self::arrayValue($address, 'region', ''));
$wcOrder->set_shipping_postcode(self::arrayValue($address, 'index', ''));
$wcOrder->set_shipping_country(self::arrayValue($address, 'country', ''));
$wcOrder->set_shipping_city(self::arrayValue($address, 'city', ''));
$wcOrder->set_shipping_address_1(self::arrayValue($address, 'text', ''));
}
/**
* @param array|\ArrayObject|\ArrayAccess $arr
* @param string $key
* @param string $def
*
* @return mixed|string
*/
private static function arrayValue($arr, $key, $def = '')
{
if (!is_array($arr) && !($arr instanceof ArrayObject) && !($arr instanceof ArrayAccess)) {
return $def;
}
if (!array_key_exists($key, $arr) && !empty($arr[$key])) {
return $def;
}
return isset($arr[$key]) ? $arr[$key] : $def;
}
/**
* Returns first phone from order data or null
*
* @param array $customerData
*
* @return string|null
*/
private static function singleCustomerPhone($customerData)
{
if (!array_key_exists('phones', $customerData)) {
return '';
}
if (empty($customerData['phones']) || !is_array($customerData['phones'])) {
return '';
}
$phones = $customerData['phones'];
$phone = reset($phones);
if (!isset($phone['number'])) {
return '';
}
return (string) $phone['number'];
}
}