diff --git a/README.md b/README.md index e3e46df..aa9e32a 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,10 @@ The recommendation list can display published (and verified) recommendations fro Items per page Number of recommendations per page - Activates pagination + + Custom label + Allows customizing the translation to for the redirect link + Meta fields Here you can select meta fields to display @@ -175,6 +179,10 @@ The recommendation list can display published (and verified) recommendations fro Module template The modules template that is being used + + Use dialog popup + Does not output the redirect link and embeds a dialog box instead. The `js_recommendation` template has to be included in the page layout + Image settings You have the possibility to add pictures to your recommendations. These are the image settings for them @@ -203,6 +211,14 @@ The recommendation list can display published (and verified) recommendations fro Recommendation archives Here you can select one or more archives to read recommendations from + + Overview page + Adds the overview page to the template to not use ``javascript:history.go(-1)`` anymore + + + Custom label + Allows customizing the translation for the overview link + Meta fields Here you can select meta fields to display diff --git a/composer.json b/composer.json index f6a8420..e53af48 100644 --- a/composer.json +++ b/composer.json @@ -35,8 +35,8 @@ "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" + "symfony/http-client": "^5.4 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "contao/core": "*", @@ -61,7 +61,7 @@ }, "extra": { "branch-alias": { - "dev-main": "1.4.x-dev" + "dev-main": "1.5.x-dev" }, "contao-manager-plugin": "Oveleon\\ContaoRecommendationBundle\\ContaoManager\\Plugin" }, diff --git a/contao/dca/tl_module.php b/contao/dca/tl_module.php index aa36199..b9eef4d 100644 --- a/contao/dca/tl_module.php +++ b/contao/dca/tl_module.php @@ -20,8 +20,8 @@ $GLOBALS['TL_DCA']['tl_module']['palettes']['__selector__'][] = 'recommendation_activate'; // Add palettes to tl_module -$GLOBALS['TL_DCA']['tl_module']['palettes']['recommendationlist'] = '{title_legend},name,headline,type;{config_legend},recommendation_archives,recommendation_readerModule,recommendation_minRating,recommendation_featured,recommendation_order,numberOfItems,perPage;{template_legend:hide},recommendation_metaFields,recommendation_template,customTpl;{image_legend:hide},imgSize,recommendation_externalSize;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; -$GLOBALS['TL_DCA']['tl_module']['palettes']['recommendationreader'] = '{title_legend},name,headline,type;{config_legend},recommendation_archives;{template_legend:hide},recommendation_metaFields,recommendation_template,customTpl;{image_legend:hide},imgSize,recommendation_externalSize;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; +$GLOBALS['TL_DCA']['tl_module']['palettes']['recommendationlist'] = '{title_legend},name,headline,type;{config_legend},recommendation_archives,recommendation_readerModule,recommendation_minRating,recommendation_featured,recommendation_order,numberOfItems,perPage,customLabel;{template_legend:hide},recommendation_metaFields,recommendation_template,customTpl,recommendation_useDialog;{image_legend:hide},imgSize,recommendation_externalSize;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; +$GLOBALS['TL_DCA']['tl_module']['palettes']['recommendationreader'] = '{title_legend},name,headline,type;{config_legend},recommendation_archives,overviewPage,customLabel;{template_legend:hide},recommendation_metaFields,recommendation_template,customTpl;{image_legend:hide},imgSize,recommendation_externalSize;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; $GLOBALS['TL_DCA']['tl_module']['palettes']['recommendationform'] = '{title_legend},name,headline,type;{config_legend},recommendation_archive,recommendation_optionalFormFields,recommendation_customFieldLabel,recommendation_notify,recommendation_moderate,recommendation_disableCaptcha;{privacy_legend},recommendation_privacyText;{redirect_legend:hide},jumpTo;{email_legend:hide},recommendation_activate;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; $GLOBALS['TL_DCA']['tl_module']['subpalettes']['recommendation_activate'] = 'recommendation_activateJumpTo,recommendation_activateText'; @@ -72,6 +72,14 @@ 'sql' => "varchar(255) NOT NULL default ''" ]; +$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_useDialog'] = [ + 'exclude' => true, + 'filter' => true, + 'inputType' => 'checkbox', + 'eval' => ['submitOnChange'=>true, 'tl_class'=>'clr'], + 'sql' => "char(1) NOT NULL default ''" +]; + $GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_order'] = [ 'exclude' => true, 'inputType' => 'select', @@ -178,14 +186,6 @@ 'sql' => "varchar(64) NOT NULL default ''" ]; -$GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_template'] = [ - 'exclude' => true, - 'inputType' => 'select', - 'options_callback' => static fn () => Controller::getTemplateGroup('recommendation_'), - 'eval' => ['includeBlankOption' => true, 'chosen' => true, 'tl_class'=>'w50'], - 'sql' => "varchar(64) NOT NULL default ''" -]; - $GLOBALS['TL_DCA']['tl_module']['fields']['recommendation_externalSize'] = [ 'inputType' => 'text', 'eval' => ['multiple'=>true, 'size'=>2, 'rgxp'=>'natural', 'nospace'=>true, 'tl_class'=>'w50'], diff --git a/contao/languages/de/default.xlf b/contao/languages/de/default.xlf index 97241b7..5da1932 100644 --- a/contao/languages/de/default.xlf +++ b/contao/languages/de/default.xlf @@ -5,6 +5,10 @@ Currently there are no recommendations. Zurzeit sind keine Bewertungen vorhanden. + + Read the recommendation: %s + Die Bewertung lesen: %s + diff --git a/contao/languages/de/tl_module.xlf b/contao/languages/de/tl_module.xlf index 796414c..473de74 100644 --- a/contao/languages/de/tl_module.xlf +++ b/contao/languages/de/tl_module.xlf @@ -45,6 +45,14 @@ Here you can select the meta fields. Hier können Sie die Meta-Felder auswählen. + + Use dialog popup + Dialog-Popup nutzen + + + Adds a dialog popup for the recommendation and disables the forwarding page. You don't need a reader module for this feature. + Fügt ein Dialog-Popup für die Bewertung hinzu und deaktiviert die Weiterleitungsseite. Für diese Funktion benötigen Sie kein Lesemodul. + Optional recommendation fields Optionale Bewertungsfelder @@ -149,6 +157,10 @@ Show only recommendations with a minimum rating. Nur Bewertungen mit einem Mindestrating anzeigen. + + To use the dialog-popup, the <em>%s</em> template needs to be included in the page layout. + Um das Dialog-Popup zu nutzen muss das <em>%s</em>-Template im Seitenlayout eingebunden sein. + diff --git a/contao/languages/en/default.xlf b/contao/languages/en/default.xlf index 7244fee..0520056 100644 --- a/contao/languages/en/default.xlf +++ b/contao/languages/en/default.xlf @@ -4,6 +4,9 @@ Currently there are no recommendations. + + Read the recommendation: %s + diff --git a/contao/languages/en/tl_module.xlf b/contao/languages/en/tl_module.xlf index 3232ae6..630e74f 100644 --- a/contao/languages/en/tl_module.xlf +++ b/contao/languages/en/tl_module.xlf @@ -34,6 +34,12 @@ Here you can select the meta fields. + + Use dialog popup + + + Adds a dialog popup for the recommendation and disables the forwarding page. You don't need a reader module for this feature. + Optional recommendation fields @@ -112,6 +118,9 @@ Show only recommendations with a minimum rating. + + To use the dialog-popup, the <em>%s</em> template needs to be included in the page layout. + diff --git a/contao/modules/ModuleRecommendation.php b/contao/modules/ModuleRecommendation.php index 18e6a6d..02a777d 100644 --- a/contao/modules/ModuleRecommendation.php +++ b/contao/modules/ModuleRecommendation.php @@ -30,6 +30,7 @@ * @property string $recommendation_template * @property mixed $recommendation_metaFields * @property mixed $recommendation_externalSize + * @property bool $recommendation_useDialog */ abstract class ModuleRecommendation extends Module { @@ -85,10 +86,18 @@ protected function parseRecommendation(RecommendationModel $objRecommendation, R $objTemplate->class = $strClass; $objTemplate->archiveId = $objRecommendationArchive->id; - if ($objRecommendationArchive->jumpTo) + $moreLabel = $this->customLabel ?: $GLOBALS['TL_LANG']['MSC']['more']; + + if ($this->recommendation_useDialog) + { + $objTemplate->dialog = true; + $objTemplate->more = $moreLabel; + $objRecommendationArchive->jumpTo = null; + } + elseif ($objRecommendationArchive->jumpTo) { $objTemplate->allowRedirect = true; - $objTemplate->more = $this->generateLink($GLOBALS['TL_LANG']['MSC']['more'], $objRecommendation, $objRecommendation->title, true); + $objTemplate->more = $this->generateLink($moreLabel, $objRecommendation, $objRecommendation->title ?: $objRecommendation->author, true); } if ($objRecommendation->title) @@ -203,7 +212,12 @@ protected function parseRecommendations(Collection $objRecommendations): array /** @var RecommendationArchiveModel $objRecommendationArchive */ $objRecommendationArchive = $recommendation->getRelated('pid'); - $arrRecommendations[] = $this->parseRecommendation($recommendation, $objRecommendationArchive, ((++$count == 1) ? ' first' : '') . (($count == $limit) ? ' last' : '') . ((($count % 2) == 0) ? ' odd' : ' even'), $count); + $arrRecommendations[] = $this->parseRecommendation( + $recommendation, + $objRecommendationArchive, + ((++$count == 1) ? ' first' : '') . (($count == $limit) ? ' last' : '') . ((($count % 2) == 0) ? ' odd' : ' even'), + $count + ); } return $arrRecommendations; @@ -253,7 +267,7 @@ protected function generateLink(string $strLink, RecommendationModel $objRecomme { return sprintf('', $this->generateRecommendationUrl($objRecommendation), - StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['readMore'], $strTitle), true), + StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['readRecommendation'], $strTitle), true), $strLink, ($blnIsReadMore ? '' : '')); } @@ -365,6 +379,6 @@ protected function translateElapsedTime(int $value, string $strUnit = 'justNow') */ protected function useAutoItem(): bool { - return version_compare(ContaoCoreBundle::getVersion(), '5', '<') ? Config::get('useAutoItem') : true; + return !str_starts_with(ContaoCoreBundle::getVersion(), '5.') ? Config::get('useAutoItem') : true; } } diff --git a/contao/modules/ModuleRecommendationReader.php b/contao/modules/ModuleRecommendationReader.php index f684ed7..afb38e4 100644 --- a/contao/modules/ModuleRecommendationReader.php +++ b/contao/modules/ModuleRecommendationReader.php @@ -9,17 +9,16 @@ namespace Oveleon\ContaoRecommendationBundle; use Contao\BackendTemplate; -use Contao\Config; use Contao\CoreBundle\ContaoCoreBundle; use Contao\CoreBundle\Exception\InternalServerErrorException; use Contao\CoreBundle\Exception\PageNotFoundException; use Contao\Environment; use Contao\Input; +use Contao\PageModel; use Contao\StringUtil; use Contao\System; use Oveleon\ContaoRecommendationBundle\Model\RecommendationArchiveModel; use Oveleon\ContaoRecommendationBundle\Model\RecommendationModel; -use Symfony\Component\HttpFoundation\Response; /** * Front end module "recommendation reader". @@ -91,11 +90,20 @@ public function generate() protected function compile() { $this->Template->recommendation = ''; - $this->Template->referer = 'javascript:history.go(-1)'; - $this->Template->back = $GLOBALS['TL_LANG']['MSC']['goBack']; + + if ($this->overviewPage) + { + $this->Template->referer = PageModel::findById($this->overviewPage)->getFrontendUrl(); + $this->Template->back = $this->customLabel ?: $GLOBALS['TL_LANG']['MSC']['goBack']; + } + else + { + $this->Template->referer = 'javascript:history.go(-1)'; + $this->Template->back = $GLOBALS['TL_LANG']['MSC']['goBack']; + } // Get the recommendation item - $objRecommendation = RecommendationModel::findPublishedByParentAndIdOrAlias(Input::get('items'), $this->recommendation_archives); + $objRecommendation = RecommendationModel::findPublishedByParentAndIdOrAlias(Input::get('auto_item'), $this->recommendation_archives); if (null === $objRecommendation) { diff --git a/contao/templates/js/js_recommendation.html5 b/contao/templates/js/js_recommendation.html5 new file mode 100644 index 0000000..f0665e5 --- /dev/null +++ b/contao/templates/js/js_recommendation.html5 @@ -0,0 +1,14 @@ + + window.addEventListener("load", () => { + new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + const elements = mutation.target.matches(".rec_show-modal") ? mutation.target : mutation.target.querySelectorAll(".rec_show-modal"); + elements.forEach(element => { + element.addEventListener("click", (el) => { + document.querySelector(`.rec_dialog_${el.currentTarget.dataset?.id}`)?.showModal(); + }) + }); + }); + }).observe(document, { attributes: false, childList: true, subtree: true }); + }) +'; diff --git a/contao/templates/recommendation/recommendation_default.html5 b/contao/templates/recommendation/recommendation_default.html5 index 6802e5e..163694f 100644 --- a/contao/templates/recommendation/recommendation_default.html5 +++ b/contao/templates/recommendation/recommendation_default.html5 @@ -42,8 +42,8 @@
- teaser && $this->allowRedirect): ?> - teaser ?> + teaser && ($this->allowRedirect || $this->dialog)): ?> + cspInlineStyles($this->teaser) : $this->teaser ?> text ?> @@ -51,6 +51,18 @@ allowRedirect): ?>

more ?>

+ dialog): ?> +

+ more ?> +

+ +
+ text ?> +
+ +
+
+
diff --git a/contao/templates/recommendation/recommendation_latest.html5 b/contao/templates/recommendation/recommendation_latest.html5 index b624c5e..668492f 100644 --- a/contao/templates/recommendation/recommendation_latest.html5 +++ b/contao/templates/recommendation/recommendation_latest.html5 @@ -38,8 +38,8 @@
- teaser && $this->allowRedirect): ?> - teaser ?> + teaser && ($this->allowRedirect || $this->dialog)): ?> + cspInlineStyles($this->teaser) : $this->teaser ?> text ?> @@ -47,6 +47,18 @@ allowRedirect): ?>

more ?>

+ dialog): ?> +

+ more ?> +

+ +
+ text ?> +
+ +
+
+
diff --git a/src/EventListener/DataContainer/ModuleListener.php b/src/EventListener/DataContainer/ModuleListener.php new file mode 100644 index 0000000..f6ae080 --- /dev/null +++ b/src/EventListener/DataContainer/ModuleListener.php @@ -0,0 +1,48 @@ +get('security.helper'); + + if ( + !$security->isGranted(ContaoCorePermissions::USER_CAN_ACCESS_MODULE, 'themes') || + !$security->isGranted(ContaoCorePermissions::USER_CAN_ACCESS_LAYOUTS) + ) { + return; + } + + $objModule = ModuleModel::findByPk($dc->id); + + if (null !== $objModule && 'recommendationlist' === $objModule->type) + { + // Get module + $objModule = Database::getInstance()->prepare("SELECT * FROM " . $dc->table . " WHERE id=?") + ->limit(1) + ->execute($dc->id); + + if (null !== $objModule && !!$objModule->recommendation_useDialog) + { + Message::addInfo(sprintf(($GLOBALS['TL_LANG']['tl_module']['includeRecTemplate'] ?? null), 'js_recommendation')); + } + } + } +} diff --git a/src/Model/RecommendationArchiveModel.php b/src/Model/RecommendationArchiveModel.php index d59c494..d88a5fc 100644 --- a/src/Model/RecommendationArchiveModel.php +++ b/src/Model/RecommendationArchiveModel.php @@ -19,6 +19,7 @@ * @property string $title * @property integer $jumpTo * @property boolean $protected + * @property boolean $useDialog * @property boolean $useAutoItem * @property string $groups * @@ -30,12 +31,16 @@ * @method static RecommendationArchiveModel|null findOneByTitle($val, array $opt=array()) * @method static RecommendationArchiveModel|null findOneByJumpTo($val, array $opt=array()) * @method static RecommendationArchiveModel|null findOneByProtected($val, array $opt=array()) + * @method static RecommendationArchiveModel|null findOneByUseDialog($val, array $opt=array()) + * @method static RecommendationArchiveModel|null findOneByUseAutoItem($val, array $opt=array()) * @method static RecommendationArchiveModel|null findOneByGroups($val, array $opt=array()) * * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByTstamp($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByTitle($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByJumpTo($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByProtected($val, array $opt=array()) + * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByUseDialog($val, array $opt=array()) + * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByUseAutoItem($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findByGroups($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findMultipleByIds($val, array $opt=array()) * @method static Collection|RecommendationArchiveModel[]|RecommendationArchiveModel|null findBy($col, $val, array $opt=array()) @@ -46,6 +51,8 @@ * @method static integer countByTitle($val, array $opt=array()) * @method static integer countByJumpTo($val, array $opt=array()) * @method static integer countByProtected($val, array $opt=array()) + * @method static integer countByUseDialog($val, array $opt=array()) + * @method static integer countByUseAutoItem($val, array $opt=array()) * @method static integer countByGroups($val, array $opt=array()) */ class RecommendationArchiveModel extends Model