first commit

This commit is contained in:
2025-08-02 16:30:27 +02:00
commit 23646bfcee
14851 changed files with 1750626 additions and 0 deletions

461
admin/parameters.php Normal file
View File

@@ -0,0 +1,461 @@
<?php
use KupShop\AdminBundle\Util\AdminSectionTree;
use KupShop\CatalogBundle\Section\SectionFilter;
use KupShop\CatalogBundle\Util\FilterUtil;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\Functional\Mapping;
use Query\Operator;
$main_class = 'Parameters';
class Parameters extends Window
{
private AdminSectionTree $adminSectionTree;
protected $nameField = 'name';
protected $defaults = [
'figure' => 'Y',
];
public function __construct()
{
$this->adminSectionTree = ServiceContainer::getService(AdminSectionTree::class);
}
public function getTemplate()
{
if ($this->getAction() == 'merge') {
return 'window/parameters.merge.tpl';
}
return parent::getTemplate();
}
public function get_vars()
{
$vars = parent::get_vars();
$ID = $this->getID();
$pageVars = getVal('body', $vars);
$pageVars['tree'] = $this->adminSectionTree->getCategories();
$pageVars['category0'] = $this->adminSectionTree->getCategory0();
$this->selected = $pageVars['selected'] = Mapping::mapKeys(
sqlQueryBuilder()
->select('id_section, filter, required')
->from('parameters_sections')
->where(Operator::equals(['id_parameter' => $this->getID()]))
->execute()->fetchAllAssociative(),
function ($k, $v) {
return [$v['id_section'], ['filter' => $v['filter'] === 'Y', 'required' => $v['required'] === 'Y']];
}
);
$this->adminSectionTree->getSelected($ID, 'parameters_sections', 'id_parameter');
$this->adminSectionTree->getOpened($pageVars['tree']);
$pageVars['opened'] = $this->adminSectionTree->opened;
$pageVars['producers'] = sqlFetchAll(sqlQueryBuilder()
->select('id, name')
->from('producers')
->execute(), 'id');
if (findModule(Modules::PRODUCERS)) {
$pageVars['producersSel'] = sqlFetchAll(sqlQueryBuilder()
->select('id_producer')
->from('parameters_producers')
->where(Operator::equals(['id_parameter' => $ID]))
->execute(), ['id_producer' => 'id_producer']);
}
// Values
$parameter = new Parameter($ID);
$pageVars['values'] = $parameter->fetchListValues();
$pageVars['data']['searchTerm'] = getVal('searchTerm');
$vars['body'] = $pageVars;
return $vars;
}
public function getData()
{
$data = parent::getData();
if (!empty($data['unit'])) {
$data['unit'] = join('|', array_map(function ($value) {
return trim($value);
}, explode(',', $data['unit'])));
}
return $data;
}
protected function getObject()
{
$data = parent::getObject();
$data['unit'] = str_replace('|', ', ', $data['unit']);
return $data;
}
protected function createObject()
{
$data = parent::createObject();
$data['data_type'] = 'float';
return $data;
}
public function handleUpdate()
{
$parameter = new Parameter();
$parameter->createFromDB($this->getID());
$SQL = parent::handleUpdate();
$ID = $this->getID();
if ($SQL) {
$data = $this->getData();
if ($parameter->unit && ($diff = array_diff($parameter->unit, explode('|', $data['unit'])))) {
sqlQueryBuilder()->update('parameters_products')
->set('unit', 'NULL')
->where(Operator::findInSet($diff, 'unit', 'OR'))
->andWhere(Operator::equals(['id_parameter' => $ID]))
->execute();
}
// ############################################
// # ZARAZENI DO SEKCI
if (findModule('products_sections')) {
$sec = getVal('sec', null, []);
$secloaded = getVal('secloaded', null, false);
if ($secloaded !== false) {
$this->saveParametersInSections($sec);
}
}
// ############################################
// ############################################
// # ZARAZENI K VYROBCUM
if (findModule('producers')) {
$this->saveProducersParameters(getVal('producers', default: []));
}
// ############################################
// # Hodnoty
$object = $this->getObject();
$data = $this->getData();
if ($object['value_type'] == 'list') {
$values = getVal('values', $data, []);
$this->createSQLFields('parameters_list');
foreach ($values as $id => $value) {
$value['id_parameter'] = $ID;
if (!empty($value['delete']) || !$id) {
unset($value['delete']);
if ($id > 0) {
$this->handleDeleteValue($id);
}
continue;
}
if (empty($value['value'])) {
continue;
}
$value = $this->getSQLFields($value);
$value['data'] = empty($values[$id]['data']) ? null : json_encode($values[$id]['data']);
if ($id < 0 || $this->isDuplicate()) {
$this->handleAddValue($value);
} else {
$this->handleUpdateValue($id, $value);
}
}
}
if ($parameter->value_type != $data['value_type']) {
$conversion = new \KupShop\CatalogBundle\Parameters\TypeConversion();
$conversion->convert($parameter, $data['value_type']);
$this->returnOK('Změna typu proběhla úspěšně');
}
if (findModule(Modules::INDEXED_FILTER)) {
\KupShop\IndexedFilterBundle\Util\FilterUrlDefaultValue::upgrade_filter_url('parameters_list');
}
}
return $SQL;
}
public function handleDeleteValue($id)
{
$this->deleteSQL('parameters_list', ['id' => $id]);
writeDownActivity(translate('logDeleteValue', 'parameters').': '.$id);
}
public function handleAddValue($values)
{
$this->insertSQL('parameters_list', $values, ['id']);
}
public function handleUpdateValue($id, $values)
{
$this->updateSQL('parameters_list', $values, ['id' => $id], ['id', 'id_parameter']);
}
public function handleMerge()
{
if (!getVal('Submit')) {
return;
}
$merge_with = getVal('merge_with');
if (empty($merge_with)) {
$this->returnError('Musíte vybrat hodnotu/hodnoty, se kterými se má tato hodnota sloučit');
}
$id_value = getVal('id_value');
foreach ($merge_with as $merge_id) {
sqlQuery('INSERT INTO parameters_products (id_parameter, id_product, value_list, unit, weight)
SELECT id_parameter, id_product, :merge_id, unit, weight
FROM parameters_products WHERE value_list = :id_value', ['id_value' => $id_value, 'merge_id' => $merge_id]);
}
sqlQuery('DELETE FROM parameters_products WHERE value_list = :id_value', ['id_value' => $id_value]);
$this->returnOK();
}
public function handleSortAlphabet()
{
$ID = $this->getID();
$parameters = sqlQueryBuilder()->select('id, value')
->from('parameters_list', 'pl')
->where(Operator::equals(['id_parameter' => $ID]))
->execute()->fetchAll();
$collator = new Collator(\KupShop\KupShopBundle\Util\Contexts::get(LanguageContext::class)->getActive()->getLocale());
$collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
usort($parameters, function ($a, $b) use ($collator) {
$valueA = $a['value'];
$valueB = $b['value'];
$numericValueA = str_replace(',', '.', $valueA);
$numericValueB = str_replace(',', '.', $valueB);
if (is_numeric($numericValueA) && is_numeric($numericValueB)) {
return (float) $numericValueA <=> (float) $numericValueB;
}
return $collator->compare((string) $valueA, (string) $valueB);
});
$i = 0;
foreach ($parameters as $parameter) {
sqlQueryBuilder()->update('parameters_list', 'pl')
->directValues(['position' => ++$i])
->where(Operator::equals(['id' => $parameter['id']]))
->execute();
}
$this->returnOK();
}
/**
* @param array<int, array{ required?: 'on', filter?: 'on' }> $sections
*/
private function saveParametersInSections(array $sections): void
{
$ID = $this->getID();
if (FilterUtil::useOrderableFilters()) {
$sectionFilters = [];
$existingIdsMap = sqlQueryBuilder()
->select('sf.id_source_section', 'sf.id')
->from('sections_filters', 'sf')
->andWhere(Operator::equals(['sf.id_parameter' => $ID]))
->andWhere('sf.id_source_section IS NOT NULL')
->execute()
->fetchAllKeyValue();
// to delete
$relationsToDelete = sqlQueryBuilder()->select('ps.id_parameter', 'ps.id_section')
->from('parameters_sections', 'ps')
->andWhere(Operator::equals(['ps.id_parameter' => $ID]));
if (!empty($sections)) {
$relationsToDelete->andWhere(Operator::not(
Operator::inIntArray(array_keys($sections), 'ps.id_section'),
));
}
foreach ($relationsToDelete->execute() as $parameter) {
$id = $existingIdsMap[$parameter['id_section']] ?? null;
if ($id === null) {
continue;
}
$sectionFilters[] = SectionFilter::deleteParameter(
id: $id,
parameterId: (int) $parameter['id_parameter'],
sectionId: (int) $parameter['id_section'],
producerId: null,
);
}
// to update
foreach ($sections as $sectionId => $section) {
if (empty($sectionId) && $sectionId !== 0) {
continue;
}
$id = $existingIdsMap[$sectionId] ?? null;
$sectionFilters[] = SectionFilter::parameter(
id: $id,
parameterId: (int) $ID,
sectionId: (int) $sectionId,
producerId: null,
enabled: (bool) ($section['filter'] ?? false),
position: FilterUtil::POSITION_LAST,
required: (bool) ($section['required'] ?? false),
);
}
if (count($sectionFilters) > 0) {
$filterUtil = ServiceContainer::getService(FilterUtil::class);
$filterUtil->updateSectionFilters($sectionFilters);
}
return;
}
sqlQueryBuilder()->delete('parameters_sections')
->where(Operator::equals(['id_parameter' => $ID]))
->andWhere(Operator::not(Operator::inIntArray(array_keys($sections), 'id_section')))
->execute();
foreach ($sections as $key => $value) {
if (!empty($key) || $key === 0) {
sqlQuery(
'INSERT INTO parameters_sections (id_parameter, id_section, filter, required)
VALUES (:id_parameter, :id_section, :filter, :required)
ON DUPLICATE KEY UPDATE filter=VALUES(filter), required=VALUES(required)',
[
'id_parameter' => $ID,
'id_section' => $key,
'filter' => ($value['filter'] ?? false) ? 'Y' : 'N',
'required' => ($value['required'] ?? false) ? 'Y' : 'N',
]
);
}
}
}
private function saveProducersParameters(array $producers): void
{
$producers = array_filter($producers, static fn ($producerId) => intval($producerId) > 0);
$ID = (int) $this->getID();
if (FilterUtil::useOrderableFilters()) {
$sectionFilters = [];
$existingIdsMap = sqlQueryBuilder()
->select('sf.id_source_producer', 'sf.id')
->from('sections_filters', 'sf')
->andWhere(Operator::equals(['sf.id_parameter' => $ID]))
->andWhere('sf.id_source_producer IS NOT NULL')
->execute()
->fetchAllKeyValue();
$producerParametersToDelete = sqlQueryBuilder()
->select('pp.id_producer', 'pp.id_parameter')
->from('parameters_producers', 'pp')
->andWhere(Operator::equals(['pp.id_parameter' => $ID]));
if (!empty($producers)) {
$producerParametersToDelete->andWhere(Operator::not(
Operator::inIntArray($producers, 'pp.id_producer'),
));
}
foreach ($producerParametersToDelete->execute() as $producer) {
$id = $existingIdsMap[$producer['id_producer']] ?? null;
$sectionFilters[] = SectionFilter::deleteParameter(
id: $id,
parameterId: $producer['id_parameter'],
sectionId: null,
producerId: (int) $producer['id_producer'],
);
}
foreach ($producers as $producerId) {
$id = $existingIdsMap[$producerId] ?? null;
$sectionFilters[] = SectionFilter::parameter(
id: $id,
parameterId: $ID,
sectionId: null,
producerId: (int) $producerId,
enabled: true,
position: FilterUtil::POSITION_LAST,
);
}
if (count($sectionFilters) > 0) {
$filterUtil = ServiceContainer::getService(FilterUtil::class);
$filterUtil->updateSectionFilters($sectionFilters);
}
return;
}
// delete old relations that are no longer present
sqlQueryBuilder()->delete('parameters_producers')
->andWhere(Operator::equals(['id_parameter' => $ID]))
->andWhere(Operator::not(Operator::inIntArray(array_values($producers), 'id_producer')))
->execute();
// fetch existing relations (no matter if invalid ones are still present because of maxscale lag)
$existingProducerIDs = sqlQueryBuilder()->select('id_producer')->from('parameters_producers')
->where(Operator::equals(['id_parameter' => $ID]))->execute()->fetchFirstColumn();
$insertNewParams = sqlQueryBuilder()->insert('parameters_producers');
$hasNewRelations = false;
foreach ($producers as $IDProd) {
if (in_array($IDProd, $existingProducerIDs)) {
continue; // skip existing relations
}
$hasNewRelations = true;
$insertNewParams->multiDirectValues([
'id_parameter' => $ID,
'id_producer' => $IDProd,
]);
}
if ($hasNewRelations) {
$insertNewParams->execute();
}
}
}