Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Types of changes
Security in case of vulnerabilities.
)

## [1.1.0](https://github.com/pdir/contao-seo-plugin/tree/1.1.0) - 2025-03-21

- [Added] Show or hide the content of your website based on multiple conditions

## [1.0.3](https://github.com/pdir/contao-seo-plugin/tree/1.0.3) - 2024-11-09

- [Fixed] do not use global namespace in OutputFrontendTemplateListener
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ We help website owners and editorial teams to get more traffic from search engin
helps users to optimize their content and make it easy to find for both users and search engines. With the Contao SEO
plugin, you have the most important on-page factors directly in view.

### Current range of functions of version 1.0.0
### Current range of functions of version 1.1.0
- SEO analysis of 8 typical on-page problems
- IndexNow function for all known providers [indexnow.org](https://www.indexnow.org/faq)
- Possibility to activate a 404 error log
- Monitoring of alias changes (experimental, must be activated in user profile)
- Display existing URL redirects in the alias view
- Show or hide the content of your website based on multiple conditions

### An outlook on further functions
- At least 30 additional tests for on-page recommendations
Expand Down Expand Up @@ -47,6 +48,9 @@ Display existing URL redirects in the alias view
![404 error log](_docs/screenshots/404-error-log.png)
404 error log

![404 error log](_docs/screenshots/conditional_content.png)
Conditional content

## German

Wir helfen Website-Betreibern und Redaktionsteams, mehr Traffic von Suchmaschinen wie Google zu erhalten. Das Contao SEO
Expand All @@ -59,6 +63,7 @@ Mit dem Contao SEO Plugin hast du die wichtigsten OnPage Faktoren direkt im Blic
- Möglichkeit, ein 404-Fehlerprotokoll zu aktivieren
- Überwachung von Alias-Änderungen (experimentell, muss im Benutzerprofil aktiviert werden)
- Anzeige bestehender URL-Weiterleitungen in der Alias-Ansicht
- Zeige oder verberge den Inhalt deiner Website auf der Grundlage mehrerer Bedingungen

### Ein Ausblick auf weitere Funktionen
- Mindestens 30 weitere Tests für Onpage Empfehlungen
Expand Down
6 changes: 6 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ services:

Pdir\ContaoSeoPlugin\EventListener\OutputFrontendTemplateListener:
public: true

Pdir\ContaoSeoPlugin\EventListener\IsVisibleElementListener:
public: true
arguments:
- '@request_stack'
- '@contao.routing.scope_matcher'
27 changes: 27 additions & 0 deletions contao/dca/tl_article.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_DCA']['tl_article']['palettes']['__selector__'][] = 'contaoSeoIsConditionalEntity';
$GLOBALS['TL_DCA']['tl_article']['subpalettes']['contaoSeoIsConditionalEntity'] = 'contaoSeoEntityCondition';

$GLOBALS['TL_DCA']['tl_article']['fields']['contaoSeoIsConditionalEntity'] = [
'exclude' => true,
'inputType' => 'checkbox',
'eval' => ['submitOnChange' => true, 'tl_class' => 'clr'],
'sql' => "char(1) NOT NULL default ''",
];

$GLOBALS['TL_DCA']['tl_article']['fields']['contaoSeoEntityCondition'] = [
'exclude' => true,
'inputType' => 'textarea',
'eval' => ['mandatory' => true, 'useRawRequestData' => true, 'style' => 'height:40px', 'tl_class' => 'clr'],
'sql' => 'text NULL',
];

foreach($GLOBALS['TL_DCA']['tl_article']['palettes'] as $key=>$value) {
if ($key == '__selector__') {
continue;
}
$GLOBALS['TL_DCA']['tl_article']['palettes'][$key] .= ',contaoSeoIsConditionalEntity';
}
27 changes: 27 additions & 0 deletions contao/dca/tl_content.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_DCA']['tl_content']['palettes']['__selector__'][] = 'contaoSeoIsConditionalEntity';
$GLOBALS['TL_DCA']['tl_content']['subpalettes']['contaoSeoIsConditionalEntity'] = 'contaoSeoEntityCondition';

$GLOBALS['TL_DCA']['tl_content']['fields']['contaoSeoIsConditionalEntity'] = [
'exclude' => true,
'inputType' => 'checkbox',
'eval' => ['submitOnChange' => true, 'tl_class' => 'clr'],
'sql' => "char(1) NOT NULL default ''",
];

$GLOBALS['TL_DCA']['tl_content']['fields']['contaoSeoEntityCondition'] = [
'exclude' => true,
'inputType' => 'textarea',
'eval' => ['mandatory' => true, 'useRawRequestData' => true, 'style' => 'height:40px', 'tl_class' => 'clr'],
'sql' => 'text NULL',
];

foreach($GLOBALS['TL_DCA']['tl_content']['palettes'] as $key=>$value) {
if ($key == '__selector__') {
continue;
}
$GLOBALS['TL_DCA']['tl_content']['palettes'][$key] .= ',contaoSeoIsConditionalEntity';
}
27 changes: 27 additions & 0 deletions contao/dca/tl_module.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_DCA']['tl_module']['palettes']['__selector__'][] = 'contaoSeoIsConditionalEntity';
$GLOBALS['TL_DCA']['tl_module']['subpalettes']['contaoSeoIsConditionalEntity'] = 'contaoSeoEntityCondition';

$GLOBALS['TL_DCA']['tl_module']['fields']['contaoSeoIsConditionalEntity'] = [
'exclude' => true,
'inputType' => 'checkbox',
'eval' => ['submitOnChange' => true, 'tl_class' => 'clr'],
'sql' => "char(1) NOT NULL default ''",
];

$GLOBALS['TL_DCA']['tl_module']['fields']['contaoSeoEntityCondition'] = [
'exclude' => true,
'inputType' => 'textarea',
'eval' => ['mandatory' => true, 'useRawRequestData' => true, 'style' => 'height:40px', 'tl_class' => 'clr'],
'sql' => 'text NULL',
];

foreach($GLOBALS['TL_DCA']['tl_module']['palettes'] as $key=>$value) {
if ($key == '__selector__') {
continue;
}
$GLOBALS['TL_DCA']['tl_module']['palettes'][$key] .= ',contaoSeoIsConditionalEntity';
}
2 changes: 2 additions & 0 deletions contao/languages/de/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@
$GLOBALS['TL_LANG']['tl_page']['rewriteStatusActive'] = 'Aktiv';
$GLOBALS['TL_LANG']['tl_page']['rewriteStatusInactive'] = 'Inaktiv';
$GLOBALS['TL_LANG']['tl_page']['rewriteListNoItems'] = 'Es wurden keine Weiterleitungen gefunden.';

$GLOBALS['TL_LANG']['MSC']['contaoSeoActiveCondition'] = 'Es ist mindestens eine Bedingung aktiv.';
6 changes: 6 additions & 0 deletions contao/languages/de/tl_article.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_article']['contaoSeoIsConditionalEntity'] = ['Nur mit erfüllter Bedingung anzeigen', 'Aktivieren Sie diese Checkbox, wenn Sie diesen Artikel nur unter gewissen Bedingungen anzeigen möchten.'];
$GLOBALS['TL_LANG']['tl_article']['contaoSeoEntityCondition'] = ['Bedingung ⚠', 'Schreiben Sie Ihre Bedingung, z. B. <code>(foo == \'de\' && bar == \'test\')</code> oder für Arrays <code>in_array(\'en\', languages)</code>'];
6 changes: 6 additions & 0 deletions contao/languages/de/tl_content.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_content']['contaoSeoIsConditionalEntity'] = ['Nur mit erfüllter Bedingung anzeigen', 'Aktivieren Sie diese Checkbox, wenn Sie dieses Element nur unter gewissen Bedingungen anzeigen möchten.'];
$GLOBALS['TL_LANG']['tl_content']['contaoSeoEntityCondition'] = ['Bedingung ⚠', 'Schreiben Sie Ihre Bedingung, z. B. <code>(foo == \'de\' && bar == \'test\')</code> oder für Arrays <code>in_array(\'en\', languages)</code>'];
6 changes: 6 additions & 0 deletions contao/languages/de/tl_module.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_module']['contaoSeoIsConditionalEntity'] = ['Nur mit erfüllter Bedingung anzeigen', 'Aktivieren Sie diese Checkbox, wenn Sie dieses Modul nur unter gewissen Bedingungen anzeigen möchten.'];
$GLOBALS['TL_LANG']['tl_module']['contaoSeoEntityCondition'] = ['Bedingung ⚠', 'Schreiben Sie Ihre Bedingung, z. B. <code>(foo == \'de\' && bar == \'test\')</code> oder für Arrays <code>in_array(\'en\', languages)</code>'];
2 changes: 2 additions & 0 deletions contao/languages/en/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@
$GLOBALS['TL_LANG']['tl_page']['rewriteStatusActive'] = 'Active';
$GLOBALS['TL_LANG']['tl_page']['rewriteStatusInactive'] = 'Inactive';
$GLOBALS['TL_LANG']['tl_page']['rewriteListNoItems'] = 'No redirects were found.';

$GLOBALS['TL_LANG']['MSC']['contaoSeoActiveCondition'] = 'At least one condition is active.';
6 changes: 6 additions & 0 deletions contao/languages/en/tl_article.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_article']['contaoSeoIsConditionalEntity'] = ['Only display with fulfilled condition', 'Activate this checkbox if you only want to display this article under certain conditions.'];
$GLOBALS['TL_LANG']['tl_article']['contaoSeoEntityCondition'] = ['Display Condition ⚠', 'Enter a PHP condition <code>(foo == \'de\' && bar == \'test\')</code> or for arrays <code>in_array(\'en\', languages)</code>.'];
6 changes: 6 additions & 0 deletions contao/languages/en/tl_content.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_content']['contaoSeoIsConditionalEntity'] = ['Only display with fulfilled condition', 'Activate this checkbox if you only want to display this element under certain conditions.'];
$GLOBALS['TL_LANG']['tl_content']['contaoSeoEntityCondition'] = ['Display Condition ⚠', 'Enter a PHP condition <code>(foo == \'de\' && bar == \'test\')</code> or for arrays <code>in_array(\'en\', languages)</code>.'];
6 changes: 6 additions & 0 deletions contao/languages/en/tl_module.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

declare(strict_types=1);

$GLOBALS['TL_LANG']['tl_module']['contaoSeoIsConditionalEntity'] = ['Only display with fulfilled condition', 'Activate this checkbox if you only want to display this module under certain conditions.'];
$GLOBALS['TL_LANG']['tl_module']['contaoSeoEntityCondition'] = ['Display Condition ⚠', 'Enter a PHP condition <code>(foo == \'de\' && bar == \'test\')</code> or for arrays <code>in_array(\'en\', languages)</code>.'];
50 changes: 50 additions & 0 deletions src/EventListener/DataContainer/EntityConditionSaveListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

/*
* pdir contao seo plugin for Contao Open Source CMS
*
* Copyright (c) 2024 pdir / digital agentur // pdir GmbH
*
* @package contao-seo-plugin
* @link https://pdir.de/contao-seo-plugin
* @license LGPL-3.0-or-later
* @author pdir GmbH <https://pdir.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Pdir\ContaoSeoPlugin\EventListener\DataContainer;

use Contao\BackendUser;
use Contao\CoreBundle\DependencyInjection\Attribute\AsCallback;
use Contao\DataContainer;
use Contao\PageModel;

#[AsCallback(table: 'tl_article', target: 'fields.contaoSeoEntityCondition.save')]
#[AsCallback(table: 'tl_content', target: 'fields.contaoSeoEntityCondition.save')]
#[AsCallback(table: 'tl_module', target: 'fields.contaoSeoEntityCondition.save')]
class EntityConditionSaveListener
{
public function __invoke($value, DataContainer $dc)
{
if (empty($value)) {
return $value;
}

// Return the processed value
return $value;
}

private function validateCondition($code)
{
// Only safe characters (letters, numbers, operators and spaces) are allowed
if (preg_match('/^[a-zA-Z0-9+\-*/%\(\)\s]+$/', $code)) {
return true;
}

return false;
}
}
49 changes: 49 additions & 0 deletions src/EventListener/IsVisibleElementListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Pdir\ContaoSeoPlugin\EventListener;

use Contao\CoreBundle\Routing\ScopeMatcher;
use Contao\CoreBundle\DependencyInjection\Attribute\AsHook;
use Contao\Model;
# use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\HttpFoundation\RequestStack;

#[AsHook('isVisibleElement')]
class IsVisibleElementListener
{
private RequestStack $requestStack;

private ScopeMatcher $scopeMatcher;

public function __construct(RequestStack $requestStack, ScopeMatcher $scopeMatcher)
{
$this->requestStack = $requestStack;
$this->scopeMatcher = $scopeMatcher;
}
public function __invoke(Model $element, bool $isVisible): bool
{
// Is back end request
if (!($request = $this->requestStack->getCurrentRequest()) || $this->scopeMatcher->isBackendRequest($request)) {

// Check if condition is active
if ($element->contaoSeoIsConditionalEntity && trim($element->contaoSeoEntityCondition) !== '') {
$element->text = '<span style="color: var(--form-border, #7abfbc);" title="'.($GLOBALS['TL_LANG']['MSC']['contaoSeoActiveCondition']?? '').'">⚠( ' .$element->contaoSeoEntityCondition.' )</span>'.$element->text;
}

return $isVisible;
}

# $expressionLanguage = new ExpressionLanguage();
# var_dump($expressionLanguage->evaluate($element->contaoSeoEntityCondition));

// Check if this element can be shown
if ($element->contaoSeoIsConditionalEntity && null !== $element->contaoSeoEntityCondition && trim($element->contaoSeoEntityCondition) !== '') {
return eval('return '.$element->contaoSeoEntityCondition.';');
}

// Otherwise we don't want to change the visibility state
return $isVisible;
}
}