arch-8.x-1.x-dev/modules/product/modules/group/src/GroupHandler.php
modules/product/modules/group/src/GroupHandler.php
<?php namespace Drupal\arch_product_group; use Drupal\arch_product\Entity\ProductInterface; use Drupal\Core\Database\Connection; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\LanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Group handler. * * @package Drupal\arch_product_group */ class GroupHandler implements GroupHandlerInterface, ContainerInjectionInterface { /** * Database connection. * * @var \Drupal\Core\Database\Connection */ protected $db; /** * Product storage. * * @var \Drupal\arch_product\Entity\Storage\ProductStorageInterface */ protected $productStorage; /** * Module handler. * * @var \Drupal\Core\Extension\ModuleHandlerInterface */ protected $moduleHandler; /** * Language manager. * * @var \Drupal\Core\Language\LanguageManagerInterface */ protected $languageManager; /** * Product cache. * * @var \Drupal\arch_product\Entity\ProductInterface[][] */ protected $cache = []; /** * GroupHandler constructor. * * @param \Drupal\Core\Database\Connection $db * Database connection. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * Entity type manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * Module handler. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * Language manager. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ public function __construct( Connection $db, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager, ) { $this->db = $db; $this->productStorage = $entity_type_manager->getStorage('product'); $this->moduleHandler = $module_handler; $this->languageManager = $language_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('database'), $container->get('entity_type.manager'), $container->get('module_handler'), $container->get('language_manager') ); } /** * {@inheritdoc} */ public function isPartOfGroup(ProductInterface $product) { $group_id = $this->getGroupIdValue($product); if (empty($group_id)) { return FALSE; } $members = $this->findGroupMembers($group_id); return count($members) > 1; } /** * {@inheritdoc} */ public function isGroupParent(ProductInterface $product) { if (!$this->isPartOfGroup($product)) { return FALSE; } return (int) $product->id() === $this->getGroupIdValue($product); } /** * {@inheritdoc} */ public function getGroupId(ProductInterface $product) { if (!$this->isPartOfGroup($product)) { return FALSE; } return $this->getGroupIdValue($product); } /** * {@inheritdoc} */ public function getGroupParent(ProductInterface $product) { if (!$this->isPartOfGroup($product)) { return NULL; } if ($this->isGroupParent($product)) { return $product; } $group_id = $this->getGroupIdValue($product); /** @var \Drupal\arch_product\Entity\ProductInterface $parent */ $parent = $this->productStorage->load($group_id); return $parent; } /** * {@inheritdoc} */ public function getGroupProducts(ProductInterface $product) { if ($group_id = $this->getGroupId($product)) { return $this->findGroupMembers($group_id); } return []; } /** * {@inheritdoc} */ public function createGroup(array $products, $group_id = NULL) { if (empty($products)) { throw new \InvalidArgumentException('Empty product list'); } foreach ($products as $product) { if ($product instanceof ProductInterface) { continue; } throw new \InvalidArgumentException('Only Product entities allowed.'); } if (empty($group_id)) { $group_id = current($products)->id(); } $transaction_id = 'product_group_create' . $group_id; $transaction_manager = $this->db->transactionManager(); try { // @todo Check this! $transaction_manager->push($transaction_id); foreach ($products as $product) { $product->set('group_id', $group_id)->save(); } return TRUE; } catch (\Exception $e) { $transaction_manager->rollback($transaction_id, $transaction_id); throw $e; } } /** * {@inheritdoc} */ public function removeFromGroup(ProductInterface $product, $group_id) { $current_group = $this->getGroupIdValue($product); if ($current_group !== (int) $group_id) { // @todo maybe we should throw an exception. return FALSE; } return (bool) $product->set('group_id', $product->id())->save(); } /** * {@inheritdoc} */ public function leaveGroup(ProductInterface $product) { if ($this->isGroupParent($product)) { throw new \LogicException('Parent group could not leave group!'); } if (!$this->isPartOfGroup($product)) { return TRUE; } return (bool) $product->set('group_id', $product->id())->save(); } /** * {@inheritdoc} */ public function addToGroup(ProductInterface $product, $group_id) { $current_group = $this->getGroupId($product); if ($current_group === (int) $group_id) { return TRUE; } if ($this->isPartOfGroup($product)) { // @todo maybe we should throw exception. // @todo Deny move of product between groups. return FALSE; } return (bool) $product->set('group_id', $group_id)->save(); } /** * {@inheritdoc} */ public function dismissGroup($group_id) { $products = $this->findGroupMembers($group_id); if (empty($products)) { return TRUE; } $transaction_id = 'product_group_dismiss' . $group_id; $transaction_manager = $this->db->transactionManager(); try { // @todo Check this! $transaction_manager->push($transaction_id); foreach ($products as $product) { if ((int) $product->id() === (int) $group_id) { continue; } $this->removeFromGroup($product, $group_id); } return TRUE; } catch (\Exception $e) { $transaction_manager->rollback($transaction_id, $transaction_id); } return FALSE; } /** * Get group ID value from product. * * @param \Drupal\arch_product\Entity\ProductInterface $product * Product entity. * * @return int * Stored group ID. */ protected function getGroupIdValue(ProductInterface $product) { $group_id = (int) $product->get('group_id')->value; return (int) ($group_id ?: $product->id()); } /** * Find members of group. * * @param int $group_id * Group ID. * @param bool $reread * Force reread DB. * * @return \Drupal\arch_product\Entity\ProductInterface[] * List of group members. */ protected function findGroupMembers($group_id, $reread = FALSE) { if ($reread || !isset($this->cache[$group_id])) { $this->cache[$group_id] = $this->productStorage->loadByProperties([ 'group_id' => $group_id, ]); $current_language_id = $this->languageManager->getCurrentLanguage()->getId(); foreach ($this->cache[$group_id] as $pid => $product) { if ( $product->language()->getId() != $current_language_id && $product->hasTranslation($current_language_id) ) { $this->cache[$group_id][$pid] = $product->getTranslation($current_language_id); } } } return $this->cache[$group_id]; } }