360 lines
14 KiB
PHP
360 lines
14 KiB
PHP
<?php
|
|
|
|
namespace KupShop\ContentBundle\Util;
|
|
|
|
use Doctrine\DBAL\Connection;
|
|
use Query\Operator;
|
|
|
|
trait BlocksTrait
|
|
{
|
|
/**
|
|
* @return array hierarchy of blocks (parental blocks has children - nested set of blocks)
|
|
*/
|
|
public function getBlocks(int $blockID, bool $forceTranslations = false)
|
|
{
|
|
$allBlocks = sqlQueryBuilder()->select(
|
|
'b.*',
|
|
"JSON_ARRAYAGG(
|
|
IF(pb.id_photo IS NULL,
|
|
NULL,
|
|
JSON_OBJECT('date_update', p.date_update, 'id_photo', pb.id_photo)
|
|
)
|
|
ORDER BY pb.position
|
|
) AS photos"
|
|
)
|
|
->from('blocks', 'b')
|
|
->leftJoin('b', 'photos_blocks_relation', 'pb', 'pb.id_block = b.id')
|
|
->where('id_root=:id_root')->setParameter('id_root', $blockID)
|
|
->leftJoin('pb', 'photos', 'p', 'pb.id_photo = p.id')
|
|
->groupBy('b.id')
|
|
->orderBy('position');
|
|
|
|
if (!isAdministration() || $forceTranslations) {
|
|
$allBlocks->andWhere(
|
|
\Query\Translation::coalesceTranslatedFields(
|
|
\KupShop\I18nBundle\Translations\BlocksTranslation::class
|
|
)
|
|
);
|
|
}
|
|
|
|
$allBlocks = $allBlocks->execute()->fetchAll();
|
|
|
|
return $this->buildBlockHierarchy($allBlocks, $blockID);
|
|
}
|
|
|
|
/**
|
|
* @param array $pool of blocks to process into hierarchy
|
|
* @param int|null $parentID to begin with - can be null
|
|
*
|
|
* @return array
|
|
*/
|
|
public function buildBlockHierarchy(array $pool, ?int $parentID = null)
|
|
{
|
|
$finalArray = [];
|
|
foreach ($pool as $index => $item) {
|
|
if ((int) $item['id_parent'] === $parentID) {
|
|
unset($pool[$index]);
|
|
$children = $this->buildBlockHierarchy($pool, $item['id']);
|
|
if (count($children) > 0) {
|
|
$item['children'] = $children;
|
|
}
|
|
$item['photos'] = array_map(function (array $photoData) {
|
|
return getImage($photoData['id_photo'], '', '', 'product_catalog', '', strtotime($photoData['date_update']));
|
|
}, array_filter(json_decode($item['photos'] ?: '[]', true)));
|
|
|
|
$finalArray[] = $item;
|
|
}
|
|
}
|
|
|
|
return $finalArray;
|
|
}
|
|
|
|
/**
|
|
* @param string $entityBlockIDFieldName = id_block
|
|
*/
|
|
public function saveBlocks(
|
|
array $data,
|
|
int $entityID,
|
|
string $entityTableName,
|
|
string $entityBlockIDFieldName = 'id_block')
|
|
{
|
|
if (!isset($_POST['relations'])) {
|
|
$this->returnError('Chyba ve formuláři');
|
|
}
|
|
// decode hierarchy relations
|
|
$relations = json_decode_strict($_POST['relations'], true);
|
|
|
|
// remove block IDs from $data and $relations when duplicating parent entity
|
|
if (getVal('Duplicate', $_REQUEST, false)) {
|
|
foreach ($data['blocks'] as $index => $block) {
|
|
if (!empty($block['id'])) {
|
|
$content = $this->selectSQL('blocks', ['id' => $block['id']], ['content', 'json_content'])->fetch();
|
|
$data['blocks'][$index] = array_merge($block, $content);
|
|
}
|
|
unset($data['blocks'][$index]['id']);
|
|
}
|
|
foreach ($relations as $index => $relation) {
|
|
$relations[$index]['parentID'] = null;
|
|
}
|
|
}
|
|
|
|
$conn = sqlGetConnection();
|
|
$conn->transactional(function (Connection $conn) use ($data, $relations, $entityID, $entityTableName, $entityBlockIDFieldName) {
|
|
$rootID = sqlQueryBuilder()->select($entityBlockIDFieldName)->from($entityTableName)
|
|
->where('id=:id')->setParameter('id', $entityID)->setMaxResults(1)->execute()->fetch();
|
|
if (isset($rootID[$entityBlockIDFieldName])) {
|
|
$rootID = $rootID[$entityBlockIDFieldName];
|
|
} elseif (count($data['blocks']) > 1) { // Create new root block only if any blocks present (0 block always present)
|
|
$this->insertSQL('blocks', []);
|
|
$rootID = sqlInsertId();
|
|
$this->updateSQL($entityTableName, [$entityBlockIDFieldName => $rootID], ['id' => $entityID]);
|
|
}
|
|
$blocksToRemove = [];
|
|
$newPosition = 1;
|
|
$counter = 0;
|
|
foreach ($data['blocks'] as $index => $block) {
|
|
$counter++;
|
|
|
|
// ignore block with index 0 (it is the default one)
|
|
if ($index == 0) {
|
|
continue;
|
|
}
|
|
|
|
// if relation is not present return error (maybe save it as a root item instead?)
|
|
if (isset($relations[$index])) {
|
|
$block['id_parent'] = $relations[$index]['parentID'];
|
|
if (is_null($block['id_parent'])) {
|
|
$block['id_parent'] = $rootID;
|
|
}
|
|
} else {
|
|
$this->returnError('Chyba ve formuláři');
|
|
}
|
|
|
|
if (!isset($block['id'])) {
|
|
// save new items
|
|
if (!isset($block['delete'])) {
|
|
$valuesToSave = [
|
|
'id_root' => $rootID,
|
|
'id_parent' => $block['id_parent'],
|
|
'position' => $newPosition,
|
|
'name' => $block['name'],
|
|
'json_content' => $block['json_content'] ?? '',
|
|
];
|
|
if (getVal('Duplicate', $_REQUEST, false)) {
|
|
$valuesToSave['content'] = $block['content'] ?? '';
|
|
}
|
|
if (isSuperuser() || getVal('Duplicate', $_REQUEST, false)) {
|
|
$valuesToSave['identifier'] = $block['identifier'];
|
|
}
|
|
$this->insertSQL('blocks', $valuesToSave);
|
|
$block['id'] = $newID = sqlInsertId();
|
|
$newPosition++;
|
|
foreach ($relations as $index2 => $arr2) {
|
|
if (!empty($arr2['parentIndex'])
|
|
&& $arr2['parentIndex'] == $index
|
|
) {
|
|
$relations[$index2]['parentID'] = (int) $newID;
|
|
}
|
|
}
|
|
}
|
|
} elseif (isset($block['delete'])) {
|
|
$blocksToRemove[] = $block['id'];
|
|
} else {
|
|
// update block
|
|
$valuesToSave = [
|
|
'id_root' => $rootID,
|
|
'id_parent' => $block['id_parent'],
|
|
'position' => $newPosition,
|
|
'name' => $block['name'],
|
|
];
|
|
if (isset($block['identifier'])) {
|
|
$valuesToSave['identifier'] = $block['identifier'];
|
|
}
|
|
$this->updateSQL('blocks', $valuesToSave, ['id' => $block['id']]);
|
|
$newPosition++;
|
|
}
|
|
|
|
// update photos - blocks relations
|
|
if (!empty($block['id'])) {
|
|
$this->deleteSQL('photos_blocks_relation', ['id_block' => $block['id']]);
|
|
foreach (getVal('photos', $block, []) as $position => $photo) {
|
|
$this->insertSQL('photos_blocks_relation', [
|
|
'id_photo' => $photo,
|
|
'id_block' => $block['id'],
|
|
'position' => $position,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count($blocksToRemove) > 0) {
|
|
$conn->createQueryBuilder()->delete('blocks')->where('id IN (:ids)')
|
|
->setParameter('ids', $blocksToRemove, Connection::PARAM_INT_ARRAY)->execute();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param null $relationTableName
|
|
*/
|
|
public function updateBlocksPhotosPositions(int $entityID, string $entityTableName, string $tableField, $relationTableName = null)
|
|
{
|
|
if (!$relationTableName) {
|
|
$relationTableName = 'photos_'.$entityTableName.'_relation';
|
|
}
|
|
|
|
$rootBlockId = $this->selectSQL($entityTableName, ['id' => $entityID], ['id_block'])->fetchColumn();
|
|
if ($rootBlockId) {
|
|
$blocks = $this->getBlocks((int) $rootBlockId);
|
|
$blockIds = [];
|
|
foreach ($blocks as $block) {
|
|
$blockIds[] = $block['id'];
|
|
}
|
|
if (!empty($blockIds)) {
|
|
sqlQuery(
|
|
'UPDATE photos_blocks_relation pbr
|
|
LEFT JOIN '.$relationTableName.' rt ON rt.'.$tableField.' = :id AND rt.id_photo = pbr.id_photo
|
|
SET pbr.position = rt.position WHERE pbr.id_photo = rt.id_photo AND pbr.id_block IN (:block_ids);',
|
|
['id' => $entityID, 'block_ids' => $blockIds],
|
|
['block_ids' => Connection::PARAM_INT_ARRAY]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Duplicate blocks by root ID.
|
|
*
|
|
* @return int|false
|
|
*
|
|
* @throws \Throwable
|
|
*/
|
|
public function duplicateBlock(int $rootBlockID)
|
|
{
|
|
return sqlGetConnection()->transactional(function () use ($rootBlockID) {
|
|
$mapping = [];
|
|
|
|
$blocks = sqlQueryBuilder()->select('*')
|
|
->from('blocks')
|
|
->where(Operator::equals(['id_root' => $rootBlockID]))
|
|
->execute();
|
|
|
|
if ($blocks) {
|
|
$this->insertSQL('blocks', []);
|
|
$rootID = sqlInsertId();
|
|
|
|
$mapping[$rootBlockID] = $rootID;
|
|
|
|
foreach ($blocks as $block) {
|
|
$originalBlockID = $block['id'];
|
|
|
|
unset($block['id']);
|
|
|
|
$block['id_parent'] = $mapping[$block['id_parent']] ?? null;
|
|
$block['id_root'] = $rootID;
|
|
|
|
sqlQueryBuilder()->insert('blocks')
|
|
->directValues($block)
|
|
->execute();
|
|
$blockID = sqlInsertId();
|
|
|
|
// copy photos relations
|
|
$photoRelations = sqlQueryBuilder()->select('*')
|
|
->from('photos_blocks_relation')
|
|
->where(Operator::equals(['id_block' => $originalBlockID]))
|
|
->execute();
|
|
|
|
foreach ($photoRelations as $photoRelation) {
|
|
$photoRelation['id_block'] = $blockID;
|
|
sqlQueryBuilder()->insert('photos_blocks_relation')
|
|
->directValues($photoRelation)
|
|
->execute();
|
|
}
|
|
|
|
// copy translations
|
|
if (findModule(\Modules::TRANSLATIONS)) {
|
|
sqlQuery('INSERT INTO blocks_translations (id_block, id_language, created, name, content, json_content)
|
|
SELECT
|
|
'.$blockID.' as id_block,
|
|
id_language,
|
|
NOW(),
|
|
name,
|
|
content,
|
|
json_content
|
|
FROM blocks_translations
|
|
WHERE id_block=:originalBlockId', ['originalBlockId' => $originalBlockID]);
|
|
}
|
|
|
|
$mapping[$originalBlockID] = $blockID;
|
|
}
|
|
|
|
return $rootID;
|
|
}
|
|
|
|
return false;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Remove blocks tree by root block ID.
|
|
*
|
|
* @param int|null $rootBlockID - if null, do nothing
|
|
*
|
|
* @return int number of affected rows
|
|
*/
|
|
public function removeBlocks(?int $rootBlockID = null)
|
|
{
|
|
// removing root block is enough, because fk_id_parent has ON DELETE CASCADE
|
|
if (isset($rootBlockID)) {
|
|
return $this->deleteSQL('blocks', ['id' => $rootBlockID]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public function renderBlock($json_content, $block = '')
|
|
{
|
|
$post_data = json_encode(['data' => $json_content]);
|
|
|
|
$curl = curl_init();
|
|
|
|
curl_setopt_array(
|
|
$curl,
|
|
[
|
|
CURLOPT_URL => isRunningOnCluster() ? 'blocek.services' : 'http://blocek.wpj.cz/',
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_ENCODING => '',
|
|
CURLOPT_MAXREDIRS => 10,
|
|
CURLOPT_TIMEOUT => 50,
|
|
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
|
CURLOPT_CUSTOMREQUEST => 'POST',
|
|
CURLOPT_HTTPHEADER => [
|
|
'content-type: application/json',
|
|
],
|
|
]
|
|
);
|
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
|
|
|
|
$response = curl_exec($curl);
|
|
$err = curl_error($curl);
|
|
|
|
curl_close($curl);
|
|
|
|
if ($err) {
|
|
$response = ['success' => false, 'error' => 'cURL Error: '.$err];
|
|
} elseif ($decode = json_decode($response, true)) {
|
|
$response = $decode;
|
|
} else {
|
|
$response = ['success' => false, 'response' => $response];
|
|
}
|
|
|
|
if (!($response['success'] ?? false)) {
|
|
$raven = getRaven();
|
|
$raven->captureException(new \Exception("Server-side rendering failed for {$block}."), ['extra' => $response]);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|