277 lines
8.2 KiB
PHP
277 lines
8.2 KiB
PHP
<?php
|
|
|
|
namespace KupShop\AdminBundle\Util;
|
|
|
|
use Doctrine\DBAL\Connection;
|
|
use KupShop\ContentBundle\Util\Block;
|
|
use Query\Operator;
|
|
|
|
class BlocksHistory
|
|
{
|
|
public const TYPE_BY_ID = 'bh.id';
|
|
public const TYPE_BY_ROOT_ID = 'id_root_block';
|
|
|
|
private $block;
|
|
|
|
public function __construct(Block $block)
|
|
{
|
|
$this->block = $block;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function saveBlocksHistory(array $blocks)
|
|
{
|
|
if ($this->isChangeInBlocks($blocks)) {
|
|
$rootId = $this->getBlocksRootId($blocks);
|
|
|
|
// Skip if no root block present
|
|
if (!$rootId) {
|
|
return false;
|
|
}
|
|
|
|
// get actual blocks hierarchy
|
|
$blocksHierarchy = $this->block->getBlocks($rootId);
|
|
$id_admin = getAdminUser()['id'] ?? null;
|
|
|
|
// ignore superuser
|
|
$id_admin = $id_admin === 0 ? null : $id_admin;
|
|
|
|
if ($idLastHistory = $this->getLastFreshHistory($rootId)) {
|
|
// update history
|
|
sqlQueryBuilder()->update('blocks_history')
|
|
->set('date', 'NOW()')
|
|
->set('id_admin', ':id_admin')
|
|
->set('data', ':data')
|
|
->where(Operator::equals(['id' => $idLastHistory]))
|
|
->setParameter('id_admin', $id_admin)
|
|
->setParameter('data', json_encode($blocksHierarchy))
|
|
->execute();
|
|
} else {
|
|
// insert history
|
|
sqlQueryBuilder()->insert('blocks_history')
|
|
->values(
|
|
[
|
|
'id_root_block' => $rootId,
|
|
'id_admin' => ':id_admin',
|
|
'date' => 'NOW()',
|
|
'data' => ':data',
|
|
]
|
|
)
|
|
->setParameter('id_admin', $id_admin)
|
|
->setParameter('data', json_encode($blocksHierarchy))
|
|
->execute();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function setBlocksHistoryName(string $name, int $historyId)
|
|
{
|
|
return sqlQueryBuilder()->update('blocks_history')
|
|
->set('name', ':name')
|
|
->setParameter('name', $name)
|
|
->where(Operator::equals(['id' => $historyId]))->execute();
|
|
}
|
|
|
|
public function deleteBlocksHistory(int $historyId)
|
|
{
|
|
return sqlQueryBuilder()->delete('blocks_history')->where(Operator::equals(['id' => $historyId]))->execute();
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*
|
|
* @throws \Exception
|
|
*/
|
|
public function revertBlocksHistory(int $id)
|
|
{
|
|
$connection = sqlGetConnection();
|
|
try {
|
|
$connection->transactional(
|
|
function (Connection $connection) use ($id) {
|
|
$history = $this->getBlocksHistory($id, BlocksHistory::TYPE_BY_ID);
|
|
if (empty($history['blocks'])) {
|
|
throw new \RuntimeException();
|
|
}
|
|
|
|
sqlQueryBuilder()->delete('blocks')->where(Operator::equals(['id_root' => $history['id_root']]))->execute();
|
|
|
|
$this->insertRevertedBlocks($history['blocks']);
|
|
}
|
|
);
|
|
} catch (\RuntimeException $e) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private function insertRevertedBlocks(array $blocks)
|
|
{
|
|
foreach ($blocks as $block) {
|
|
$children = $block['children'] ?? null;
|
|
$photos = $block['photos'];
|
|
unset($block['photos'], $block['children']);
|
|
if (empty($block['json_content'])) {
|
|
$blockObj = new \stdClass();
|
|
$blockObj->type = 'legacy';
|
|
$settings = new \stdClass();
|
|
$settings->html = $block['content'];
|
|
$blockObj->settings = $settings;
|
|
|
|
$json = json_encode([$blockObj]);
|
|
$block['json_content'] = $json;
|
|
}
|
|
|
|
sqlQueryBuilder()->insert('blocks')
|
|
->directValues($block)
|
|
->execute();
|
|
|
|
foreach ($photos as $photo) {
|
|
if (!empty($photo['id'])) {
|
|
sqlQueryBuilder()->insert('photos_blocks_relation')
|
|
->values(['id_photo' => $photo['id'], 'id_block' => $block['id']])
|
|
->execute();
|
|
}
|
|
}
|
|
|
|
if ($children) {
|
|
$this->insertRevertedBlocks($children);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $type
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getBlocksHistory(int $id, $type = self::TYPE_BY_ROOT_ID)
|
|
{
|
|
$histories = sqlQueryBuilder()->select('bh.*, a.login')->from('blocks_history', 'bh')
|
|
->leftJoin('bh', 'admins', 'a', 'bh.id_admin = a.id')
|
|
->where(Operator::equals([$type => $id]))
|
|
->orderBy('date', 'DESC')
|
|
->execute()->fetchAll();
|
|
|
|
$dateFormat = \Settings::getDateFormat().' '.\Settings::getTimeFormat();
|
|
$return = [];
|
|
foreach ($histories as $history) {
|
|
$return[$history['id']] = [
|
|
'id' => $history['id'],
|
|
'id_root' => $history['id_root_block'],
|
|
'admin_login' => $history['login'],
|
|
'name' => $history['name'],
|
|
'date' => (new \DateTime($history['date']))->format($dateFormat),
|
|
'blocks' => json_decode($history['data'], true),
|
|
];
|
|
}
|
|
|
|
if ($type == self::TYPE_BY_ID) {
|
|
return reset($return);
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isChangeInBlocks(array $blocks)
|
|
{
|
|
foreach ($blocks as $blockId => $block) {
|
|
if ($blockId == 0) {
|
|
continue;
|
|
}
|
|
|
|
if ($blockId < 0 || $this->isBlockUpdated($block)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param array $block Array that represents single block
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isBlockUpdated(array $block)
|
|
{
|
|
if (!empty($block['delete'])) {
|
|
return true;
|
|
}
|
|
|
|
$dbBlock = $this->getBlock($block['id']);
|
|
$compare = ['id' => $block['id'], 'name' => $block['name'], 'content' => $block['content'] ?? ''];
|
|
if (!empty($block['photos'])) {
|
|
$compare['photos'] = $block['photos'];
|
|
}
|
|
|
|
// Editace z adminu, ignoruju obsah
|
|
if (!isset($block['content'])) {
|
|
unset($dbBlock['content']);
|
|
unset($compare['content']);
|
|
}
|
|
|
|
if ($compare == $dbBlock) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getLastFreshHistory(int $rootId)
|
|
{
|
|
$lastHistory = sqlQueryBuilder()->select('id')->from('blocks_history')
|
|
->where(Operator::equals(['id_root_block' => $rootId]))
|
|
->andWhere('date > DATE_SUB(NOW(), INTERVAL 1 HOUR)')
|
|
->orderBy('date', 'DESC')
|
|
->setMaxResults(1)
|
|
->execute()->fetch();
|
|
|
|
if ($lastHistory) {
|
|
return $lastHistory['id'];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function getBlocksRootId(array $blocks)
|
|
{
|
|
$blockId = null;
|
|
foreach ($blocks as $block) {
|
|
if (!empty($block['id'])) {
|
|
$blockId = $block['id'];
|
|
}
|
|
}
|
|
|
|
return sqlQueryBuilder()->select('id_root')->from('blocks')
|
|
->where(Operator::equals(['id' => $blockId]))
|
|
->execute()->fetchColumn();
|
|
}
|
|
|
|
private function getBlock(int $id)
|
|
{
|
|
$block = sqlQueryBuilder()->select('b.id, b.name, b.content, GROUP_CONCAT(pb.id_photo) as photos')->from('blocks', 'b')
|
|
->leftJoin('b', 'photos_blocks_relation', 'pb', 'pb.id_block = b.id')
|
|
->where(Operator::equals(['id' => $id]))
|
|
->execute()->fetch();
|
|
$block['photos'] = explode(',', $block['photos']);
|
|
$block['photos'] = array_filter($block['photos'], function ($x) {
|
|
return !empty($x);
|
|
});
|
|
if (empty($block['photos'])) {
|
|
unset($block['photos']);
|
|
}
|
|
|
|
return $block;
|
|
}
|
|
}
|