Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mischabraam committed Jul 7, 2023
1 parent 8494fb9 commit afe34fd
Show file tree
Hide file tree
Showing 22 changed files with 754 additions and 21 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
.idea
composer.lock
vendor
20 changes: 20 additions & 0 deletions Api/Data/StoreLinkedInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace IODigital\Core\Api\Data;

/**
* Interface StoreLinkedInterface
*
* Below values are all provided in the IODigital\Core\Model\ResourceModel\AbstractStoreLinkedCollection
* performAfterLoad();
*
* @method array getStoreId()
* @method StoreLinkedInterface setStoreId(array $storeId)
* @method string getStoreCode()
* @method StoreLinkedInterface setStoreCode(string $storeCode)
*/
interface StoreLinkedInterface
{
}
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

54 changes: 54 additions & 0 deletions Model/Config/Source/LogLevel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace IODigital\Core\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;
use Psr\Log\LogLevel as PsrLogLevel;

class LogLevel implements OptionSourceInterface
{
/**
* Returns array of Psr Log Levels.
*
* @return array<array<string, string>>
*/
public function toOptionArray()
{
return [
[
'label' => PsrLogLevel::EMERGENCY,
'value' => PsrLogLevel::EMERGENCY,
],
[
'label' => PsrLogLevel::ALERT,
'value' => PsrLogLevel::ALERT,
],
[
'label' => PsrLogLevel::CRITICAL,
'value' => PsrLogLevel::CRITICAL,
],
[
'label' => PsrLogLevel::ERROR,
'value' => PsrLogLevel::ERROR,
],
[
'label' => PsrLogLevel::WARNING,
'value' => PsrLogLevel::WARNING,
],
[
'label' => PsrLogLevel::NOTICE,
'value' => PsrLogLevel::NOTICE,
],
[
'label' => PsrLogLevel::INFO,
'value' => PsrLogLevel::INFO,
],
[
'label' => PsrLogLevel::DEBUG,
'value' => PsrLogLevel::DEBUG,
],
];
}
}
162 changes: 162 additions & 0 deletions Model/ResourceModel/AbstractStoreLinkedCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<?php

declare(strict_types=1);

namespace IODigital\Core\Model\ResourceModel;

use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
use Magento\Framework\Data\Collection\EntityFactoryInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;

use function array_search;
use function count;
use function current;
use function in_array;
use function is_array;
use function key;

/**
* This class can be used for collection for entities which have a store view link
*/
abstract class AbstractStoreLinkedCollection extends AbstractCollection
{
protected const STORE_LINK_TABLE_ALIAS = 'store_link_table';

protected const STORE_LINK_TABLE_STORE_ID_ALIAS = 'store_id';

public function __construct(
protected EntityFactoryInterface $entityFactory,
protected LoggerInterface $logger,
protected FetchStrategyInterface $fetchStrategy,
protected ManagerInterface $eventManager,
protected StoreManagerInterface $storeManager,
protected MetadataPool $metadataPool,
protected ?AdapterInterface $connection = null,
protected ?AbstractDb $resource = null
) {
parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
}

protected function performAfterLoad(string $tableName, ?string $linkField): void
{
$linkedIds = $this->getColumnValues($this->getIdFieldName());
if (count($linkedIds)) {
$connection = $this->getConnection();
$select = $connection->select()
->from([static::STORE_LINK_TABLE_ALIAS => $this->getTable($tableName)])
->where(static::STORE_LINK_TABLE_ALIAS . '.' . $linkField . ' IN (?)', $linkedIds);

$result = $connection->fetchAll($select);

$storesData = [];
foreach ($result as $storeData) {
$storesData[$storeData[$linkField]][] = $storeData[static::STORE_LINK_TABLE_STORE_ID_ALIAS];
}

foreach ($this as $item) {
$linkedId = $item->getData($this->getIdFieldName());
$storeIds = $storesData[$linkedId] ?? [Store::DEFAULT_STORE_ID];

$storeIdKey = array_search(Store::DEFAULT_STORE_ID, $storeIds, true);
if ($storeIdKey !== false) {
$stores = $this->storeManager->getStores(false, true);
$storeId = current($stores)->getId();
$storeCode = key($stores);
} else {
$storeId = current($storeIds);
$storeCode = $this->storeManager->getStore($storeId)->getCode();
}
$item->setData('_first_store_id', $storeId);
$item->setData('store_code', $storeCode);
$item->setData('store_id', $storeIds);
}
}
}

/**
* Add field filter to collection
*
* @param array|string $field
* @param string|int|array|null $condition
* @return $this
*/
public function addFieldToFilter($field, $condition = null): self
{
if ($field === 'store_id') {
return $this->addStoreFilter($condition, false);
}

return parent::addFieldToFilter($field, $condition);
}

/**
* Add filter by store
*
* @param int|array|Store $store
* @param bool $withAdmin
* @return $this
*/
public function addStoreFilter($store, bool $withAdmin = true): self
{
if (!$this->getFlag('store_filter_added')) {
$this->performAddStoreFilter($store, $withAdmin);
$this->setFlag('store_filter_added', true);
}

return $this;
}

/**
* Perform adding filter by store
*
* @param int|array|Store $store
* @param bool $withAdmin
* @return void
*/
protected function performAddStoreFilter($store, bool $withAdmin = true): void
{
if ($store instanceof Store) {
$store = [$store->getId()];
}

if (!is_array($store)) {
$store = [$store];
}

if ($withAdmin) {
$store[] = Store::DEFAULT_STORE_ID;
}

$conditions = [['in' => $store]];

// When results when the default store are retrieved, also search for where no store was set yet
if (in_array(Store::DEFAULT_STORE_ID, $store)) {
$conditions[] = ['null' => true];
}

$this->addFilter('store', $conditions, 'public');
}

/**
* Join store relation table if there is store filter
*/
protected function joinStoreRelationTable(string $tableName, ?string $linkField): void
{
if ($this->getFilter('store')) {
$this->getSelect()->joinLeft(
['store_table' => $this->getTable($tableName)],
'main_table.' . $this->getIdFieldName() . ' = store_table.' . $linkField,
[]
)->group(
'main_table.' . $this->getIdFieldName()
);
}
}
}
39 changes: 39 additions & 0 deletions Model/ResourceModel/AbstractStoreLinkedReadHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace IODigital\Core\Model\ResourceModel;

use Magento\Framework\EntityManager\Operation\ExtensionInterface;
use Magento\Framework\Exception\LocalizedException;

/**
* This class can be used for readHandlers for entities which have a store view link
* Do keep in mind that the right resourceModel should be passed as argument.
*
* Note: This class is actually not abstract to make it possible create a virtual type of this class.
*/
class AbstractStoreLinkedReadHandler implements ExtensionInterface
{
public function __construct(
protected AbstractStoreLinkedResource $resourceModel
) {
}

/**
* @param object $entity
* @param array $arguments
* @return object
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @throws LocalizedException
*/
public function execute($entity, $arguments = [])
{
if ($entity->getId()) {
$stores = $this->resourceModel->lookupStoreIds((int) $entity->getId());
$entity->setData('store_id', $stores);
}

return $entity;
}
}
Loading

0 comments on commit afe34fd

Please sign in to comment.