Commit 7c77b9a9 authored by Tino Goratsch's avatar Tino Goratsch

Merge branch 'release/v4.1.29'

parents 1962b984 b39965e5
......@@ -19,6 +19,14 @@ exclude_paths:
- "ACP3/Core/Test/**/*"
- "ACP3/Modules/ACP3/**/Test/**/*"
- "ACP3/Modules/ACP3/Filemanager/libraries/kcfinder/**/*"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/libs/**/*"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/bootbox.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/bootstrap.min.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/bootstrap-datetimepicker.min.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/dataTables.bootstrap.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/html5shiv.min.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/jquery.dataTables.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/jquery.fancybox.pack.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/jquery.min.js"
- "ACP3/Modules/ACP3/System/Resources/Assets/js/moment.min.js"
- "ACP3/Modules/ACP3/WYSIWYGCKEditor/Resources/Assets/js/ckeditor/plugins/**/*"
- "vendor/**/*"
......@@ -14,7 +14,7 @@ interface BootstrapInterface extends HttpKernelInterface
/**
* Contains the current ACP3 version string
*/
const VERSION = '4.1.28';
const VERSION = '4.1.29';
/**
* Performs some startup checks
......
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Cache\Event\Listener;
use ACP3\Core\Cache\Purge;
use ACP3\Core\Environment\ApplicationPath;
class OnModelAfterSaveListener
{
/**
* @var ApplicationPath
*/
private $applicationPath;
/**
* OnModelAfterSaveListener constructor.
* @param ApplicationPath $applicationPath
*/
public function __construct(ApplicationPath $applicationPath)
{
$this->applicationPath = $applicationPath;
}
public function purgeHttpCache()
{
Purge::doPurge($this->applicationPath->getCacheDir() . 'http');
}
}
......@@ -60,11 +60,7 @@ abstract class AbstractFrontendAction extends Core\Controller\AbstractWidgetActi
*/
public function preDispatch()
{
$path = $this->request->getArea() . '/' . $this->request->getFullPathWithoutArea();
if ($this->acl->hasPermission($path) === false) {
throw new Core\ACL\Exception\AccessForbiddenException();
}
parent::preDispatch();
$this->view->assign([
'PHP_SELF' => $this->appPath->getPhpSelf(),
......@@ -82,8 +78,6 @@ abstract class AbstractFrontendAction extends Core\Controller\AbstractWidgetActi
'LANG' => $this->translator->getShortIsoCode(),
]);
parent::preDispatch();
return $this;
}
......
......@@ -94,9 +94,16 @@ abstract class AbstractWidgetAction implements ActionInterface
/**
* @return $this
* @throws Core\ACL\Exception\AccessForbiddenException
*/
public function preDispatch()
{
$path = $this->request->getArea() . '/' . $this->request->getFullPathWithoutArea();
if ($this->acl->hasPermission($path) === false) {
throw new Core\ACL\Exception\AccessForbiddenException();
}
return $this;
}
......
......@@ -8,6 +8,7 @@ namespace ACP3\Core\DependencyInjection;
use ACP3\Core\Environment\ApplicationPath;
use ACP3\Core\Helpers\DataGrid\DependencyInjection\RegisterColumnRendererPass;
use ACP3\Core\Model\DataProcessor\DependencyInjection\RegisterColumnTypesCompilerPass;
use ACP3\Core\Modules;
use ACP3\Core\Validation\DependencyInjection\RegisterValidationRulesPass;
use ACP3\Core\View\Renderer\Smarty\DependencyInjection\RegisterSmartyPluginsPass;
......@@ -77,6 +78,7 @@ class ServiceContainerBuilder extends ContainerBuilder
$this->addCompilerPass(new RegisterColumnRendererPass());
$this->addCompilerPass(new RegisterValidationRulesPass());
$this->addCompilerPass(new RegisterWysiwygEditorsCompilerPass());
$this->addCompilerPass(new RegisterColumnTypesCompilerPass());
$loader = new YamlFileLoader($this, new FileLocator(__DIR__));
$loader->load($this->applicationPath->getClassesDir() . 'config/services.yml');
......
......@@ -54,7 +54,7 @@ class Alerts
$this->view->assign('confirm', $confirm);
return 'system/alerts/confirm_box.tpl';
return 'System/Alerts/confirm_box.tpl';
}
return '';
}
......
......@@ -26,40 +26,49 @@ abstract class AbstractModel
* @var AbstractRepository
*/
protected $repository;
/**
* @var DataProcessor
*/
private $dataProcessor;
/**
* AbstractModel constructor.
* @param EventDispatcherInterface $eventDispatcher
* @param DataProcessor $dataProcessor
* @param AbstractRepository $repository
*/
public function __construct(
EventDispatcherInterface $eventDispatcher,
DataProcessor $dataProcessor,
AbstractRepository $repository
) {
$this->eventDispatcher = $eventDispatcher;
$this->repository = $repository;
$this->dataProcessor = $dataProcessor;
}
/**
* @param array $data
* @param array $columnData
* @param null|int $entryId
* @return bool|int
*/
protected function save(array $data, $entryId = null)
public function save(array $columnData, $entryId = null)
{
$this->dispatchBeforeSaveEvent($this->repository, $data, $entryId);
$columnData = $this->prepareData($columnData);
if (intval($entryId)) {
$result = $this->repository->update($data, $entryId);
} else {
$result = $this->repository->insert($data);
$this->dispatchBeforeSaveEvent($this->repository, $columnData, $entryId);
if ($entryId === null) {
$result = $this->repository->insert($columnData);
if ($result !== false) {
$entryId = $result;
}
} else {
$result = $this->repository->update($columnData, $entryId);
}
$this->dispatchAfterSaveEvent($this->repository, $data, $entryId);
$this->dispatchAfterSaveEvent($this->repository, $columnData, $entryId);
return $result;
}
......@@ -92,6 +101,20 @@ abstract class AbstractModel
);
}
/**
* @param array $data
* @return array
*/
protected function prepareData(array $data)
{
return $this->dataProcessor->processColumnData($data, $this->getAllowedColumns());
}
/**
* @return array
*/
abstract protected function getAllowedColumns();
/**
* @param AbstractRepository $repository
* @param array $data
......
......@@ -31,19 +31,21 @@ abstract class AbstractNestedSetModel extends AbstractModel
/**
* AbstractNestedSetModel constructor.
* @param EventDispatcherInterface $eventDispatcher
* @param DataProcessor $dataProcessor
* @param AbstractRepository $repository
* @param Insert $insertOperation
* @param Edit $editOperation
* @param $deleteOperation
* @param Delete $deleteOperation
*/
public function __construct(
EventDispatcherInterface $eventDispatcher,
DataProcessor $dataProcessor,
AbstractRepository $repository,
Insert $insertOperation,
Edit $editOperation,
Delete $deleteOperation
) {
parent::__construct($eventDispatcher, $repository);
parent::__construct($eventDispatcher, $dataProcessor, $repository);
$this->insertOperation = $insertOperation;
$this->editOperation = $editOperation;
......@@ -51,16 +53,18 @@ abstract class AbstractNestedSetModel extends AbstractModel
}
/**
* @param array $data
* @param array $columnData
* @param int|null $entryId
* @return bool|int
*/
protected function save(array $data, $entryId = null)
public function save(array $columnData, $entryId = null)
{
$this->dispatchBeforeSaveEvent($this->repository, $data, $entryId);
$columnData = $this->prepareData($columnData);
$this->dispatchBeforeSaveEvent($this->repository, $columnData, $entryId);
if ($entryId === null) {
$result = $this->insertOperation->execute($data, $data['parent_id']);
$result = $this->insertOperation->execute($columnData, $columnData['parent_id']);
if ($result !== false) {
$entryId = $result;
......@@ -68,13 +72,13 @@ abstract class AbstractNestedSetModel extends AbstractModel
} else {
$result = $this->editOperation->execute(
$entryId,
$data['parent_id'],
isset($data['block_id']) ? $data['block_id'] : 0,
$data
$columnData['parent_id'],
isset($columnData['block_id']) ? $columnData['block_id'] : 0,
$columnData
);
}
$this->dispatchAfterSaveEvent($this->repository, $data, $entryId);
$this->dispatchAfterSaveEvent($this->repository, $columnData, $entryId);
return $result;
}
......
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model;
use ACP3\Core\Model\DataProcessor\ColumnTypeStrategyFactory;
class DataProcessor
{
/**
* @var ColumnTypeStrategyFactory
*/
protected $factory;
/**
* DataProcessor constructor.
* @param ColumnTypeStrategyFactory $factory
*/
public function __construct(ColumnTypeStrategyFactory $factory)
{
$this->factory = $factory;
}
/**
* @param array $columnData
* @param array $columnConstraints
* @return array
*/
public function processColumnData(array $columnData, array $columnConstraints)
{
$data = [];
foreach ($columnData as $column => $value) {
if (array_key_exists($column, $columnConstraints)) {
$data[$column] = $this->factory->getStrategy($columnConstraints[$column])->doEscape($value);
}
}
return $data;
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
class BooleanColumnType implements ColumnTypeStrategyInterface
{
/**
* @param mixed $value
* @return bool
*/
public function doEscape($value)
{
return boolval($value);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
interface ColumnTypeStrategyInterface
{
/**
* @param mixed $value
* @return mixed
*/
public function doEscape($value);
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
use ACP3\Core\Date;
class DateTimeColumnType implements ColumnTypeStrategyInterface
{
/**
* @var Date
*/
protected $date;
/**
* DateTimeColumnType constructor.
* @param Date $date
*/
public function __construct(Date $date)
{
$this->date = $date;
}
/**
* @param string $value
* @return string
*/
public function doEscape($value)
{
return $this->date->toSQL($value);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
class DoubleColumnType implements ColumnTypeStrategyInterface
{
/**
* @param mixed $value
* @return float
*/
public function doEscape($value)
{
return doubleval($value);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
class IntegerColumnType implements ColumnTypeStrategyInterface
{
/**
* @param mixed $value
* @return int
*/
public function doEscape($value)
{
return intval($value);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
class RawColumnType implements ColumnTypeStrategyInterface
{
/**
* @param mixed $value
* @return mixed
*/
public function doEscape($value)
{
return $value;
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
use ACP3\Core\Helpers\Secure;
class TextColumnType implements ColumnTypeStrategyInterface
{
/**
* @var Secure
*/
protected $secure;
/**
* TextColumnType constructor.
* @param Secure $secure
*/
public function __construct(Secure $secure)
{
$this->secure = $secure;
}
/**
* @param mixed $value
* @return string
*/
public function doEscape($value)
{
return $this->secure->strEncode($value);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\ColumnType;
class TextWysiwygColumnType extends TextColumnType
{
/**
* @inheritdoc
*/
public function doEscape($value)
{
return $this->secure->strEncode($value, true);
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor;
use ACP3\Core\Model\DataProcessor\ColumnType\ColumnTypeStrategyInterface;
class ColumnTypeStrategyFactory
{
/**
* @var ColumnTypeStrategyInterface[]
*/
protected $columnTypes = [];
/**
* @param ColumnTypeStrategyInterface $columnTypeStrategy
* @param $columnTypeName
* @return $this
*/
public function registerColumnType(ColumnTypeStrategyInterface $columnTypeStrategy, $columnTypeName)
{
$this->columnTypes[$columnTypeName] = $columnTypeStrategy;
return $this;
}
/**
* @param string $columnType
* @return ColumnTypeStrategyInterface
*/
public function getStrategy($columnType)
{
if (!isset($this->columnTypes[$columnType])) {
throw new \InvalidArgumentException('Invalid column type constraint given: ' . $columnType);
}
return $this->columnTypes[$columnType];
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor;
interface ColumnTypes
{
const COLUMN_TYPE_DATETIME = 'datetime';
const COLUMN_TYPE_BOOLEAN = 'boolean';
const COLUMN_TYPE_INT = 'integer';
const COLUMN_TYPE_DOUBLE = 'double';
const COLUMN_TYPE_TEXT = 'text';
const COLUMN_TYPE_TEXT_WYSIWYG = 'text_wysiwyg';
const COLUMN_TYPE_RAW = 'raw';
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Core\Model\DataProcessor\DependencyInjection;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class RegisterColumnTypesCompilerPass implements CompilerPassInterface
{
/**
* @param ContainerBuilder $container
*/
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('core.model.column_type_strategy_factory');
$plugins = $container->findTaggedServiceIds('core.model.column_type');
foreach ($plugins as $serviceId => $tags) {
$definition->addMethodCall(
'registerColumnType',
[new Reference($serviceId), reset($tags)['columnType']]
);
}
}
}
<?php
/**
* Copyright (c) 2016 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/