release 1.2

This commit is contained in:
Jean-Christian Denis 2023-10-12 21:33:20 +02:00
parent 69fba5ca7b
commit c8840a3291
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
22 changed files with 324 additions and 340 deletions

View file

@ -1,3 +1,9 @@
noodles 1.2 - 2023.10.12
===========================================================
* Require Dotclear 2.28
* Require PHP 8.1
* Upgrade to Dotclear 2.28
noodles 1.1 - 2023.08.15 noodles 1.1 - 2023.08.15
=========================================================== ===========================================================
* Require Dotclear 2.27 * Require Dotclear 2.27

View file

@ -1,26 +1,22 @@
# README # README
[![Release](https://img.shields.io/badge/release-1.1-a2cbe9.svg)](https://git.dotclear.watch/JcDenis/oodles/releases) [![Release](https://img.shields.io/badge/release-1.2-a2cbe9.svg)](https://git.dotclear.watch/JcDenis/noodles/releases)
[![Date](https://img.shields.io/badge/date-2023.08.15-c44d58.svg)](https://git.dotclear.watch/JcDenis/oodles/releases) ![Date](https://img.shields.io/badge/date-2023.10.12-c44d58.svg)
[![Dotclear](https://img.shields.io/badge/dotclear-v2.27-137bbb.svg)](https://fr.dotclear.org/download) [![Dotclear](https://img.shields.io/badge/dotclear-v2.28-137bbb.svg)](https://fr.dotclear.org/download)
[![Dotaddict](https://img.shields.io/badge/dotaddict-official-9ac123.svg)](https://plugins.dotaddict.org/dc2/details/oodles) [![Dotaddict](https://img.shields.io/badge/dotaddict-official-9ac123.svg)](https://plugins.dotaddict.org/dc2/details/oodles)
[![License](https://img.shields.io/github/license/JcDenis/oodles)](https://git.dotclear.watch/JcDenis/oodles/blob/master/LICENSE) [![License](https://img.shields.io/github/license/JcDenis/noodles)](https://git.dotclear.watch/JcDenis/noodles/blob/master/LICENSE)
## WHAT IS NOODLES ? ## ABOUT
_noodles_ is a plugin for the open-source _whiteListCom_ is a plugin for the open-source web publishing software called [Dotclear](https://www.dotclear.org).
web publishing software called Dotclear.
It adds gravatars everywhere it is possible on > Add gravatars everywhere it is possible on your blog. comments, posts, widgets...
your blog. comments, posts, widgets...
## REQUIREMENTS ## REQUIREMENTS
_noodles_ requires: * Dotclear 2.28
* Permissions admin
* Dotclear 2.26
* PHP 8.1+ * PHP 8.1+
* Permissions admin
## USAGE ## USAGE
@ -32,9 +28,11 @@ go to ''configure plugin'', fill in form.
## LINKS ## LINKS
* License : [GNU GPL v2](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.html) * [License](https://git.dotclear.watch/JcDenis/noodles/src/branch/master/LICENSE)
* Source & contribution : [Gitea Page](https://git.dotclear.watch/JcDenis/oodles) or [GitHub Page](https://github.com/JcDenis/oodles) * [Packages & details](https://git.dotclear.watch/JcDenis/noodles/releases) (or on [Dotaddict](https://plugins.dotaddict.org/dc2/details/noodles))
* Packages & details: [Gitea Page](https://git.dotclear.watch/JcDenis/oodles/releases) or [Dotaddict Page](https://plugins.dotaddict.org/dc2/details/oodles) * [Sources & contributions](https://git.dotclear.watch/JcDenis/noodles) (or on [GitHub](https://github.com/JcDenis/noodles))
* [Issues & security](https://git.dotclear.watch/JcDenis/noodles/issues) (or on [GitHub](https://github.com/JcDenis/noodles/issues))
## CONTRIBUTORS ## CONTRIBUTORS

View file

@ -1,38 +1,30 @@
<?php <?php
/** /**
* @brief noodles, a plugin for Dotclear 2 * @file
* @brief The plugin noodles definition
* @ingroup noodles
* *
* @package Dotclear * @defgroup noodles Plugin noodles.
* @subpackage Plugin
* *
* @author Jean-Christian Denis and contributors * Add users gravatars everywhere.
* *
* @copyright Jean-Christian Denis * @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_RC_PATH')) { declare(strict_types=1);
return null;
}
$this->registerModule( $this->registerModule(
'Noodles', 'Noodles',
'Add users gravatars everywhere', 'Add users gravatars everywhere',
'Jean-Christian Denis and contributors', 'Jean-Christian Denis and contributors',
'1.1', '1.2',
[ [
'requires' => [ 'requires' => [['core', '2.28']],
['php', '8.1'], 'permissions' => 'My',
['core', '2.27'], 'settings' => ['self' => ''],
], 'type' => 'plugin',
'permissions' => dcCore::app()->auth->makePermissions([ 'support' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/issues',
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN, 'details' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/src/branch/master/README.md',
]), 'repository' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/raw/branch/master/dcstore.xml',
'settings' => [
'self' => '',
],
'type' => 'plugin',
'support' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/issues',
'details' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/src/branch/master/README.md',
'repository' => 'https://git.dotclear.watch/JcDenis/' . basename(__DIR__) . '/raw/branch/master/dcstore.xml',
] ]
); );

View file

@ -2,11 +2,11 @@
<modules xmlns:da="http://dotaddict.org/da/"> <modules xmlns:da="http://dotaddict.org/da/">
<module id="noodles"> <module id="noodles">
<name>Noodles</name> <name>Noodles</name>
<version>1.1</version> <version>1.2</version>
<author>Jean-Christian Denis and contributors</author> <author>Jean-Christian Denis and contributors</author>
<desc>Add users gravatars everywhere</desc> <desc>Add users gravatars everywhere</desc>
<file>https://git.dotclear.watch/JcDenis/noodles/releases/download/v1.1/plugin-noodles.zip</file> <file>https://git.dotclear.watch/JcDenis/noodles/releases/download/v1.2/plugin-noodles.zip</file>
<da:dcmin>2.27</da:dcmin> <da:dcmin>2.28</da:dcmin>
<da:details>https://git.dotclear.watch/JcDenis/noodles/src/branch/master/README.md</da:details> <da:details>https://git.dotclear.watch/JcDenis/noodles/src/branch/master/README.md</da:details>
<da:support>https://git.dotclear.watch/JcDenis/noodles/issues</da:support> <da:support>https://git.dotclear.watch/JcDenis/noodles/issues</da:support>
</module> </module>

View file

@ -21,7 +21,7 @@ L10n::$locales['See local default avatar.']
L10n::$locales['Enable plugin noodles on this blog'] = 'Activer le plugin Noodles sur ce blog'; L10n::$locales['Enable plugin noodles on this blog'] = 'Activer le plugin Noodles sur ce blog';
L10n::$locales['Image API:'] = 'API des avatars :'; L10n::$locales['Image API:'] = 'API des avatars :';
L10n::$locales['Default image:'] = 'Avatar par défaut :'; L10n::$locales['Default image:'] = 'Avatar par défaut :';
L10n::$locales['You can add your own default avatar by adding file "%s" in media manager.'] = 'Vous pouvez ajouter votr epropre avatar par défaut en ajoutant un fichier "%s" au gestionnaire de média.'; L10n::$locales['You can add your own default avatar by adding file "%s" in media manager.'] = 'Vous pouvez ajouter votre propre avatar par défaut en ajoutant un fichier "%s" au gestionnaire de média.';
L10n::$locales['Search area'] = 'Zone de recherche'; L10n::$locales['Search area'] = 'Zone de recherche';
L10n::$locales['Rating'] = 'Évaluation'; L10n::$locales['Rating'] = 'Évaluation';
L10n::$locales['Target'] = 'Cible'; L10n::$locales['Target'] = 'Cible';

View file

@ -58,7 +58,7 @@ msgstr "Avatar par défaut :"
#: src/Manage.php:130 #: src/Manage.php:130
msgid "You can add your own default avatar by adding file \"%s\" in media manager." msgid "You can add your own default avatar by adding file \"%s\" in media manager."
msgstr "Vous pouvez ajouter votr epropre avatar par défaut en ajoutant un fichier \"%s\" au gestionnaire de média." msgstr "Vous pouvez ajouter votre propre avatar par défaut en ajoutant un fichier \"%s\" au gestionnaire de média."
#: src/Manage.php:136 #: src/Manage.php:136
msgid "Search area" msgid "Search area"

View file

@ -1,21 +1,18 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use Dotclear\Core\Process; use Dotclear\Core\Process;
/**
* @brief noodles backend class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Backend extends Process class Backend extends Process
{ {
public static function init(): bool public static function init(): bool

View file

@ -1,23 +1,20 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
/**
* @brief noodles combo helper.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Combo class Combo
{ {
/** /**
* @return array<string,string> * @return array<string,string>
*/ */
public static function api(): array public static function api(): array
{ {

View file

@ -1,23 +1,19 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use dcUtils;
use Dotclear\Core\Process; use Dotclear\Core\Process;
/**
* @brief noodles frontend class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Frontend extends Process class Frontend extends Process
{ {
public static function init(): bool public static function init(): bool
@ -37,7 +33,7 @@ class Frontend extends Process
return false; return false;
} }
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), My::path() . '/default-templates'); App::frontend()->tpl->setPath(App::frontend()->tpl->getPath(), My::path() . '/default-templates');
foreach ($targets->dump() as $target) { foreach ($targets->dump() as $target) {
if ($target->active() && $target->hasPhpCallback()) { if ($target->active() && $target->hasPhpCallback()) {
@ -45,15 +41,15 @@ class Frontend extends Process
} }
} }
dcCore::app()->addBehavior('publicHeadContent', function (): void { App::behavior()->addBehavior('publicHeadContent', function (): void {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return; return;
} }
echo echo
dcUtils::cssLoad(dcCore::app()->blog->url . dcCore::app()->url->getURLFor('noodles_css')) . App::plugins()->cssLoad(App::blog()->url() . App::url()->getURLFor('noodles_css')) .
dcUtils::jsLoad(dcCore::app()->blog->url . dcCore::app()->url->getBase('noodles_file') . '/js/jquery.noodles.js') . App::plugins()->jsLoad(App::blog()->url() . App::url()->getBase('noodles_file') . '/js/jquery.noodles.js') .
dcUtils::jsLoad(dcCore::app()->blog->url . dcCore::app()->url->getURLFor('noodles_js')); App::plugins()->jsLoad(App::blog()->url() . App::url()->getURLFor('noodles_js'));
}); });
return true; return true;

View file

@ -1,25 +1,26 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use Dotclear\Helper\File\Path; use Dotclear\Helper\File\Path;
/**
* @brief noodles image helper.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Image class Image
{ {
/** @var string The current class major version */ /**
* The current class major version.
*
* @var string VERSION
*/
public const VERSION = '2'; public const VERSION = '2';
/** /**
@ -27,9 +28,7 @@ class Image
*/ */
public static function getArray(): array public static function getArray(): array
{ {
if (is_null(dcCore::app()->blog) if (!App::blog()->isDefined() || !App::url()->getBase('noodles_file')) {
|| !dcCore::app()->url->getBase('noodles_file')
) {
return [ return [
'theme' => ['dir' => null, 'url' => null], 'theme' => ['dir' => null, 'url' => null],
'public' => ['dir' => null, 'url' => null], 'public' => ['dir' => null, 'url' => null],
@ -37,23 +36,23 @@ class Image
]; ];
} }
$public_url = dcCore::app()->blog->settings->get('system')->get('public_url'); $public_url = App::blog()->settings()->get('system')->get('public_url');
if (!is_string($public_url)) { if (!is_string($public_url)) {
$public_url = ''; $public_url = '';
} }
return [ return [
'theme' => [ 'theme' => [
'dir' => Path::real(dcCore::app()->blog->themes_path . '/' . dcCore::app()->blog->settings->get('system')->get('theme') . '/img') . '/' . My::IMAGE, 'dir' => Path::real(App::blog()->themesPath() . '/' . App::blog()->settings()->get('system')->get('theme') . '/img') . '/' . My::IMAGE,
'url' => dcCore::app()->blog->settings->get('system')->get('themes_url') . dcCore::app()->blog->settings->get('system')->get('theme') . '/img/' . My::IMAGE, 'url' => App::blog()->settings()->get('system')->get('themes_url') . App::blog()->settings()->get('system')->get('theme') . '/img/' . My::IMAGE,
], ],
'public' => [ 'public' => [
'dir' => Path::real(dcCore::app()->blog->public_path) . '/' . My::IMAGE, 'dir' => Path::real(App::blog()->publicPath()) . '/' . My::IMAGE,
'url' => dcCore::app()->blog->host . Path::clean($public_url) . '/' . My::IMAGE, 'url' => App::blog()->host() . Path::clean($public_url) . '/' . My::IMAGE,
], ],
'module' => [ 'module' => [
'dir' => Path::real(My::path() . '/default-templates/img') . '/' . My::IMAGE, 'dir' => Path::real(My::path() . '/default-templates/img') . '/' . My::IMAGE,
'url' => dcCore::app()->blog->url . dcCore::app()->url->getBase('noodles_file') . '/img/' . My::IMAGE, 'url' => App::blog()->url() . App::url()->getBase('noodles_file') . '/img/' . My::IMAGE,
], ],
]; ];
} }

View file

@ -1,23 +1,20 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Exception; use Exception;
/**
* @brief noodles install class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Install extends Process class Install extends Process
{ {
public static function init(): bool public static function init(): bool
@ -33,10 +30,6 @@ class Install extends Process
try { try {
$s = My::settings(); $s = My::settings();
if (is_null($s)) {
return false;
}
# Set module settings
$s->put('active', false, 'boolean', 'enable module', false, true); $s->put('active', false, 'boolean', 'enable module', false, true);
$s->put('api', 'http://www.gravatar.com/', 'string', 'external API', false, true); $s->put('api', 'http://www.gravatar.com/', 'string', 'external API', false, true);
$s->put('local', false, 'boolean', 'use local image', false, true); $s->put('local', false, 'boolean', 'use local image', false, true);
@ -44,7 +37,7 @@ class Install extends Process
return true; return true;
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
return false; return false;
} }

View file

@ -1,20 +1,10 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use Dotclear\Core\Backend\{ use Dotclear\Core\Backend\{
Notices, Notices,
Page Page
@ -33,6 +23,13 @@ use Dotclear\Helper\Html\Form\{
}; };
use Exception; use Exception;
/**
* @brief noodles manage class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Manage extends Process class Manage extends Process
{ {
public static function init(): bool public static function init(): bool
@ -47,7 +44,7 @@ class Manage extends Process
} }
// nullsafe check // nullsafe check
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return false; return false;
} }
@ -81,11 +78,11 @@ class Manage extends Process
} }
$targets->export(); $targets->export();
dcCore::app()->blog->triggerBlog(); App::blog()->triggerBlog();
Notices::addSuccessNotice(__('Configuration successfully updated')); Notices::addSuccessNotice(__('Configuration successfully updated'));
My::redirect(); My::redirect();
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); App::error()->add($e->getMessage());
} }
return true; return true;
@ -98,7 +95,7 @@ class Manage extends Process
} }
// nullsafe check // nullsafe check
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return; return;
} }

View file

@ -1,26 +1,39 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use Dotclear\App;
use Dotclear\Module\MyPlugin; use Dotclear\Module\MyPlugin;
/** /**
* This module definitions. * @brief noodles My helper.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class My extends MyPlugin class My extends MyPlugin
{ {
/** @var string Default image name */ /**
* Default image name.
*
* @var string IMAGE
*/
public const IMAGE = 'default-avatar.png'; public const IMAGE = 'default-avatar.png';
protected static function checkCustomContext(int $context): ?bool
{
return match ($context) {
// Allow BACKEND and MANAGE and MENU to also content admin
self::BACKEND, self::MANAGE, self::MENU => App::task()->checkContext('BACKEND')
&& App::blog()->isDefined()
&& App::auth()->check(App::auth()->makePermissions([
App::auth()::PERMISSION_CONTENT_ADMIN,
]), App::blog()->id()),
default => null,
};
}
} }

View file

@ -1,22 +1,19 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use Dotclear\Core\Process; use Dotclear\Core\Process;
/**
* @brief noodles prepend class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Prepend extends Process class Prepend extends Process
{ {
public static function init(): bool public static function init(): bool
@ -31,32 +28,32 @@ class Prepend extends Process
} }
// public URL for noodles files // public URL for noodles files
dcCore::app()->url->register( App::url()->register(
'noodles_file', 'noodles_file',
'noodles', 'noodles',
'^noodles/(.+)$', '^noodles/(.+)$',
[UrlHandler::class, 'file'] UrlHandler::file(...)
); );
// public URL for noodles service // public URL for noodles service
dcCore::app()->url->register( App::url()->register(
'noodles_service', 'noodles_service',
'noodle', 'noodle',
'^noodle/$', '^noodle/$',
[UrlHandler::class, 'service'] UrlHandler::service(...)
); );
// public URL for targets CSS contents // public URL for targets CSS contents
dcCore::app()->url->register( App::url()->register(
'noodles_css', 'noodles_css',
'noodles.css', 'noodles.css',
'^noodles\.css', '^noodles\.css',
[UrlHandler::class, 'css'] UrlHandler::css(...)
); );
// public URL for targets JS contents // public URL for targets JS contents
dcCore::app()->url->register( App::url()->register(
'noodles_js', 'noodles_js',
'noodles.js', 'noodles.js',
'^noodles\.js', '^noodles\.js',
[UrlHandler::class, 'js'] UrlHandler::js(...)
); );
return true; return true;

View file

@ -1,40 +1,57 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
/** /**
* Target definition. * @brief noodles target definition.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class Target class Target
{ {
/** @var bool The noodle activation */ /**
* The noodle activation.
*
* @var bool $active
*/
private bool $active = false; private bool $active = false;
/** @var string The noodle rating */ /**
* The noodle rating.
*
* @var string $rating
*/
private string $rating = 'g'; private string $rating = 'g';
/** @var int The noodle size */ /**
* The noodle size.
*
* @var int $size
*/
private int $size = 16; private int $size = 16;
/** @var string The noodle css */ /**
* The noodle css.
*
* @var string $css */
private string $css = ''; private string $css = '';
/** @var string The noodle target */ /**
* The noodle target.
*
* @var string $target
*/
private string $target = ''; private string $target = '';
/** @var string The noodle place */ /**
* The noodle place.
*
* @var string $place
*/
private string $place = 'prepend'; private string $place = 'prepend';
/** /**

View file

@ -1,20 +1,10 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles\Target; namespace Dotclear\Plugin\noodles\Target;
use dcCore; use Dotclear\App;
use Dotclear\Database\MetaRecord; use Dotclear\Database\MetaRecord;
use Dotclear\Plugin\noodles\{ use Dotclear\Plugin\noodles\{
Image, Image,
@ -24,7 +14,11 @@ use Dotclear\Plugin\noodles\{
}; };
/** /**
* Target rendering adapt to plugin authorMode. * @brief noodles target rendreing for plugin authorMode.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class AuthorMode class AuthorMode
{ {
@ -34,7 +28,7 @@ class AuthorMode
if (!$ok || !$m[1]) { if (!$ok || !$m[1]) {
return ''; return '';
} }
$rs = dcCore::app()->getUser($m[1]); $rs = App::users()->getUser($m[1]);
if ($rs->isEmpty()) { if ($rs->isEmpty()) {
return ''; return '';
} }
@ -47,7 +41,7 @@ class AuthorMode
public static function author(Target $target): void public static function author(Target $target): void
{ {
if ($target->active()) { if ($target->active()) {
dcCore::app()->addBehavior('publicHeadContent', [self::class, 'publicHeadContent']); App::behavior()->addBehavior('publicHeadContent', self::publicHeadContent(...));
} }
} }
@ -57,14 +51,14 @@ class AuthorMode
$target = $targets->get('author'); $target = $targets->get('author');
if (is_null($target) if (is_null($target)
|| is_null(dcCore::app()->ctx) || !isset(App::frontend()->ctx)
|| is_null(dcCore::app()->blog) || !App::blog()->isDefined()
|| dcCore::app()->ctx->__get('current_tpl') != 'author.html' || App::frontend()->ctx->__get('current_tpl') != 'author.html'
) { ) {
return; return;
} }
$u = dcCore::app()->ctx->__get('users'); $u = App::frontend()->ctx->__get('users');
if (!($u instanceof MetaRecord)) { if (!($u instanceof MetaRecord)) {
return; return;
} }
@ -72,7 +66,7 @@ class AuthorMode
if (!is_string($u)) { if (!is_string($u)) {
return; return;
} }
$u = dcCore::app()->getUser($u)->f('user_email'); $u = App::users()->getUser($u)->f('user_email');
if (!is_string($u)) { if (!is_string($u)) {
$u = ''; $u = '';
} }

View file

@ -1,39 +1,32 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles\Target; namespace Dotclear\Plugin\noodles\Target;
use dcCore; use Dotclear\App;
use Dotclear\Plugin\noodles\Target; use Dotclear\Plugin\noodles\Target;
/** /**
* Target generic rendering. * @brief noodles target generic rendering.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class Generic class Generic
{ {
public static function postURL(Target $target, string $content = ''): string public static function postURL(Target $target, string $content = ''): string
{ {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return ''; return '';
} }
$types = dcCore::app()->getPostTypes(); $reg = '@^' . str_replace('%s', '(.*?)', preg_quote(App::blog()->url() . App::postTypes()->get('post')->public_url)) . '$@';
$reg = '@^' . str_replace('%s', '(.*?)', preg_quote(dcCore::app()->blog->url . $types['post']['public_url'])) . '$@'; $ok = preg_match($reg, $content, $m);
$ok = preg_match($reg, $content, $m);
if (!$ok || !$m[1]) { if (!$ok || !$m[1]) {
return ''; return '';
} }
$rs = dcCore::app()->blog->getPosts(['no_content' => 1, 'post_url' => urldecode($m[1]), 'limit' => 1]); $rs = App::blog()->getPosts(['no_content' => 1, 'post_url' => urldecode($m[1]), 'limit' => 1]);
if ($rs->isEmpty()) { if ($rs->isEmpty()) {
return ''; return '';
} }

View file

@ -1,20 +1,10 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles\Target; namespace Dotclear\Plugin\noodles\Target;
use dcCore; use Dotclear\App;
use Dotclear\Database\MetaRecord; use Dotclear\Database\MetaRecord;
use Dotclear\Plugin\noodles\{ use Dotclear\Plugin\noodles\{
Image, Image,
@ -24,7 +14,11 @@ use Dotclear\Plugin\noodles\{
}; };
/** /**
* Target complete rendering. * @brief noodles target complete rendreing.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class Other class Other
{ {
@ -36,7 +30,7 @@ class Other
$bhv = $target->place() == 'prepend' || $target->place() == 'before' ? $bhv = $target->place() == 'prepend' || $target->place() == 'before' ?
'publicEntryBeforeContent' : 'publicEntryAfterContent'; 'publicEntryBeforeContent' : 'publicEntryAfterContent';
dcCore::app()->addBehavior($bhv, [self::class, 'publicEntryContent']); App::behavior()->addBehavior($bhv, self::publicEntryContent(...));
} }
public static function publicEntryContent(): void public static function publicEntryContent(): void
@ -45,14 +39,14 @@ class Other
$target = $targets->get('posts'); $target = $targets->get('posts');
if (is_null($target) if (is_null($target)
|| is_null(dcCore::app()->ctx) || !isset(App::frontend()->ctx)
|| is_null(dcCore::app()->blog) || !App::blog()->isDefined()
|| dcCore::app()->ctx->__get('current_tpl') != 'post.html' || App::frontend()->ctx->__get('current_tpl') != 'post.html'
) { ) {
return; return;
} }
$m = dcCore::app()->ctx->__get('posts'); $m = App::frontend()->ctx->__get('posts');
if (!($m instanceof MetaRecord)) { if (!($m instanceof MetaRecord)) {
return; return;
} }
@ -76,7 +70,7 @@ class Other
$bhv = $target->place() == 'prepend' || $target->place() == 'before' ? $bhv = $target->place() == 'prepend' || $target->place() == 'before' ?
'publicCommentBeforeContent' : 'publicCommentAfterContent'; 'publicCommentBeforeContent' : 'publicCommentAfterContent';
dcCore::app()->addBehavior($bhv, [self::class, 'publicCommentContent']); App::behavior()->addBehavior($bhv, self::publicCommentContent(...));
} }
public static function publicCommentContent(): void public static function publicCommentContent(): void
@ -85,14 +79,14 @@ class Other
$target = $targets->get('comments'); $target = $targets->get('comments');
if (is_null($target) if (is_null($target)
|| is_null(dcCore::app()->ctx) || !isset(App::frontend()->ctx)
|| is_null(dcCore::app()->blog) || !App::blog()->isDefined()
|| dcCore::app()->ctx->__get('current_tpl') != 'post.html' || App::frontend()->ctx->__get('current_tpl') != 'post.html'
) { ) {
return; return;
} }
$m = dcCore::app()->ctx->__get('comments'); $m = App::frontend()->ctx->__get('comments');
if (!($m instanceof MetaRecord)) { if (!($m instanceof MetaRecord)) {
return; return;
} }

View file

@ -1,37 +1,31 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles\Target; namespace Dotclear\Plugin\noodles\Target;
use dcCore; use Dotclear\App;
use Dotclear\Plugin\noodles\Target; use Dotclear\Plugin\noodles\Target;
/** /**
* Target rendering adapt to plugin Widgets. * @brief noodles target rendreing for plugin widgets.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
class Widgets class Widgets
{ {
public static function lastcomments(Target $target, string $content = ''): string public static function lastcomments(Target $target, string $content = ''): string
{ {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return ''; return '';
} }
$ok = preg_match('@\#c([0-9]+)$@', urldecode($content), $m); $ok = preg_match('@\#c([0-9]+)$@', urldecode($content), $m);
if (!$ok || !$m[1]) { if (!$ok || !$m[1]) {
return ''; return '';
} }
$rs = dcCore::app()->blog->getComments(['no_content' => 1, 'comment_id' => $m[1], 'limit' => 1]); $rs = App::blog()->getComments(['no_content' => 1, 'comment_id' => $m[1], 'limit' => 1]);
if ($rs->isEmpty()) { if ($rs->isEmpty()) {
return ''; return '';
} }

View file

@ -1,40 +1,54 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use Exception; use Exception;
/** /**
* Targets stack. * @brief noodles targets stack.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
final class Targets final class Targets
{ {
/** @var Targets The noodles instance */ /**
* The noodles instance.
*
* @var Targets $instance
*/
private static $instance; private static $instance;
/** @ var bool The activation */ /**
* The activation.
*
* @var bool $active
*/
public readonly bool $active; public readonly bool $active;
/** @ var string The API URL */ /**
* The API URL.
*
* @var string $api
*/
public readonly string $api; public readonly string $api;
/** @ var bool Use local image */ /**
* Use local image.
*
* @var bool $local
*/
public readonly bool $local; public readonly bool $local;
/** @var array<string,Target> The noodles stack */ /**
* The noodles stack.
*
* @var array<string,Target> $targets
*/
private array $targets = []; private array $targets = [];
/** /**
@ -55,7 +69,7 @@ final class Targets
$this->local = is_bool($local) ? $local : false; $this->local = is_bool($local) ? $local : false;
// add noodles // add noodles
dcCore::app()->callBehavior('TargetsConstruct', $this); App::behavior()->callBehavior('TargetsConstruct', $this);
// add default noodles // add default noodles
$this->registerDefault(); $this->registerDefault();
@ -176,7 +190,7 @@ final class Targets
*/ */
private function registerDefault(): void private function registerDefault(): void
{ {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
return; return;
} }
@ -185,7 +199,7 @@ final class Targets
(new Target( (new Target(
id: 'posts', id: 'posts',
name: __('Entries'), name: __('Entries'),
php_callback: [Target\Other::class, 'publicPosts'] php_callback: Target\Other::publicPosts(...)
)) ))
->setSize(48) ->setSize(48)
->setCss('float:right;margin:4px;') ->setCss('float:right;margin:4px;')
@ -196,7 +210,7 @@ final class Targets
(new Target( (new Target(
id: 'comments', id: 'comments',
name: __('Comments'), name: __('Comments'),
php_callback: [Target\Other::class, 'publicComments'] php_callback: Target\Other::publicComments(...)
)) ))
->setActive(true) ->setActive(true)
->setSize(48) ->setSize(48)
@ -208,19 +222,19 @@ final class Targets
(new Target( (new Target(
id: 'titlesposts', id: 'titlesposts',
name: __('Entries titles'), name: __('Entries titles'),
js_callback: [Target\Generic::class, 'postURL'] js_callback: Target\Generic::postURL(...)
)) ))
->setTarget('.post-title a') ->setTarget('.post-title a')
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')
); );
if (dcCore::app()->plugins->moduleExists('widgets')) { if (App::plugins()->moduleExists('widgets')) {
# Widget Selected entries # Widget Selected entries
$this->set( $this->set(
(new Target( (new Target(
id: 'bestof', id: 'bestof',
name: __('Selected entries'), name: __('Selected entries'),
js_callback: [Target\Generic::class, 'postURL'] js_callback: Target\Generic::postURL(...)
)) ))
->setTarget('.selected li a') ->setTarget('.selected li a')
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')
@ -231,7 +245,7 @@ final class Targets
(new Target( (new Target(
id: 'lastposts', id: 'lastposts',
name: __('Last entries'), name: __('Last entries'),
js_callback: [Target\Generic::class, 'postURL'] js_callback: Target\Generic::postURL(...)
)) ))
->setTarget('.lastposts li a') ->setTarget('.lastposts li a')
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')
@ -242,7 +256,7 @@ final class Targets
(new Target( (new Target(
id: 'lastcomments', id: 'lastcomments',
name: __('Last comments'), name: __('Last comments'),
js_callback: [Target\Widgets::class, 'lastcomments'] js_callback: Target\Widgets::lastcomments(...)
)) ))
->setActive(true) ->setActive(true)
->setTarget('.lastcomments li a') ->setTarget('.lastcomments li a')
@ -251,14 +265,14 @@ final class Targets
} }
# Plugin auhtorMode # Plugin auhtorMode
if (dcCore::app()->plugins->moduleExists('authorMode') if (App::plugins()->moduleExists('authorMode')
&& dcCore::app()->blog->settings->get('authormode')->get('authormode_active') && App::blog()->settings()->get('authormode')->get('authormode_active')
) { ) {
$this->set( $this->set(
(new Target( (new Target(
id: 'authorswidget', id: 'authorswidget',
name: __('Authors widget'), name: __('Authors widget'),
js_callback: [Target\AuthorMode::class, 'authors'] js_callback: Target\AuthorMode::authors(...)
)) ))
->setTarget('#authors ul li a') ->setTarget('#authors ul li a')
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')
@ -268,7 +282,7 @@ final class Targets
(new Target( (new Target(
id: 'author', id: 'author',
name: __('Author'), name: __('Author'),
php_callback: [Target\AuthorMode::class, 'author'] php_callback: Target\AuthorMode::author(...)
)) ))
->setActive(true) ->setActive(true)
->setSize(48) ->setSize(48)
@ -280,7 +294,7 @@ final class Targets
(new Target( (new Target(
id: 'authors', id: 'authors',
name: __('Authors'), name: __('Authors'),
js_callback: [Target\AuthorMode::class, 'authors'] js_callback: Target\AuthorMode::authors(...)
)) ))
->setActive(true) ->setActive(true)
->setSize(32) ->setSize(32)
@ -290,14 +304,14 @@ final class Targets
} }
# Plugin rateIt # Plugin rateIt
if (dcCore::app()->plugins->moduleExists('rateIt') if (App::plugins()->moduleExists('rateIt')
&& dcCore::app()->blog->settings->get('rateit')->get('rateit_active') && App::blog()->settings()->get('rateit')->get('rateit_active')
) { ) {
$this->set( $this->set(
(new Target( (new Target(
id: 'rateitpostsrank', id: 'rateitpostsrank',
name: __('Top rated entries'), name: __('Top rated entries'),
js_callback: [Target\Generic::class, 'postURL'] js_callback: Target\Generic::postURL(...)
)) ))
->setTarget('.rateitpostsrank.rateittypepost ul li a') // Only "post" type ->setTarget('.rateitpostsrank.rateittypepost ul li a') // Only "post" type
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')
@ -305,12 +319,12 @@ final class Targets
} }
# Plugin lastpostsExtend # Plugin lastpostsExtend
if (dcCore::app()->plugins->moduleExists('lastpostsExtend')) { if (App::plugins()->moduleExists('lastpostsExtend')) {
$this->set( $this->set(
(new Target( (new Target(
id: 'lastpostsextend', id: 'lastpostsextend',
name: __('Last entries (extend)'), name: __('Last entries (extend)'),
js_callback: [Target\Generic::class, 'postURL'] js_callback: Target\Generic::postURL(...)
)) ))
->setTarget('.lastpostsextend ul li a') ->setTarget('.lastpostsextend ul li a')
->setCss('margin-right:2px;') ->setCss('margin-right:2px;')

View file

@ -1,23 +1,19 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore;
use Dotclear\Core\Process; use Dotclear\Core\Process;
use Dotclear\Plugin\Uninstaller\Uninstaller; use Dotclear\Plugin\Uninstaller\Uninstaller;
/**
* @brief noodles uninstall class.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class Uninstall extends Process class Uninstall extends Process
{ {
public static function init(): bool public static function init(): bool
@ -27,7 +23,7 @@ class Uninstall extends Process
public static function process(): bool public static function process(): bool
{ {
if (!self::status() || !dcCore::app()->plugins->moduleExists('Uninstaller')) { if (!self::status()) {
return false; return false;
} }

View file

@ -1,28 +1,25 @@
<?php <?php
/**
* @brief noodles, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1); declare(strict_types=1);
namespace Dotclear\Plugin\noodles; namespace Dotclear\Plugin\noodles;
use dcCore; use Dotclear\App;
use dcUrlHandlers; use Dotclear\Core\Frontend\Url;
use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Files;
use Dotclear\Helper\File\Path; use Dotclear\Helper\File\Path;
use Dotclear\Helper\Html\Html; use Dotclear\Helper\Html\Html;
use Dotclear\Helper\Html\XmlTag; use Dotclear\Helper\Html\XmlTag;
use Exception; use Exception;
class UrlHandler extends dcUrlHandlers /**
* @brief noodles URL handler.
* @ingroup noodles
*
* @author Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
class UrlHandler extends Url
{ {
public static function css(?string $args): void public static function css(?string $args): void
{ {
@ -43,7 +40,7 @@ class UrlHandler extends dcUrlHandlers
public static function js(?string $args): void public static function js(?string $args): void
{ {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
self::p404(); self::p404();
} }
@ -62,7 +59,7 @@ class UrlHandler extends dcUrlHandlers
echo echo
"\$(function(){if(!document.getElementById){return;} \n" . "\$(function(){if(!document.getElementById){return;} \n" .
"\$.fn.noodles.defaults.service_url = '" . Html::escapeJS(dcCore::app()->blog->url . dcCore::app()->url->getBase('noodles_service') . '/') . "'; \n" . "\$.fn.noodles.defaults.service_url = '" . Html::escapeJS(App::blog()->url() . App::url()->getBase('noodles_service') . '/') . "'; \n" .
"\$.fn.noodles.defaults.service_func = '" . Html::escapeJS('getNoodle') . "'; \n" . "\$.fn.noodles.defaults.service_func = '" . Html::escapeJS('getNoodle') . "'; \n" .
implode("\n", $targets) . implode("\n", $targets) .
"})\n"; "})\n";
@ -72,7 +69,7 @@ class UrlHandler extends dcUrlHandlers
public static function service(string $args): void public static function service(string $args): void
{ {
if (is_null(dcCore::app()->blog)) { if (!App::blog()->isDefined()) {
self::p404(); self::p404();
} }
@ -147,7 +144,7 @@ class UrlHandler extends dcUrlHandlers
public static function file(string $args): void public static function file(string $args): void
{ {
if (is_null(dcCore::app()->blog) if (!App::blog()->isDefined()
|| !Targets::instance()->active || !Targets::instance()->active
|| str_contains('..', $args) || str_contains('..', $args)
|| !preg_match('#^([^\?]*)#', $args, $m) || !preg_match('#^([^\?]*)#', $args, $m)
@ -169,12 +166,12 @@ class UrlHandler extends dcUrlHandlers
header('Content-Type: ' . $type . '; charset=UTF-8'); header('Content-Type: ' . $type . '; charset=UTF-8');
header('Content-Length: ' . filesize($f)); header('Content-Length: ' . filesize($f));
if ($type != 'text/css' || dcCore::app()->blog->settings->get('system')->get('url_scan') == 'path_info') { if ($type != 'text/css' || App::blog()->settings()->get('system')->get('url_scan') == 'path_info') {
readfile($f); readfile($f);
} else { } else {
echo preg_replace( echo preg_replace(
'#url\((?!(http:)|/)#', '#url\((?!(http:)|/)#',
'url(' . dcCore::app()->blog->url . dcCore::app()->url->getBase('noodles_file') . '/', 'url(' . App::blog()->url() . App::url()->getBase('noodles_file') . '/',
(string) file_get_contents($f) (string) file_get_contents($f)
); );
} }
@ -187,7 +184,7 @@ class UrlHandler extends dcUrlHandlers
if (str_contains($file, '..')) { if (str_contains($file, '..')) {
return ''; return '';
} }
$paths = dcCore::app()->tpl->getPath(); $paths = App::frontend()->tpl->getPath();
foreach ($paths as $path) { foreach ($paths as $path) {
if (preg_match('/tpl(\/|)$/', $path)) { if (preg_match('/tpl(\/|)$/', $path)) {