Commit 424dce07 authored by Tino Goratsch's avatar Tino Goratsch

Merge branch 'release/v4.7.0'

parents ebf44fed f7391b49
......@@ -14,7 +14,7 @@ interface BootstrapInterface extends HttpKernelInterface
/**
* Contains the current ACP3 version string
*/
const VERSION = '4.6.2';
const VERSION = '4.7.0';
/**
* Performs some startup checks
......
......@@ -24,6 +24,10 @@ class Libraries
'enabled' => true,
'js' => 'jquery.min.js'
],
'js-cookie' => [
'enabled' => true,
'js' => 'js.cookie.js',
],
'fancybox' => [
'enabled' => false,
'dependencies' => ['jquery'],
......
......@@ -62,7 +62,7 @@ class RewriteInternalUri
{
$rootDir = str_replace('/', '\/', $this->appPath->getWebRoot());
$host = $this->request->getServer()->get('HTTP_HOST');
$pattern = '/<a([^>]+)href="(http(s?):\/\/' . $host . ')?(' . $rootDir . ')?(index\.php)?(\/?)((?i:[a-z\d_\-]+\/){2,})"/i';
$pattern = '/(<a([^>]+)href=")?(http(s?):\/\/' . $host . ')?(' . $rootDir . ')?(index\.php)?(\/?)((?i:[a-z\d_\-]+\/){2,})(")?/i';
return preg_replace_callback(
$pattern,
......@@ -78,11 +78,15 @@ class RewriteInternalUri
*/
private function rewriteInternalUriCallback(array $matches)
{
if ($this->internalUriValidationRule->isValid($matches[7]) === true) {
$resourceParts = explode('/', $matches[7]);
if ($this->internalUriValidationRule->isValid($matches[8]) === true) {
$resourceParts = explode('/', $matches[8]);
$path = $this->getResourcePath($resourceParts);
if ($this->controllerActionExists->controllerActionExists($path) === true) {
return '<a' . $matches[1] . 'href="' . $this->router->route($matches[7]) . '"';
if (!empty($matches[1])) {
return '<a' . $matches[2] . 'href="' . $this->router->route($matches[8]) . '"';
}
return $this->router->route($matches[8]);
}
}
......
......@@ -2,6 +2,7 @@
namespace ACP3\Core\Helpers;
use ACP3\Core\Environment\ApplicationPath;
use ACP3\Core\Validation\Exceptions\ValidationFailedException;
/**
* Class Upload
......@@ -37,14 +38,24 @@ class Upload
* Temporäre Datei
* @param string $filename
* Dateiname
* @param bool $retainFilename
*
* @param bool $retainFilename
* @return array
* @throws ValidationFailedException
*/
public function moveFile($tmpFilename, $filename, $retainFilename = false)
{
$path = $this->appPath->getUploadsDir() . $this->directory . '/';
if (!is_dir($path)) {
$result = @mkdir($path);
if (!$result) {
throw new ValidationFailedException(
[sprintf('Could not create folder "%s"', $this->directory)]
);
}
}
if ($retainFilename === true) {
$newFilename = $filename;
} else {
......
......@@ -9,6 +9,7 @@ namespace ACP3\Core\Modules\Helper;
use ACP3\Core;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
/**
* Class Action
......@@ -83,13 +84,13 @@ class Action
/**
* @param \Exception $exception
* @return array|JsonResponse
* @return array|Response
*/
public function renderErrorBoxOnFailedFormValidation(\Exception $exception)
{
$errors = $this->alerts->errorBox($exception->getMessage());
if ($this->request->isXmlHttpRequest()) {
return new JsonResponse(['success' => false, 'content' => $errors]);
return new Response($errors, 400);
}
return ['error_msg' => $errors];
......
......@@ -49,6 +49,6 @@ class LibrariesTest extends \PHPUnit_Framework_TestCase
$this->libraries->enableLibraries(['foobar']);
$this->assertEquals(['jquery', 'foobar'], $this->libraries->getEnabledLibraries());
$this->assertEquals(['jquery', 'js-cookie', 'foobar'], $this->libraries->getEnabledLibraries());
}
}
......@@ -51,7 +51,7 @@ class AssetsTest extends \PHPUnit_Framework_TestCase
public function testDefaultLibrariesEnabled()
{
$libraries = $this->assets->getEnabledLibrariesAsString();
$this->assertEquals('jquery,bootstrap', $libraries);
$this->assertEquals('jquery,js-cookie,bootstrap', $libraries);
}
public function testEnableDatepicker()
......@@ -59,7 +59,7 @@ class AssetsTest extends \PHPUnit_Framework_TestCase
$this->assets->enableLibraries(['datetimepicker']);
$libraries = $this->assets->getEnabledLibrariesAsString();
$this->assertEquals('moment,jquery,bootstrap,datetimepicker', $libraries);
$this->assertEquals('moment,jquery,js-cookie,bootstrap,datetimepicker', $libraries);
}
public function testFetchAdditionalThemeCssFiles()
......
......@@ -184,4 +184,39 @@ HTML;
->with($route)
->willReturn($alias);
}
public function testRewriteInternalUriWithMatchingInlineUri()
{
$this->setUpAppPathExpectations();
$this->setUpRequestMockExpectations();
$this->setUpValidationRuleMockExpectations(1, 'foo/bar/baz/', true);
$this->setUpControllerActionExistsMockExpectations(1, 'frontend/foo/bar/baz', false);
$this->setUpRouterMockExpectations(0, '', '');
$content = <<<HTML
http://example.com/foo/bar/baz/
HTML;
$this->assertEquals($content, $this->rewriteInternalUri->rewriteInternalUri($content));
}
public function testRewriteInternalUriWithMatchingInlineUriAndExistingAlias()
{
$this->setUpAppPathExpectations();
$this->setUpRequestMockExpectations();
$this->setUpValidationRuleMockExpectations(1, 'foo/bar/baz/', true);
$this->setUpControllerActionExistsMockExpectations(1, 'frontend/foo/bar/baz', true);
$this->setUpRouterMockExpectations(1, 'foo/bar/baz/', '/foo-bar/');
$content = <<<HTML
http://example.com/foo/bar/baz/
HTML;
$expected = <<<HTML
/foo-bar/
HTML;
$this->assertEquals($expected, $this->rewriteInternalUri->rewriteInternalUri($content));
}
}
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"suggest": {
"acp3/module-seo": "Provides additional SEO capabilities"
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"autoload": {
"psr-4": {
......
{extends file="asset:System/layout.ajax-form.tpl"}
{block CONTENT_AJAX_FORM}
{include file="asset:System/Partials/form_group.input_number.tpl" name="width" value=$form.width required=true label={lang t="categories|image_width"} help={lang t="system|statements_in_pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="height" value=$form.height required=true label={lang t="categories|image_height"} help={lang t="system|statements_in_pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="filesize" value=$form.filesize required=true label={lang t="categories|image_filesize"} help={lang t="system|statements_in_byte"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="width" value=$form.width required=true label={lang t="categories|image_width"} input_group_after={lang t="system|pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="height" value=$form.height required=true label={lang t="categories|image_height"} input_group_after={lang t="system|pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="filesize" value=$form.filesize required=true label={lang t="categories|image_filesize"} input_group_after={lang t="system|byte"}}
{include file="asset:System/Partials/form_group.submit.tpl" form_token=$form_token back_url={uri args="acp/categories"}}
{/block}
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
......@@ -8,15 +8,73 @@ namespace ACP3\Modules\ACP3\Contact\Controller\Admin\Index;
use ACP3\Core;
use ACP3\Modules\ACP3\Contact;
use ACP3\Modules\ACP3\System\Installer\Schema;
/**
* Class Index
* @package ACP3\Modules\ACP3\Contact\Controller\Admin\Index
*/
class Index extends Core\Controller\AbstractAdminAction
{
/**
* @var Contact\Model\Repository\DataGridRepository
*/
private $dataGridRepository;
/**
* Index constructor.
* @param Core\Controller\Context\FrontendContext $context
* @param Contact\Model\Repository\DataGridRepository $dataGridRepository
*/
public function __construct(
Core\Controller\Context\FrontendContext $context,
Contact\Model\Repository\DataGridRepository $dataGridRepository
) {
parent::__construct($context);
$this->dataGridRepository = $dataGridRepository;
}
public function execute()
{
return;
/** @var Core\Helpers\DataGrid $dataGrid */
$dataGrid = $this->get('core.helpers.data_grid');
$dataGrid
->setRepository($this->dataGridRepository)
->setRecordsPerPage($this->resultsPerPage->getResultsPerPage(Schema::MODULE_NAME))
->setIdentifier('#acp-table')
->setEnableOptions(false);
$this->addDataGridColumns($dataGrid);
return [
'grid' => $dataGrid->render()
];
}
/**
* @param Core\Helpers\DataGrid $dataGrid
*/
protected function addDataGridColumns(Core\Helpers\DataGrid $dataGrid)
{
$dataGrid
->addColumn([
'label' => $this->translator->t('system', 'date'),
'type' => Core\Helpers\DataGrid\ColumnRenderer\DateColumnRenderer::class,
'fields' => ['date'],
'default_sort' => true,
'default_sort_direction' => 'desc'
], 40)
->addColumn([
'label' => $this->translator->t('system', 'name'),
'type' => Core\Helpers\DataGrid\ColumnRenderer\TextColumnRenderer::class,
'fields' => ['name'],
], 30)
->addColumn([
'label' => $this->translator->t('system', 'email_address'),
'type' => Core\Helpers\DataGrid\ColumnRenderer\TextColumnRenderer::class,
'fields' => ['mail'],
], 20)
->addColumn([
'label' => $this->translator->t('system', 'message'),
'type' => Core\Helpers\DataGrid\ColumnRenderer\Nl2pColumnRenderer::class,
'fields' => ['message'],
], 10);
}
}
......@@ -31,12 +31,17 @@ class Index extends Core\Controller\AbstractFrontendAction
* @var Contact\Model\ContactFormModel
*/
protected $contactFormModel;
/**
* @var Contact\Model\ContactsModel
*/
protected $contactsModel;
/**
* @param \ACP3\Core\Controller\Context\FrontendContext $context
* @param \ACP3\Core\Helpers\Forms $formsHelper
* @param \ACP3\Core\Helpers\FormToken $formTokenHelper
* @param \ACP3\Modules\ACP3\Contact\Validation\FormValidation $formValidation
* @param Contact\Model\ContactsModel $contactsModel
* @param Contact\Model\ContactFormModel $contactFormModel
*/
public function __construct(
......@@ -44,6 +49,7 @@ class Index extends Core\Controller\AbstractFrontendAction
Core\Helpers\Forms $formsHelper,
Core\Helpers\FormToken $formTokenHelper,
Contact\Validation\FormValidation $formValidation,
Contact\Model\ContactsModel $contactsModel,
Contact\Model\ContactFormModel $contactFormModel
) {
parent::__construct($context);
......@@ -52,6 +58,7 @@ class Index extends Core\Controller\AbstractFrontendAction
$this->formTokenHelper = $formTokenHelper;
$this->formValidation = $formValidation;
$this->contactFormModel = $contactFormModel;
$this->contactsModel = $contactsModel;
}
/**
......@@ -81,6 +88,8 @@ class Index extends Core\Controller\AbstractFrontendAction
$formData = $this->request->getPost()->all();
$this->formValidation->validate($formData);
$this->contactsModel->save($formData);
$bool = $this->contactFormModel->sendContactFormEmail($formData);
if (isset($formData['copy'])) {
......
......@@ -50,6 +50,16 @@ class Migration extends Modules\Installer\AbstractMigration
40 => [
"INSERT INTO `{pre}settings` (`id`, `module_id`, `name`, `value`) VALUES ('', '{moduleId}', 'mobile_phone', '');",
"INSERT INTO `{pre}settings` (`id`, `module_id`, `name`, `value`) VALUES ('', '{moduleId}', 'picture_credits', '');"
],
41 => [
"CREATE TABLE `{pre}contacts` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`date` DATETIME NOT NULL,
`mail` VARCHAR(120) NOT NULL,
`name` VARCHAR(80) NOT NULL,
`message` TEXT NOT NULL,
PRIMARY KEY (`id`)
) {ENGINE} {CHARSET};"
]
];
}
......
......@@ -25,7 +25,7 @@ class Schema implements Modules\Installer\SchemaInterface
*/
public function getSchemaVersion()
{
return 40;
return 41;
}
/**
......@@ -33,7 +33,16 @@ class Schema implements Modules\Installer\SchemaInterface
*/
public function createTables()
{
return [];
return [
"CREATE TABLE `{pre}contacts` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`date` DATETIME NOT NULL,
`mail` VARCHAR(120) NOT NULL,
`name` VARCHAR(80) NOT NULL,
`message` TEXT NOT NULL,
PRIMARY KEY (`id`)
) {ENGINE} {CHARSET};"
];
}
/**
......
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Contact\Model;
use ACP3\Core\Model\AbstractModel;
use ACP3\Core\Model\DataProcessor\ColumnTypes;
class ContactsModel extends AbstractModel
{
/**
* @inheritdoc
*/
public function save(array $rawData, $entryId = null)
{
$rawData['date'] = 'now';
return parent::save($rawData, $entryId);
}
/**
* @inheritdoc
*/
protected function getAllowedColumns()
{
return [
'date' => ColumnTypes::COLUMN_TYPE_DATETIME,
'name' => ColumnTypes::COLUMN_TYPE_TEXT,
'mail' => ColumnTypes::COLUMN_TYPE_TEXT,
'message' => ColumnTypes::COLUMN_TYPE_TEXT,
];
}
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Contact\Model\Repository;
use ACP3\Core\Model\Repository\AbstractRepository;
class ContactsRepository extends AbstractRepository
{
const TABLE_NAME = 'contacts';
}
<?php
/**
* Copyright (c) 2017 by the ACP3 Developers.
* See the LICENCE file at the top-level module directory for licencing details.
*/
namespace ACP3\Modules\ACP3\Contact\Model\Repository;
class DataGridRepository extends \ACP3\Core\Model\Repository\DataGridRepository
{
const TABLE_NAME = ContactsRepository::TABLE_NAME;
}
{extends file="asset:System/layout.header-bar.tpl"}
{extends file="asset:System/layout.admin-grid.tpl"}
{block HEADER_BAR_OPTIONS}
{check_access mode="link" path="acp/contact/index/settings" class="glyphicon glyphicon-cog"}
{/block}
{block CONTENT_AFTER_HEADER_BAR}
{redirect_message}
{include file="asset:System/Partials/no_results.tpl" no_results_text={lang t="system|select_menu_item"}}
{block ADMIN_GRID_CONTENT}
{include file="asset:System/Partials/datagrid.tpl" dataTable=$grid}
{/block}
{extends file="asset:System/layout.ajax-form.tpl"}
{block CONTENT_AJAX_FORM}
{include file="asset:System/Partials/form_group.input_text.tpl" name="name" value=$form.name required=true maxlength=20 readonly=$form.name_disabled label={lang t="system|name"}}
{include file="asset:System/Partials/form_group.input_text.tpl" name="name" value=$form.name required=true maxlength=80 readonly=$form.name_disabled label={lang t="system|name"}}
{include file="asset:System/Partials/form_group.input_email.tpl" name="mail" value=$form.mail required=true readonly=$form.mail_disabled maxlength=120 label={lang t="system|email_address"}}
{include file="asset:System/Partials/form_group.textarea.tpl" name="message" value=$form.message required=true label={lang t="system|message"}}
{include file="asset:System/Partials/form_group.checkbox.tpl" options=$copy}
......
services:
contact.controller.admin.index.index:
class: ACP3\Modules\ACP3\Contact\Controller\Admin\Index\Index
parent: core.controller.admin
arguments:
- '@core.context.frontend'
- '@contact.model.repository.data_grid_repository'
contact.controller.admin.index.settings:
class: ACP3\Modules\ACP3\Contact\Controller\Admin\Index\Settings
......@@ -22,6 +24,7 @@ services:
- '@core.helpers.forms'
- '@core.helpers.formToken'
- '@contact.validator'
- '@contact.model.contacts_model'
- '@contact.model.contact_form_model'
contact.controller.widget.index.index:
......
services:
contact.model.repository.data_grid_repository:
class: ACP3\Modules\ACP3\Contact\Model\Repository\DataGridRepository
arguments:
- '@core.db'
contact.model.repository.contacts_repository:
class: ACP3\Modules\ACP3\Contact\Model\Repository\ContactsRepository
arguments:
- '@core.db'
contact.model.contacts_model:
class: ACP3\Modules\ACP3\Contact\Model\ContactsModel
arguments:
- '@core.event_dispatcher'
- '@core.model.data_processor'
- '@contact.model.repository.contacts_repository'
contact.model.contact_form_model:
class: ACP3\Modules\ACP3\Contact\Model\ContactFormModel
arguments:
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"suggest": {
"acp3/module-captcha": "Provides basic protection against spam bots."
......
{extends file="asset:System/layout.ajax-form.tpl"}
{block CONTENT_AJAX_FORM}
{include file="asset:System/Partials/form_group.input_number.tpl" name="width" value=$form.width required=true label={lang t="emoticons|image_width"} help={lang t="system|statements_in_pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="height" value=$form.height required=true label={lang t="emoticons|image_height"} help={lang t="system|statements_in_pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="filesize" value=$form.filesize required=true label={lang t="emoticons|image_filesize"} help={lang t="system|statements_in_byte"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="width" value=$form.width required=true label={lang t="emoticons|image_width"} input_group_after={lang t="system|pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="height" value=$form.height required=true label={lang t="emoticons|image_height"} input_group_after={lang t="system|pixel"}}
{include file="asset:System/Partials/form_group.input_number.tpl" name="filesize" value=$form.filesize required=true label={lang t="emoticons|image_filesize"} input_group_after={lang t="system|byte"}}
{include file="asset:System/Partials/form_group.submit.tpl" form_token=$form_token back_url={uri args="acp/emoticons"}}
{/block}
......@@ -17,12 +17,12 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-errors": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-errors": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"autoload": {
"psr-4": {
......
......@@ -17,11 +17,11 @@
"prefer-stable": true,
"require": {
"acp3/composer-installer": "*",
"acp3/core": "^4.6.2",
"acp3/setup": "^4.6.2",
"acp3/module-permissions": "^4.6.2",
"acp3/module-system": "^4.6.2",
"acp3/module-users": "^4.6.2"
"acp3/core": "^4.7.0",
"acp3/setup": "^4.7.0",
"acp3/module-permissions": "^4.7.0",
"acp3/module-system": "^4.7.0",
"acp3/module-users": "^4.7.0"
},
"autoload": {
"psr-4": {
......
......@@ -17,12 +17,12 @@
"prefer-stable": true,