diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a01604a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# Composer
+/composer.lock
+/vendor/
+
+# PhpUnit
+/.phpunit.result.cache
+/phpunit.xml
+
+# IDE
+/.idea
diff --git a/README.md b/README.md
index 00b1d7e..28a834a 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
---
-> Working with **Contao 4.9** and up to **Contao 4.13** (PHP ^7.4 and PHP 8)
+> Working with **Contao 4.13** and **Contao 5.1** (PHP ^8.1)
---
diff --git a/composer.json b/composer.json
index 1944f7d..0788d4e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,46 +1,74 @@
{
- "name": "oveleon/contao-recommendation-bundle",
- "type": "contao-bundle",
- "description": "Recommendation integration for Contao 4 Open Source CMS",
- "keywords": ["contao","recommendation-bundle"],
- "homepage": "https://www.oveleon.de/",
- "license": "MIT",
- "authors": [
- {
- "name": "Oveleon",
- "homepage": "https://oveleon.de/",
- "role": "Developer"
- }
- ],
- "require": {
- "php": "^7.4 || ^8.0",
- "contao/core-bundle":"^4.9"
+ "name": "oveleon/contao-recommendation-bundle",
+ "type": "contao-bundle",
+ "description": "Recommendation integration for Contao Open Source CMS",
+ "keywords": [
+ "contao",
+ "recommendation-bundle",
+ "recommendation",
+ "reviews"
+ ],
+ "homepage": "https://www.oveleon.de/",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Oveleon",
+ "homepage": "https://oveleon.de/",
+ "role": "Developer"
},
- "require-dev": {
- "contao/manager-plugin": "^2.0"
+ {
+ "name": "Sebastian Zoglowek",
+ "homepage": "https://github.com/zoglo",
+ "role": "Developer"
},
- "conflict": {
- "contao/core": "*",
- "contao/manager-plugin": "<2.0 || >=3.0"
+ {
+ "name": "Fabian Ekert",
+ "homepage": "https://github.com/eki89",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": "^8.1",
+ "contao/core-bundle": "^4.13 || ^5.1"
+ },
+ "require-dev": {
+ "contao/manager-plugin": "^2.3.1",
+ "contao/test-case": "^5.1",
+ "phpunit/phpunit": "^9.5",
+ "symfony/http-client": "^5.4 || ^6.0",
+ "symfony/phpunit-bridge": "^5.4 || ^6.0"
+ },
+ "conflict": {
+ "contao/core": "*",
+ "contao/manager-plugin": "<2.0 || >=3.0"
+ },
+ "suggest": {
+ "oveleon/contao-google-recommendation-bundle": "This bundle imports Google reviews into the contao-recommendation-bundle"
+ },
+ "autoload": {
+ "psr-4": {
+ "Oveleon\\ContaoRecommendationBundle\\": "src/"
},
- "autoload": {
- "psr-4": {
- "Oveleon\\ContaoRecommendationBundle\\": "src/"
- },
- "classmap": [
- "src/Resources/contao/"
- ],
- "exclude-from-classmap": [
- "src/Resources/contao/config/",
- "src/Resources/contao/dca/",
- "src/Resources/contao/languages/",
- "src/Resources/contao/templates/"
- ]
+ "classmap": [
+ "contao/"
+ ],
+ "exclude-from-classmap": [
+ "contao/config/",
+ "contao/dca/",
+ "contao/languages/",
+ "contao/templates/"
+ ]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.3.x-dev"
},
- "extra": {
- "branch-alias": {
- "dev-master": "1.2.x-dev"
- },
- "contao-manager-plugin": "Oveleon\\ContaoRecommendationBundle\\ContaoManager\\Plugin"
+ "contao-manager-plugin": "Oveleon\\ContaoRecommendationBundle\\ContaoManager\\Plugin"
+ },
+ "config": {
+ "allow-plugins": {
+ "php-http/discovery": true,
+ "contao/manager-plugin": true
}
+ }
}
diff --git a/config/services.yaml b/config/services.yaml
new file mode 100644
index 0000000..e31ca06
--- /dev/null
+++ b/config/services.yaml
@@ -0,0 +1,9 @@
+services:
+ _defaults:
+ autowire: true
+ autoconfigure: true
+ public: true
+
+ Oveleon\ContaoRecommendationBundle\:
+ resource: '../src/'
+ exclude: '../src/{Model,DependencyInjection,Resources}'
diff --git a/contao/config/config.php b/contao/config/config.php
new file mode 100644
index 0000000..36e49be
--- /dev/null
+++ b/contao/config/config.php
@@ -0,0 +1,41 @@
+ [
+ 'tables' => ['tl_recommendation_archive', 'tl_recommendation']
+ ]
+]);
+
+ArrayUtil::arrayInsert($GLOBALS['BE_MOD']['system'], 3, [
+ 'recommendation_settings' => [
+ 'tables' => ['tl_recommendation_settings'],
+ 'hideInNavigation' => true
+ ]
+]);
+
+// Front end modules
+ArrayUtil::arrayInsert($GLOBALS['FE_MOD'], 2, [
+ 'recommendation' => [
+ 'recommendationform' => ModuleRecommendationForm::class,
+ 'recommendationlist' => ModuleRecommendationList::class,
+ 'recommendationreader' => ModuleRecommendationReader::class
+ ]
+]);
+
+// Add permissions
+$GLOBALS['TL_PERMISSIONS'][] = 'recommendations';
+$GLOBALS['TL_PERMISSIONS'][] = 'recommendationp';
+
+// Models
+$GLOBALS['TL_MODELS']['tl_recommendation'] = RecommendationModel::class;
+$GLOBALS['TL_MODELS']['tl_recommendation_archive'] = RecommendationArchiveModel::class;
diff --git a/src/Resources/contao/dca/tl_module.php b/contao/dca/tl_module.php
similarity index 62%
rename from src/Resources/contao/dca/tl_module.php
rename to contao/dca/tl_module.php
index a4571ee..131df1b 100644
--- a/src/Resources/contao/dca/tl_module.php
+++ b/contao/dca/tl_module.php
@@ -6,9 +6,15 @@
* (c) https://www.oveleon.de/
*/
-Contao\System::loadLanguageFile('tl_recommendation');
-Contao\System::loadLanguageFile('tl_recommendation_notification');
-Contao\System::loadLanguageFile('tl_recommendation_list');
+use Contao\Backend;
+use Contao\BackendUser;
+use Contao\System;
+use Contao\Controller;
+use Oveleon\ContaoRecommendationBundle\Security\ContaoRecommendationPermissions;
+
+System::loadLanguageFile('tl_recommendation');
+System::loadLanguageFile('tl_recommendation_notification');
+System::loadLanguageFile('tl_recommendation_list');
// Add a palette selector
$GLOBALS['TL_DCA']['tl_module']['palettes']['__selector__'][] = 'recommendation_activate';
@@ -21,222 +27,185 @@
$GLOBALS['TL_DCA']['tl_module']['subpalettes']['recommendation_activate'] = 'recommendation_activateJumpTo,recommendation_activateText';
// Add fields to tl_module
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_archives'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_archives'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_archives'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'options_callback' => array('tl_module_recommendation', 'getRecommendationArchives'),
- 'eval' => array('multiple'=>true, 'mandatory'=>true),
+ 'options_callback' => ['tl_module_recommendation', 'getRecommendationArchives'],
+ 'eval' => ['multiple'=>true, 'mandatory'=>true],
'sql' => "blob NULL"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_archive'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_archive'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_archive'] = [
'exclude' => true,
'inputType' => 'select',
- 'options_callback' => array('tl_module_recommendation', 'getRecommendationArchives'),
- 'eval' => array('mandatory'=>true, 'includeBlankOption'=>true, 'tl_class'=>'w50 clr'),
+ 'options_callback' => ['tl_module_recommendation', 'getRecommendationArchives'],
+ 'eval' => ['mandatory'=>true, 'includeBlankOption'=>true, 'tl_class'=>'w50 clr'],
'sql' => "int(10) unsigned NOT NULL default 0"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_featured'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_featured'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_featured'] = [
'default' => 'all_items',
'exclude' => true,
'inputType' => 'select',
- 'options' => array('all_items', 'featured', 'unfeatured', 'featured_first'),
+ 'options' => ['all_items', 'featured', 'unfeatured', 'featured_first'],
'reference' => &$GLOBALS['TL_LANG']['tl_recommendation_list'],
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "varchar(16) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_readerModule'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_readerModule'] = [
'exclude' => true,
'inputType' => 'select',
- 'options_callback' => array('tl_module_recommendation', 'getReaderModules'),
+ 'options_callback' => ['tl_module_recommendation', 'getReaderModules'],
'reference' => &$GLOBALS['TL_LANG']['tl_module'],
- 'eval' => array('includeBlankOption'=>true, 'tl_class'=>'w50'),
+ 'eval' => ['includeBlankOption'=>true, 'tl_class'=>'w50'],
'sql' => "int(10) unsigned NOT NULL default 0"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_metaFields'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_metaFields'],
- 'default' => array('date', 'author'),
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_metaFields'] = [
+ 'default' => ['date', 'author'],
'exclude' => true,
'inputType' => 'checkbox',
- 'options' => array('image', 'date', 'author', 'rating', 'location', 'customField'),
+ 'options' => ['image', 'date', 'author', 'rating', 'location', 'customField'],
'reference' => &$GLOBALS['TL_LANG']['tl_recommendation'],
- 'eval' => array('multiple'=>true),
+ 'eval' => ['multiple'=>true],
'sql' => "varchar(255) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_order'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_order'] = [
'exclude' => true,
'inputType' => 'select',
- 'options' => array('order_date_asc', 'order_date_desc', 'order_random', 'order_rating_desc'),
+ 'options' => ['order_date_asc', 'order_date_desc', 'order_random', 'order_rating_desc'],
'reference' => &$GLOBALS['TL_LANG']['tl_recommendation_list'],
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "varchar(32) NOT NULL default 'order_date_desc'"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_minRating'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_minRating'] = [
'exclude' => true,
'inputType' => 'select',
- 'options' => array(1=> 'minOne', 2=>'minTwo', 3=>'minThree', 4=>'minFour', 5=>'minFive'),
+ 'options' => [1=> 'minOne', 2=>'minTwo', 3=>'minThree', 4=>'minFour', 5=>'minFive'],
'reference' => &$GLOBALS['TL_LANG']['tl_recommendation_list'],
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "char(1) NOT NULL default '1'"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_optionalFormFields'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_optionalFormFields'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_optionalFormFields'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'options' => array('title', 'location', 'email', 'customField'),
+ 'options' => ['title', 'location', 'email', 'customField'],
'reference' => &$GLOBALS['TL_LANG']['tl_recommendation'],
- 'eval' => array('multiple'=>true, 'tl_class'=>'w50 clr'),
+ 'eval' => ['multiple'=>true, 'tl_class'=>'w50 clr'],
'sql' => "varchar(255) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_customFieldLabel'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_customFieldLabel'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_customFieldLabel'] = [
'exclude' => true,
'inputType' => 'text',
- 'eval' => array('maxlength'=>64, 'tl_class'=>'w50 clr'),
+ 'eval' => ['maxlength'=>64, 'tl_class'=>'w50 clr'],
'sql' => "varchar(64) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_notify'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_notify'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_notify'] = [
'default' => true,
'exclude' => true,
'inputType' => 'checkbox',
- 'eval' => array('tl_class'=>'w50 clr'),
+ 'eval' => ['tl_class'=>'w50 clr'],
'sql' => "char(1) NOT NULL default '1'"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_moderate'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_moderate'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_moderate'] = [
'default' => true,
'exclude' => true,
'inputType' => 'checkbox',
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "char(1) NOT NULL default '1'"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_disableCaptcha'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_disableCaptcha'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_disableCaptcha'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "char(1) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_disableCaptcha'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_disableCaptcha'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_disableCaptcha'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'eval' => array('tl_class'=>'w50'),
+ 'eval' => ['tl_class'=>'w50'],
'sql' => "char(1) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_privacyText'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_privacyText'] = [
'exclude' => true,
'inputType' => 'textarea',
- 'eval' => array('style'=>'height:100px', 'allowHtml'=>true),
+ 'eval' => ['style'=>'height:100px', 'allowHtml'=>true],
'sql' => "text NULL"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activate'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activate'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'eval' => array('submitOnChange'=>true),
+ 'eval' => ['submitOnChange'=>true],
'sql' => "char(1) NOT NULL default ''"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activateJumpTo'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activateJumpTo'] = [
'exclude' => true,
'inputType' => 'pageTree',
'foreignKey' => 'tl_page.title',
- 'eval' => array('fieldType'=>'radio'),
+ 'eval' => ['fieldType'=>'radio'],
'sql' => "int(10) unsigned NOT NULL default 0",
- 'relation' => array('type'=>'hasOne', 'load'=>'lazy')
-);
+ 'relation' => ['type'=>'hasOne', 'load'=>'lazy']
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activateText'] = array
-(
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_activateText'] = [
'exclude' => true,
'inputType' => 'textarea',
- 'eval' => array('style'=>'height:120px', 'decodeEntities'=>true, 'alwaysSave'=>true),
- 'load_callback' => array
- (
- array('tl_module_recommendation', 'getRecommendationActivationDefault')
- ),
+ 'eval' => ['style'=>'height:120px', 'decodeEntities'=>true, 'alwaysSave'=>true],
+ 'load_callback' =>
+ [
+ ['tl_module_recommendation', 'getRecommendationActivationDefault']
+ ],
'sql' => "text NULL"
-);
+];
-$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_template'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_module']['recommendation_template'],
+$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_template'] = [
'exclude' => true,
'inputType' => 'select',
'options_callback' => static fn () => Controller::getTemplateGroup('recommendation_'),
- 'eval' => array('includeBlankOption' => true, 'chosen' => true, 'tl_class'=>'w50'),
+ 'eval' => ['includeBlankOption' => true, 'chosen' => true, 'tl_class'=>'w50'],
'sql' => "varchar(64) NOT NULL default ''"
-);
-
+];
-/**
- * Provide miscellaneous methods that are used by the data configuration array.
- *
- * @author Fabian Ekert
- */
-class tl_module_recommendation extends Contao\Backend
+class tl_module_recommendation extends Backend
{
-
/**
* Import the back end user object
*/
public function __construct()
{
parent::__construct();
- $this->import('Contao\BackendUser', 'User');
+ $this->import(BackendUser::class, 'User');
}
/**
* Get all recommendation archives and return them as array
- *
- * @return array
*/
- public function getRecommendationArchives()
+ public function getRecommendationArchives(): array
{
if (!$this->User->isAdmin && !is_array($this->User->recommendations))
{
- return array();
+ return [];
}
- $arrArchives = array();
+ $arrArchives = [];
$objArchives = $this->Database->execute("SELECT id, title FROM tl_recommendation_archive ORDER BY title");
+ $security = System::getContainer()->get('security.helper');
while ($objArchives->next())
{
- if ($this->User->hasAccess($objArchives->id, 'recommendations'))
+ if ($security->isGranted(ContaoRecommendationPermissions::USER_CAN_EDIT_ARCHIVE, $objArchives->id))
{
$arrArchives[$objArchives->id] = $objArchives->title;
}
@@ -247,12 +216,10 @@ public function getRecommendationArchives()
/**
* Get all recommendation reader modules and return them as array
- *
- * @return array
*/
- public function getReaderModules()
+ public function getReaderModules(): array
{
- $arrModules = array();
+ $arrModules = [];
$objModules = $this->Database->execute("SELECT m.id, m.name, t.name AS theme FROM tl_module m LEFT JOIN tl_theme t ON m.pid=t.id WHERE m.type='recommendationreader' ORDER BY t.name, m.name");
while ($objModules->next())
@@ -265,12 +232,8 @@ public function getReaderModules()
/**
* Load the default recommendation activation text
- *
- * @param mixed $varValue
- *
- * @return mixed
*/
- public function getRecommendationActivationDefault($varValue)
+ public function getRecommendationActivationDefault(mixed $varValue): mixed
{
if (trim($varValue) === '')
{
diff --git a/contao/dca/tl_recommendation.php b/contao/dca/tl_recommendation.php
new file mode 100644
index 0000000..28f655b
--- /dev/null
+++ b/contao/dca/tl_recommendation.php
@@ -0,0 +1,261 @@
+ [
+ 'dataContainer' => DC_Table::class,
+ 'ptable' => 'tl_recommendation_archive',
+ 'switchToEdit' => true,
+ 'enableVersioning' => true,
+ 'onload_callback' => [
+ [RecommendationListener::class, 'checkRecommendationPermission'],
+ [RecommendationListener::class, 'generateSitemap']
+ ],
+ 'oncut_callback' => [
+ [RecommendationListener::class, 'scheduleUpdate']
+ ],
+ 'ondelete_callback' => [
+ [RecommendationListener::class, 'scheduleUpdate']
+ ],
+ 'onsubmit_callback' => [
+ [RecommendationListener::class, 'adjustTime'],
+ [RecommendationListener::class, 'scheduleUpdate']
+ ],
+ 'oninvalidate_cache_tags_callback' => [
+ [RecommendationListener::class, 'addSitemapCacheInvalidationTag'],
+ ],
+ 'sql' => [
+ 'keys' => [
+ 'id' => 'primary',
+ 'alias' => 'index',
+ 'pid,start,stop,published' => 'index'
+ ]
+ ]
+ ],
+
+ // List
+ 'list' => [
+ 'sorting' => [
+ 'mode' => DataContainer::MODE_PARENT,
+ 'fields' => ['date DESC'],
+ 'headerFields' => ['title', 'jumpTo', 'tstamp', 'protected'],
+ 'panelLayout' => 'filter;sort,search,limit',
+ 'child_record_callback' => [RecommendationListener::class, 'listRecommendations'],
+ 'child_record_class' => 'no_padding'
+ ],
+ 'global_operations' => [
+ 'all' => [
+ 'href' => 'act=select',
+ 'class' => 'header_edit_all',
+ 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"'
+ ]
+ ],
+ 'operations' => [
+ 'edit' => [
+ 'href' => 'act=edit',
+ 'icon' => 'edit.svg'
+ ],
+ 'copy' => [
+ 'href' => 'act=paste&mode=copy',
+ 'icon' => 'copy.svg'
+ ],
+ 'cut' => [
+ 'href' => 'act=paste&mode=cut',
+ 'icon' => 'cut.svg'
+ ],
+ 'delete' => [
+ 'href' => 'act=delete',
+ 'icon' => 'delete.svg',
+ 'attributes' => 'onclick="if(!confirm(\'' . ($GLOBALS['TL_LANG']['MSC']['deleteConfirm'] ?? null) . '\'))return false;Backend.getScrollOffset()"'
+ ],
+ 'toggle' => [
+ 'href' => 'act=toggle&field=published',
+ 'icon' => 'visible.svg',
+ 'showInHeader' => true
+ ],
+ 'feature' => [
+ 'href' => 'act=toggle&field=featured',
+ 'icon' => 'featured.svg',
+ ],
+ 'show' => [
+ 'href' => 'act=show',
+ 'icon' => 'show.svg'
+ ]
+ ]
+ ],
+
+ // Palettes
+ 'palettes' => [
+ 'default' => '{title_legend},author,title,alias,email,location;{date_legend},date,time;{recommendation_legend},text,imageUrl,rating,customField;{teaser_legend:hide},teaser;{expert_legend:hide},cssClass,featured;{publish_legend},published,start,stop'
+ ],
+
+ // Fields
+ 'fields' => [
+ 'id' => [
+ 'sql' => "int(10) unsigned NOT NULL auto_increment"
+ ],
+ 'pid' => [
+ 'foreignKey' => 'tl_recommendation_archive.title',
+ 'sql' => "int(10) unsigned NOT NULL default '0'",
+ 'relation' => ['type'=>'belongsTo', 'load'=>'lazy']
+ ],
+ 'tstamp' => [
+ 'sql' => "int(10) unsigned NOT NULL default '0'"
+ ],
+ 'title' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'sorting' => true,
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC,
+ 'inputType' => 'text',
+ 'eval' => ['maxlength'=>255, 'tl_class'=>'w50 clr'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'alias' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'alias', 'doNotCopy'=>true, 'unique'=>true, 'maxlength'=>128, 'tl_class'=>'w50'],
+ 'save_callback' => [
+ [RecommendationListener::class, 'generateRecommendationAlias']
+ ],
+ 'sql' => "varchar(255) BINARY NOT NULL default ''"
+ ],
+ 'author' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'sorting' => true,
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC,
+ 'inputType' => 'text',
+ 'eval' => ['doNotCopy'=>true, 'mandatory'=>true, 'maxlength'=>128, 'tl_class'=>'w50'],
+ 'sql' => "varchar(128) NOT NULL default ''"
+ ],
+ 'email' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'text',
+ 'eval' => ['doNotCopy'=>true, 'maxlength'=>255, 'rgxp'=>'email', 'decodeEntities'=>true, 'tl_class'=>'w50'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'location' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'sorting' => true,
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC,
+ 'inputType' => 'text',
+ 'eval' => ['doNotCopy'=>true, 'maxlength'=>128, 'tl_class'=>'w50'],
+ 'sql' => "varchar(128) NOT NULL default ''"
+ ],
+ 'date' => [
+ 'default' => time(),
+ 'exclude' => true,
+ 'filter' => true,
+ 'sorting' => true,
+ 'flag' => DataContainer::SORT_MONTH_DESC,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'date', 'mandatory'=>true, 'doNotCopy'=>true, 'datepicker'=>true, 'tl_class'=>'w50 wizard'],
+ 'load_callback' => [
+ [RecommendationListener::class, 'loadDate']
+ ],
+ 'sql' => "int(10) unsigned NOT NULL default 0"
+ ],
+ 'time' => [
+ 'default' => time(),
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'time', 'mandatory'=>true, 'doNotCopy'=>true, 'tl_class'=>'w50'],
+ 'load_callback' => [
+ [RecommendationListener::class, 'loadTime']
+ ],
+ 'sql' => "int(10) unsigned NOT NULL default 0"
+ ],
+ 'teaser' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'textarea',
+ 'eval' => ['rte'=>'tinyMCE', 'tl_class'=>'clr'],
+ 'sql' => "mediumtext NULL"
+ ],
+ 'text' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'textarea',
+ 'eval' => ['mandatory'=>true, 'rte'=>'tinyMCE', 'tl_class'=>'clr'],
+ 'sql' => "mediumtext NULL"
+ ],
+ 'imageUrl' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'url', 'decodeEntities'=>true, 'maxlength'=>255, 'dcaPicker'=>true, 'tl_class'=>'w50 wizard'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'rating' => [
+ 'default' => 5,
+ 'exclude' => true,
+ 'search' => true,
+ 'filter' => true,
+ 'sorting' => true,
+ 'inputType' => 'select',
+ 'options' => [1,2,3,4,5],
+ 'eval' => ['mandatory'=>true, 'tl_class'=>'w50'],
+ 'sql' => "char(1) NOT NULL default ''"
+ ],
+ 'customField' => [
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'eval' => ['doNotCopy'=>true, 'maxlength'=>255, 'tl_class'=>'w100 clr'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'cssClass' => [
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'eval' => ['tl_class'=>'w50'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'featured' => [
+ 'exclude' => true,
+ 'toggle' => true,
+ 'filter' => true,
+ 'inputType' => 'checkbox',
+ 'eval' => ['tl_class'=>'w50 m12'],
+ 'sql' => "char(1) NOT NULL default ''"
+ ],
+ 'verified' => [
+ 'filter' => true,
+ 'eval' => ['isBoolean'=>true],
+ 'sql' => "char(1) NOT NULL default '1'"
+ ],
+ 'published' => [
+ 'exclude' => true,
+ 'toggle' => true,
+ 'filter' => true,
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC,
+ 'inputType' => 'checkbox',
+ 'eval' => ['doNotCopy'=>true],
+ 'sql' => "char(1) NOT NULL default ''"
+ ],
+ 'start' => [
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'datim', 'datepicker'=>true, 'tl_class'=>'w50 wizard'],
+ 'sql' => "varchar(10) NOT NULL default ''"
+ ],
+ 'stop' => [
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'eval' => ['rgxp'=>'datim', 'datepicker'=>true, 'tl_class'=>'w50 wizard'],
+ 'sql' => "varchar(10) NOT NULL default ''"
+ ]
+ ]
+];
diff --git a/contao/dca/tl_recommendation_archive.php b/contao/dca/tl_recommendation_archive.php
new file mode 100644
index 0000000..fe5a269
--- /dev/null
+++ b/contao/dca/tl_recommendation_archive.php
@@ -0,0 +1,139 @@
+ [
+ 'dataContainer' => DC_Table::class,
+ 'ctable' => ['tl_recommendation'],
+ 'switchToEdit' => true,
+ 'enableVersioning' => true,
+ 'oncreate_callback' => [
+ [RecommendationArchiveListener::class, 'adjustPermissions']
+ ],
+ 'oncopy_callback' => [
+ [RecommendationArchiveListener::class, 'adjustPermissions']
+ ],
+ 'oninvalidate_cache_tags_callback' => [
+ [RecommendationArchiveListener::class, 'addSitemapCacheInvalidationTag'],
+ ],
+ 'sql' => [
+ 'keys' => [
+ 'id' => 'primary'
+ ]
+ ]
+ ],
+
+ // List
+ 'list' => [
+ 'sorting' => [
+ 'mode' => DataContainer::MODE_SORTED,
+ 'fields' => ['title'],
+ 'flag' => DataContainer::SORT_INITIAL_LETTER_ASC,
+ 'panelLayout' => 'filter;search,limit'
+ ],
+ 'label' => [
+ 'fields' => ['title'],
+ 'format' => '%s'
+ ],
+ 'global_operations' => [
+ 'settings' => [
+ 'href' => 'do=recommendation_settings',
+ 'class' => '',
+ 'icon' => 'edit.svg',
+ 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"'
+ ],
+ 'all' => [
+ 'href' => 'act=select',
+ 'class' => 'header_edit_all',
+ 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"'
+ ]
+ ],
+ 'operations' => [
+ 'editheader' => [
+ 'href' => 'act=edit',
+ 'icon' => 'header.svg',
+ 'button_callback' => [RecommendationArchiveListener::class, 'editHeader']
+ ],
+ 'edit' => [
+ 'href' => 'table=tl_recommendation',
+ 'icon' => 'edit.svg'
+ ],
+ 'copy' => [
+ 'href' => 'act=copy',
+ 'icon' => 'copy.svg',
+ 'button_callback' => [RecommendationArchiveListener::class, 'copyArchive']
+ ],
+ 'delete' => [
+ 'href' => 'act=delete',
+ 'icon' => 'delete.svg',
+ 'attributes' => 'onclick="if(!confirm(\'' . ($GLOBALS['TL_LANG']['MSC']['deleteConfirm'] ?? null) . '\'))return false;Backend.getScrollOffset()"',
+ 'button_callback' => [RecommendationArchiveListener::class, 'deleteArchive']
+ ],
+ 'show' => [
+ 'href' => 'act=show',
+ 'icon' => 'show.svg'
+ ]
+ ]
+ ],
+
+ // Palettes
+ 'palettes' => [
+ '__selector__' => ['protected'],
+ 'default' => '{title_legend},title,jumpTo;{protected_legend:hide},protected'
+ ],
+
+ // Subpalettes
+ 'subpalettes' => [
+ 'protected' => 'groups'
+ ],
+
+ // Fields
+ 'fields' => [
+ 'id' => [
+ 'sql' => "int(10) unsigned NOT NULL auto_increment"
+ ],
+ 'tstamp' => [
+ 'sql' => "int(10) unsigned NOT NULL default '0'"
+ ],
+ 'title' => [
+ 'exclude' => true,
+ 'search' => true,
+ 'inputType' => 'text',
+ 'eval' => ['mandatory'=>true, 'maxlength'=>255, 'tl_class'=>'w50'],
+ 'sql' => "varchar(255) NOT NULL default ''"
+ ],
+ 'jumpTo' => [
+ 'exclude' => true,
+ 'inputType' => 'pageTree',
+ 'foreignKey' => 'tl_page.title',
+ 'eval' => ['fieldType'=>'radio', 'tl_class'=>'clr'],
+ 'sql' => "int(10) unsigned NOT NULL default '0'",
+ 'relation' => ['type'=>'hasOne', 'load'=>'eager']
+ ],
+ 'protected' => [
+ 'exclude' => true,
+ 'filter' => true,
+ 'inputType' => 'checkbox',
+ 'eval' => ['submitOnChange'=>true],
+ 'sql' => "char(1) NOT NULL default ''"
+ ],
+ 'groups' => [
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'foreignKey' => 'tl_member_group.name',
+ 'eval' => ['mandatory'=>true, 'multiple'=>true],
+ 'sql' => "blob NULL",
+ 'relation' => ['type'=>'hasMany', 'load'=>'lazy']
+ ]
+ ]
+];
diff --git a/contao/dca/tl_recommendation_settings.php b/contao/dca/tl_recommendation_settings.php
new file mode 100644
index 0000000..ebb78ff
--- /dev/null
+++ b/contao/dca/tl_recommendation_settings.php
@@ -0,0 +1,49 @@
+ [
+ 'dataContainer' => DC_File::class,
+ 'closed' => true
+ ],
+
+ // Palettes
+ 'palettes' => [
+ 'default' => '{recommendation_legend},recommendationDefaultImage,recommendationActiveColor;'
+ ],
+
+ // Fields
+ 'fields' => [
+ 'recommendationDefaultImage' => [
+ 'inputType' => 'fileTree',
+ 'eval' => ['fieldType'=>'radio', 'filesOnly'=>true, 'isGallery'=>true, 'extensions'=> Config::get('validImageTypes'), 'tl_class'=>'clr']
+ ],
+ 'recommendationActiveColor' => [
+ 'inputType' => 'text',
+ 'eval' => ['maxlength'=>6, 'multiple'=>true, 'size'=>1, 'colorpicker'=>true, 'isHexColor'=>true, 'decodeEntities'=>true, 'tl_class'=>'w50 wizard'],
+ 'save_callback' => [
+ // See contao/issues (#6105)
+ static function ($value)
+ {
+ if (!\is_array($value))
+ {
+ return StringUtil::restoreBasicEntities($value);
+ }
+
+ return serialize(array_map('\Contao\StringUtil::restoreBasicEntities', $value));
+ }
+ ]
+ ]
+ ]
+];
diff --git a/contao/dca/tl_user.php b/contao/dca/tl_user.php
new file mode 100644
index 0000000..a1cde50
--- /dev/null
+++ b/contao/dca/tl_user.php
@@ -0,0 +1,35 @@
+addLegend('recommendation_legend', 'amg_legend', PaletteManipulator::POSITION_BEFORE)
+ ->addField(['recommendations', 'recommendationp'], 'recommendation_legend', PaletteManipulator::POSITION_APPEND)
+ ->applyToPalette('extend', 'tl_user')
+ ->applyToPalette('custom', 'tl_user')
+;
+
+// Add fields to tl_user_group
+$GLOBALS['TL_DCA']['tl_user']['fields']['recommendations'] = [
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'foreignKey' => 'tl_recommendation_archive.title',
+ 'eval' => ['multiple'=>true],
+ 'sql' => "blob NULL"
+];
+
+$GLOBALS['TL_DCA']['tl_user']['fields']['recommendationp'] = [
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'options' => ['create', 'delete'],
+ 'reference' => &$GLOBALS['TL_LANG']['MSC'],
+ 'eval' => ['multiple'=>true],
+ 'sql' => "blob NULL"
+];
diff --git a/src/Resources/contao/dca/tl_user_group.php b/contao/dca/tl_user_group.php
similarity index 50%
rename from src/Resources/contao/dca/tl_user_group.php
rename to contao/dca/tl_user_group.php
index 52071ad..0af419e 100644
--- a/src/Resources/contao/dca/tl_user_group.php
+++ b/contao/dca/tl_user_group.php
@@ -6,31 +6,29 @@
* (c) https://www.oveleon.de/
*/
+use Contao\CoreBundle\DataContainer\PaletteManipulator;
+
// Extend the default palette
-Contao\CoreBundle\DataContainer\PaletteManipulator::create()
- ->addLegend('recommendation_legend', 'amg_legend', Contao\CoreBundle\DataContainer\PaletteManipulator::POSITION_BEFORE)
- ->addField(array('recommendations', 'recommendationp'), 'recommendation_legend', Contao\CoreBundle\DataContainer\PaletteManipulator::POSITION_APPEND)
+PaletteManipulator::create()
+ ->addLegend('recommendation_legend', 'amg_legend', PaletteManipulator::POSITION_BEFORE)
+ ->addField(['recommendations', 'recommendationp'], 'recommendation_legend', PaletteManipulator::POSITION_APPEND)
->applyToPalette('default', 'tl_user_group')
;
// Add fields to tl_user_group
-$GLOBALS['TL_DCA']['tl_user_group']['fields']['recommendations'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_user']['recommendations'],
+$GLOBALS['TL_DCA']['tl_user_group']['fields']['recommendations'] = [
'exclude' => true,
'inputType' => 'checkbox',
'foreignKey' => 'tl_recommendation_archive.title',
- 'eval' => array('multiple'=>true),
+ 'eval' => ['multiple'=>true],
'sql' => "blob NULL"
-);
+];
-$GLOBALS['TL_DCA']['tl_user_group']['fields']['recommendationp'] = array
-(
- 'label' => &$GLOBALS['TL_LANG']['tl_user']['recommendationp'],
+$GLOBALS['TL_DCA']['tl_user_group']['fields']['recommendationp'] = [
'exclude' => true,
'inputType' => 'checkbox',
- 'options' => array('create', 'delete'),
+ 'options' => ['create', 'delete'],
'reference' => &$GLOBALS['TL_LANG']['MSC'],
- 'eval' => array('multiple'=>true),
+ 'eval' => ['multiple'=>true],
'sql' => "blob NULL"
-);
+];
diff --git a/src/Resources/contao/languages/de/default.xlf b/contao/languages/de/default.xlf
similarity index 70%
rename from src/Resources/contao/languages/de/default.xlf
rename to contao/languages/de/default.xlf
index 1d7701f..97241b7 100644
--- a/src/Resources/contao/languages/de/default.xlf
+++ b/contao/languages/de/default.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/modules.xlf b/contao/languages/de/modules.xlf
similarity index 94%
rename from src/Resources/contao/languages/de/modules.xlf
rename to contao/languages/de/modules.xlf
index a187565..9b6d02e 100644
--- a/src/Resources/contao/languages/de/modules.xlf
+++ b/contao/languages/de/modules.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_module.xlf b/contao/languages/de/tl_module.xlf
similarity index 98%
rename from src/Resources/contao/languages/de/tl_module.xlf
rename to contao/languages/de/tl_module.xlf
index 123da80..8fed375 100644
--- a/src/Resources/contao/languages/de/tl_module.xlf
+++ b/contao/languages/de/tl_module.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_recommendation.xlf b/contao/languages/de/tl_recommendation.xlf
similarity index 99%
rename from src/Resources/contao/languages/de/tl_recommendation.xlf
rename to contao/languages/de/tl_recommendation.xlf
index db80856..f5b4311 100644
--- a/src/Resources/contao/languages/de/tl_recommendation.xlf
+++ b/contao/languages/de/tl_recommendation.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_recommendation_archive.xlf b/contao/languages/de/tl_recommendation_archive.xlf
similarity index 96%
rename from src/Resources/contao/languages/de/tl_recommendation_archive.xlf
rename to contao/languages/de/tl_recommendation_archive.xlf
index 6647544..dade3fa 100644
--- a/src/Resources/contao/languages/de/tl_recommendation_archive.xlf
+++ b/contao/languages/de/tl_recommendation_archive.xlf
@@ -1,12 +1,12 @@
-
+
Titel
-
+
Bitte geben Sie den Archiv-Titel ein.
diff --git a/src/Resources/contao/languages/de/tl_recommendation_list.xlf b/contao/languages/de/tl_recommendation_list.xlf
similarity index 94%
rename from src/Resources/contao/languages/de/tl_recommendation_list.xlf
rename to contao/languages/de/tl_recommendation_list.xlf
index 8cb36e9..4dcc15c 100644
--- a/src/Resources/contao/languages/de/tl_recommendation_list.xlf
+++ b/contao/languages/de/tl_recommendation_list.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_recommendation_notification.xlf b/contao/languages/de/tl_recommendation_notification.xlf
similarity index 95%
rename from src/Resources/contao/languages/de/tl_recommendation_notification.xlf
rename to contao/languages/de/tl_recommendation_notification.xlf
index a1ba652..faafae8 100644
--- a/src/Resources/contao/languages/de/tl_recommendation_notification.xlf
+++ b/contao/languages/de/tl_recommendation_notification.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_recommendation_settings.xlf b/contao/languages/de/tl_recommendation_settings.xlf
similarity index 89%
rename from src/Resources/contao/languages/de/tl_recommendation_settings.xlf
rename to contao/languages/de/tl_recommendation_settings.xlf
index 37347ab..cd147f0 100644
--- a/src/Resources/contao/languages/de/tl_recommendation_settings.xlf
+++ b/contao/languages/de/tl_recommendation_settings.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/de/tl_user.xlf b/contao/languages/de/tl_user.xlf
similarity index 89%
rename from src/Resources/contao/languages/de/tl_user.xlf
rename to contao/languages/de/tl_user.xlf
index e0bbd9b..305763a 100644
--- a/src/Resources/contao/languages/de/tl_user.xlf
+++ b/contao/languages/de/tl_user.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/contao/languages/de/tl_user_group.xlf b/contao/languages/de/tl_user_group.xlf
new file mode 100644
index 0000000..faf9fe6
--- /dev/null
+++ b/contao/languages/de/tl_user_group.xlf
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Bewertungsrechte
+
+
+
+ Erlaubte Archive
+
+
+
+ Hier können Sie den Zugriff auf ein oder mehrere Bewertungs-Archive erlauben.
+
+
+
+ Archivrechte
+
+
+
+ Hier können Sie die Archivrechte festlegen.
+
+
+
+
diff --git a/src/Resources/contao/languages/en/default.xlf b/contao/languages/en/default.xlf
similarity index 68%
rename from src/Resources/contao/languages/en/default.xlf
rename to contao/languages/en/default.xlf
index 48abcdb..7244fee 100644
--- a/src/Resources/contao/languages/en/default.xlf
+++ b/contao/languages/en/default.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/modules.xlf b/contao/languages/en/modules.xlf
similarity index 93%
rename from src/Resources/contao/languages/en/modules.xlf
rename to contao/languages/en/modules.xlf
index 6002ff0..cb85905 100644
--- a/src/Resources/contao/languages/en/modules.xlf
+++ b/contao/languages/en/modules.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_module.xlf b/contao/languages/en/tl_module.xlf
similarity index 98%
rename from src/Resources/contao/languages/en/tl_module.xlf
rename to contao/languages/en/tl_module.xlf
index a7e0744..45df350 100644
--- a/src/Resources/contao/languages/en/tl_module.xlf
+++ b/contao/languages/en/tl_module.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_recommendation.xlf b/contao/languages/en/tl_recommendation.xlf
similarity index 98%
rename from src/Resources/contao/languages/en/tl_recommendation.xlf
rename to contao/languages/en/tl_recommendation.xlf
index 665104b..1073f30 100644
--- a/src/Resources/contao/languages/en/tl_recommendation.xlf
+++ b/contao/languages/en/tl_recommendation.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_recommendation_archive.xlf b/contao/languages/en/tl_recommendation_archive.xlf
similarity index 95%
rename from src/Resources/contao/languages/en/tl_recommendation_archive.xlf
rename to contao/languages/en/tl_recommendation_archive.xlf
index 65cea85..966798d 100644
--- a/src/Resources/contao/languages/en/tl_recommendation_archive.xlf
+++ b/contao/languages/en/tl_recommendation_archive.xlf
@@ -1,11 +1,11 @@
-
+
-
+
diff --git a/src/Resources/contao/languages/en/tl_recommendation_list.xlf b/contao/languages/en/tl_recommendation_list.xlf
similarity index 93%
rename from src/Resources/contao/languages/en/tl_recommendation_list.xlf
rename to contao/languages/en/tl_recommendation_list.xlf
index c602cf1..7014289 100644
--- a/src/Resources/contao/languages/en/tl_recommendation_list.xlf
+++ b/contao/languages/en/tl_recommendation_list.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_recommendation_notification.xlf b/contao/languages/en/tl_recommendation_notification.xlf
similarity index 93%
rename from src/Resources/contao/languages/en/tl_recommendation_notification.xlf
rename to contao/languages/en/tl_recommendation_notification.xlf
index 32535f5..dda2248 100644
--- a/src/Resources/contao/languages/en/tl_recommendation_notification.xlf
+++ b/contao/languages/en/tl_recommendation_notification.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_recommendation_settings.xlf b/contao/languages/en/tl_recommendation_settings.xlf
similarity index 88%
rename from src/Resources/contao/languages/en/tl_recommendation_settings.xlf
rename to contao/languages/en/tl_recommendation_settings.xlf
index e4e3396..15c2e9a 100644
--- a/src/Resources/contao/languages/en/tl_recommendation_settings.xlf
+++ b/contao/languages/en/tl_recommendation_settings.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Resources/contao/languages/en/tl_user.xlf b/contao/languages/en/tl_user.xlf
similarity index 88%
rename from src/Resources/contao/languages/en/tl_user.xlf
rename to contao/languages/en/tl_user.xlf
index 26da2b3..59e1c15 100644
--- a/src/Resources/contao/languages/en/tl_user.xlf
+++ b/contao/languages/en/tl_user.xlf
@@ -1,5 +1,5 @@
-
+
diff --git a/contao/languages/en/tl_user_group.xlf b/contao/languages/en/tl_user_group.xlf
new file mode 100644
index 0000000..aa0555d
--- /dev/null
+++ b/contao/languages/en/tl_user_group.xlf
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Resources/contao/modules/ModuleRecommendation.php b/contao/modules/ModuleRecommendation.php
similarity index 66%
rename from src/Resources/contao/modules/ModuleRecommendation.php
rename to contao/modules/ModuleRecommendation.php
index d55781a..e7a8b55 100644
--- a/src/Resources/contao/modules/ModuleRecommendation.php
+++ b/contao/modules/ModuleRecommendation.php
@@ -9,64 +9,50 @@
namespace Oveleon\ContaoRecommendationBundle;
use Contao\Config;
-use Contao\Controller;
+use Contao\CoreBundle\Security\ContaoCorePermissions;
use Contao\Date;
use Contao\FilesModel;
use Contao\FrontendTemplate;
-use Contao\FrontendUser;
use Contao\Model\Collection;
use Contao\Module;
use Contao\PageModel;
use Contao\StringUtil;
use Contao\System;
+use Exception;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationModel;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationArchiveModel;
+use Symfony\Component\Filesystem\Path;
/**
* Parent class for recommendation modules.
*
* @property string $recommendation_template
* @property mixed $recommendation_metaFields
- *
- * @author Fabian Ekert
- * @author Sebastian Zoglowek
*/
abstract class ModuleRecommendation extends Module
{
-
/**
* Sort out protected archives
- *
- * @param array $arrArchives
- *
- * @return array
*/
- protected function sortOutProtected($arrArchives)
+ protected function sortOutProtected(array $arrArchives): array
{
if (empty($arrArchives) || !\is_array($arrArchives))
{
return $arrArchives;
}
- $this->import(FrontendUser::class, 'User');
$objArchive = RecommendationArchiveModel::findMultipleByIds($arrArchives);
- $arrArchives = array();
+ $arrArchives = [];
if ($objArchive !== null)
{
+ $security = System::getContainer()->get('security.helper');
+
while ($objArchive->next())
{
- if ($objArchive->protected)
+ if ($objArchive->protected && !$security->isGranted(ContaoCorePermissions::MEMBER_IN_GROUPS, StringUtil::deserialize($objArchive->groups, true)))
{
- if (!FE_USER_LOGGED_IN)
- {
- continue;
- }
-
- $groups = StringUtil::deserialize($objArchive->groups);
-
- if (empty($groups) || !\is_array($groups) || !\count(array_intersect($groups, $this->User->groups)))
- {
- continue;
- }
+ continue;
}
$arrArchives[] = $objArchive->id;
@@ -78,21 +64,13 @@ protected function sortOutProtected($arrArchives)
/**
* Parse an item and return it as string
- *
- * @param RecommendationModel $objRecommendation
- * @param RecommendationArchiveModel $objRecommendationArchive
- * @param string $strClass
- * @param integer $intCount
- *
- * @return string
*/
- protected function parseRecommendation($objRecommendation, $objRecommendationArchive, $strClass='', $intCount=0)
+ protected function parseRecommendation(RecommendationModel $objRecommendation, RecommendationArchiveModel $objRecommendationArchive, string $strClass='', int $intCount=0): string
{
- /** @var FrontendTemplate|object $objTemplate */
$objTemplate = new FrontendTemplate($this->recommendation_template ?: 'recommendation_default');
$objTemplate->setData($objRecommendation->row());
- if ($objRecommendation->cssClass != '')
+ if ($objRecommendation->cssClass)
{
$strClass = ' ' . $objRecommendation->cssClass . $strClass;
}
@@ -142,29 +120,34 @@ protected function parseRecommendation($objRecommendation, $objRecommendationArc
// Parsing image meta field to template for backwards compatibility // Works for recommendation_default.html5
$objTemplate->addRecommendationImage = array_key_exists('image', $arrMeta);
+ $container = System::getContainer();
+
// Add an image
if ($objRecommendation->imageUrl != '')
{
- $objRecommendation->imageUrl = Controller::replaceInsertTags($objRecommendation->imageUrl);
+ $objRecommendation->imageUrl = $container->get('contao.insert_tag.parser')->replace($objRecommendation->imageUrl);
+
+ // Insert tag parser on contao ^5 returns a leading slash whilst contao 4.13 does not
+ if (Path::isAbsolute($objRecommendation->imageUrl))
+ {
+ $objRecommendation->imageUrl = substr($objRecommendation->imageUrl,1);
+ }
if ($this->isExternal($objRecommendation->imageUrl))
{
$objTemplate->addExternalImage = true;
-
$objTemplate->imageUrl = $objRecommendation->imageUrl;
}
else
{
$objModel = FilesModel::findByPath($objRecommendation->imageUrl);
-
- $this->addInternalImage($objModel, $objRecommendation, $objTemplate);
+ $this->addInternalImage($objModel, $objTemplate);
}
}
elseif (Config::get('recommendationDefaultImage'))
{
$objModel = FilesModel::findByUuid(Config::get('recommendationDefaultImage'));
-
- $this->addInternalImage($objModel, $objRecommendation, $objTemplate);
+ $this->addInternalImage($objModel, $objTemplate);
}
// HOOK: add custom logic
@@ -178,10 +161,10 @@ protected function parseRecommendation($objRecommendation, $objRecommendationArc
}
// Tag recommendations
- if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
+ if ($container->has('fos_http_cache.http.symfony_response_tagger'))
{
- $responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
- $responseTagger->addTags(array('contao.db.tl_recommendation.' . $objRecommendation->id));
+ $responseTagger = $container->get('fos_http_cache.http.symfony_response_tagger');
+ $responseTagger->addTags(['contao.db.tl_recommendation.' . $objRecommendation->id]);
}
return $objTemplate->parse();
@@ -189,22 +172,18 @@ protected function parseRecommendation($objRecommendation, $objRecommendationArc
/**
* Parse one or more items and return them as array
- *
- * @param Collection $objRecommendations
- *
- * @return array
*/
- protected function parseRecommendations($objRecommendations)
+ protected function parseRecommendations(Collection $objRecommendations): array
{
$limit = $objRecommendations->count();
if ($limit < 1)
{
- return array();
+ return [];
}
$count = 0;
- $arrRecommendations = array();
+ $arrRecommendations = [];
while ($objRecommendations->next())
{
@@ -222,24 +201,20 @@ protected function parseRecommendations($objRecommendations)
/**
* Return the meta fields of a recommendation as array
- *
- * @param RecommendationModel $objRecommendation
- *
- * @return array
*/
- protected function getMetaFields($objRecommendation)
+ protected function getMetaFields(RecommendationModel $objRecommendation): array
{
$meta = StringUtil::deserialize($this->recommendation_metaFields);
if (!\is_array($meta))
{
- return array();
+ return [];
}
/** @var PageModel $objPage */
global $objPage;
- $return = array();
+ $return = [];
foreach ($meta as $field)
{
@@ -263,15 +238,8 @@ protected function getMetaFields($objRecommendation)
/**
* Generate a link and return it as string
- *
- * @param string $strLink
- * @param RecommendationModel $objRecommendation
- * @param string $strTitle
- * @param boolean $blnIsReadMore
- *
- * @return string
*/
- protected function generateLink($strLink, $objRecommendation, $strTitle, $blnIsReadMore=false)
+ protected function generateLink(string $strLink, RecommendationModel $objRecommendation, string $strTitle, bool $blnIsReadMore=false): string
{
return sprintf('%s%s',
$this->generateRecommendationUrl($objRecommendation),
@@ -282,28 +250,20 @@ protected function generateLink($strLink, $objRecommendation, $strTitle, $blnIsR
/**
* Generate a URL and return it as string
- *
- * @param RecommendationModel $objRecommendation
- *
- * @return string
*/
- protected function generateRecommendationUrl($objRecommendation)
+ protected function generateRecommendationUrl(RecommendationModel $objRecommendation): string
{
$objPage = PageModel::findByPk($objRecommendation->getRelated('pid')->jumpTo);
- return ampersand($objPage->getFrontendUrl((Config::get('useAutoItem') ? '/' : '/items/') . ($objRecommendation->alias ?: $objRecommendation->id)));
+ return StringUtil::ampersand($objPage->getFrontendUrl((Config::get('useAutoItem') ? '/' : '/items/') . ($objRecommendation->alias ?: $objRecommendation->id)));
}
/**
* Check whether path is external
- *
- * @param string $strPath The file path
- *
- * @return boolean
*/
- protected function isExternal($strPath)
+ protected function isExternal(string $strPath): bool
{
- if (substr($strPath, 0, 7) == 'http://' || substr($strPath, 0, 8) == 'https://')
+ if (str_starts_with($strPath, 'http://') || str_starts_with($strPath, 'https://'))
{
return true;
}
@@ -313,48 +273,47 @@ protected function isExternal($strPath)
/**
* Add an internal image to template
- *
- * @param FilesModel $objModel The files model
- * @param RecommendationModel $objRecommendation The recommendation model
- * @param FrontendTemplate $objTemplate The frontend template
*/
- protected function addInternalImage($objModel, $objRecommendation, &$objTemplate)
+ protected function addInternalImage($objModel, &$objTemplate): void
{
- if ($objModel !== null && is_file(TL_ROOT . '/' . $objModel->path))
+ if (null !== $objModel)
{
+ $imgSize = $this->imgSize ?: null;
$objTemplate->addInternalImage = true;
- // Do not override the field now that we have a model registry (see #6303)
- $arrRecommendation = $objRecommendation->row();
-
// Override the default image size
- if ($this->imgSize != '')
+ if ($this->imgSize)
{
$size = StringUtil::deserialize($this->imgSize);
if ($size[0] > 0 || $size[1] > 0 || is_numeric($size[2]) || ($size[2][0] ?? null) === '_')
{
- $arrRecommendation['size'] = $this->imgSize;
+ $imgSize = $this->imgSize;
}
}
- $arrRecommendation['singleSRC'] = $objModel->path;
- $this->addImageToTemplate($objTemplate, $arrRecommendation, null, null, $objModel);
+ $figureBuilder = System::getContainer()
+ ->get('contao.image.studio')
+ ->createFigureBuilder()
+ ->from($objModel->path)
+ ->setSize($imgSize);
+
+ if (null !== ($figure = $figureBuilder->buildIfResourceExists()))
+ {
+ $figure->applyLegacyTemplateData($objTemplate);
+ }
}
}
/**
- * Parses a timestamp into a human readable string
- *
- * @param string $strDateTime
- *
- * @return string
+ * Parses a timestamp into a human-readable string
+ * @throws Exception
*/
- protected function getElapsedTime($strDateTime)
+ protected function getElapsedTime(string $strDateTime): string
{
$objElapsedTime = (new \DateTime($strDateTime))->diff(new \DateTime());
- if(($years = $objElapsedTime->y) > 0)
+ if (($years = $objElapsedTime->y) > 0)
{
return $this->translateElapsedTime($years, 'year');
}
@@ -382,13 +341,8 @@ protected function getElapsedTime($strDateTime)
/**
* Translates elapsed time
- *
- * @param integer $value
- * @param string $strUnit
- *
- * @return string
*/
- protected function translateElapsedTime($value, $strUnit = 'justNow')
+ protected function translateElapsedTime(int $value, string $strUnit = 'justNow'): string
{
return sprintf($GLOBALS['TL_LANG']['tl_recommendation'][$strUnit][!($value>1)], $value);
}
diff --git a/src/Resources/contao/modules/ModuleRecommendationForm.php b/contao/modules/ModuleRecommendationForm.php
similarity index 74%
rename from src/Resources/contao/modules/ModuleRecommendationForm.php
rename to contao/modules/ModuleRecommendationForm.php
index 4957d83..a5d76a3 100644
--- a/src/Resources/contao/modules/ModuleRecommendationForm.php
+++ b/contao/modules/ModuleRecommendationForm.php
@@ -10,7 +10,6 @@
use Contao\BackendTemplate;
use Contao\CoreBundle\Exception\InternalServerErrorException;
-use Contao\CoreBundle\Monolog\ContaoContext;
use Contao\CoreBundle\OptIn\OptIn;
use Contao\Email;
use Contao\Environment;
@@ -21,7 +20,8 @@
use Contao\StringUtil;
use Contao\System;
use Contao\Widget;
-use Psr\Log\LogLevel;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationArchiveModel;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationModel;
/**
* Front end module "recommendation form".
@@ -39,8 +39,6 @@
* @property integer $jumpTo
* @property boolean $recommendation_activate
* @property string $recommendation_activateText
- *
- * @author Sebastian Zoglowek
*/
class ModuleRecommendationForm extends ModuleRecommendation
{
@@ -55,18 +53,18 @@ class ModuleRecommendationForm extends ModuleRecommendation
*
* @return string
*/
- public function generate()
+ public function generate(): string
{
$request = System::getContainer()->get('request_stack')->getCurrentRequest();
if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request))
{
$objTemplate = new BackendTemplate('be_wildcard');
- $objTemplate->wildcard = '### ' . mb_strtoupper($GLOBALS['TL_LANG']['FMD']['recommendationform'][0], 'UTF-8') . ' ###';
+ $objTemplate->wildcard = '### ' . $GLOBALS['TL_LANG']['FMD']['recommendationform'][0] . ' ###';
$objTemplate->title = $this->headline;
$objTemplate->id = $this->id;
$objTemplate->link = $this->name;
- $objTemplate->href = 'contao/main.php?do=themes&table=tl_module&act=edit&id=' . $this->id;
+ $objTemplate->href = StringUtil::specialcharsUrl(System::getContainer()->get('router')->generate('contao_backend', array('do'=>'themes', 'table'=>'tl_module', 'act'=>'edit', 'id'=>$this->id)));
return $objTemplate->parse();
}
@@ -84,7 +82,7 @@ public function generate()
/**
* Generate the module
*/
- protected function compile()
+ protected function compile(): void
{
System::loadLanguageFile('tl_recommendation');
System::loadLanguageFile('tl_recommendation_notification');
@@ -98,70 +96,61 @@ protected function compile()
}
// Form fields
- $arrFields = array
- (
- 'author' => array
- (
+ $arrFields = [
+ 'author' => [
'name' => 'author',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['author'],
'inputType' => 'text',
- 'eval' => array('mandatory'=>true, 'maxlength'=>128)
- ),
- 'rating' => array
- (
+ 'eval' => ['mandatory'=>true, 'maxlength'=>128]
+ ],
+ 'rating' => [
'name' => 'rating',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['rating'],
'inputType' => 'select',
- 'options' => array(5,4,3,2,1),
- 'eval' => array('mandatory'=>true)
- ),
- 'title' => array
- (
+ 'options' => [5,4,3,2,1],
+ 'eval' => ['mandatory'=>true]
+ ],
+ 'title' => [
'name' => 'title',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['title'],
'inputType' => 'text',
- 'eval' => array('optional'=>true, 'maxlength'=>255),
- ),
- 'customField' => array
- (
+ 'eval' => ['optional'=>true, 'maxlength'=>255],
+ ],
+ 'customField' => [
'name' => 'customField',
'label' => $this->recommendation_customFieldLabel ?: $GLOBALS['TL_LANG']['tl_recommendation']['customFieldLabel'],
'inputType' => 'text',
- 'eval' => array('optional'=>true, 'maxlength'=>255),
- ),
- 'location' => array
- (
+ 'eval' => ['optional'=>true, 'maxlength'=>255],
+ ],
+ 'location' => [
'name' => 'location',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['location'],
'inputType' => 'text',
- 'eval' => array('optional'=>true, 'maxlength'=>128),
- ),
- 'text' => array
- (
+ 'eval' => ['optional'=>true, 'maxlength'=>128],
+ ],
+ 'text' => [
'name' => 'text',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['text'],
'inputType' => 'textarea',
- 'eval' => array('mandatory'=>true, 'rows'=>4, 'cols'=>40)
- ),
- 'email' => array
- (
+ 'eval' => ['mandatory'=>true, 'rows'=>4, 'cols'=>40]
+ ],
+ 'email' => [
'name' => 'email',
'label' => $GLOBALS['TL_LANG']['tl_recommendation']['email'],
'inputType' => 'text',
- 'eval' => array('optional'=>true, 'maxlength'=>255, 'rgxp'=>'email', 'decodeEntities'=>true),
- ),
- );
+ 'eval' => ['optional'=>true, 'maxlength'=>255, 'rgxp'=>'email', 'decodeEntities'=>true],
+ ],
+ ];
// Captcha
- if (!$this->recommendation_disableCaptcha == true)
+ if (!$this->recommendation_disableCaptcha)
{
- $arrFields['captcha'] = array
- (
+ $arrFields['captcha'] = [
'name' => 'captcha',
'label' => $GLOBALS['TL_LANG']['MSC']['securityQuestion'],
'inputType' => 'captcha',
- 'eval' => array('mandatory'=>true)
- );
+ 'eval' => ['mandatory'=>true]
+ ];
}
// Set e-mail as mandatory and non-optional if comments should be validated via activation mail
@@ -174,18 +163,17 @@ protected function compile()
// Set an opt-in checkbox when privacy text is given
if ($this->recommendation_privacyText)
{
- $arrFields['privacy'] = array
- (
+ $arrFields['privacy'] = [
'name' => 'privacy',
'inputType' => 'checkbox',
- 'options' => array(1=>$this->recommendation_privacyText),
- 'eval' => array('mandatory'=>true)
- );
+ 'options' => [1=>$this->recommendation_privacyText],
+ 'eval' => ['mandatory'=>true]
+ ];
}
$doNotSubmit = false;
- $arrWidgets = array();
- $strFormId = 'recommendation_' . $this->id;
+ $arrWidgets = [];
+ $strFormId = 'recommendation_' . $this->id;
// Optional recommendation form fields
$arrOptionalFormFields = StringUtil::deserialize($this->recommendation_optionalFormFields, true);
@@ -194,7 +182,7 @@ protected function compile()
foreach ($arrFields as $fieldName => $arrField)
{
// Check for optional form fields
- if(($arrField['eval']['optional'] ?? null) && !\in_array($fieldName, $arrOptionalFormFields))
+ if (($arrField['eval']['optional'] ?? null) && !\in_array($fieldName, $arrOptionalFormFields))
{
continue;
}
@@ -230,17 +218,18 @@ protected function compile()
$arrWidgets[$arrField['name']] = $objWidget;
}
- $this->Template->fields = $arrWidgets;
- $this->Template->submit = $GLOBALS['TL_LANG']['tl_recommendation']['recommendation_submit'];
- $this->Template->formId = $strFormId;
- $this->Template->hasError = $doNotSubmit;
+ $this->Template->fields = $arrWidgets;
+ $this->Template->submit = $GLOBALS['TL_LANG']['tl_recommendation']['recommendation_submit'];
+ $this->Template->formId = $strFormId;
+ $this->Template->hasError = $doNotSubmit;
+ $this->Template->requestToken = System::getContainer()->get('contao.csrf.token_manager')->getDefaultTokenValue();
- $session = System::getContainer()->get('session');
+ $objSession = System::getContainer()->get('request_stack')->getSession();
// Do not index or cache the page with the confirmation message
- if ($session->isStarted())
+ if ($objSession->isStarted())
{
- $flashBag = $session->getFlashBag();
+ $flashBag = $objSession->getFlashBag();
if ($flashBag->has('recommendation_added'))
{
@@ -255,7 +244,7 @@ protected function compile()
// Do not parse any tags in the recommendation
$strText = StringUtil::specialchars(trim($arrWidgets['text']->value));
- $strText = str_replace(array('&', '<', '>'), array('[&]', '[lt]', '[gt]'), $strText);
+ $strText = str_replace(['&', '<', '>'], ['[&]', '[lt]', '[gt]'], $strText);
// Remove multiple line feeds
$strText = preg_replace('@\n\n+@', "\n\n", $strText);
@@ -264,8 +253,7 @@ protected function compile()
$strText = preg_replace('/(href|src|on[a-z]+)="[^"]*(contao\/main\.php|typolight\/main\.php|javascript|vbscri?pt|script|alert|document|cookie|window)[^"]*"+/i', '$1="#"', $strText);
// Prepare the record
- $arrData = array
- (
+ $arrData = [
'tstamp' => $time,
'pid' => $this->recommendation_archive,
'title' => $arrWidgets['title']->value ?: '',
@@ -279,7 +267,7 @@ protected function compile()
'text' => $this->convertLineFeeds($strText),
'rating' => $arrWidgets['rating']->value,
'published' => $this->recommendation_moderate ? '' : 1
- );
+ ];
// Store the recommendation
$objRecommendation = new RecommendationModel();
@@ -308,7 +296,7 @@ protected function compile()
}
else
{
- $session->getFlashBag()->set('recommendation_added', $this->getFlashBagMessage());
+ $objSession->getFlashBag()->set('recommendation_added', $this->getFlashBagMessage());
}
$this->reload();
@@ -317,12 +305,8 @@ protected function compile()
/**
* Convert line feeds to
tags
- *
- * @param string $strText
- *
- * @return string
*/
- public function convertLineFeeds($strText)
+ public function convertLineFeeds(string $strText): string
{
$strText = preg_replace('/\r?\n/', '
', $strText);
@@ -332,23 +316,20 @@ public function convertLineFeeds($strText)
$strText = '' . $strText . '
';
}
- $arrReplace = array
- (
+ $arrReplace = [
'@
\s?
\s?@' => "
\n", // Convert two linebreaks into a new paragraph
'@\s?
@' => '', // Remove BR tags before closing P tags
'@ '
@' => '
' // Do not nest DIVs inside paragraphs
- );
+ ];
return preg_replace(array_keys($arrReplace), array_values($arrReplace), $strText);
}
/**
* Get flashbag message
- *
- * @return string
*/
- protected function getFlashBagMessage()
+ protected function getFlashBagMessage(): string
{
// Confirmation e-mail
if ($this->recommendation_activate)
@@ -368,22 +349,20 @@ protected function getFlashBagMessage()
/**
* Sends a notification to the administrator
- *
- * @param RecommendationModel $objRecommendation
*/
- protected function sendNotificationMail($objRecommendation)
+ protected function sendNotificationMail(RecommendationModel $objRecommendation): void
{
$strText = $objRecommendation->text;
$objEmail = new Email();
- $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL'];
- $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME'];
+ $objEmail->from = $GLOBALS['TL_ADMIN_EMAIL'] ?? null;
+ $objEmail->fromName = $GLOBALS['TL_ADMIN_NAME'] ?? null;
$objEmail->subject = sprintf($GLOBALS['TL_LANG']['tl_recommendation_notification']['email_subject'], Idna::decode(Environment::get('host')));
// Convert the recommendation to plain text
$strText = strip_tags($strText);
$strText = StringUtil::decodeEntities($strText);
- $strText = str_replace(array('[&]', '[lt]', '[gt]'), array('&', '<', '>'), $strText);
+ $strText = str_replace(['[&]', '[lt]', '[gt]'], ['&', '<', '>'], $strText);
// Add the recommendation details
$objEmail->text = sprintf(
@@ -407,39 +386,44 @@ protected function sendNotificationMail($objRecommendation)
/**
* Send the verification mail
- *
- * @param array $arrData
- * @param integer $id
*/
- protected function sendVerificationMail($arrData, $id)
+ protected function sendVerificationMail(array $arrData, int $id): void
{
+ $container = System::getContainer();
+
/** @var OptIn $optIn */
- $optIn = System::getContainer()->get('contao.opt-in');
- $optInToken = $optIn->create('rec', $arrData['email'], array('tl_recommendation'=>array($id)));
+ $optIn = $container->get('contao.opt_in');
+ $optInToken = $optIn->create('rec', $arrData['email'], ['tl_recommendation'=> [$id]]);
// Prepare the simple token data
$arrTokenData = $arrData;
- $arrTokenData['token'] = $optInToken->getIdentifier();
- $arrTokenData['domain'] = Idna::decode(Environment::get('host'));
- $arrTokenData['link'] = Idna::decode(Environment::get('base')) . Environment::get('request') . ((strpos(Environment::get('request'), '?') !== false) ? '&' : '?') . 'token=' . $optInToken->getIdentifier();
+ $arrTokenData['token'] = $optInToken->getIdentifier();
+ $arrTokenData['domain'] = Idna::decode(Environment::get('host'));
+ $arrTokenData['link'] = Idna::decode(Environment::get('base')) . Environment::get('request') . ((str_contains(Environment::get('request'), '?')) ? '&' : '?') . 'token=' . $optInToken->getIdentifier();
$arrTokenData['channel'] = '';
// Send the token
- $optInToken->send(sprintf($GLOBALS['TL_LANG']['tl_recommendation_notification']['email_activation'][0], Idna::decode(Environment::get('host'))), StringUtil::parseSimpleTokens($this->recommendation_activateText, $arrTokenData));
+ $optInToken->send(sprintf($GLOBALS['TL_LANG']['tl_recommendation_notification']['email_activation'][0], Idna::decode(Environment::get('host'))), $container->get('contao.string.simple_token_parser')->parse($this->recommendation_activateText, $arrTokenData));
}
/**
* Verifies the recommendation
*/
- protected function verifyRecommendation()
+ protected function verifyRecommendation(): void
{
$this->Template = new FrontendTemplate('mod_message');
/** @var OptIn $optin */
- $optIn = System::getContainer()->get('contao.opt-in');
+ $optIn = System::getContainer()->get('contao.opt_in');
// Find an unconfirmed token
- if ((!$optInToken = $optIn->find(Input::get('token'))) || !$optInToken->isValid() || \count($arrRelated = $optInToken->getRelatedRecords()) < 1 || key($arrRelated) != 'tl_recommendation' || \count($arrIds = current($arrRelated)) < 1)
+ if (
+ (!$optInToken = $optIn->find(Input::get('token'))) ||
+ !$optInToken->isValid() ||
+ \count($arrRelated = $optInToken->getRelatedRecords()) < 1 ||
+ key($arrRelated) != 'tl_recommendation' ||
+ \count($arrIds = current($arrRelated)) < 1
+ )
{
$this->Template->type = 'error';
$this->Template->message = $GLOBALS['TL_LANG']['MSC']['invalidToken'];
@@ -455,7 +439,7 @@ protected function verifyRecommendation()
return;
}
- $arrRecommendations = array();
+ $arrRecommendations = [];
foreach ($arrIds as $intId)
{
@@ -481,7 +465,6 @@ protected function verifyRecommendation()
$objRecommendation->verified = 1;
$objRecommendation->save();
-
// Notify system administrator via e-mail
if ($this->recommendation_notify)
{
@@ -492,7 +475,7 @@ protected function verifyRecommendation()
// Log activity
$logger = System::getContainer()->get('monolog.logger.contao');
- $logger->log(LogLevel::INFO, 'Recommendation ID ' . $objRecommendation->id . ' (' . Idna::decodeEmail($objRecommendation->email) . ') has been verified', array('contao' => new ContaoContext(__METHOD__, TL_ACCESS)));
+ $logger?->info('Recommendation ID ' . $objRecommendation->id . ' (' . Idna::decodeEmail($objRecommendation->email) . ') has been verified');
// Redirect to the jumpTo page
if (($objTarget = $this->objModel->getRelated('recommendation_activateJumpTo')) instanceof PageModel)
@@ -512,3 +495,5 @@ protected function verifyRecommendation()
}
}
}
+
+class_alias(ModuleRecommendationForm::class, 'ModuleRecommendationForm');
diff --git a/src/Resources/contao/modules/ModuleRecommendationList.php b/contao/modules/ModuleRecommendationList.php
similarity index 91%
rename from src/Resources/contao/modules/ModuleRecommendationList.php
rename to contao/modules/ModuleRecommendationList.php
index b414791..d74745a 100644
--- a/src/Resources/contao/modules/ModuleRecommendationList.php
+++ b/contao/modules/ModuleRecommendationList.php
@@ -17,6 +17,7 @@
use Contao\Pagination;
use Contao\StringUtil;
use Contao\System;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationModel;
/**
* Front end module "recommendation list".
@@ -24,12 +25,9 @@
* @property array $recommendation_archives
* @property string $recommendation_featured
* @property string $recommendation_order
- *
- * @author Fabian Ekert
*/
class ModuleRecommendationList extends ModuleRecommendation
{
-
/**
* Template
* @var string
@@ -41,18 +39,18 @@ class ModuleRecommendationList extends ModuleRecommendation
*
* @return string
*/
- public function generate()
+ public function generate(): string
{
$request = System::getContainer()->get('request_stack')->getCurrentRequest();
if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request))
{
$objTemplate = new BackendTemplate('be_wildcard');
- $objTemplate->wildcard = '### ' . mb_strtoupper($GLOBALS['TL_LANG']['FMD']['recommendationlist'][0], 'UTF-8') . ' ###';
+ $objTemplate->wildcard = '### ' . $GLOBALS['TL_LANG']['FMD']['recommendationlist'][0] . ' ###';
$objTemplate->title = $this->headline;
$objTemplate->id = $this->id;
$objTemplate->link = $this->name;
- $objTemplate->href = 'contao/main.php?do=themes&table=tl_module&act=edit&id=' . $this->id;
+ $objTemplate->href = StringUtil::specialcharsUrl(System::getContainer()->get('router')->generate('contao_backend', array('do'=>'themes', 'table'=>'tl_module', 'act'=>'edit', 'id'=>$this->id)));
return $objTemplate->parse();
}
@@ -114,7 +112,7 @@ protected function compile()
$blnFeatured = null;
}
- $this->Template->recommendations = array();
+ $this->Template->recommendations = [];
$this->Template->empty = $GLOBALS['TL_LANG']['MSC']['emptyRecommendationList'];
// Get the total number of items
@@ -137,7 +135,7 @@ protected function compile()
}
// Get the current page
- $id = 'page_n' . $this->id;
+ $id = 'page_r' . $this->id;
$page = Input::get($id) ?? 1;
// Do not index or cache the page if the page number is outside the range
@@ -203,14 +201,6 @@ protected function countItems($recommendationArchives, $blnFeatured, $minRating)
/**
* Fetch the matching items
- *
- * @param array $recommendationArchives
- * @param boolean $blnFeatured
- * @param integer $limit
- * @param integer $offset
- * @param integer $minRating
- *
- * @return Collection|RecommendationModel|null
*/
protected function fetchItems($recommendationArchives, $blnFeatured, $limit, $offset, $minRating)
{
@@ -257,6 +247,8 @@ protected function fetchItems($recommendationArchives, $blnFeatured, $limit, $of
$order .= "$t.date DESC";
}
- return RecommendationModel::findPublishedByPids($recommendationArchives, $blnFeatured, $limit, $offset, $minRating, array('order'=>$order));
+ return RecommendationModel::findPublishedByPids($recommendationArchives, $blnFeatured, $limit, $offset, $minRating, ['order'=>$order]);
}
}
+
+class_alias(ModuleRecommendationList::class, 'ModuleRecommendationList');
diff --git a/src/Resources/contao/modules/ModuleRecommendationReader.php b/contao/modules/ModuleRecommendationReader.php
similarity index 83%
rename from src/Resources/contao/modules/ModuleRecommendationReader.php
rename to contao/modules/ModuleRecommendationReader.php
index 465d6db..afe756f 100644
--- a/src/Resources/contao/modules/ModuleRecommendationReader.php
+++ b/contao/modules/ModuleRecommendationReader.php
@@ -16,13 +16,13 @@
use Contao\Input;
use Contao\StringUtil;
use Contao\System;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationArchiveModel;
+use Oveleon\ContaoRecommendationBundle\Model\RecommendationModel;
/**
* Front end module "recommendation reader".
*
* @property array $recommendation_archives
- *
- * @author Fabian Ekert
*/
class ModuleRecommendationReader extends ModuleRecommendation
{
@@ -45,11 +45,11 @@ public function generate()
if ($request && System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request))
{
$objTemplate = new BackendTemplate('be_wildcard');
- $objTemplate->wildcard = '### ' . mb_strtoupper($GLOBALS['TL_LANG']['FMD']['recommendationreader'][0], 'UTF-8') . ' ###';
+ $objTemplate->wildcard = '### ' . $GLOBALS['TL_LANG']['FMD']['recommendationreader'][0] . ' ###';
$objTemplate->title = $this->headline;
$objTemplate->id = $this->id;
$objTemplate->link = $this->name;
- $objTemplate->href = 'contao/main.php?do=themes&table=tl_module&act=edit&id=' . $this->id;
+ $objTemplate->href = StringUtil::specialcharsUrl(System::getContainer()->get('router')->generate('contao_backend', array('do'=>'themes', 'table'=>'tl_module', 'act'=>'edit', 'id'=>$this->id)));
return $objTemplate->parse();
}
@@ -85,7 +85,7 @@ protected function compile()
$this->Template->referer = 'javascript:history.go(-1)';
$this->Template->back = $GLOBALS['TL_LANG']['MSC']['goBack'];
- // Get the news item
+ // Get the recommendation item
$objRecommendation = RecommendationModel::findPublishedByParentAndIdOrAlias(Input::get('items'), $this->recommendation_archives);
if (null === $objRecommendation)
@@ -100,3 +100,5 @@ protected function compile()
$this->Template->recommendation = $arrRecommendation;
}
}
+
+class_alias(ModuleRecommendationReader::class, 'ModuleRecommendationReader');
diff --git a/src/Resources/contao/templates/modules/mod_recommendationform.html5 b/contao/templates/modules/mod_recommendationform.html5
similarity index 89%
rename from src/Resources/contao/templates/modules/mod_recommendationform.html5
rename to contao/templates/modules/mod_recommendationform.html5
index 0adb651..3eb51a8 100644
--- a/src/Resources/contao/templates/modules/mod_recommendationform.html5
+++ b/contao/templates/modules/mod_recommendationform.html5
@@ -10,7 +10,7 @@