HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/magento.bikenow.co/vendor/klarna/module-core/Model/Api/Builder.php
<?php
/**
 * This file is part of the Klarna Core module
 *
 * (c) Klarna Bank AB (publ)
 *
 * For the full copyright and license information, please view the NOTICE
 * and LICENSE files that were distributed with this source code.
 */
declare(strict_types=1);

namespace Klarna\Core\Model\Api;

use Exception;
use Klarna\Core\Api\BuilderInterface;
use Klarna\Core\Helper\ConfigHelper;
use Klarna\Core\Helper\KlarnaConfig;
use Klarna\Core\Model\Checkout\Orderline\AbstractLine;
use Klarna\Core\Model\Checkout\Orderline\Collector;
use Magento\Customer\Api\Data\AddressInterface;
use Magento\Customer\Model\AddressRegistry;
use Magento\Customer\Model\Data\Address as CustomerAddress;
use Magento\Directory\Helper\Data as DirectoryHelper;
use Magento\Framework\DataObject;
use Magento\Framework\DataObject\Copy;
use Magento\Framework\DataObjectFactory;
use Magento\Framework\Event\ManagerInterface as EventManager;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Url;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Address;
use Magento\Sales\Model\AbstractModel;
use Magento\Store\Api\Data\StoreInterface;

/**
 * Base class to generate API configuration
 *
 * @method Builder setShippingUnitPrice($integer)
 * @method int getShippingUnitPrice()
 * @method Builder setShippingTaxRate($integer)
 * @method int getShippingTaxRate()
 * @method Builder setShippingTotalAmount($integer)
 * @method int getShippingTotalAmount()
 * @method Builder setShippingTaxAmount($integer)
 * @method int getShippingTaxAmount()
 * @method Builder setShippingTitle($string)
 * @method string getShippingTitle()
 * @method Builder setShippingReference($integer)
 * @method int getShippingReference()
 * @method Builder setDiscountUnitPrice($integer)
 * @method int getDiscountUnitPrice()
 * @method Builder setDiscountTaxRate($integer)
 * @method int getDiscountTaxRate()
 * @method Builder setDiscountTotalAmount($integer)
 * @method int getDiscountTotalAmount()
 * @method Builder setDiscountTaxAmount($integer)
 * @method int getDiscountTaxAmount()
 * @method Builder setDiscountTitle($integer)
 * @method int getDiscountTitle()
 * @method Builder setDiscountReference($integer)
 * @method int getDiscountReference()
 * @method Builder setTaxUnitPrice($integer)
 * @method int getTaxUnitPrice()
 * @method Builder setTaxTotalAmount($integer)
 * @method int getTaxTotalAmount()
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
abstract class Builder extends DataObject implements BuilderInterface
{

    /**
     * @var string
     */
    public $prefix = '';
    /**
     * @var Collector
     */
    protected $orderLineCollector = null;
    /**
     * @var EventManager
     */
    protected $eventManager;
    /**
     * @var array
     */
    protected $orderLines = [];
    /**
     * @var AbstractModel|Quote
     */
    protected $object = null;
    /**
     * @var array
     */
    protected $request = [];
    /**
     * @var bool
     */
    protected $inRequestSet = false;
    /**
     * @var ConfigHelper
     */
    protected $configHelper;
    /**
     * @var Url
     */
    protected $url;
    /**
     * @var DirectoryHelper
     */
    protected $directoryHelper;
    /**
     * @var DateTime
     */
    protected $coreDate;
    /**
     * @var KlarnaConfig
     */
    protected $klarnaConfig;
    /**
     * @var DataObjectFactory
     */
    protected $dataObjectFactory;
    /**
     * @var Copy
     */
    private $objCopyService;
    /**
     * @var AddressRegistry
     */
    private $addressRegistry;

    /**
     * Init
     *
     * @param EventManager      $eventManager
     * @param Collector         $collector
     * @param Url               $url
     * @param ConfigHelper      $configHelper
     * @param DirectoryHelper   $directoryHelper
     * @param DateTime          $coreDate
     * @param Copy              $objCopyService
     * @param AddressRegistry   $addressRegistry
     * @param KlarnaConfig      $klarnaConfig
     * @param DataObjectFactory $dataObjectFactory
     * @param array             $data
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        EventManager $eventManager,
        Collector $collector,
        Url $url,
        ConfigHelper $configHelper,
        DirectoryHelper $directoryHelper,
        DateTime $coreDate,
        Copy $objCopyService,
        AddressRegistry $addressRegistry,
        KlarnaConfig $klarnaConfig,
        DataObjectFactory $dataObjectFactory,
        array $data = []
    ) {
        parent::__construct($data);
        $this->eventManager       = $eventManager;
        $this->orderLineCollector = $collector;
        $this->url                = $url;
        $this->configHelper       = $configHelper;
        $this->directoryHelper    = $directoryHelper;
        $this->coreDate           = $coreDate;
        $this->objCopyService     = $objCopyService;
        $this->addressRegistry    = $addressRegistry;
        $this->klarnaConfig       = $klarnaConfig;
        $this->dataObjectFactory  = $dataObjectFactory;
    }

    /**
     * Generate order body
     *
     * @param string $type
     * @return BuilderInterface
     * @throws LocalizedException
     */
    public function generateRequest($type = self::GENERATE_TYPE_CREATE)
    {
        $this->collectOrderLines($this->getObject()->getStore());
        return $this;
    }

    /**
     * Collect order lines
     *
     * @param StoreInterface $store
     * @return BuilderInterface
     * @throws LocalizedException
     */
    public function collectOrderLines(StoreInterface $store): self
    {
        /** @var AbstractLine $model */
        foreach ($this->getOrderLinesCollector()->getCollectors($store) as $model) {
            $model->collect($this);
        }

        return $this;
    }

    /**
     * Get totals collector model
     *
     * @return Collector
     */
    public function getOrderLinesCollector(): Collector
    {
        return $this->orderLineCollector;
    }

    /**
     * Get the object used to generate request
     *
     * @return AbstractModel|Quote
     */
    public function getObject()
    {
        return $this->object;
    }

    /**
     * Set the object used to generate request
     *
     * @param AbstractModel|Quote $object
     * @return BuilderInterface
     */
    public function setObject($object): self
    {
        $this->object = $object;

        return $this;
    }

    /**
     * Get request
     *
     * @return array
     */
    abstract public function getRequest();

    /**
     * Set generated request
     *
     * @param array  $request
     * @param string $type
     * @return BuilderInterface
     */
    public function setRequest(array $request, $type = self::GENERATE_TYPE_CREATE): self
    {
        $this->request = $this->cleanNulls($request);

        if (!$this->inRequestSet) {
            $this->inRequestSet = true;
            $this->eventManager->dispatch(
                $this->prefix . "_builder_set_request_{$type}",
                [
                    'builder' => $this
                ]
            );

            $this->eventManager->dispatch(
                $this->prefix . '_builder_set_request',
                [
                    'builder' => $this
                ]
            );
            $this->inRequestSet = false;
        }

        return $this;
    }

    /**
     * Remove items that are not allowed to be null
     *
     * @param array $request
     * @return array
     */
    protected function cleanNulls(array $request): array
    {
        $disallowNulls = [
            'customer',
            'billing_address',
            'shipping_address',
            'external_payment_methods'
        ];
        foreach ($disallowNulls as $key) {
            if (empty($request[$key])) {
                unset($request[$key]);
            }
        }
        return $request;
    }

    /**
     * Get order lines as array
     *
     * @param StoreInterface $store
     * @param bool           $orderItemsOnly
     * @return array
     * @throws LocalizedException
     */
    public function getOrderLines(StoreInterface $store, $orderItemsOnly = false): array
    {
        /** @var AbstractLine $model */
        foreach ($this->getOrderLinesCollector()->getCollectors($store) as $model) {
            if ($model->isIsTotalCollector() && $orderItemsOnly) {
                continue;
            }

            $model->fetch($this);
        }

        return $this->orderLines;
    }

    /**
     * Add an order line
     *
     * @param array $orderLine
     * @return BuilderInterface
     */
    public function addOrderLine(array $orderLine): self
    {
        $this->orderLines[] = $orderLine;

        return $this;
    }

    /**
     * Remove all order lines
     *
     * @return BuilderInterface
     */
    public function resetOrderLines(): self
    {
        $this->orderLines = [];

        return $this;
    }

    /**
     * Get merchant references
     *
     * @param CartInterface $quote
     * @return DataObject
     */
    public function getMerchantReferences(CartInterface $quote): DataObject
    {
        $merchantReferences = $this->dataObjectFactory->create([
            'data' => [
                'merchant_reference_1' => $quote->getReservedOrderId(),
                'merchant_reference_2' => ''
            ]
        ]);

        $this->eventManager->dispatch(
            $this->prefix . '_merchant_reference_update',
            [
                'quote'                     => $quote,
                'merchant_reference_object' => $merchantReferences
            ]
        );
        return $merchantReferences;
    }

    /**
     * Get Terms URL
     *
     * @param StoreInterface $store
     * @param string         $configPath
     * @return mixed|string
     * @deprecated
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function getTermsUrl(StoreInterface $store, string $configPath = 'terms_url')
    {
        return '';
    }

    /**
     * Populate prefill values
     *
     * @param array          $create
     * @param CartInterface  $quote
     * @param StoreInterface $store
     * @return mixed
     */
    public function prefill(array $create, CartInterface $quote, StoreInterface $store)
    {
        /**
         * Customer
         */
        $create['customer'] = $this->getCustomerData($quote);

        /**
         * Billing Address
         */
        $create['billing_address'] = $this->getAddressData($quote, Address::TYPE_BILLING);

        /**
         * Shipping Address
         */
        if (isset($create['billing_address'])
            && $this->configHelper->isCheckoutConfigFlag('separate_address', $store)
        ) {
            $create['shipping_address'] = $this->getAddressData($quote, Address::TYPE_SHIPPING);
        }
        return $create;
    }

    /**
     * Get customer details
     *
     * @param CartInterface $quote
     * @return array
     */
    public function getCustomerData(CartInterface $quote): ?array
    {
        if (!$quote->getCustomerIsGuest() && $quote->getCustomerDob()) {
            return [
                'date_of_birth' => $this->coreDate->date('Y-m-d', $quote->getCustomerDob())
            ];
        }

        return null;
    }

    /**
     * Auto fill user address details
     *
     * @param CartInterface $quote
     * @param string        $type
     *
     * @return array
     */
    protected function getAddressData(CartInterface $quote, $type = null): array
    {
        $result = [];
        if ($quote->getCustomerEmail()) {
            $result['email'] = $quote->getCustomerEmail();
        }

        $address = $quote->getShippingAddress();
        if ($type === Address::TYPE_BILLING || $quote->isVirtual()) {
            $address = $quote->getBillingAddress();
        }

        return $this->processAddress($result, $quote, $address);
    }

    /**
     * @param array         $result
     * @param CartInterface $quote
     * @param Address       $address
     * @return array
     */
    private function processAddress(array $result, CartInterface $quote, Address $address = null): array
    {
        $resultObject = $this->dataObjectFactory->create(['data' => $result]);
        if ($address) {
            $address->explodeStreetAddress();
            $this->objCopyService->copyFieldsetToTarget(
                'sales_convert_quote_address',
                'to_klarna',
                $address,
                $resultObject
            );

            /*
             * Making sure the billing address' organization name is empty
             * during requests to prevent error when B2B is disabled
             */
            if ($this->shouldClearOrganizationName($quote, $address)) {
                $resultObject->setOrganizationName('');
            }
            if ($address->getCountryId() === 'US') {
                $resultObject->setRegion($address->getRegionCode());
            }
        }

        $street_address = $this->prepareStreetAddressArray($resultObject);
        $resultObject->setStreetAddress($street_address[0]);
        $resultObject->setData('street_address2', $street_address[1]);

        if (isset($result['email'])) {
            $resultObject->setEmail($result['email']);
        }

        return array_filter($resultObject->toArray());
    }

    /**
     * @param DataObject $resultObject
     * @return array
     */
    private function prepareStreetAddressArray(DataObject $resultObject): array
    {
        $street_address = $resultObject->getStreetAddress();
        if (!is_array($street_address)) {
            $street_address = [$street_address];
        }
        if (count($street_address) === 1) {
            $street_address[] = '';
        }
        return $street_address;
    }

    /**
     * Verifies if we should clear the organization name from the address object
     *
     * @param CartInterface $quote
     * @param Address       $address
     * @return bool
     */
    private function shouldClearOrganizationName(CartInterface $quote, Address $address): bool
    {
        $store = $quote->getStore();
        $b2bEnabled = $this->configHelper->isPaymentConfigFlag('enable_b2b', $store);
        $isBillingAddress = $address->getAddressType() === Address::TYPE_BILLING;

        return !$b2bEnabled && $isBillingAddress;
    }

    /**
     * @param array $items
     * @return BuilderInterface
     */
    public function setItems($items): self
    {
        $this->setData('items', $items);
        return $this;
    }

    /**
     * @return array
     */
    public function getItems(): array
    {
        return $this->getData('items');
    }
}