xero-8.x-2.x-dev/src/XeroItemManager.php

src/XeroItemManager.php
<?php

namespace Drupal\xero;

use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\xero\Plugin\DataType\XeroItemList;
use Drupal\xero\TypedData\XeroComplexItemInterface;

/**
 * Provides a service for managing Xero items.
 *
 * This is a simplifying wrapper around Xero queries.
 */
class XeroItemManager implements XeroItemManagerInterface {

  use StringTranslationTrait;

  /**
   * The typed data manager.
   *
   * @var \Drupal\Core\TypedData\TypedDataManagerInterface
   */
  protected $typedDataManager;

  /**
   * A Xero query factory.
   *
   * @var \Drupal\xero\XeroQueryFactory
   */
  protected $xeroQueryFactory;

  /**
   * A logger channel for recording errors.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected $logger;

  /**
   * Whether or not to throw errors generated when the query is executed.
   *
   * @var bool
   */
  protected $throwErrors = FALSE;

  /**
   * Constructs a new XeroItemManager object.
   *
   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
   *   The typed data manager.
   * @param \Drupal\xero\XeroQueryFactory $xero_query_factory
   *   The Xero query factory.
   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
   *   The Drupal logger factory.
   */
  public function __construct(TypedDataManagerInterface $typed_data_manager, XeroQueryFactory $xero_query_factory, LoggerChannelFactoryInterface $logger_factory) {
    $this->typedDataManager = $typed_data_manager;
    $this->xeroQueryFactory = $xero_query_factory;
    $this->logger = $logger_factory->get('xero');
  }

  /**
   * {@inheritDoc}
   */
  public function createItem(XeroComplexItemInterface $item): bool|XeroComplexItemInterface {
    return $this->sendItem($item, 'put');
  }

  /**
   * {@inheritDoc}
   */
  public function updateItem(XeroComplexItemInterface $item): bool|XeroComplexItemInterface {
    return $this->sendItem($item, 'post');
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   * @throws \Throwable
   */
  public function loadItem($type, $guid): bool|XeroComplexItemInterface {
    $xeroQuery = $this->xeroQueryFactory->get();
    $xeroQuery->setType($type)
      ->setId($guid)
      ->throwErrors($this->throwErrors);

    $item_list = $xeroQuery->execute();

    if ($item_list instanceof XeroItemList && count($item_list) === 1) {
      $result = $item_list->get(0);
    }
    else {
      $result = FALSE;
      $this->logger->error('Could not load @type @guid from Xero', [
        '@type' => $type,
        '@guid' => $guid,
      ]);
    }
    return $result;
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   * @throws \Throwable
   */
  public function reloadItem(XeroComplexItemInterface $item): bool|XeroComplexItemInterface {
    $type = $item->getDataDefinition()->getDataType();
    $guidName = $item->getXeroProperty('guid_name');
    if ($guidName) {
      $guid = $item->get($guidName)->getString();
    }
    else {
      throw new \InvalidArgumentException($this->t('Xero data type @type does not have an ID property', [
        '@type' => $item->getName(),
      ]));
    }
    return $this->loadItem($type, $guid);
  }

  /**
   * Sends a single item to Xero.
   *
   * @param \Drupal\xero\TypedData\XeroComplexItemInterface $item
   *   The Xero item to update.
   * @param string $method
   *   The HTTP method to use.
   *
   * @return \Drupal\xero\TypedData\XeroComplexItemInterface|bool
   *   A typed data representation of the Xero item, or FALSE if unsuccessful.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   * @throws \Throwable
   */
  protected function sendItem(XeroComplexItemInterface $item, string $method): bool|XeroComplexItemInterface {
    $type = $item->getDataDefinition()->getDataType();

    /** @var \Drupal\Core\TypedData\ListDataDefinition $list_definition */
    $list_definition = $this->typedDataManager->createListDataDefinition($type);
    $items = $this->typedDataManager->create($list_definition, []);
    $items->offsetSet(0, $item);

    // Do the remote creation.
    $xeroQuery = $this->xeroQueryFactory->get();
    $xeroQuery->setType($type)
      ->setData($items)
      ->setMethod($method)
      ->throwErrors($this->throwErrors);

    // If the method is post, then the id must be set or XeroQuery
    // will change the method to put.
    $guidName = $item->getXeroProperty('guid_name');
    $guid = $item->get($guidName)->getString();
    if (!empty($guid)) {
      $xeroQuery->setId($guid);
    }

    /** @var \Drupal\xero\Plugin\DataType\XeroItemList $result */
    $result = $xeroQuery->execute();

    if ($result instanceof XeroItemList && $result->count() > 0) {
      return $result->get(0);
    }

    $this->logger->error(
      'Sending @type data by @method to Xero failed for this data:\n @item_data', [
        '@type' => $type,
        '@method' => $method,
        '@item_data' => print_r($this->preparePropertiesAsStringArray($item), TRUE),
      ]
    );

    return FALSE;
  }

  /**
   * {@inheritdoc}
   *
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function findItem($type, array $conditions, $unique = FALSE): bool|XeroComplexItemInterface|null {
    $xeroQuery = $this->xeroQueryFactory->get();
    $xeroQuery->setType($type)
      ->throwErrors($this->throwErrors);
    foreach ($conditions as $condition) {
      // The third argument is optional.
      if (isset($condition[2])) {
        $xeroQuery->addCondition($condition[0], $condition[1], $condition[2]);
      }
      else {
        $xeroQuery->addCondition($condition[0], $condition[1]);
      }
    }

    $item_list = $xeroQuery->execute();

    // If there is a single matching item, return it.
    // If there are multiple matching items, return the first one only if
    // the match is not required to be unique.
    if ($item_list && $item_list instanceof XeroItemList) {
      $result = NULL;
      $count = count($item_list);
      if ($count !== 0 && ($unique === FALSE || $count === 1)) {
        $result = $item_list->get(0);
      }
    }
    else {
      $result = FALSE;
      $this->logger->error(
        'Unexpected response when trying to find @type data on Xero with these conditions:\n @item_data', [
          '@type' => $type,
          '@conditions' => print_r($conditions, TRUE),
        ]
      );
    }

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function throwErrors($shouldThrow = TRUE): XeroItemManagerInterface {
    $this->throwErrors = $shouldThrow;
    return $this;
  }

  /**
   * Convert an item into a pretty-printable array of string properties.
   *
   * @param \Drupal\xero\TypedData\XeroComplexItemInterface $item
   *   The item to prepare a string array from.
   *
   * @return array
   *   An array of properties specified on the item, keyed by property name.
   *
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   */
  protected function preparePropertiesAsStringArray(XeroComplexItemInterface $item) {
    $properties = $item->getSpecifiedProperties();
    $result = [];
    foreach ($properties as $name => $property) {
      $result[$name] = $item->get($name)->getString();
    }
    return $result;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc