Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true,
"phpro/grumphp": true,
"emico/code-quality": true
"emico/code-quality": true,
"magento/magento-composer-installer": true,
"emico/codeception-m2": true
}
}
}
2 changes: 0 additions & 2 deletions src/Model/ResourceModel/Page/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ protected function _construct()
}

/**
* Initialize select with join
*
* @return $this
*/
protected function _initSelect()
Expand Down
97 changes: 97 additions & 0 deletions src/Model/ResourceModel/Page/Grid/Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace Emico\AttributeLanding\Model\ResourceModel\Page\Grid;

use Magento\Framework\DB\Select;
use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult;
use Zend_Db_Expr;

class Collection extends SearchResult
{
/**
* Add the store URL and store name aggregation just before the collection loads,
* after SearchResult has finished setting up its base SELECT.
*
* @return $this
*/
protected function _beforeLoad()
{
$this->getSelect()
->joinLeft(
['emico_attributelanding_page_store' => $this->getTable('emico_attributelanding_page_store')],
'main_table.page_id = emico_attributelanding_page_store.page_id',
[
'store_urls' => new Zend_Db_Expr(
'GROUP_CONCAT(DISTINCT CONCAT(emico_attributelanding_page_store.store_id, \':\', emico_attributelanding_page_store.url_path) '
. 'ORDER BY emico_attributelanding_page_store.store_id SEPARATOR \',\')'
),
'name' => new Zend_Db_Expr(
'GROUP_CONCAT(DISTINCT CONCAT(emico_attributelanding_page_store.store_id, \':\', emico_attributelanding_page_store.name) '
. 'ORDER BY emico_attributelanding_page_store.store_id SEPARATOR \',\')'
),
]
)
->group('main_table.page_id');
return parent::_beforeLoad();
}

/**
* Override the count SELECT to include the store join and GROUP BY when a HAVING
* clause is present, so GROUP_CONCAT aggregate filters work correctly during pagination.
*
* @return Select
*/
public function getSelectCountSql()
{
$countSelect = parent::getSelectCountSql();

$having = $countSelect->getPart(Select::HAVING);
if (empty($having)) {
return $countSelect;
}

$countSelect->joinLeft(
['emico_attributelanding_page_store' => $this->getTable('emico_attributelanding_page_store')],
'main_table.page_id = emico_attributelanding_page_store.page_id',
[]
);
$countSelect->group('main_table.page_id');

return $this->getConnection()->select()->from($countSelect, [new Zend_Db_Expr('COUNT(*)')]);
}

/**
* Intercept store_urls and name filters and apply them as HAVING clauses so they
* work against the GROUP_CONCAT aggregates instead of raw columns.
*
* @param string|array $field
* @param mixed $condition
* @return $this
*/
public function addFieldToFilter($field, $condition = null)
{
if ($field === 'store_urls') {
$value = is_array($condition) ? ($condition['like'] ?? reset($condition)) : $condition;
$value = trim((string) $value, '%');
$this->getSelect()->having(
'GROUP_CONCAT(DISTINCT CONCAT(emico_attributelanding_page_store.store_id, \':\', emico_attributelanding_page_store.url_path) ORDER BY emico_attributelanding_page_store.store_id SEPARATOR \',\') LIKE ?',
'%' . $value . '%'
);
return $this;
}

if ($field === 'name') {
$value = is_array($condition) ? ($condition['like'] ?? reset($condition)) : $condition;
$value = trim((string) $value, '%');
$this->getSelect()->having(
'GROUP_CONCAT(DISTINCT CONCAT(emico_attributelanding_page_store.store_id, \':\', emico_attributelanding_page_store.name) ORDER BY emico_attributelanding_page_store.store_id SEPARATOR \',\') LIKE ?',
'%' . $value . '%'
);
return $this;
}

return parent::addFieldToFilter($field, $condition);
}
}
75 changes: 75 additions & 0 deletions src/Ui/Component/Listing/Column/StoreUrls.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace Emico\AttributeLanding\Ui\Component\Listing\Column;

use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Ui\Component\Listing\Columns\Column;

class StoreUrls extends Column
{
/**
* @param ContextInterface $context
* @param UiComponentFactory $uiComponentFactory
* @param StoreRepositoryInterface $storeRepository
* @param array $components
* @param array $data
*/
public function __construct(
ContextInterface $context,
UiComponentFactory $uiComponentFactory,
private readonly StoreRepositoryInterface $storeRepository,
array $components = [],
array $data = []
) {
parent::__construct($context, $uiComponentFactory, $components, $data);
}

/**
* Prepare Data Source by replacing the raw store_urls string with a human-readable list.
*
* @param array $dataSource
* @return array
*/
public function prepareDataSource(array $dataSource): array
{
if (!isset($dataSource['data']['items'])) {
return $dataSource;
}

$stores = $this->storeRepository->getList();
$storeNames = [];
foreach ($stores as $store) {
$storeNames[(int) $store->getId()] = $store->getName();
}

$columnName = $this->getData('name');
foreach (array_keys($dataSource['data']['items']) as $index) {
$raw = $dataSource['data']['items'][$index][$columnName] ?? '';

if ($raw === '') {
$dataSource['data']['items'][$index][$columnName] = '';
continue;
}

$lines = [];
foreach (explode(',', (string) $raw) as $entry) {
$parts = explode(':', $entry, 2);
if (count($parts) !== 2) {
continue;
}
[$storeId, $urlPath] = $parts;
$storeId = (int) $storeId;
$storeName = $storeId === 0 ? __('Global') : ($storeNames[$storeId] ?? __('Store %1', $storeId));
$lines[] = sprintf('%s: %s', $storeName, $urlPath);
}

$dataSource['data']['items'][$index][$columnName] = implode('<br/>', $lines);
}

return $dataSource;
}
}
5 changes: 2 additions & 3 deletions src/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
type="Emico\AttributeLanding\Model\FilterHider\MagentoFilterHider"/>
<preference for="Magento\Catalog\Block\Breadcrumbs" type="Emico\AttributeLanding\Block\Catalog\Breadcrumbs"/>

<virtualType name="Emico\AttributeLanding\Model\ResourceModel\Page\Grid\Collection"
type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
<type name="Emico\AttributeLanding\Model\ResourceModel\Page\Grid\Collection">
<arguments>
<argument name="mainTable" xsi:type="string">emico_attributelanding_page</argument>
<argument name="resourceModel" xsi:type="string">
Emico\AttributeLanding\Model\ResourceModel\Page\Collection
</argument>
</arguments>
</virtualType>
</type>

<virtualType name="Emico\AttributeLanding\Model\ResourceModel\OverviewPage\Grid\Collection"
type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@
<label translate="true">ID</label>
</settings>
</column>
<column name="name" sortOrder="35">
<column class="Emico\AttributeLanding\Ui\Component\Listing\Column\StoreUrls" name="name" sortOrder="35">
<settings>
<filter>text</filter>
<label translate="true">Name</label>
<sortable>false</sortable>
<bodyTmpl>ui/grid/cells/html</bodyTmpl>
</settings>
</column>
<column name="created_at" sortOrder="47">
Expand All @@ -102,6 +104,14 @@
<label translate="true">Updated at</label>
</settings>
</column>
<column class="Emico\AttributeLanding\Ui\Component\Listing\Column\StoreUrls" name="store_urls" sortOrder="49">
<settings>
<label translate="true">Store URLs</label>
<sortable>false</sortable>
<filter>text</filter>
<bodyTmpl>ui/grid/cells/html</bodyTmpl>
</settings>
</column>
<actionsColumn class="Emico\AttributeLanding\Ui\Component\Listing\Column\PageActions" name="actions" sortOrder="50">
<settings>
<indexField>page_id</indexField>
Expand Down
24 changes: 0 additions & 24 deletions tests/Functional/InitialTest.php

This file was deleted.

Loading