src/module-elasticsuite-thesaurus/Model/ResourceModel/Thesaurus/Collection.php
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\Elasticsuite________
* @author Romain Ruaud <romain.ruaud@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteThesaurus\Model\ResourceModel\Thesaurus;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\Store;
use Smile\ElasticsuiteThesaurus\Api\Data\ThesaurusInterface;
/**
* Thesaurus Collection Resource Model
*
* @category Smile
* @package Smile\ElasticsuiteThesaurus
* @author Romain Ruaud <romain.ruaud@smile.fr>
*/
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
/**
* Store for filter
*
* @var integer
*/
private $storeId;
/**
* Store manager
*
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $storeManager;
/**
* Search resource helper
*
* @var \Magento\Framework\DB\Helper
*/
private $resourceHelper;
/**
* If link with terms has already been established
*
* @var boolean
*/
private $termsLinked = false;
/**
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory Entity Factory
* @param \Psr\Log\LoggerInterface $logger Logger
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy Fetch Strategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager Event Manager
* @param \Magento\Store\Model\StoreManagerInterface $storeManager Store Manager
* @param \Magento\Framework\DB\Helper $resourceHelper Resource Helper
* @param \Magento\Framework\DB\Adapter\AdapterInterface $connection Database Connection
* @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource Abstract Resource
*/
public function __construct(
\Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\DB\Helper $resourceHelper,
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
\Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
) {
$this->storeManager = $storeManager;
$this->resourceHelper = $resourceHelper;
parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
}
/**
* Set Store ID for filter
*
* @param Store|int $store The store
*
* @return $this
*/
public function setStoreId($store)
{
if ($store instanceof Store) {
$store = $store->getId();
}
$this->storeId = $store;
return $this;
}
/**
* Retrieve Store ID Filter
*
* @return int|null
*/
public function getStoreId()
{
return $this->storeId;
}
/**
* Set thesaurus term to filter
*
* @param string $term The term to filter
*
* @return $this
*/
public function setTermFilter($term)
{
$term = preg_replace("/[\s-]/", "%", $term);
$this->addTermFilterToSelect($term);
return $this;
}
/**
* Filter collection by specified store ids
*
* @param array|int $storeIds The store ids to filter
*
* @return $this
*/
public function addStoreFilter($storeIds)
{
$defaultStoreId = Store::DEFAULT_STORE_ID;
if (!is_array($storeIds)) {
$storeIds = [$storeIds];
}
if (!in_array($defaultStoreId, $storeIds)) {
$storeIds[] = $defaultStoreId;
}
$this->getSelect()
->join(
['store_table' => $this->getTable(ThesaurusInterface::STORE_TABLE_NAME)],
'main_table.' . ThesaurusInterface::THESAURUS_ID . ' = store_table.' . ThesaurusInterface::THESAURUS_ID,
[]
)
->where('store_table.store_id IN (?)', $storeIds)
->group('main_table.' . ThesaurusInterface::THESAURUS_ID);
return $this;
}
/**
* Join store relation table if there is store filter
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
protected function _renderFiltersBefore()
{
if ($this->getFilter('store')) {
$this->getSelect()->join(
['store_table' => $this->getTable(ThesaurusInterface::STORE_TABLE_NAME)],
'main_table.' . ThesaurusInterface::THESAURUS_ID . ' = store_table.' . ThesaurusInterface::THESAURUS_ID,
[]
)->group(
'main_table.' . ThesaurusInterface::THESAURUS_ID
);
}
parent::_renderFiltersBefore();
}
/**
* Init model for collection
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
protected function _construct()
{
$this->_init(
'Smile\ElasticsuiteThesaurus\Model\Thesaurus',
'Smile\ElasticsuiteThesaurus\Model\ResourceModel\Thesaurus'
);
}
/**
* Perform operations after collection load
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*
* @return $this
*/
protected function _afterLoad()
{
$this->loadStores();
$this->loadTermsData();
return parent::_afterLoad();
}
/**
* Inject terms data on collection
*
* @param string $term Term filter text.
*
* @return $this
*/
private function addTermFilterToSelect($term)
{
$select = $this->getSelect();
if ($this->termsLinked === false) {
$select->joinLeft(
['expansion_table' => $this->getTable(ThesaurusInterface::EXPANSION_TABLE_NAME)],
new \Zend_Db_Expr("main_table.thesaurus_id = expansion_table.thesaurus_id"),
[
'expansion_terms' => new \Zend_Db_Expr("GROUP_CONCAT( DISTINCT expansion_table.term SEPARATOR ',')"),
]
);
$select->joinLeft(
['reference_table' => $this->getTable(ThesaurusInterface::REFERENCE_TABLE_NAME)],
new \Zend_Db_Expr(
"reference_table.term_id = expansion_table.term_id " .
"AND main_table." . ThesaurusInterface::THESAURUS_ID . " = reference_table." . ThesaurusInterface::THESAURUS_ID
),
['reference_terms' => new \Zend_Db_Expr("GROUP_CONCAT( DISTINCT reference_table.term SEPARATOR ',')")]
);
$select->group("main_table." . ThesaurusInterface::THESAURUS_ID);
$select->where("expansion_table.term LIKE '%{$term}%'", $term)
->orWhere("reference_table.term LIKE '%{$term}%'", $term);
$this->termsLinked = true;
}
return $select;
}
/**
* Perform operations after collection load
*
* @return void
*/
private function loadStores()
{
$itemIds = array_keys($this->_items);
if (count($itemIds)) {
$connection = $this->getConnection();
$select = $connection->select()
->from(['thesaurus_entity_store' => $this->getTable(ThesaurusInterface::STORE_TABLE_NAME)])
->where('thesaurus_entity_store.' . ThesaurusInterface::THESAURUS_ID . ' IN (?)', $itemIds)
;
$result = [];
foreach ($connection->fetchAll($select) as $item) {
$result[$item[ThesaurusInterface::THESAURUS_ID]][] = $item[ThesaurusInterface::STORE_ID];
}
if ($result) {
foreach ($this as $item) {
$entityId = $item->getData(ThesaurusInterface::THESAURUS_ID);
if (!isset($result[$entityId])) {
continue;
}
$storeCodes = [];
$storeIds = [];
foreach ($result[$entityId] as $storeId) {
if ($storeId == 0) {
$storeIds = array_map(function (StoreInterface $store) {
return $store->getId();
}, $this->storeManager->getStores(false, true));
$storeCodes = array_map(function (StoreInterface $store) {
return $store->getCode();
}, $this->storeManager->getStores(false, true));
}
if ($storeId != 0) {
$storeCodes[] = $this->storeManager->getStore($storeId)->getCode();
$storeIds[] = $storeId;
}
}
$item->setData('store_ids', $storeIds);
$item->setData('store_codes', implode(";", $storeCodes));
}
}
}
}
/**
* Perform operations after collection load
*
* @return void
*/
private function loadTermsData()
{
$select = $this->getConnection()->select();
$itemIds = array_keys($this->_items);
$select->from(['exp' => $this->getTable(ThesaurusInterface::EXPANSION_TABLE_NAME)], [])
->joinLeft(
['ref' => $this->getTable(ThesaurusInterface::REFERENCE_TABLE_NAME)],
"exp.thesaurus_id = ref.thesaurus_id AND exp.term_id = ref.term_id",
[]
)
->where('exp.thesaurus_id IN (?)', $itemIds)
->group(["exp.thesaurus_id", "exp.term_id"])
->columns(
[
'thesaurus_id' => 'exp.thesaurus_id',
'expansions_terms' => new \Zend_Db_Expr("GROUP_CONCAT(exp.term)"),
'expanded_term' => 'ref.term',
]
);
$data = $this->getConnection()->fetchAll($select);
$this->addTermData($data);
$this->addTermExportData($data);
}
/**
* Process terms of each thesaurus and display a summary for each thesaurus.
*
* @param array $termData Raw terms data loaded from the DB.
*
* @return $this
*/
private function addTermData($termData)
{
$labelsByThesaurusId = [];
foreach ($termData as $currentTerm) {
$label = $currentTerm['expansions_terms'];
if (isset($currentTerm['expanded_term']) && $currentTerm['expanded_term']) {
$label = sprintf("%s => %s", $currentTerm['expanded_term'], $label);
}
$labelsByThesaurusId[$currentTerm['thesaurus_id']][] = $label;
}
foreach ($labelsByThesaurusId as $thesaurusId => $labels) {
$this->_items[$thesaurusId]->setData('terms_summary', implode(" <br/> ", $labels));
}
return $this;
}
/**
* Process terms of each thesaurus for export.
*
* @param array $termData Raw terms data loaded from the DB.
*
* @return $this
*/
private function addTermExportData($termData)
{
$labelsByThesaurusId = [];
foreach ($termData as $currentTerm) {
$label = $currentTerm['expansions_terms'];
if (isset($currentTerm['expanded_term']) && $currentTerm['expanded_term']) {
$label = sprintf("%s:%s", $currentTerm['expanded_term'], $label);
}
$labelsByThesaurusId[$currentTerm['thesaurus_id']][] = $label;
}
foreach ($labelsByThesaurusId as $thesaurusId => $labels) {
$this->_items[$thesaurusId]->setData('terms_export', implode(";", $labels));
}
return $this;
}
}