full upgrade to Dotclear 2.27

This commit is contained in:
Jean-Christian Denis 2023-08-24 13:55:44 +02:00
parent faaaac0569
commit 7eae6b30fb
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
28 changed files with 3544 additions and 2245 deletions

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xml:lang="{{tpl:BlogLanguage}}">
<title type="html">{{tpl:BlogName encode_xml="1"}} - {{tpl:c2PageTitle encode_xml="1"}}</title>
<subtitle type="html">{{tpl:c2PageDescription encode_xml="1"}}</subtitle>
<link href="{{tpl:SysSelfURI}}" rel="self" type="application/atom+xml"/>
<link href="{{tpl:BlogURL}}" rel="alternate" type="text/html" title="{{tpl:BlogDescription encode_xml="1"}}"/>
<updated>{{tpl:BlogUpdateDate iso8601="1"}}</updated>
<author>
<name>{{tpl:BlogEditor encode_xml="1"}}</name>
</author>
<id>{{tpl:c2PageFeedID}}</id>
<generator uri="http://www.dotclear.net/">Dotclear</generator>
<tpl:c2Entries>
<entry>
<title>{{tpl:c2EntryTitle encode_xml="1"}}</title>
<link href="{{tpl:c2EntryURL encode_xml="1"}}" rel="alternate" type="text/html" title="{{tpl:c2EntryTitle encode_xml="1"}}" />
<id>{{tpl:c2EntryFeedID}}</id>
<updated>{{tpl:c2EntryDate iso8601="1"}}</updated>
<author><name>{{tpl:c2EntryFromAuthor encode_xml="1"}}</name></author>
<tpl:c2EntryIf has_category="1"><dc:subject>{{tpl:c2EntryCategory encode_xml="1"}}</dc:subject></tpl:c2EntryIf>
<content type="html">
&lt;p&gt;{{tpl:c2EntryImg absolute_urls="1" encode_xml="1"}}&lt;br /&gt;
{{tpl:c2EntryDescription absolute_urls="1" encode_xml="1"}}&lt;/p&gt;
</content>
</entry>
</tpl:c2Entries>
</feed>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet title="XSL formatting" type="text/xsl" href="{{tpl:BlogURL}}feed/rss2/xslt" ?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{tpl:BlogName encode_xml="1"}} - {{tpl:c2PageTitle encode_xml="1"}}</title>
<link>{{tpl:BlogURL}}</link>
<atom:link href="{{tpl:SysSelfURI}}" rel="self" type="application/rss+xml"/>
<description>{{tpl:c2PageDescription encode_xml="1"}}</description>
<language>{{tpl:BlogLanguage}}</language>
<pubDate>{{tpl:BlogUpdateDate rfc822="1"}}</pubDate>
<copyright>{{tpl:BlogCopyrightNotice encode_xml="1"}}</copyright>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>Dotclear</generator>
<tpl:c2Entries>
<item>
<title>{{tpl:c2EntryTitle encode_xml="1"}}</title>
<link>{{tpl:c2EntryURL encode_xml="1"}}</link>
<tpl:c2EntryIf has_category="1"><categorie>{{tpl:c2EntryCategory encode_xml="1"}}</categorie></tpl:c2EntryIf>
<guid isPermaLink="false">{{tpl:c2EntryFeedID}}</guid>
<pubDate>{{tpl:c2EntryDate rfc822="1"}}</pubDate>
<dc:creator>{{tpl:c2EntryFromAuthor encode_xml="1"}}</dc:creator>
<description>
&lt;p&gt;{{tpl:c2EntryImg encode_xml="1"}}&lt;br /&gt;
{{tpl:c2EntryDescription encode_xml="1"}}&lt;/p&gt;
</description>
</item>
</tpl:c2Entries>
</channel>
</rss>

View file

@ -0,0 +1,163 @@
{{tpl:extends parent="__layout.html"}}
<tpl:Block name="head-title">
<title>{{tpl:c2PageTitle encode_html="1"}} - {{tpl:BlogName encode_html="1"}}
</title>
</tpl:Block>
<tpl:Block name="meta-robots">
<meta name="ROBOTS" content="{{tpl:BlogMetaRobots robots="NOINDEX"}}" />
</tpl:Block>
<tpl:Block name="meta-entry">
<meta name="description" lang="{{tpl:BlogLanguage}}" content="{{tpl:BlogDescription encode_html="1" cut_string="180" remove_html="1"}}" />
<meta name="author" content="{{tpl:BlogEditor encode_html="1"}}" />
<meta name="date" content="{{tpl:BlogUpdateDate iso8601="1"}}" />
</tpl:Block>
<tpl:Block name="head-linkrel">
<link rel="contents" href="{{tpl:c2PageURL}}" title="{{tpl:lang Cinecturlink}}" />
<tpl:c2Entries no_content="1">
<tpl:c2EntriesHeader>
<tpl:c2Pagination>
<tpl:c2PaginationIf end="0">
<link rel="previous" title="{{tpl:lang previous links}}" href="{{tpl:c2PaginationURL offset="1"}}" />
</tpl:c2PaginationIf>
<tpl:c2PaginationIf start="0">
<link rel="next" title="{{tpl:lang next links}}" href="{{tpl:c2PaginationURL offset="-1"}}" />
</tpl:c2PaginationIf>
</tpl:c2Pagination>
</tpl:c2EntriesHeader>
<link rel="chapter" href="{{tpl:c2EntryURL}}" title="{{tpl:c2EntryTitle encode_html="1"}}" />
</tpl:c2Entries>
<link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="{{tpl:c2PageFeedURL type="atom"}}" />
</tpl:Block>
<tpl:Block name="body-tag">
<body class="dc-post dc-cinecturlink">
</tpl:Block>
<tpl:Block name="main-content">
<tpl:Block name="main-content-before"></tpl:Block>
<tpl:Block name="main-content-main">
<tpl:Block name="main-content-header">
<header id="content-info">
<tpl:Block name="main-content-header-title">
<h2>
<tpl:c2If operator="or" request_link="1" request_cat="1">
<a href="{{tpl:c2PageURL}}" title="{{tpl:lang view all links}}">{{tpl:c2PageTitle encode_html="1"}}</a> &rsaquo; <tpl:c2Categories><tpl:c2CategoryIf current="1">{{tpl:c2CategoryTitle}}
</tpl:c2CategoryIf>
</tpl:c2Categories>
{{tpl:else}}
{{tpl:c2PageTitle encode_html="1"}}
</tpl:c2If>
</h2>
</tpl:Block>
<tpl:Block name="main-content-header-feed">
<tpl:c2CategoryIf has_entries="1">
<ul class="content-info__feed">
<li><a type="application/atom+xml" href="{{tpl:c2PageFeedURL type="atom"}}"
title="{{tpl:lang This entries Atom feed}}" class="feed">{{tpl:lang Entries feed}}</a></li>
<tpl:c2Categories>
<tpl:c2CategoryIf current="1">
<li><a type="application/atom+xml" href="{{tpl:c2CategoryFeedURL type="atom"}}"
title="{{tpl:lang This category's entries Atom feed}}" class="feed">{{tpl:lang Category's entries feed}}</a></li>
</tpl:c2CategoryIf>
</tpl:c2Categories>
</ul>
</tpl:c2CategoryIf>
</tpl:Block>
<tpl:Block name="main-content-header-desc">
<div class="content-info__cat-desc">
{{tpl:c2PageDescription}}
</div>
</tpl:Block>
<tpl:Block name="main-content-header-subcats">
<tpl:c2Categories>
<tpl:c2CategoriesHeader>
<div id="subcategories" class="content-info__sub-cat">
<h3>{{tpl:lang Categories}}</h3>
<ul>
</tpl:c2CategoriesHeader>
<tpl:c2CategoryIf current="1">
<li class="post-cat">{{tpl:c2CategoryTitle}}</li>
</tpl:c2CategoryIf>
<tpl:c2CategoryIf current="0">
<li class="post-cat"><a href="{{tpl:c2CategoryURL}}" title="{{tpl:c2CategoryDescription remove_html="1"}}">{{tpl:c2CategoryTitle}}</a> </li>
</tpl:c2CategoryIf>
<tpl:c2CategoriesFooter>
</ul>
</div>
</tpl:c2CategoriesFooter>
</tpl:c2Categories>
</tpl:Block>
</header> <!-- # End #content-info -->
</tpl:Block>
<tpl:Block name="main-content-inner"></tpl:Block>
<div class="content-inner">
<tpl:c2Entries order="link_creadt" sort="desc">
<tpl:Block name="_entry-full-before"></tpl:Block>
<tpl:Block name="_entry-full-main">
<article id="p{{tpl:c2EntryID}}" class="post {{tpl:c2EntryIfOdd}} {{tpl:c2EntryIfFirst}} full" lang="{{tpl:c2EntryLang}}" role="article">
<tpl:Block name="_entry-full-header">
<header>
<tpl:Block name="_entry-full-header-date"></tpl:Block>
<tpl:Block name="_entry-full-header-title">
<h2 class="post-title"><a href="{{tpl:c2EntryURL}}">{{tpl:c2EntryTitle encode_html="1"}}</a></h2>
</tpl:Block>
</header>
</tpl:Block>
<tpl:Block name="_entry-full-behavior-before-content">
<!-- # --BEHAVIOR-- publicEntryBeforeContent -->
{{tpl:SysBehavior behavior="publicEntryBeforeContent"}}
</tpl:Block>
<tpl:Block name="_entry-full-content">
<tpl:Block name="_entry-full-content-excerpt">
{{tpl:c2EntryImg style="float:left; margin: 0 1em 1em 0;"}}
</tpl:Block>
<tpl:Block name="_entry-full-content-main">
<div class="post-content">{{tpl:c2EntryDescription remove_html="1"}}</div>
</tpl:Block>
</tpl:Block>
<tpl:Block name="_entry-full-behavior-after-content">
<!-- # --BEHAVIOR-- publicEntryAfterContent -->
{{tpl:SysBehavior behavior="publicEntryAfterContent"}}
</tpl:Block>
<tpl:Block name="_entry-full-footer">
<footer class="post-meta">
<tpl:Block name="_entry-full-footer-info">
<tpl:Block name="_entry-full-footer-post-info">
<p class="post-info">
<span class="post-author">{{tpl:lang By}} {{tpl:c2EntryFromAuthor}} (<a href="{{tpl:c2EntryURL}}" title="{{tpl:lang link}}">{{tpl:lang link}}</a>), </span>
<span class="post-author">{{tpl:lang By}} {{tpl:c2EntryFromAuthor}}, </span>
<span class="post-date"><time datetime="{tpl:c2EntryDate}}, {{tpl:c2EntryTime}}">{{tpl:c2EntryDate}}</time>.</span>
<tpl:c2EntryIf has_category="1">
<span class="post-cat"><a href="{{tpl:c2EntryCategoryURL}}">{{tpl:c2EntryCategory encode_html="1"}}</a></span>
</tpl:c2EntryIf>
</p>
</tpl:Block>
<tpl:Block name="_entry-full-footer-post-tags"></tpl:Block>
</tpl:Block>
<tpl:Block name="_entry-full-footer-counters"></tpl:Block>
</footer>
</tpl:Block>
</article>
</tpl:Block>
<tpl:Block name="_entry-full-after"></tpl:Block>
<tpl:c2EntriesFooter>
<tpl:c2Pagination>
<p class="pagination"><tpl:c2PaginationIf end="0"><a href="{{tpl:c2PaginationURL offset="+1"}}" class="prev">&#171;
{{tpl:lang previous links}}</a> - </tpl:c2PaginationIf>
{{tpl:lang page}} {{tpl:c2PaginationCurrent}} {{tpl:lang of}} {{tpl:c2PaginationCounter}}
<tpl:c2PaginationIf start="0"> - <a href="{{tpl:c2PaginationURL offset="-1"}}" class="next">{{tpl:lang next links}}
&#187;</a></tpl:c2PaginationIf></p>
</tpl:c2Pagination>
</tpl:c2EntriesFooter>
</tpl:c2Entries>
</div> <!-- # End #content-inner -->
</tpl:Block>
</tpl:Block>
<tpl:Block name="main-content-after"></tpl:Block>
</tpl:Block>

121
locales/fr/main.lang.php Normal file
View file

@ -0,0 +1,121 @@
<?php
/**
* @package Dotclear
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
#
# DOT NOT MODIFY THIS FILE !
#
use Dotclear\Helper\L10n;
L10n::$locales['previous links'] = 'liens précédents';
L10n::$locales['next links'] = 'liens suivants';
L10n::$locales['view all links'] = 'voir tous les liens';
L10n::$locales['Category\'s entries feed'] = 'Fil de cette catégorie';
L10n::$locales['link'] = 'lien';
L10n::$locales['Rating'] = 'Évaluation';
L10n::$locales['Links per page'] = 'Liens par page';
L10n::$locales['General'] = 'Général';
L10n::$locales['Enable plugin'] = 'Activer le plugin';
L10n::$locales['Public folder of images (under public folder of blog):'] = 'Dossier publique des images (dans le répertoire "public" du blog) :';
L10n::$locales['Or create a new public folder of images:'] = 'Ou créer un nouveau dossier public :';
L10n::$locales['Maximum width of images (in pixel):'] = 'Largeur maximum des images (en pixels) :';
L10n::$locales['Update cache when use "Random" or "Number of view" order on widget (Need reload of widgets on change)'] = 'Mettre à jour le cache lors de l\'utilisation de l\'ordre "Aléatoire" ou "Nombre d\'affichages" dans le widget (Nécessite le rechargement du widget)';
L10n::$locales['This increases the random effect, but updates the cache of the blog whenever the widget is displayed, which reduces the perfomances of your blog.'] = 'Ceci augmente l\'effet aléatoire, mais met à jour le cache à chaque affichage du widget, ce qui diminue les performances du blog.';
L10n::$locales['Public page'] = 'Page publique';
L10n::$locales['Enable public page'] = 'Activer la page publique';
L10n::$locales['Public page has url: %s'] = 'La page publique à l\'URL: %s';
L10n::$locales['Title of the public page:'] = 'Titre de la page publique :';
L10n::$locales['Description of the public page:'] = 'Description de la page publique :';
L10n::$locales['Limit number of entries per page on pulic page to:'] = 'Limiter le nombre d\'entrée par page sur la page public à :';
L10n::$locales['You must provide a specific folder for images.'] = 'Vous devez fournir un dossier spécifique pour les images.';
L10n::$locales['links'] = 'liens';
L10n::$locales['Back to links list'] = 'Retour à la liste des liens';
L10n::$locales['Links actions'] = 'Actions sur les liens';
L10n::$locales['Change rating'] = 'Changer l\'évaluation';
L10n::$locales['No links selected'] = 'Aucun lien sélectionné';
L10n::$locales['Category of %s link successfully changed.'] = [
'Catégorie du lien changée',
'Catégorie des %s liens changée',
];
L10n::$locales['Note of %s link successfully changed.'] = [
'Note du lien changée',
'Note des %s liens changée',
];
L10n::$locales['Change note for this selection'] = 'Changer la note pour la séletion';
L10n::$locales['Note:'] = 'Note :';
L10n::$locales['No link matches the filter'] = 'Aucun lien pour ce filtre';
L10n::$locales['No link'] = 'Aucun lien';
L10n::$locales['List of %s links matching the filter.'] = 'Liste des %s liens correspondant au filtre.';
L10n::$locales['List of links. (%s)'] = 'Liste des liens. (%s)';
L10n::$locales['My cinecturlink'] = 'Mes cinecturlink';
L10n::$locales['Category with same name already exists.'] = 'Une catégorie portant le même nom existe déjà.';
L10n::$locales['Category successfully created.'] = 'Catégory créée.';
L10n::$locales['Category successfully updated.'] = 'Catégorie mise à jour.';
L10n::$locales['Category successfully deleted.'] = 'Catégorie effacé.';
L10n::$locales['No link uses this category.'] = 'Aucun lien n\'utilise cette catégorie.';
L10n::$locales['A link uses this category.'] = [
'Un lien utilise cette catégorie.',
'%s liens utilisent cette catégorie.',
];
L10n::$locales['Categories successfully reordered.'] = 'Catégories réordonnées.';
L10n::$locales['Categories successfully deleted.'] = 'Catégories effacées.';
L10n::$locales['New Link'] = 'Nouveau lien';
L10n::$locales['There is no category'] = 'Il n\'y a pas de catégorie';
L10n::$locales['Categories list'] = 'Liste des catégories';
L10n::$locales['Check to delete'] = 'Cocher pour supprimer';
L10n::$locales['You must provide a title.'] = 'Vous devez fournir un titre.';
L10n::$locales['You must provide an author.'] = 'Vous devez spécifier un auteur';
L10n::$locales['You must provide a link to an image.'] = 'Vous devez fournir un lien vers une image.';
L10n::$locales['Link with same name already exists.'] = 'Un lien avec le même titre existe déjà.';
L10n::$locales['Link successfully created.'] = 'Lien crée.';
L10n::$locales['Unknown link.'] = 'Lien inconnu.';
L10n::$locales['Link successfully updated.'] = 'Lien mis à jour.';
L10n::$locales['Link successfully deleted.'] = 'Lien effacé.';
L10n::$locales['New link'] = 'Nouveau lien';
L10n::$locales['Details URL:'] = 'Liens vers les détails :';
L10n::$locales['Search with Google'] = 'Rechercher avec Google';
L10n::$locales['Image URL:'] = 'Lien vers l\'image :';
L10n::$locales['Search with Amazon'] = 'Rechercher avec Amazon';
L10n::$locales['There is no image in cinecturlink media path.'] = 'Il n\'y a pas d\'image dans le chemin des média cinecturlink.';
L10n::$locales['or select from repository:'] = 'ou selectionner depuis le dépôt :';
L10n::$locales['Go to media manager to add image to cinecturlink path.'] = 'Aller dans le gestionnaire de média pour ajouter des images au chemin des cinecturlink.';
L10n::$locales['Rating:'] = 'Évaluation :';
L10n::$locales['Manage links'] = 'Gérer les liens';
L10n::$locales['Edit categories'] = 'Gérer les catégories';
L10n::$locales['Selected links action:'] = 'Action sur les liens selectionnés :';
L10n::$locales['Plugin cinecturlink2'] = 'Extension cinecturlink 2';
L10n::$locales['link creation'] = 'Création de lien';
L10n::$locales['A new cineturlink named "%s" was added by "%s"'] = 'Un nouveau cinecturlink nommé "%s" a été ajouté par "%s"';
L10n::$locales['updating link'] = 'Mise à jour de lien';
L10n::$locales['Cinecturlink named "%s" has been updated by "%s"'] = 'Le cinecturlink nommé "%s" a été mis à jour par "%s"';
L10n::$locales['link deletion'] = 'Suppression de lien';
L10n::$locales['Cinecturlink named "%s" has been deleted by "%s"'] = 'Le cinecturlink nommé "%s" a été effacé par "%s"';
L10n::$locales['No link title'] = 'Pas de titre de lien';
L10n::$locales['No link description'] = 'Pas de description de lien';
L10n::$locales['No such link ID'] = 'ID de lien inconnu';
L10n::$locales['No category title'] = 'Pas de titre de catégorie';
L10n::$locales['No category description'] = 'Pas de description de catégorie';
L10n::$locales['No such category ID'] = 'ID de catégorie inconnu';
L10n::$locales['Failed to create public folder for images.'] = 'Impossible de créer le repertoire publique pour les images.';
L10n::$locales['Update date'] = 'Date de mise à jour';
L10n::$locales['My rating'] = 'Mon évaluation';
L10n::$locales['Random'] = 'Aléatoire';
L10n::$locales['Number of views'] = 'Nombre d\'affichages';
L10n::$locales['Show selection of cinecturlinks'] = 'Afficher une selection de cinecturlink';
L10n::$locales['Sort: (only for date, note and title)'] = 'Ordre: (seulement pour date, note et titre)';
L10n::$locales['Limit:'] = 'Limite :';
L10n::$locales['Enable link'] = 'Autoriser les liens';
L10n::$locales['Show author'] = 'Afficher l\'auteur';
L10n::$locales['Show my rating'] = 'Afficher mon évaluation';
L10n::$locales['Show description'] = 'Afficher la description';
L10n::$locales['Show a link to cinecturlink page'] = 'Afficher un lien vers la page publique';
L10n::$locales['List of categories of cinecturlink'] = 'Liste des catégories de cinecturlink';
L10n::$locales['My cinecturlink by categories'] = 'Mes cinecturlink par catégories';
L10n::$locales['Show number of links'] = 'Afficher le nombre de liens';
L10n::$locales['More links'] = 'Plus de liens';
L10n::$locales['all links'] = 'tous les liens';
L10n::$locales['view links of this category'] = 'voir les liens de cette catégorie';

View file

@ -1,23 +1,41 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: cinecturlink2 0.9.1\n" "Project-Id-Version: cinecturlink2 2.0\n"
"POT-Creation-Date: \n" "POT-Creation-Date: \n"
"PO-Revision-Date: 2021-11-02T22:51:46+00:00\n" "PO-Revision-Date: 2023-08-24T11:53:59+00:00\n"
"Last-Translator: Jean-Christian Denis\n" "Last-Translator: Jean-Christain Denis\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "My cinecturlink" msgid "previous links"
msgstr "Mes cinecturlink" msgstr "liens précédents"
msgid "next links"
msgstr "liens suivants"
msgid "view all links"
msgstr "voir tous les liens"
msgid "Category's entries feed"
msgstr "Fil de cette catégorie"
msgid "link"
msgstr "lien"
msgid "Rating" msgid "Rating"
msgstr "Évaluation" msgstr "Évaluation"
msgid "You must provide a specific folder for images." msgid "Links per page"
msgstr "Vous devez fournir un dossier spécifique pour les images." msgstr "Liens par page"
msgid "General"
msgstr "Général"
msgid "Enable plugin"
msgstr "Activer le plugin"
msgid "Public folder of images (under public folder of blog):" msgid "Public folder of images (under public folder of blog):"
msgstr "Dossier publique des images (dans le répertoire \"public\" du blog) :" msgstr "Dossier publique des images (dans le répertoire \"public\" du blog) :"
@ -52,23 +70,194 @@ msgstr "Description de la page publique :"
msgid "Limit number of entries per page on pulic page to:" msgid "Limit number of entries per page on pulic page to:"
msgstr "Limiter le nombre d'entrée par page sur la page public à :" msgstr "Limiter le nombre d'entrée par page sur la page public à :"
msgid "Informations" msgid "You must provide a specific folder for images."
msgstr "Informations" msgstr "Vous devez fournir un dossier spécifique pour les images."
msgid "Once the extension has been configured and your links have been created, you can place one of the cinecturlink widgets in the sidebar." msgid "links"
msgstr "Une fois l'extension configurée et vos liens créés, vous pouvez placer un des widgets cinecturlink dans la barre latérale." msgstr "liens"
msgid "In order to open links in new window you can use plugin %s." msgid "Back to links list"
msgstr "Afin d'ouvrir les liens dans une nouvelle page vous pouvez utiliser l'extension %s." msgstr "Retour à la liste des liens"
msgid "In order to change URL of public page you can use plugin %s." msgid "Links actions"
msgstr "Afin de changer l'URL de la page publique vous pouvez utiliser l'extension %s." msgstr "Actions sur les liens"
msgid "You can add public pages of cinecturlink to the plugin %s." msgid "Change rating"
msgstr "Vous pouvez ajouter les pages publiques de cinecturlink à l'extension %s." msgstr "Changer l'évaluation"
msgid "The plugin Cinecturlink2 is compatible with plugin %s." msgid "No links selected"
msgstr "L'extension Cinecturlink2 est compatible avec l'extension %s." msgstr "Aucun lien sélectionné"
msgid "Category of %s link successfully changed."
msgid_plural "Category of %s links successfully changed."
msgstr[0] "Catégorie du lien changée"
msgstr[1] "Catégorie des %s liens changée"
msgid "Note of %s link successfully changed."
msgid_plural "Note of %s links successfully changed."
msgstr[0] "Note du lien changée"
msgstr[1] "Note des %s liens changée"
msgid "Change note for this selection"
msgstr "Changer la note pour la séletion"
msgid "Note:"
msgstr "Note :"
msgid "No link matches the filter"
msgstr "Aucun lien pour ce filtre"
msgid "No link"
msgstr "Aucun lien"
msgid "List of %s links matching the filter."
msgstr "Liste des %s liens correspondant au filtre."
msgid "List of links. (%s)"
msgstr "Liste des liens. (%s)"
msgid "My cinecturlink"
msgstr "Mes cinecturlink"
msgid "Category with same name already exists."
msgstr "Une catégorie portant le même nom existe déjà."
msgid "Category successfully created."
msgstr "Catégory créée."
msgid "Category successfully updated."
msgstr "Catégorie mise à jour."
msgid "Category successfully deleted."
msgstr "Catégorie effacé."
msgid "No link uses this category."
msgstr "Aucun lien n'utilise cette catégorie."
msgid "A link uses this category."
msgid_plural "%s links use this category."
msgstr[0] "Un lien utilise cette catégorie."
msgstr[1] "%s liens utilisent cette catégorie."
msgid "Categories successfully reordered."
msgstr "Catégories réordonnées."
msgid "Categories successfully deleted."
msgstr "Catégories effacées."
msgid "New Link"
msgstr "Nouveau lien"
msgid "There is no category"
msgstr "Il n'y a pas de catégorie"
msgid "Categories list"
msgstr "Liste des catégories"
msgid "Check to delete"
msgstr "Cocher pour supprimer"
msgid "You must provide a title."
msgstr "Vous devez fournir un titre."
msgid "You must provide an author."
msgstr "Vous devez spécifier un auteur"
msgid "You must provide a link to an image."
msgstr "Vous devez fournir un lien vers une image."
msgid "Link with same name already exists."
msgstr "Un lien avec le même titre existe déjà."
msgid "Link successfully created."
msgstr "Lien crée."
msgid "Unknown link."
msgstr "Lien inconnu."
msgid "Link successfully updated."
msgstr "Lien mis à jour."
msgid "Link successfully deleted."
msgstr "Lien effacé."
msgid "New link"
msgstr "Nouveau lien"
msgid "Details URL:"
msgstr "Liens vers les détails :"
msgid "Search with Google"
msgstr "Rechercher avec Google"
msgid "Image URL:"
msgstr "Lien vers l'image :"
msgid "Search with Amazon"
msgstr "Rechercher avec Amazon"
msgid "There is no image in cinecturlink media path."
msgstr "Il n'y a pas d'image dans le chemin des média cinecturlink."
msgid "or select from repository:"
msgstr "ou selectionner depuis le dépôt :"
msgid "Go to media manager to add image to cinecturlink path."
msgstr "Aller dans le gestionnaire de média pour ajouter des images au chemin des cinecturlink."
msgid "Rating:"
msgstr "Évaluation :"
msgid "Manage links"
msgstr "Gérer les liens"
msgid "Edit categories"
msgstr "Gérer les catégories"
msgid "Selected links action:"
msgstr "Action sur les liens selectionnés :"
msgid "Plugin cinecturlink2"
msgstr "Extension cinecturlink 2"
msgid "link creation"
msgstr "Création de lien"
msgid "A new cineturlink named \"%s\" was added by \"%s\""
msgstr "Un nouveau cinecturlink nommé \"%s\" a été ajouté par \"%s\""
msgid "updating link"
msgstr "Mise à jour de lien"
msgid "Cinecturlink named \"%s\" has been updated by \"%s\""
msgstr "Le cinecturlink nommé \"%s\" a été mis à jour par \"%s\""
msgid "link deletion"
msgstr "Suppression de lien"
msgid "Cinecturlink named \"%s\" has been deleted by \"%s\""
msgstr "Le cinecturlink nommé \"%s\" a été effacé par \"%s\""
msgid "No link title"
msgstr "Pas de titre de lien"
msgid "No link description"
msgstr "Pas de description de lien"
msgid "No such link ID"
msgstr "ID de lien inconnu"
msgid "No category title"
msgstr "Pas de titre de catégorie"
msgid "No category description"
msgstr "Pas de description de catégorie"
msgid "No such category ID"
msgstr "ID de catégorie inconnu"
msgid "Failed to create public folder for images."
msgstr "Impossible de créer le repertoire publique pour les images."
msgid "Update date" msgid "Update date"
msgstr "Date de mise à jour" msgstr "Date de mise à jour"
@ -115,9 +304,6 @@ msgstr "Mes cinecturlink par catégories"
msgid "Show number of links" msgid "Show number of links"
msgstr "Afficher le nombre de liens" msgstr "Afficher le nombre de liens"
msgid "view all links"
msgstr "voir tous les liens"
msgid "More links" msgid "More links"
msgstr "Plus de liens" msgstr "Plus de liens"
@ -127,212 +313,3 @@ msgstr "tous les liens"
msgid "view links of this category" msgid "view links of this category"
msgstr "voir les liens de cette catégorie" msgstr "voir les liens de cette catégorie"
msgid "previous links"
msgstr "liens précédents"
msgid "next links"
msgstr "liens suivants"
msgid "These entries Atom feed"
msgstr "Fil atom de ces billets"
msgid "Category's entries feed"
msgstr "Fil de cette catégorie"
msgid "link"
msgstr "lien"
msgid "category"
msgstr "catégorie"
msgid "No link title"
msgstr "Pas de titre de lien"
msgid "No link description"
msgstr "Pas de description de lien"
msgid "No such link ID"
msgstr "ID de lien inconnu"
msgid "No category title"
msgstr "Pas de titre de catégorie"
msgid "No category description"
msgstr "Pas de description de catégorie"
msgid "No such category ID"
msgstr "ID de catégorie inconnu"
msgid "Failed to create public folder for images."
msgstr "Impossible de créer le repertoire publique pour les images."
msgid "Plugin cinecturlink2"
msgstr "Extension cinecturlink 2"
msgid "link creation"
msgstr "Création de lien"
msgid "A new cineturlink named \"%s\" was added by \"%s\""
msgstr "Un nouveau cinecturlink nommé \"%s\" a été ajouté par \"%s\""
msgid "updating link"
msgstr "Mise à jour de lien"
msgid "Cinecturlink named \"%s\" has been updated by \"%s\""
msgstr "Le cinecturlink nommé \"%s\" a été mis à jour par \"%s\""
msgid "link deletion"
msgstr "Suppression de lien"
msgid "Cinecturlink named \"%s\" has been deleted by \"%s\""
msgstr "Le cinecturlink nommé \"%s\" a été effacé par \"%s\""
msgid "No link matches the filter"
msgstr "Aucun lien pour ce filtre"
msgid "No link"
msgstr "Aucun lien"
msgid "List of %s links matching the filter."
msgstr "Liste des %s liens correspondant au filtre."
msgid "List of links (%s)"
msgstr "Listes des liens (%s)"
msgid "image"
msgstr "image"
msgid "Links successfully deleted."
msgstr "Liens effacés."
msgid "Delete links"
msgstr "Effacer des liens"
msgid "Links successfully updated."
msgstr "Liens mis à jour."
msgid "Update links rating"
msgstr "Changer l'évaluation"
msgid "Update links category"
msgstr "Changer la catégorie"
msgid "Change rating"
msgstr "Changer l'évaluation"
msgid "You must provide a title."
msgstr "Vous devez fournir un titre."
msgid "You must provide an author."
msgstr "Vous devez spécifier un auteur"
msgid "You must provide a link to an image."
msgstr "Vous devez fournir un lien vers une image."
msgid "Link with same name already exists."
msgstr "Un lien avec le même titre existe déjà."
msgid "Link successfully created."
msgstr "Lien crée."
msgid "Unknown link."
msgstr "Lien inconnu."
msgid "Link successfully updated."
msgstr "Lien mis à jour."
msgid "Link successfully deleted."
msgstr "Lien effacé."
msgid "New link"
msgstr "Nouveau lien"
msgid "Categories successfully reordered."
msgstr "Catégories réordonnées."
msgid "Categories successfully deleted."
msgstr "Catégories effacées."
msgid "Category with same name already exists."
msgstr "Une catégorie portant le même nom existe déjà."
msgid "Category successfully created."
msgstr "Catégory créée."
msgid "Category successfully updated."
msgstr "Catégorie mise à jour."
msgid "Category successfully deleted."
msgstr "Catégorie effacé."
msgid "There is no link"
msgstr "Il n'y a pas de lien"
msgid "New rating:"
msgstr "Nouvelle évaluation :"
msgid "New category:"
msgstr "Nouvelle catégorie :"
msgid "Edit categories"
msgstr "Gérer les catégories"
msgid "New Link"
msgstr "Nouveau lien"
msgid "New Category"
msgstr "Nouvelle catégorie"
msgid "Selected links action:"
msgstr "Action sur les liens selectionnés :"
msgid "Details URL:"
msgstr "Liens vers les détails :"
msgid "Search with Google"
msgstr "Rechercher avec Google"
msgid "Image URL:"
msgstr "Lien vers l'image :"
msgid "Search with Amazon"
msgstr "Rechercher avec Amazon"
msgid "There is no image in cinecturlink media path."
msgstr "Il n'y a pas d'image dans le chemin des média cinecturlink."
msgid "or select from repository:"
msgstr "ou selectionner depuis le dépôt :"
msgid "Go to media manager to add image to cinecturlink path."
msgstr "Aller dans le gestionnaire de média pour ajouter des images au chemin des cinecturlink."
msgid "Rating:"
msgstr "Évaluation :"
msgid "There is no category"
msgstr "Il n'y a pas de catégorie"
msgid "Categories list"
msgstr "Liste des catégories"
msgid "name"
msgstr "nom"
msgid "description"
msgstr "description"
msgid "Check to delete"
msgstr "Cocher pour supprimer"
msgid "Delete selection"
msgstr "Effacer la selection"
msgid "No link uses this category."
msgstr "Aucun lien n'utilise cette catégorie."
msgid "A link uses this category."
msgid_plural "%s links use this category."
msgstr[0] "Un lien utilise cette catégorie."
msgstr[1] "%s liens utilisent cette catégorie."

View file

@ -10,73 +10,235 @@
* @copyright Jean-Christian Denis * @copyright 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_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
}
require_once __DIR__ . '/_widgets.php'; namespace Dotclear\Plugin\cinecturlink2;
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem( use ArrayObject;
__('My cinecturlink'), use dcCore;
cinecturlink2AdminUrl(), use dcSettings;
cinecturlink2AdminIcon(), use Dotclear\Core\Backend\Favorites;
preg_match('/' . preg_quote(cinecturlink2AdminUrl()) . '(&.*)?$/', $_SERVER['REQUEST_URI']), use Dotclear\Core\Process;
dcCore::app()->auth->check(cinecturlink2AdminPerm(), dcCore::app()->blog->id) use Dotclear\Helper\Html\Form\{
); Checkbox,
Div,
Input,
Label,
Note,
Number,
Para,
Select,
Text
};
use Dotclear\Helper\File\Files;
dcCore::app()->addBehavior('adminColumnsListsV2', function (ArrayObject $cols) { class Backend extends Process
$cols['c2link'] = [
__('Cinecturlink'),
[
'date' => [true, __('Date')],
'cat' => [true, __('Category')],
'author' => [true, __('Author')],
'desc' => [false, __('Description')],
'link' => [true, __('Liens')],
'note' => [true, __('Rating')],
],
];
});
dcCore::app()->addBehavior('adminFiltersListsV2', function (ArrayObject $sorts) {
$sorts['c2link'] = [
__('Cinecturlink'),
[
__('Date') => 'link_upddt',
__('Title') => 'link_title',
__('Category') => 'cat_id',
__('Author') => 'link_author',
__('Description') => 'link_desc',
__('Link') => 'link_url',
__('Rating') => 'link_note',
],
'link_upddt',
'desc',
[__('Links per page'), 30],
];
});
dcCore::app()->addBehavior('adminDashboardFavoritesV2', function (dcFavorites $favs) {
$favs->register('cinecturlink2', [
'title' => __('My cinecturlink'),
'url' => cinecturlink2AdminUrl() . '#links',
'small-icon' => cinecturlink2AdminIcon(),
'large-icon' => cinecturlink2AdminIcon(),
'permissions' => cinecturlink2AdminPerm(),
]);
});
function cinecturlink2AdminUrl(): string
{ {
return dcCore::app()->adminurl->get('admin.plugin.cinecturlink2'); public static function init(): bool
} {
return self::status(My::checkContext(My::BACKEND));
}
function cinecturlink2AdminIcon(): string public static function process(): bool
{ {
return urldecode(dcPage::getPF('cinecturlink2/icon.svg')); if (!self::status()) {
} return false;
}
function cinecturlink2AdminPerm(): string My::addBackendMenuItem();
{
return dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_CONTENT_ADMIN]); dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initLinks']);
dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initCats']);
dcCore::app()->addBehaviors([
'adminColumnsListsV2' => function (ArrayObject $cols) {
$cols[My::id()] = [
My::name(),
[
'date' => [true, __('Date')],
'cat' => [true, __('Category')],
'author' => [true, __('Author')],
'desc' => [false, __('Description')],
'link' => [true, __('Links')],
'note' => [true, __('Rating')],
],
];
},
'adminFiltersListsV2' => function (ArrayObject $sorts) {
$sorts[My::id()] = [
My::name(),
[
__('Date') => 'link_upddt',
__('Title') => 'link_title',
__('Category') => 'cat_id',
__('Author') => 'link_author',
__('Description') => 'link_desc',
__('Link') => 'link_url',
__('Rating') => 'link_note',
],
'link_upddt',
'desc',
[__('Links per page'), 30],
];
},
'adminDashboardFavoritesV2' => function (Favorites $favs) {
$favs->register(My::id(), [
'title' => My::name(),
'url' => My::manageUrl() . '#links',
'small-icon' => My::icons(),
'large-icon' => My::icons(),
'permissions' => dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_CONTENT_ADMIN]),
]);
},
'adminBlogPreferencesFormV2' => function (dcSettings $blog_settings): void {
$s = $blog_settings->get(My::id());
$url = (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase(My::id());
$public_nbrpp = (int) $s->get('public_nbrpp');
if ($public_nbrpp < 1) {
$public_nbrpp = 10;
}
echo (new Div())
->class('fieldset')
->items([
(new Text('h4', My::name()))
->id(My::id() . '_params'),
(new Text('h5', __('General'))),
(new Para())
->items([
(new Checkbox(My::id() . 'active', (bool) $s->get('avtive')))
->value(1),
(new Label(__('Enable plugin'), Label::OUTSIDE_LABEL_AFTER))
->class('classic')
->for(My::id() . 'active'),
]),
(new Para())
->items([
(new Label(__('Public folder of images (under public folder of blog):'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'folder'),
(new Select(My::id() . 'folder'))
->items(Utils::getPublicDirs())
->default((string) $s->get('folder')),
]),
(new Para())
->items([
(new Label(__('Or create a new public folder of images:'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'newdir'),
(new Input(My::id() . 'newdir'))
->size(65)
->maxlenght(255)
->value(''),
]),
(new Para())
->items([
(new Label(__('Maximum width of images (in pixel):'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'widthmax')
->class('classic'),
(new Number(My::id() . 'widthmax'))
->min(10)
->max(512)
->value((string) abs((int) $s->get('widthmax'))),
]),
(new Text('hr')),
(new Text('h5', __('Widget'))),
(new Para())
->items([
(new Checkbox(My::id() . 'triggeronrandom', (bool) $s->get('triggeronrandom')))
->value(1),
(new Label(__('Update cache when use "Random" or "Number of view" order on widget (Need reload of widgets on change)'), Label::OUTSIDE_LABEL_AFTER))
->class('classic')
->for(My::id() . 'triggeronrandom'),
]),
(new Note())
->text(__('This increases the random effect, but updates the cache of the blog whenever the widget is displayed, which reduces the perfomances of your blog.'))
->class('form-note'),
(new Text('hr')),
(new Text('h5', __('Public page'))),
(new Para())
->items([
(new Checkbox(My::id() . 'public_active', (bool) $s->get('public_active')))
->value(1),
(new Label(__('Enable public page'), Label::OUTSIDE_LABEL_AFTER))
->class('classic')
->for(My::id() . 'public_active'),
]),
(new Note())
->text(sprintf(__('Public page has url: %s'), '<a href="' . $url . '" title="public page">' . $url . '</a>'))
->class('form-note'),
(new Para())
->items([
(new Label(__('Title of the public page:'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'public_title'),
(new Input(My::id() . 'public_title'))
->size(65)
->maxlenght(255)
->value((string) $s->get('public_title')),
]),
(new Para())
->items([
(new Label(__('Description of the public page:'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'public_description'),
(new Input(My::id() . 'public_description'))
->size(65)
->maxlenght(255)
->value((string) $s->get('public_description')),
]),
(new Para())
->items([
(new Label(__('Limit number of entries per page on pulic page to:'), Label::OUTSIDE_LABEL_BEFORE))
->for(My::id() . 'public_nbrpp')
->class('classic'),
(new Number(My::id() . 'public_nbrpp'))
->min(1)
->max(256)
->value($public_nbrpp),
]),
])
->render();
},
'adminBeforeBlogSettingsUpdate' => function (dcSettings $blog_settings): void {
$s = $blog_settings->get(My::id());
$active = !empty($_POST[My::id() . 'active']);
$widthmax = abs((int) $_POST[My::id() . 'widthmax']);
$newdir = (string) Files::tidyFileName($_POST[My::id() . 'newdir']);
$folder = empty($newdir) ? (string) Files::tidyFileName($_POST[My::id() . 'folder']) : $newdir;
$triggeronrandom = !empty($_POST[My::id() . 'triggeronrandom']);
$public_active = !empty($_POST[My::id() . 'public_active']);
$public_title = (string) $_POST[My::id() . 'public_title'];
$public_description = (string) $_POST[My::id() . 'public_description'];
$public_nbrpp = (int) $_POST[My::id() . 'public_nbrpp'];
if ($public_nbrpp < 1) {
$public_nbrpp = 10;
}
if (empty($folder)) {
dcCore::app()->error->add(__('You must provide a specific folder for images.'));
return;
}
Utils::makePublicDir(
DC_ROOT . '/' . dcCore::app()->blog?->settings->get('system')->get('public_path'),
$folder,
true
);
$s->put('avtive', $active);
$s->put('public_active', $public_active);
$s->put('public_title', $public_title);
$s->put('public_description', $public_description);
$s->put('public_nbrpp', $public_nbrpp);
$s->put('widthmax', $widthmax);
$s->put('folder', $folder);
$s->put('triggeronrandom', $triggeronrandom);
},
]);
return true;
}
} }

105
src/BackendActionsLinks.php Normal file
View file

@ -0,0 +1,105 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use ArrayObject;
use dcCore;
use Dotclear\Core\Backend\Action\Actions;
use Dotclear\Core\Backend\Page;
use Dotclear\Database\MetaRecord;
use Dotclear\Helper\Html\Form\{
Link,
Para
};
use Exception;
class BackendActionsLinks extends Actions
{
protected $use_render = true;
public Utils $utils;
public function __construct(string $uri, array $redirect_args = [])
{
$this->utils = new Utils();
parent::__construct($uri, $redirect_args);
$this->redirect_fields = [
'sortby', 'order', 'page', 'nb',
];
$this->field_entries = 'entries';
$this->caller_title = __('links');
$this->loadDefaults();
}
protected function loadDefaults(): void
{
BackendActionsLinksDefault::addDefaultLinksActions($this);
# --BEHAVIOR-- cinecturlink2AddDefaultLinksActions - BackendActionsLinks
dcCore::app()->callBehavior('cinecturlink2AddDefaultLinksActions', $this);
}
public function beginPage(string $breadcrumb = '', string $head = ''): void
{
Page::openModule(
My::name(),
$head
);
echo
$breadcrumb .
(new Para())->items([
(new Link())
->class('back')
->href($this->getRedirection(true))
->text(__('Back to links list')),
])->render();
}
public function endPage(): void
{
Page::closeModule();
}
public function error(Exception $e): void
{
dcCore::app()->error->add($e->getMessage());
$this->beginPage(
Page::breadcrumb([
__('Plugins') => '',
$this->getCallerTitle() => $this->getRedirection(true),
__('Links actions') => '',
])
);
$this->endPage();
}
protected function fetchEntries(ArrayObject $from): void
{
if (!empty($from['entries']) && is_array($from['entries'])) {
$params = [
'link_id' => $from['entries'],
];
$rs = $this->utils->getLinks($params);
while ($rs->fetch()) {
$this->entries[$rs->f('link_id')] = $rs->f('link_title');
}
$this->rs = $rs;
} else {
$this->rs = MetaRecord::newFromArray([]);
}
}
}

View file

@ -0,0 +1,203 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use ArrayObject;
use dcCore;
use Dotclear\Core\Backend\{
Notices,
Page
};
use Dotclear\Helper\Html\Form\{
Form,
Hidden,
Label,
Para,
Select,
Submit,
Text
};
use Exception;
class BackendActionsLinksDefault
{
public static function addDefaultLinksActions(BackendActionsLinks $ap): void
{
$ap->addAction(
[__('Delete') => 'dellinks'],
[self::class, 'doDeleteLinks']
);
$ap->addAction(
[__('Change rating') => 'updlinksnote'],
[self::class, 'doChangeNote']
);
$ap->addAction(
[__('Change category') => 'updlinkscat'],
[self::class, 'doChangeCategory']
);
}
public static function doDeleteLinks(BackendActionsLinks $ap, ArrayObject $post): void
{
$ids = $ap->getIDs();
if (empty($ids)) {
$ap->error(new Exception(__('No links selected')));
return;
}
foreach ($ids as $id) {
$ap->utils->delLink($id);
}
Notices::addSuccessNotice(sprintf(
__(
'%d links has been successfully deleted.',
'%d links have been successfully deleted.',
count($ids)
),
count($ids)
));
$ap->redirect(true);
}
public static function doChangeCategory(BackendActionsLinks $ap, ArrayObject $post): void
{
if (isset($post['upd_cat_id'])) {
$ids = $ap->getIDs();
if (empty($ids)) {
$ap->error(new Exception(__('No links selected')));
return;
}
$cat_id = is_numeric($post['upd_cat_id']) ? abs((int) $post['upd_cat_id']) : null;
$cur = dcCore::app()->con->openCursor($ap->utils->table);
foreach ($ids as $id) {
$cur->clean();
$cur->setField('cat_id', $cat_id == 0 ? null : $cat_id);
$ap->utils->updLink($id, $cur);
}
Notices::addSuccessNotice(sprintf(
__('Category of %s link successfully changed.', 'Category of %s links successfully changed.', count($ids)),
count($ids)
));
$ap->redirect(true);
} else {
$ap->beginPage(
Page::breadcrumb([
__('Plugins') => '',
$ap->getCallerTitle() => $ap->getRedirection(true),
__('Change category for this selection') => '',
])
);
echo
(new Form('form-action'))
->method('post')
->action($ap->getURI())
->fields([
(new Text('', $ap->getCheckboxes())),
(new Para())
->items(array_merge(
$ap->hiddenFields(),
[
(new Label(__('Category:'), Label::OUTSIDE_LABEL_BEFORE))
->for('upd_cat_id'),
(new Select('upd_cat_id'))
->items(Combo::categoriesCombo()),
(new Submit('do-action'))
->value(__('Save')),
(new Hidden(['action'], 'updlinkscat')),
dcCore::app()->formNonce(false),
]
)),
])
->render();
$ap->endPage();
}
}
public static function doChangeNote(BackendActionsLinks $ap, ArrayObject $post): void
{
if (isset($post['upd_link_note'])) {
$ids = $ap->getIDs();
if (empty($ids)) {
$ap->error(new Exception(__('No links selected')));
return;
}
$link_note = is_numeric($post['upd_link_note']) ? abs((int) $post['upd_link_note']) : 10;
if ($link_note > 20) {
$link_note = 10;
}
$cur = dcCore::app()->con->openCursor($ap->utils->table);
foreach ($ids as $id) {
$cur->clean();
$cur->setField('link_note', $link_note);
$ap->utils->updLink($id, $cur);
}
Notices::addSuccessNotice(sprintf(
__('Note of %s link successfully changed.', 'Note of %s links successfully changed.', count($ids)),
count($ids)
));
$ap->redirect(true);
} else {
$ap->beginPage(
Page::breadcrumb([
__('Plugins') => '',
$ap->getCallerTitle() => $ap->getRedirection(true),
__('Change note for this selection') => '',
])
);
echo
(new Form('form-action'))
->method('post')
->action($ap->getURI())
->fields([
(new Text('', $ap->getCheckboxes())),
(new Para())
->items(array_merge(
$ap->hiddenFields(),
[
(new Label(__('Note:'), Label::OUTSIDE_LABEL_BEFORE))
->for('upd_link_note'),
(new Select('upd_link_note'))
->items(Combo::notesCombo()),
(new Submit('do-action'))
->value(__('Save')),
(new Hidden(['action'], 'updlinksnote')),
dcCore::app()->formNonce(false),
]
)),
])
->render();
$ap->endPage();
}
}
}

View file

@ -10,148 +10,166 @@
* @copyright Jean-Christian Denis * @copyright 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_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
}
class adminlistCinecturlink2 namespace Dotclear\Plugin\cinecturlink2;
use ArrayObject;
use dcCore;
use Dotclear\Core\Backend\Filter\Filters;
use Dotclear\Core\Backend\Listing\{
Listing,
Pager
};
use Dotclear\Helper\Date;
use Dotclear\Helper\Html\Form\{
Checkbox,
Div,
Link,
Note,
Para,
Text,
Table, Tbody, Th, Tr, Td, Caption
};
use Dotclear\Helper\Html\Html;
class BackendListingLinks extends Listing
{ {
public $redir = ''; private string $redir;
protected $rs; public function display(Filters $filter, string $enclose_block = '', string $redir = ''): void
protected $rs_count;
protected $html_prev;
protected $html_next;
public function __construct($rs, $rs_count)
{ {
$this->rs = &$rs;
$this->rs_count = $rs_count;
$this->html_prev = __('&#171; prev.');
$this->html_next = __('next &#187;');
}
public function userColumns($type, $cols)
{
$cols_user = @dcCore::app()->auth->user_prefs->interface->cols;
if (is_array($cols_user) || $cols_user instanceof ArrayObject) {
if (isset($cols_user[$type])) {
foreach ($cols_user[$type] as $cn => $cd) {
if (!$cd && isset($cols[$cn])) {
unset($cols[$cn]);
}
}
}
}
}
public function display($page, $nb_per_page, $enclose_block = '', $filter = false, $redir = '')
{
$this->redir = $redir;
if ($this->rs->isEmpty()) { if ($this->rs->isEmpty()) {
if ($filter) { echo (new Note())
echo '<p><strong>' . __('No link matches the filter') . '</strong></p>'; ->class('info')
} else { ->text($filter->show() ? __('No link matches the filter') : __('No link'))
echo '<p><strong>' . __('No link') . '</strong></p>'; ->render();
}
} else {
$pager = new dcPager($page, $this->rs_count, $nb_per_page, 10);
$links = [];
if (isset($_REQUEST['links'])) {
foreach ($_REQUEST['links'] as $v) {
$links[(int) $v] = true;
}
}
$cols = [ return;
'title' => '<th colspan="2" class="first">' . __('Title') . '</th>',
'author' => '<th scope="col">' . __('Author') . '</th>',
'desc' => '<th scope="col">' . __('Description') . '</th>',
'link' => '<th scope="col">' . __('Links') . '</th>',
'cat' => '<th scope="col">' . __('Category') . '</th>',
'note' => '<th scope="col">' . __('Rating') . '</th>',
'date' => '<th scope="col">' . __('Date') . '</th>',
];
$cols = new ArrayObject($cols);
$this->userColumns('c2link', $cols);
$html_block = '<div class="table-outer">' .
'<table>' .
'<caption>' . (
$filter ?
sprintf(__('List of %s links matching the filter.'), $this->rs_count) :
sprintf(__('List of links (%s)'), $this->rs_count)
) . '</caption>' .
'<thead>' .
'<tr>' . implode(iterator_to_array($cols)) . '</tr>' .
'</thead>' .
'<tbody>%s</tbody>' .
'</table>' .
'%s</div>';
$enclose_blocks = explode('%s', $enclose_block);
$blocks = explode('%s', $html_block);
echo $pager->getLinks() . $enclose_blocks[0] . $blocks[0];
while ($this->rs->fetch()) {
echo $this->linkLine(isset($links[$this->rs->link_id]));
}
echo $blocks[1] . $blocks[2] . $enclose_blocks[1] . $pager->getLinks();
} }
$this->redir = $redir;
$links = [];
if (isset($_REQUEST['entries'])) {
foreach ($_REQUEST['entries'] as $v) {
$links[(int) $v] = true;
}
}
$pager = new Pager((int) $filter->value('page'), $this->rs_count, (int) $filter->value('nb'), 10);
$cols = new ArrayObject([
'title' => (new Th())
->text(__('Title'))
->class('first')
->colspan(2),
'author' => (new Th())
->text(__('Author'))
->scope('col'),
'desc' => (new Th())
->text(__('Description'))
->scope('col'),
'link' => (new Th())
->text(__('Link'))
->scope('col'),
'cat' => (new Th())
->text(__('Category'))
->scope('col'),
'note' => (new Th())
->text(__('Rating'))
->scope('col'),
'date' => (new Th())
->text(__('Date'))
->scope('col'),
]);
$this->userColumns(My::id(), $cols);
$lines = [];
while ($this->rs->fetch()) {
$lines[] = $this->linkLine(isset($links[$this->rs->link_id]));
}
echo
$pager->getLinks() .
sprintf(
$enclose_block,
(new Div())
->class('table-outer')
->items([
(new Table())
->items([
(new Caption(
$filter->show() ?
sprintf(__('List of %s links matching the filter.'), $this->rs_count) :
sprintf(__('List of links. (%s)'), $this->rs_count)
)),
(new Tr())
->items(iterator_to_array($cols)),
(new Tbody())
->items($lines),
]),
])
->render()
) .
$pager->getLinks();
} }
private function linkLine($checked) private function linkLine(bool $checked): Para
{ {
$cols = [ $cols = new ArrayObject([
'check' => '<td class="nowrap minimal">' . 'check' => (new Td())
form::checkbox(['entries[]'], $this->rs->link_id, ['checked' => $checked]) . ->class('nowrap minimal')
'</td>', ->items([
'title' => '<td class="nowrap" scope="row">' . (new Checkbox(['entries[]'], $checked))
'<a href="' . dcCore::app()->adminurl->get( ->value($this->rs->link_id),
'admin.plugin.cinecturlink2', ]),
['part' => 'link', 'linkid' => $this->rs->link_id, 'redir' => $this->redir] 'title' => (new Td())
) . '" title="' . __('Edit') . '">' . ->class('maximal')
html::escapeHTML($this->rs->link_title) . '</a>' . ->items([
'</td>', (new Link())
'author' => '<td class="nowrap">' . ->href(My::manageUrl(['part' => 'link', 'linkid' => $this->rs->link_id, 'redir' => $this->redir]))
html::escapeHTML($this->rs->link_author) . ->title(__('Edit'))
'</td>', ->text(Html::escapeHTML($this->rs->link_title)),
'desc' => '<td class="maximal">' . ]),
html::escapeHTML($this->rs->link_desc) . 'author' => (new Td())
'</td>', ->text(Html::escapeHTML($this->rs->link_author))
'link' => '<td class="nowrap">' . ->class('nowrap'),
'<a href="' . $this->rs->link_url . '" title="' . 'desc' => (new Td())
html::escapeHTML($this->rs->link_url) . ->text(Html::escapeHTML($this->rs->link_desc))
'">' . __('URL') . '</a> ' . ->class('nowrap'),
'<a href="' . $this->rs->link_img . '" title="' . 'link' => (new Text('td'))
html::escapeHTML($this->rs->link_img) . ->separator(' ')
'">' . __('image') . '</a> ' . ->items([
'</td>', (new Link())
'cat' => '<td class="nowrap minimal">' . ->href($this->rs->link_url)
'<a href="' . dcCore::app()->adminurl->get( ->title(__('URL'))
'admin.plugin.cinecturlink2', ->text(Html::escapeHTML($this->rs->link_title)),
['part' => 'cat', 'catid' => $this->rs->cat_id, 'redir' => $this->redir] (new Link())
) . '" title="' . __('Edit') . '">' . ->href($this->rs->link_img)
html::escapeHTML($this->rs->cat_title) . '</a>' . ->title(__('image'))
'</td>', ->text(Html::escapeHTML($this->rs->link_title)),
'note' => '</td>' . ]),
'<td class="nowrap count minimal">' . 'cat' => (new Td())
html::escapeHTML($this->rs->link_note) . '/20' . ->items([
'</td>', (new Link())
'date' => '<td class="nowrap count minimal">' . ->href(My::manageUrl(['part' => 'cat', 'catid' => $this->rs->cat_id, 'redir' => $this->redir]))
dt::dt2str( ->title(__('Edit'))
dcCore::app()->blog->settings->system->date_format . ', ' . dcCore::app()->blog->settings->system->time_format, ->text(Html::escapeHTML($this->rs->cat_title)),
$this->rs->link_upddt, ]),
dcCore::app()->auth->getInfo('user_tz') 'note' => (new Td())
) . ->text(Html::escapeHTML($this->rs->link_note))
'</td>', ->class('number'),
]; 'date' => (new Td())
->text(Html::escapeHTML(Date::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->link_upddt, (string) dcCore::app()->auth->getInfo('user_tz'))))
->class('nowrap'),
]);
$cols = new ArrayObject($cols); $this->userColumns(My::id(), $cols);
$this->userColumns('c2link', $cols);
return '<tr class="line">' . implode(iterator_to_array($cols)) . '</tr>' . "\n"; return
(new Para('p' . $this->rs->kut_id, 'tr'))
->class('line')
->items(iterator_to_array($cols));
} }
} }

87
src/Combo.php Normal file
View file

@ -0,0 +1,87 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use dcMedia;
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\L10n;
use Exception;
class Combo
{
/**
* @return array<string,string>
*/
public static function categoriesCombo(): array
{
$stack = ['-' => ''];
try {
$rs = (new Utils())->getCategories();
while ($rs->fetch()) {
$stack[Html::escapeHTML((string) $rs->f('cat_title'))] = $rs->f('cat_id');
}
} catch (Exception $e) {
}
return $stack;
}
/**
* @return array<string,string>
*/
public static function langsCombo(): array
{
return L10n::getISOcodes(true);
}
/**
* @return array<int,int>
*/
public static function notesCombo(): array
{
return range(0, 20);
}
/**
* @return array<string,string>
*/
public static function mediaCombo(): array
{
$stack = $tmp = [];
$dir = null;
try {
dcCore::app()->media = new dcMedia();
dcCore::app()->media->chdir(My::settings()->folder);
dcCore::app()->media->getDir();
$dir = & dcCore::app()->media->dir;
foreach ($dir['files'] as $file) {
if (!in_array($file->extension, My::ALLOWED_MEDIA_EXTENSION)) {
continue;
}
$tmp[$file->media_title] = $file->file_url;
}
if (!empty($tmp)) {
$stack = array_merge(['-' => ''], $tmp);
}
} catch (Exception $e) {
}
return $stack;
}
}

View file

@ -1,144 +0,0 @@
<?php
/**
* @brief cinecturlink2, 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
*/
if (!defined('DC_CONTEXT_MODULE')) {
return null;
}
# Check user perms
dcPage::check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]));
$redir = empty($_REQUEST['redir']) ?
dcCore::app()->admin->list->getURL() . '#plugins' : $_REQUEST['redir'];
dcCore::app()->blog->settings->addNamespace('cinecturlink2');
$s = dcCore::app()->blog->settings->cinecturlink2;
$cinecturlink2_active = (bool) $s->cinecturlink2_active;
$cinecturlink2_widthmax = abs((int) $s->cinecturlink2_widthmax);
$cinecturlink2_folder = (string) $s->cinecturlink2_folder;
$cinecturlink2_triggeronrandom = (bool) $s->cinecturlink2_triggeronrandom;
$cinecturlink2_public_active = (bool) $s->cinecturlink2_public_active;
$cinecturlink2_public_title = (string) $s->cinecturlink2_public_title;
$cinecturlink2_public_description = (string) $s->cinecturlink2_public_description;
$cinecturlink2_public_nbrpp = (int) $s->cinecturlink2_public_nbrpp;
if ($cinecturlink2_public_nbrpp < 1) {
$cinecturlink2_public_nbrpp = 10;
}
$combo_dirs = cinecturlink2::getPublicDirs();
if (!empty($_POST['save'])) {
try {
$cinecturlink2_active = !empty($_POST['cinecturlink2_active']);
$cinecturlink2_widthmax = abs((int) $_POST['cinecturlink2_widthmax']);
$cinecturlink2_newdir = (string) files::tidyFileName($_POST['cinecturlink2_newdir']);
$cinecturlink2_folder = empty($cinecturlink2_newdir) ?
(string) files::tidyFileName($_POST['cinecturlink2_folder']) :
$cinecturlink2_newdir;
$cinecturlink2_triggeronrandom = !empty($_POST['cinecturlink2_triggeronrandom']);
$cinecturlink2_public_active = !empty($_POST['cinecturlink2_public_active']);
$cinecturlink2_public_title = (string) $_POST['cinecturlink2_public_title'];
$cinecturlink2_public_description = (string) $_POST['cinecturlink2_public_description'];
$cinecturlink2_public_nbrpp = (int) $_POST['cinecturlink2_public_nbrpp'];
if ($cinecturlink2_public_nbrpp < 1) {
$cinecturlink2_public_nbrpp = 10;
}
if (empty($cinecturlink2_folder)) {
throw new Exception(__('You must provide a specific folder for images.'));
}
cinecturlink2::makePublicDir(
DC_ROOT . '/' . dcCore::app()->blog->settings->system->public_path,
$cinecturlink2_folder,
true
);
$s->put('cinecturlink2_active', $cinecturlink2_active);
$s->put('cinecturlink2_public_active', $cinecturlink2_public_active);
$s->put('cinecturlink2_public_title', $cinecturlink2_public_title);
$s->put('cinecturlink2_public_description', $cinecturlink2_public_description);
$s->put('cinecturlink2_public_nbrpp', $cinecturlink2_public_nbrpp);
$s->put('cinecturlink2_widthmax', $cinecturlink2_widthmax);
$s->put('cinecturlink2_folder', $cinecturlink2_folder);
$s->put('cinecturlink2_triggeronrandom', $cinecturlink2_triggeronrandom);
dcAdminNotices::addSuccessNotice(
__('Configuration successfully updated.')
);
dcCore::app()->adminurl->redirect(
'admin.plugins',
['module' => 'cinecturlink2', 'conf' => 1, 'redir' => dcCore::app()->admin->list->getRedir()]
);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
echo '
<div class="fieldset">
<h4>' . __('General') . '</h4>
<p><label class="classic" for="cinecturlink2_active">' .
form::checkbox('cinecturlink2_active', 1, $cinecturlink2_active) .
__('Enable plugin') . '</label></p>
<p><label for="cinecturlink2_folder">' . __('Public folder of images (under public folder of blog):') . '</label>' .
form::combo('cinecturlink2_folder', $combo_dirs, $cinecturlink2_folder) . '</p>
<p><label for="cinecturlink2_newdir">' . __('Or create a new public folder of images:') . '</label>' .
form::field('cinecturlink2_newdir', 60, 64, '', 'maximal') . '</p>
<p><label for="cinecturlink2_widthmax">' . __('Maximum width of images (in pixel):') . '</label>' .
form::number('cinecturlink2_widthmax', 10, 512, $cinecturlink2_widthmax) . '</p>
</div>
<div class="fieldset">
<h4>' . __('Widget') . '</h4>
<p><label class="classic" for="cinecturlink2_triggeronrandom">' .
form::checkbox('cinecturlink2_triggeronrandom', 1, $cinecturlink2_triggeronrandom) .
__('Update cache when use "Random" or "Number of view" order on widget (Need reload of widgets on change)') . '</label></p>
<p class="form-note">' . __('This increases the random effect, but updates the cache of the blog whenever the widget is displayed, which reduces the perfomances of your blog.') . '</p>
</div>
<div class="fieldset">
<h4>' . __('Public page') . '</h4>
<p><label class="classic" for="cinecturlink2_public_active">' .
form::checkbox('cinecturlink2_public_active', 1, $cinecturlink2_public_active) .
__('Enable public page') . '</label></p>
<p class="form-note">' . sprintf(__('Public page has url: %s'), '<a href="' . dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . '" title="public page">' . dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . '</a>') . '</p>
<p><label for="cinecturlink2_public_title">' . __('Title of the public page:') . '</label>' .
form::field('cinecturlink2_public_title', 60, 255, $cinecturlink2_public_title, 'maximal') . '</p>
<p><label for="cinecturlink2_public_description">' . __('Description of the public page:') . '</label>' .
form::field('cinecturlink2_public_description', 60, 255, $cinecturlink2_public_description, 'maximal') . '</p>
<p><label for="cinecturlink2_public_nbrpp">' . __('Limit number of entries per page on pulic page to:') . '</label>' .
form::number('cinecturlink2_public_nbrpp', 1, 100, $cinecturlink2_public_nbrpp) . '</p>
</div>
<div class="fieldset">
<h4>' . __('Informations') . '</h4>
<ul>
<li>' . __('Once the extension has been configured and your links have been created, you can place one of the cinecturlink widgets in the sidebar.') . '</li>
<li>' . sprintf(__('In order to open links in new window you can use plugin %s.'), '<a href="http://plugins.dotaddict.org/dc2/details/externalLinks">External Links</a>') . '</li>
<li>' . sprintf(__('In order to change URL of public page you can use plugin %s.'), '<a href="http://lab.dotclear.org/wiki/plugin/myUrlHandlers">My URL handlers</a>') . '</li>
<li>' . sprintf(__('You can add public pages of cinecturlink to the plugin %s.'), '<a href="http://plugins.dotaddict.org/dc2/details/sitemaps">sitemaps</a>') . '</li>
<li>' . sprintf(__('The plugin Cinecturlink2 is compatible with plugin %s.'), '<a href="http://plugins.dotaddict.org/dc2/details/rateIt">Rate it</a>') . '</li>
<li>' . sprintf(__('The plugin Cinecturlink2 is compatible with plugin %s.'), '<a href="http://plugins.dotaddict.org/dc2/details/activityReport">Activity report</a>') . '</li>
</ul>
</div>';

View file

@ -10,545 +10,100 @@
* @copyright Jean-Christian Denis * @copyright 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;
}
require_once __DIR__ . '/_widgets.php'; namespace Dotclear\Plugin\cinecturlink2;
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); use dcCore;
use Dotclear\Core\Process;
$c2_tpl_values = [ class Frontend extends Process
'c2PageFeedID',
'c2PageFeedURL',
'c2PageURL',
'c2PageTitle',
'c2PageDescription',
'c2EntryIfOdd',
'c2EntryIfFirst',
'c2EntryFeedID',
'c2EntryID',
'c2EntryTitle',
'c2EntryDescription',
'c2EntryFromAuthor',
'c2EntryAuthorCommonName',
'c2EntryAuthorDisplayName',
'c2EntryAuthorEmail',
'c2EntryAuthorID',
'c2EntryAuthorLink',
'c2EntryAuthorURL',
'c2EntryLang',
'c2EntryURL',
'c2EntryCategory',
'c2EntryCategoryID',
'c2EntryCategoryURL',
'c2EntryImg',
'c2EntryDate',
'c2EntryTime',
'c2PaginationCounter',
'c2PaginationCurrent',
'c2PaginationURL',
'c2CategoryFeedID',
'c2CategoryFeedURL',
'c2CategoryID',
'c2CategoryTitle',
'c2CategoryDescription',
'c2CategoryURL',
];
$c2_tpl_blocks = [
'c2If',
'c2Entries',
'c2EntriesHeader',
'c2EntriesFooter',
'c2EntryIf',
'c2Pagination',
'c2PaginationIf',
'c2Categories',
'c2CategoriesHeader',
'c2CategoriesFooter',
'c2CategoryIf',
];
if (dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_active) {
foreach ($c2_tpl_blocks as $v) {
dcCore::app()->tpl->addBlock($v, ['tplCinecturlink2', $v]);
}
foreach ($c2_tpl_values as $v) {
dcCore::app()->tpl->addValue($v, ['tplCinecturlink2', $v]);
}
} else {
foreach (array_merge($c2_tpl_blocks, $c2_tpl_values) as $v) {
dcCore::app()->tpl->addBlock($v, ['tplCinecturlink2', 'disable']);
}
}
class urlCinecturlink2 extends dcUrlHandlers
{ {
public static function c2Page($args) public static function init(): bool
{ {
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); return self::status(My::checkContext(My::FRONTEND));
$args = (string) $args;
if (!dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_active
|| !dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_active) {
self::p404();
return null;
}
dcCore::app()->tpl->setPath(
dcCore::app()->tpl->getPath(),
__DIR__ . '/default-templates/'
);
$params = [];
$n = self::getPageArgs($args, 'c2page');
if ($n) {
$GLOBALS['c2_page_number'] = $n;
}
$caturl = dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl;
if (!$caturl) {
$caturl = 'c2cat';
}
$c = self::getPageArgs($args, $caturl);
if ($c) {
if (is_numeric($c)) {
$params['cat_id'] = (int) $c;
} else {
$params['cat_title'] = urldecode($c);
}
}
$f = self::getPageArgs($args, 'feed');
if ($f && in_array($f, ['atom', 'rss2'])) {
$mime = $f == 'atom' ? 'application/atom+xml' : 'application/xml';
//dcCore::app()->ctx->short_feed_items = dcCore::app()->blog->settings->system->short_feed_items;
$params['limit'] = dcCore::app()->blog->settings->system->nb_post_per_feed;
dcCore::app()->ctx->c2_page_params = $params;
header('X-Robots-Tag: ' . context::robotsPolicy(dcCore::app()->blog->settings->system->robots_policy, ''));
self::serveDocument('cinecturlink2-' . $f . '.xml', $mime);
} else {
$d = self::getPageArgs($args, 'c2detail');
if ($d) {
if (is_numeric($d)) {
$params['link_id'] = (int) $d;
} else {
$params['link_title'] = urldecode($d);
}
}
$params['limit'] = dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_nbrpp;
dcCore::app()->ctx->c2_page_params = $params;
self::serveDocument('cinecturlink2.html', 'text/html');
}
return null;
} }
protected static function getPageArgs(&$args, $part) public static function process(): bool
{ {
if (preg_match('#(^|/)' . $part . '/([^/]+)#', $args, $m)) { if (!self::status()) {
$args = preg_replace('#(^|/)' . $part . '/([^/]+)#', '', $args); return false;
return $m[2];
} }
return false; dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initLinks']);
} dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initCats']);
}
$values = [
class tplCinecturlink2 'c2PageFeedID',
{ 'c2PageFeedURL',
public static function disable($a, $c = null) 'c2PageURL',
{ 'c2PageTitle',
return ''; 'c2PageDescription',
}
'c2EntryIfOdd',
public static function c2PageURL($a) 'c2EntryIfFirst',
{ 'c2EntryFeedID',
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase(\'cinecturlink2\')') . '; ?>'; 'c2EntryID',
} 'c2EntryTitle',
'c2EntryDescription',
public static function c2PageTitle($a) 'c2EntryFromAuthor',
{ 'c2EntryAuthorCommonName',
return "<?php \$title = (string) dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_title; if (empty(\$title)) { \$title = __('My cinecturlink'); } echo " . sprintf(dcCore::app()->tpl->getFilters($a), '$title') . '; ?>'; 'c2EntryAuthorDisplayName',
} 'c2EntryAuthorEmail',
'c2EntryAuthorID',
public static function c2PageFeedURL($a) 'c2EntryAuthorLink',
{ 'c2EntryAuthorURL',
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("cinecturlink2")."/feed/' . (!empty($a['type']) && preg_match('#^(rss2|atom)$#', $a['type']) ? $a['type'] : 'atom') . '"') . '; ?>'; 'c2EntryLang',
} 'c2EntryURL',
'c2EntryCategory',
public static function c2PageFeedID($a) 'c2EntryCategoryID',
{ 'c2EntryCategoryURL',
return 'urn:md5:<?php echo md5(dcCore::app()->blog->id."cinecturlink2"); ?>'; 'c2EntryImg',
} 'c2EntryDate',
'c2EntryTime',
public static function c2PageDescription($a)
{ 'c2PaginationCounter',
return '<?php $description = (string) dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_description; echo ' . sprintf(dcCore::app()->tpl->getFilters($a), '$description') . '; ?>'; 'c2PaginationCurrent',
} 'c2PaginationURL',
public static function c2If($a, $c) 'c2CategoryFeedID',
{ 'c2CategoryFeedURL',
$if = []; 'c2CategoryID',
'c2CategoryTitle',
$operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&'; 'c2CategoryDescription',
'c2CategoryURL',
if (isset($a['request_link'])) { ];
$sign = (bool) $a['request_link'] ? '' : '!';
$if[] = $sign . '(isset(dcCore::app()->ctx->c2_page_params["link_id"]) || isset(dcCore::app()->ctx->c2_page_params["link_title"]))'; $blocks = [
} 'c2If',
if (isset($a['request_cat'])) { 'c2Entries',
$sign = (bool) $a['request_cat'] ? '' : '!'; 'c2EntriesHeader',
$if[] = $sign . '(isset(dcCore::app()->ctx->c2_page_params["cat_id"]) || isset(dcCore::app()->ctx->c2_page_params["cat_title"]))'; 'c2EntriesFooter',
} 'c2EntryIf',
return empty($if) ? $c : '<?php if(' . implode(' ' . $operator . ' ', $if) . ") : ?>\n" . $c . "<?php endif; ?>\n"; 'c2Pagination',
} 'c2PaginationIf',
public static function c2Entries($a, $c) 'c2Categories',
{ 'c2CategoriesHeader',
$lastn = isset($a['lastn']) ? abs((int) $a['lastn']) + 0 : -1; 'c2CategoriesFooter',
'c2CategoryIf',
$res = 'if (!isset($c2_page_number)) { $c2_page_number = 1; }' . "\n"; ];
if ($lastn != 0) { if (My::settings()?->active) {
if ($lastn > 0) { foreach ($blocks as $v) {
$res .= "\$params['limit'] = " . $lastn . ";\n"; dcCore::app()->tpl->addBlock($v, [FrontendTemplate::class, $v]);
} else { }
$res .= "if (!isset(\$params['limit']) || \$params['limit'] < 1) { \$params['limit'] = 10; }\n"; foreach ($values as $v) {
} dcCore::app()->tpl->addValue($v, [FrontendTemplate::class, $v]);
if (!isset($a['ignore_pagination']) || $a['ignore_pagination'] == '0') { }
$res .= "\$params['limit'] = array(((\$c2_page_number-1)*\$params['limit']),\$params['limit']);\n"; } else {
} else { foreach (array_merge($blocks, $values) as $v) {
$res .= "\$params['limit'] = array(0, \$params['limit']);\n"; dcCore::app()->tpl->addBlock($v, [FrontendTemplate::class, 'disable']);
} }
} }
if (isset($a['category'])) { return true;
if ($a['category'] == 'null') {
$res .= "\$params['sql'] = ' AND L.cat_id IS NULL ';\n";
} elseif (is_numeric($a['category'])) {
$res .= "\$params['cat_id'] = " . (int) $a['category'] . ";\n";
} else {
$res .= "\$params['cat_title'] = '" . $a['category'] . "';\n";
}
}
$sort = isset($a['sort']) && $a['sort'] == 'asc' ? ' asc' : ' desc';
$sortby = isset($a['order']) && in_array($a['order'], ['link_count','link_upddt','link_creadt','link_note','link_title']) ? $a['order'] : 'link_upddt';
$res .= "\$params['order'] = '" . $sortby . $sort . "';\n";
return
"<?php \n" .
"\$params = is_array(dcCore::app()->ctx->c2_page_params) ? dcCore::app()->ctx->c2_page_params : array(); \n" .
$res .
"dcCore::app()->ctx->c2_params = \$params; unset(\$params);\n" .
"if (!dcCore::app()->ctx->exists('cinecturlink')) { dcCore::app()->ctx->cinecturlink = new cinecturlink2(); } \n" .
"dcCore::app()->ctx->c2_entries = dcCore::app()->ctx->cinecturlink->getLinks(dcCore::app()->ctx->c2_params); \n" .
'while (dcCore::app()->ctx->c2_entries->fetch()) : ?>' . $c . '<?php endwhile; ' . "\n" .
"dcCore::app()->ctx->pop('c2_entries'); dcCore::app()->ctx->pop('c2_params'); \n" .
"?>\n";
}
public static function c2EntriesHeader($a, $c)
{
return '<?php if (dcCore::app()->ctx->c2_entries->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2EntriesFooter($a, $c)
{
return '<?php if (dcCore::app()->ctx->c2_entries->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2EntryIf($a, $c)
{
$if = [];
$operator = isset($a['operator']) ? self::getOperator($a['operator']) : '&&';
if (isset($a['has_category'])) {
$sign = (bool) $a['has_category'] ? '!' : '=';
$if[] = '(dcCore::app()->ctx->exists("c2_entries") && "" ' . $sign . '= dcCore::app()->ctx->c2_entries->cat_title)';
}
return empty($if) ? $c : '<?php if(' . implode(' ' . $operator . ' ', $if) . ") : ?>\n" . $c . "<?php endif; ?>\n";
}
public static function c2EntryIfFirst($a)
{
return '<?php if (dcCore::app()->ctx->c2_entries->index() == 0) { echo "' . (isset($a['return']) ? addslashes(html::escapeHTML($a['return'])) : 'first') . '"; } ?>';
}
public static function c2EntryIfOdd($a)
{
return '<?php if ((dcCore::app()->ctx->c2_entries->index()+1)%2 == 1) { echo "' . (isset($a['return']) ? addslashes(html::escapeHTML($a['return'])) : 'odd') . '"; } ?>';
}
public static function c2EntryFeedID($a)
{
return 'urn:md5:<?php echo md5(dcCore::app()->ctx->c2_entries->blog_id.dcCore::app()->ctx->c2_entries->link_id.dcCore::app()->ctx->c2_entries->link_creadt); ?>';
}
public static function c2EntryID($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_id', $a);
}
public static function c2EntryTitle($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_title', $a);
}
public static function c2EntryDescription($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_desc', $a);
}
public static function c2EntryAuthorCommonName($a)
{
return self::getGenericValue('dcUtils::getUserCN(dcCore::app()->ctx->c2_entries->user_id,dcCore::app()->ctx->c2_entries->user_name,dcCore::app()->ctx->c2_entries->user_firstname,dcCore::app()->ctx->c2_entries->user_displayname)', $a);
}
public static function c2EntryAuthorDisplayName($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_displayname', $a);
}
public static function c2EntryAuthorID($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_id', $a);
}
public static function c2EntryAuthorEmail($a)
{
return self::getGenericValue((isset($a['spam_protected']) && !$a['spam_protected'] ? 'dcCore::app()->ctx->c2_entries->user_email' : "strtr(dcCore::app()->ctx->c2_entries->user_email,array('@'=>'%40','.'=>'%2e'))"), $a);
}
public static function c2EntryAuthorLink($a)
{
return self::getGenericValue('sprintf((dcCore::app()->ctx->c2_entries->user_url ? \'<a href="%2$s">%1$s</a>\' : \'%1$s\'),html::escapeHTML(dcUtils::getUserCN(dcCore::app()->ctx->c2_entries->user_id,dcCore::app()->ctx->c2_entries->user_name,dcCore::app()->ctx->c2_entries->user_firstname,dcCore::app()->ctx->c2_entries->user_displayname)),html::escapeHTML(dcCore::app()->ctx->c2_entries->user_url))', $a);
}
public static function c2EntryAuthorURL($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_url', $a);
}
public static function c2EntryFromAuthor($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_author', $a);
}
public static function c2EntryLang($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_lang', $a);
}
public static function c2EntryURL($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_url', $a);
}
public static function c2EntryCategory($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->cat_title', $a);
}
public static function c2EntryCategoryID($a)
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->cat_id', $a);
}
public static function c2EntryCategoryURL($a)
{
return self::getGenericValue('dcCore::app()->blog->url.dcCore::app()->url->getBase("cinecturlink2")."/".dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl."/".urlencode(dcCore::app()->ctx->c2_entries->cat_title)', $a);
}
public static function c2EntryImg($a)
{
$f = dcCore::app()->tpl->getFilters($a);
$style = isset($a['style']) ? html::escapeHTML($a['style']) : '';
return
"<?php if (dcCore::app()->ctx->exists('c2_entries')) { " .
'$widthmax = (integer) dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_widthmax; ' .
"\$img = sprintf('<img src=\"%s\" alt=\"%s\" %s/>'," .
'dcCore::app()->ctx->c2_entries->link_img, ' .
"html::escapeHTML(dcCore::app()->ctx->c2_entries->link_title.' - '.dcCore::app()->ctx->c2_entries->link_author), " .
"(\$widthmax ? ' style=\"width:'.\$widthmax.'px;$style\"' : '') " .
'); ' .
'echo ' . sprintf($f, '$img') . "; unset(\$img); } ?> \n";
}
public static function c2EntryDate($a)
{
$format = !empty($a['format']) ? addslashes($a['format']) : '';
if (!empty($a['rfc822'])) {
$p = 'dt::rfc822(strtotime(dcCore::app()->ctx->c2_entries->link_creadt), dcCore::app()->blog->settings->system->blog_timezone)';
} elseif (!empty($a['iso8601'])) {
$p = 'dt::iso8601(strtotime(dcCore::app()->ctx->c2_entries->link_creadt), dcCore::app()->blog->settings->system->blog_timezone)';
} elseif ($format) {
$p = "dt::dt2str('" . $format . "', dcCore::app()->ctx->c2_entries->link_creadt)";
} else {
$p = 'dt::dt2str(dcCore::app()->blog->settings->system->date_format, dcCore::app()->ctx->c2_entries->link_creadt)';
}
return self::getGenericValue($p, $a);
}
public static function c2EntryTime($a)
{
return self::getGenericValue('dt::dt2str(' . (!empty($a['format']) ? "'" . addslashes($a['format']) . "'" : 'dcCore::app()->blog->settings->system->time_format') . ', dcCore::app()->ctx->c2_entries->link_creadt)', $a);
}
public static function c2Pagination($a, $c)
{
$p = "<?php\n" .
"\$params = dcCore::app()->ctx->c2_params;\n" .
"dcCore::app()->ctx->c2_pagination = dcCore::app()->ctx->cinecturlink->getLinks(\$params,true); unset(\$params);\n" .
"?>\n";
return isset($a['no_context']) ? $p . $c : $p . '<?php if (dcCore::app()->ctx->c2_pagination->f(0) > dcCore::app()->ctx->c2_entries->count()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2PaginationCounter($a)
{
return self::getGenericValue('cinecturlink2Context::PaginationNbPages()', $a);
}
public static function c2PaginationCurrent($a)
{
return self::getGenericValue('cinecturlink2Context::PaginationPosition(' . (isset($a['offset']) ? (int) $a['offset'] : 0) . ')', $a);
}
public static function c2PaginationIf($a, $c)
{
$if = [];
if (isset($a['start'])) {
$sign = (bool) $a['start'] ? '' : '!';
$if[] = $sign . 'cinecturlink2Context::PaginationStart()';
}
if (isset($a['end'])) {
$sign = (bool) $a['end'] ? '' : '!';
$if[] = $sign . 'cinecturlink2Context::PaginationEnd()';
}
return empty($if) ? $c : '<?php if(' . implode(' && ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function c2PaginationURL($a)
{
return self::getGenericValue('cinecturlink2Context::PaginationURL(' . (isset($a['offset']) ? (int) $a['offset'] : 0) . ')', $a);
}
public static function c2Categories($a, $c)
{
return
"<?php \n" .
"if (!dcCore::app()->ctx->exists('cinecturlink')) { dcCore::app()->ctx->cinecturlink = new cinecturlink2(); } \n" .
"dcCore::app()->ctx->c2_categories = dcCore::app()->ctx->cinecturlink->getCategories(); \n" .
'while (dcCore::app()->ctx->c2_categories->fetch()) : ?>' . $c . '<?php endwhile; ' . "\n" .
"dcCore::app()->ctx->c2_categories = null; \n" .
"?>\n";
}
public static function c2CategoriesHeader($a, $c)
{
return '<?php if (dcCore::app()->ctx->c2_categories->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoriesFooter($a, $c)
{
return '<?php if (dcCore::app()->ctx->c2_categories->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoryIf($a, $c)
{
$if = [];
if (isset($a['current'])) {
$sign = (bool) $a['current'] ? '' : '!';
$if[] = $sign . 'cinecturlink2Context::CategoryCurrent()';
}
if (isset($a['first'])) {
$sign = (bool) $a['first'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->c2_categories->isStart()';
}
return empty($if) ? $c : '<?php if(' . implode(' && ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoryFeedURL($a)
{
$p = !empty($a['type']) ? $a['type'] : 'atom';
if (!preg_match('#^(rss2|atom)$#', $p)) {
$p = 'atom';
}
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("cinecturlink2")."/".dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl."/".urlencode(dcCore::app()->ctx->c2_categories->cat_title)."/feed/' . $p . '"') . '; ?>';
}
public static function c2CategoryFeedID($a)
{
return 'urn:md5:<?php echo md5(dcCore::app()->blog->id."cinecturlink2".dcCore::app()->ctx->c2_categories->cat_id); ?>';
}
public static function c2CategoryID($a)
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_id') . '; } ?>';
}
public static function c2CategoryTitle($a)
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_title') . '; } ?>';
}
public static function c2CategoryDescription($a)
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_desc') . '; } ?>';
}
public static function c2CategoryURL($a)
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("cinecturlink2")."/".dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl."/".urlencode(dcCore::app()->ctx->c2_categories->cat_title)') . '; } ?>';
}
protected static function getGenericValue($p, $a)
{
return "<?php if (dcCore::app()->ctx->exists('c2_entries')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), "$p") . '; } ?>';
}
protected static function getOperator($op)
{
switch (strtolower($op)) {
case 'or':
case '||':
return '||';
case 'and':
case '&&':
default:
return '&&';
}
} }
} }

View file

@ -10,7 +10,13 @@
* @copyright Jean-Christian Denis * @copyright 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
*/ */
class cinecturlink2Context declare(strict_types=1);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
class FrontendContext
{ {
public static function PaginationNbPages() public static function PaginationNbPages()
{ {

389
src/FrontendTemplate.php Normal file
View file

@ -0,0 +1,389 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use ArrayObject;
use dcCore;
use dcTemplate;
use Dotclear\Helper\Html\Html;
class FrontendTemplate
{
public static function disable(ArrayObject $a, ?string $c = null): string
{
return '';
}
public static function c2PageURL(ArrayObject $a): string
{
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase(\'cinecturlink2\')') . '; ?>';
}
public static function c2PageTitle(ArrayObject $a): string
{
return "<?php \$title = (string) dcCore::app()->blog->settings->cinecturlink2->public_title; if (empty(\$title)) { \$title = __('My cinecturlink'); } echo " . sprintf(dcCore::app()->tpl->getFilters($a), '$title') . '; ?>';
}
public static function c2PageFeedURL(ArrayObject $a): string
{
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("' . My::id() . '")."/feed/' . (!empty($a['type']) && preg_match('#^(rss2|atom)$#', $a['type']) ? $a['type'] : 'atom') . '"') . '; ?>';
}
public static function c2PageFeedID(ArrayObject $a): string
{
return 'urn:md5:<?php echo md5(dcCore::app()->blog->id."' . My::id() . '"); ?>';
}
public static function c2PageDescription(ArrayObject $a): string
{
return '<?php $description = (string) dcCore::app()->blog->settings->cinecturlink2->public_description; echo ' . sprintf(dcCore::app()->tpl->getFilters($a), '$description') . '; ?>';
}
public static function c2If(ArrayObject $a, string $c): string
{
$if = [];
$operator = isset($a['operator']) ? dcTemplate::getOperator($a['operator']) : '&&';
if (isset($a['request_link'])) {
$sign = (bool) $a['request_link'] ? '' : '!';
$if[] = $sign . '(isset(dcCore::app()->ctx->c2_page_params["link_id"]) || isset(dcCore::app()->ctx->c2_page_params["link_title"]))';
}
if (isset($a['request_cat'])) {
$sign = (bool) $a['request_cat'] ? '' : '!';
$if[] = $sign . '(isset(dcCore::app()->ctx->c2_page_params["cat_id"]) || isset(dcCore::app()->ctx->c2_page_params["cat_title"]))';
}
return empty($if) ? $c : '<?php if(' . implode(' ' . $operator . ' ', $if) . ") : ?>\n" . $c . "<?php endif; ?>\n";
}
public static function c2Entries(ArrayObject $a, string $c): string
{
$lastn = isset($a['lastn']) ? abs((int) $a['lastn']) + 0 : -1;
$res = 'if (!isset($c2_page_number)) { $c2_page_number = 1; }' . "\n";
if ($lastn != 0) {
if ($lastn > 0) {
$res .= "\$params['limit'] = " . $lastn . ";\n";
} else {
$res .= "if (!isset(\$params['limit']) || \$params['limit'] < 1) { \$params['limit'] = 10; }\n";
}
if (!isset($a['ignore_pagination']) || $a['ignore_pagination'] == '0') {
$res .= "\$params['limit'] = array(((\$c2_page_number-1)*\$params['limit']),\$params['limit']);\n";
} else {
$res .= "\$params['limit'] = array(0, \$params['limit']);\n";
}
}
if (isset($a['category'])) {
if ($a['category'] == 'null') {
$res .= "\$params['sql'] = ' AND L.cat_id IS NULL ';\n";
} elseif (is_numeric($a['category'])) {
$res .= "\$params['cat_id'] = " . (int) $a['category'] . ";\n";
} else {
$res .= "\$params['cat_title'] = '" . $a['category'] . "';\n";
}
}
$sort = isset($a['sort']) && $a['sort'] == 'asc' ? ' asc' : ' desc';
$sortby = isset($a['order']) && in_array($a['order'], ['link_count','link_upddt','link_creadt','link_note','link_title']) ? $a['order'] : 'link_upddt';
$res .= "\$params['order'] = '" . $sortby . $sort . "';\n";
return
"<?php \n" .
"\$params = is_array(dcCore::app()->ctx->c2_page_params) ? dcCore::app()->ctx->c2_page_params : array(); \n" .
$res .
"dcCore::app()->ctx->c2_params = \$params; unset(\$params);\n" .
"if (!dcCore::app()->ctx->exists('cinecturlink')) { dcCore::app()->ctx->cinecturlink = new " . Utils::class . "(); } \n" .
"dcCore::app()->ctx->c2_entries = dcCore::app()->ctx->cinecturlink->getLinks(dcCore::app()->ctx->c2_params); \n" .
'while (dcCore::app()->ctx->c2_entries->fetch()) : ?>' . $c . '<?php endwhile; ' . "\n" .
"dcCore::app()->ctx->pop('c2_entries'); dcCore::app()->ctx->pop('c2_params'); \n" .
"?>\n";
}
public static function c2EntriesHeader(ArrayObject $a, string $c): string
{
return '<?php if (dcCore::app()->ctx->c2_entries->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2EntriesFooter(ArrayObject $a, string $c): string
{
return '<?php if (dcCore::app()->ctx->c2_entries->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2EntryIf(ArrayObject $a, string $c): string
{
$if = [];
$operator = isset($a['operator']) ? dcTemplate::getOperator($a['operator']) : '&&';
if (isset($a['has_category'])) {
$sign = (bool) $a['has_category'] ? '!' : '=';
$if[] = '(dcCore::app()->ctx->exists("c2_entries") && "" ' . $sign . '= dcCore::app()->ctx->c2_entries->cat_title)';
}
return empty($if) ? $c : '<?php if(' . implode(' ' . $operator . ' ', $if) . ") : ?>\n" . $c . "<?php endif; ?>\n";
}
public static function c2EntryIfFirst(ArrayObject $a): string
{
return '<?php if (dcCore::app()->ctx->c2_entries->index() == 0) { echo "' . (isset($a['return']) ? addslashes(Html::escapeHTML($a['return'])) : 'first') . '"; } ?>';
}
public static function c2EntryIfOdd(ArrayObject $a): string
{
return '<?php if ((dcCore::app()->ctx->c2_entries->index()+1)%2 == 1) { echo "' . (isset($a['return']) ? addslashes(Html::escapeHTML($a['return'])) : 'odd') . '"; } ?>';
}
public static function c2EntryFeedID(ArrayObject $a): string
{
return 'urn:md5:<?php echo md5(dcCore::app()->ctx->c2_entries->blog_id.dcCore::app()->ctx->c2_entries->link_id.dcCore::app()->ctx->c2_entries->link_creadt); ?>';
}
public static function c2EntryID(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_id', $a);
}
public static function c2EntryTitle(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_title', $a);
}
public static function c2EntryDescription(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_desc', $a);
}
public static function c2EntryAuthorCommonName(ArrayObject $a): string
{
return self::getGenericValue('dcUtils::getUserCN(dcCore::app()->ctx->c2_entries->user_id,dcCore::app()->ctx->c2_entries->user_name,dcCore::app()->ctx->c2_entries->user_firstname,dcCore::app()->ctx->c2_entries->user_displayname)', $a);
}
public static function c2EntryAuthorDisplayName(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_displayname', $a);
}
public static function c2EntryAuthorID(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_id', $a);
}
public static function c2EntryAuthorEmail(ArrayObject $a): string
{
return self::getGenericValue((isset($a['spam_protected']) && !$a['spam_protected'] ? 'dcCore::app()->ctx->c2_entries->user_email' : "strtr(dcCore::app()->ctx->c2_entries->user_email,array('@'=>'%40','.'=>'%2e'))"), $a);
}
public static function c2EntryAuthorLink(ArrayObject $a): string
{
return self::getGenericValue('sprintf((dcCore::app()->ctx->c2_entries->user_url ? \'<a href="%2$s">%1$s</a>\' : \'%1$s\'),html::escapeHTML(dcUtils::getUserCN(dcCore::app()->ctx->c2_entries->user_id,dcCore::app()->ctx->c2_entries->user_name,dcCore::app()->ctx->c2_entries->user_firstname,dcCore::app()->ctx->c2_entries->user_displayname)),html::escapeHTML(dcCore::app()->ctx->c2_entries->user_url))', $a);
}
public static function c2EntryAuthorURL(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->user_url', $a);
}
public static function c2EntryFromAuthor(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_author', $a);
}
public static function c2EntryLang(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_lang', $a);
}
public static function c2EntryURL(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->link_url', $a);
}
public static function c2EntryCategory(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->cat_title', $a);
}
public static function c2EntryCategoryID(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->ctx->c2_entries->cat_id', $a);
}
public static function c2EntryCategoryURL(ArrayObject $a): string
{
return self::getGenericValue('dcCore::app()->blog->url.dcCore::app()->url->getBase("' . My::id() . '")."/".dcCore::app()->blog->settings->cinecturlink2->public_caturl."/".urlencode(dcCore::app()->ctx->c2_entries->cat_title)', $a);
}
public static function c2EntryImg(ArrayObject $a): string
{
$f = dcCore::app()->tpl->getFilters($a);
$style = isset($a['style']) ? Html::escapeHTML($a['style']) : '';
return
"<?php if (dcCore::app()->ctx->exists('c2_entries')) { " .
'$widthmax = (integer) dcCore::app()->blog->settings->cinecturlink2->widthmax; ' .
"\$img = sprintf('<img src=\"%s\" alt=\"%s\" %s/>'," .
'dcCore::app()->ctx->c2_entries->link_img, ' .
"html::escapeHTML(dcCore::app()->ctx->c2_entries->link_title.' - '.dcCore::app()->ctx->c2_entries->link_author), " .
"(\$widthmax ? ' style=\"width:'.\$widthmax.'px;$style\"' : '') " .
'); ' .
'echo ' . sprintf($f, '$img') . "; unset(\$img); } ?> \n";
}
public static function c2EntryDate(ArrayObject $a): string
{
$format = !empty($a['format']) ? addslashes($a['format']) : '';
if (!empty($a['rfc822'])) {
$p = 'dt::rfc822(strtotime(dcCore::app()->ctx->c2_entries->link_creadt), dcCore::app()->blog->settings->system->blog_timezone)';
} elseif (!empty($a['iso8601'])) {
$p = 'dt::iso8601(strtotime(dcCore::app()->ctx->c2_entries->link_creadt), dcCore::app()->blog->settings->system->blog_timezone)';
} elseif ($format) {
$p = "dt::dt2str('" . $format . "', dcCore::app()->ctx->c2_entries->link_creadt)";
} else {
$p = 'dt::dt2str(dcCore::app()->blog->settings->system->date_format, dcCore::app()->ctx->c2_entries->link_creadt)';
}
return self::getGenericValue($p, $a);
}
public static function c2EntryTime(ArrayObject $a): string
{
return self::getGenericValue('dt::dt2str(' . (!empty($a['format']) ? "'" . addslashes($a['format']) . "'" : 'dcCore::app()->blog->settings->system->time_format') . ', dcCore::app()->ctx->c2_entries->link_creadt)', $a);
}
public static function c2Pagination(ArrayObject $a, string $c): string
{
$p = "<?php\n" .
"\$params = dcCore::app()->ctx->c2_params;\n" .
"dcCore::app()->ctx->c2_pagination = dcCore::app()->ctx->cinecturlink->getLinks(\$params,true); unset(\$params);\n" .
"?>\n";
return isset($a['no_context']) ? $p . $c : $p . '<?php if (dcCore::app()->ctx->c2_pagination->f(0) > dcCore::app()->ctx->c2_entries->count()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2PaginationCounter(ArrayObject $a): string
{
return self::getGenericValue(FrontendContext::class . '::PaginationNbPages()', $a);
}
public static function c2PaginationCurrent(ArrayObject $a): string
{
return self::getGenericValue(FrontendContext::class . '::PaginationPosition(' . (isset($a['offset']) ? (int) $a['offset'] : 0) . ')', $a);
}
public static function c2PaginationIf(ArrayObject $a, string $c): string
{
$if = [];
if (isset($a['start'])) {
$sign = (bool) $a['start'] ? '' : '!';
$if[] = $sign . FrontendContext::class . '::PaginationStart()';
}
if (isset($a['end'])) {
$sign = (bool) $a['end'] ? '' : '!';
$if[] = $sign . FrontendContext::class . '::PaginationEnd()';
}
return empty($if) ? $c : '<?php if(' . implode(' && ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function c2PaginationURL($a): string
{
return self::getGenericValue(FrontendContext::class . '::PaginationURL(' . (isset($a['offset']) ? (int) $a['offset'] : 0) . ')', $a);
}
public static function c2Categories(ArrayObject $a, string $c): string
{
return
"<?php \n" .
"if (!dcCore::app()->ctx->exists('cinecturlink')) { dcCore::app()->ctx->cinecturlink = new " . Utils::class . "(); } \n" .
"dcCore::app()->ctx->c2_categories = dcCore::app()->ctx->cinecturlink->getCategories(); \n" .
'while (dcCore::app()->ctx->c2_categories->fetch()) : ?>' . $c . '<?php endwhile; ' . "\n" .
"dcCore::app()->ctx->c2_categories = null; \n" .
"?>\n";
}
public static function c2CategoriesHeader(ArrayObject $a, string $c): string
{
return '<?php if (dcCore::app()->ctx->c2_categories->isStart()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoriesFooter(ArrayObject $a, string $c): string
{
return '<?php if (dcCore::app()->ctx->c2_categories->isEnd()) : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoryIf(ArrayObject $a, string $c): string
{
$if = [];
if (isset($a['current'])) {
$sign = (bool) $a['current'] ? '' : '!';
$if[] = $sign . FrontendContext::class . '::CategoryCurrent()';
}
if (isset($a['first'])) {
$sign = (bool) $a['first'] ? '' : '!';
$if[] = $sign . 'dcCore::app()->ctx->c2_categories->isStart()';
}
return empty($if) ? $c : '<?php if(' . implode(' && ', $if) . ') : ?>' . $c . '<?php endif; ?>';
}
public static function c2CategoryFeedURL(ArrayObject $a): string
{
$p = !empty($a['type']) ? $a['type'] : 'atom';
if (!preg_match('#^(rss2|atom)$#', $p)) {
$p = 'atom';
}
return '<?php echo ' . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("' . My::id() . '")."/".dcCore::app()->blog->settings->cinecturlink2->public_caturl."/".urlencode(dcCore::app()->ctx->c2_categories->cat_title)."/feed/' . $p . '"') . '; ?>';
}
public static function c2CategoryFeedID(ArrayObject $a): string
{
return 'urn:md5:<?php echo md5(dcCore::app()->blog->id."' . My::id() . '".dcCore::app()->ctx->c2_categories->cat_id); ?>';
}
public static function c2CategoryID(ArrayObject $a): string
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_id') . '; } ?>';
}
public static function c2CategoryTitle(ArrayObject $a): string
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_title') . '; } ?>';
}
public static function c2CategoryDescription(ArrayObject $a): string
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->ctx->c2_categories->cat_desc') . '; } ?>';
}
public static function c2CategoryURL(ArrayObject $a): string
{
return "<?php if (dcCore::app()->ctx->exists('c2_categories')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), 'dcCore::app()->blog->url.dcCore::app()->url->getBase("' . My::id() . '")."/".dcCore::app()->blog->settings->cinecturlink2->public_caturl."/".urlencode(dcCore::app()->ctx->c2_categories->cat_title)') . '; } ?>';
}
protected static function getGenericValue(string $p, ArrayObject $a): string
{
return "<?php if (dcCore::app()->ctx->exists('c2_entries')) { echo " . sprintf(dcCore::app()->tpl->getFilters($a), "$p") . '; } ?>';
}
}

99
src/FrontendUrl.php Normal file
View file

@ -0,0 +1,99 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use dcUrlHandlers;
use context;
use Dotclear\Core\Frontend\Utility;
use Dotclear\Helper\File\Path;
class FrontendUrl extends dcUrlHandlers
{
public static function c2Page(?string $args)
{
$args = (string) $args;
if (!My::settings()->avtive
|| !My::settings()->public_active) {
self::p404();
}
$tplset = dcCore::app()->themes->getDefine(dcCore::app()->blog->settings->system->theme)->get('tplset');
$tpldir = Path::real(dcCore::app()->plugins->getDefine(My::id())->get('root')) . DIRECTORY_SEPARATOR . Utility::TPL_ROOT . DIRECTORY_SEPARATOR;
dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), $tpldir . (!empty($tplset) && is_dir($tpldir . $tplset) ? $tplset : DC_DEFAULT_TPLSET));
$params = [];
$n = self::getPageArgs($args, 'c2page');
if ($n) {
$GLOBALS['c2_page_number'] = $n;
}
$caturl = My::settings()->public_caturl;
if (!$caturl) {
$caturl = 'c2cat';
}
$c = self::getPageArgs($args, $caturl);
if ($c) {
if (is_numeric($c)) {
$params['cat_id'] = (int) $c;
} else {
$params['cat_title'] = urldecode($c);
}
}
$f = self::getPageArgs($args, 'feed');
if (!empty($f) && in_array($f, ['atom', 'rss2'])) {
$mime = $f == 'atom' ? 'application/atom+xml' : 'application/xml';
//dcCore::app()->ctx->short_feed_items = dcCore::app()->blog->settings->system->short_feed_items;
$params['limit'] = dcCore::app()->blog->settings->system->nb_post_per_feed;
dcCore::app()->ctx->c2_page_params = $params;
header('X-Robots-Tag: ' . context::robotsPolicy(dcCore::app()->blog->settings->system->robots_policy, ''));
self::serveDocument('cinecturlink2-' . $f . '.xml', $mime);
} else {
$d = self::getPageArgs($args, 'c2detail');
if (!empty($d)) {
if (is_numeric($d)) {
$params['link_id'] = (int) $d;
} else {
$params['link_title'] = urldecode($d);
}
}
$params['limit'] = (int) My::settings()->public_nbrpp;
dcCore::app()->ctx->c2_page_params = $params;
self::serveDocument('cinecturlink2.html', 'text/html');
}
return null;
}
protected static function getPageArgs(string &$args, string $part): string
{
if (preg_match('#(^|/)' . $part . '/([^/]+)#', $args, $m)) {
$args = preg_replace('#(^|/)' . $part . '/([^/]+)#', '', $args);
return $m[2];
}
return '';
}
}

View file

@ -10,76 +10,119 @@
* @copyright Jean-Christian Denis * @copyright 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_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
}
try { namespace Dotclear\Plugin\cinecturlink2;
if (!dcCore::app()->newVersion(
basename(__DIR__), use dcCore;
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version') use dcNamespace;
)) { use Dotclear\Core\Process;
return null; use Dotclear\Database\Structure;
use Dotclear\Database\Statement\UpdateStatement;
use Exception;
class Install extends Process
{
public static function init(): bool
{
return self::status(My::checkContext(My::INSTALL));
} }
$s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); public static function process(): bool
$s->{initCinecturlink2::CINECTURLINK_TABLE_NAME} {
->link_id('bigint', 0, false) if (!self::status()) {
->blog_id('varchar', 32, false) return false;
->cat_id('bigint', 0, true) }
->user_id('varchar', 32, true)
->link_type('varchar', 32, false, "'cinecturlink'")
->link_title('varchar', 255, false)
->link_desc('varchar', 255, false)
->link_author('varchar', 255, false)
->link_lang('varchar', 5, false, "'en'")
->link_url('varchar', 255, false)
->link_img('varchar', 255, false)
->link_creadt('timestamp', 0, false, 'now()')
->link_upddt('timestamp', 0, false, 'now()')
->link_pos('smallint', 0, false, "'0'")
->link_note('smallint', 0, false, "'10'")
->link_count('bigint', 0, false, "'0'")
->primary('pk_cinecturlink2', 'link_id') try {
->index('idx_cinecturlink2_title', 'btree', 'link_title') self::upgradeSettings();
->index('idx_cinecturlink2_author', 'btree', 'link_author')
->index('idx_cinecturlink2_blog_id', 'btree', 'blog_id')
->index('idx_cinecturlink2_cat_id', 'btree', 'cat_id')
->index('idx_cinecturlink2_user_id', 'btree', 'user_id')
->index('idx_cinecturlink2_type', 'btree', 'link_type');
$s->{initCinecturlink2::CATEGORY_TABLE_NAME} $s = new Structure(dcCore::app()->con, dcCore::app()->prefix);
->cat_id('bigint', 0, false) $s->{My::CINECTURLINK_TABLE_NAME}
->blog_id('varchar', 32, false) ->link_id('bigint', 0, false)
->cat_title('varchar', 255, false) ->blog_id('varchar', 32, false)
->cat_desc('varchar', 255, false) ->cat_id('bigint', 0, true)
->cat_creadt('timestamp', 0, false, 'now()') ->user_id('varchar', 32, true)
->cat_upddt('timestamp', 0, false, 'now()') ->link_type('varchar', 32, false, "'cinecturlink'")
->cat_pos('smallint', 0, false, "'0'") ->link_title('varchar', 255, false)
->link_desc('varchar', 255, false)
->link_author('varchar', 255, false)
->link_lang('varchar', 5, false, "'en'")
->link_url('varchar', 255, false)
->link_img('varchar', 255, false)
->link_creadt('timestamp', 0, false, 'now()')
->link_upddt('timestamp', 0, false, 'now()')
->link_pos('smallint', 0, false, "'0'")
->link_note('smallint', 0, false, "'10'")
->link_count('bigint', 0, false, "'0'")
->primary('pk_cinecturlink2_cat', 'cat_id') ->primary('pk_cinecturlink2', 'link_id')
->index('idx_cinecturlink2_cat_blog_id', 'btree', 'blog_id') ->index('idx_cinecturlink2_title', 'btree', 'link_title')
->unique('uk_cinecturlink2_cat_title', 'cat_title', 'blog_id'); ->index('idx_cinecturlink2_author', 'btree', 'link_author')
->index('idx_cinecturlink2_blog_id', 'btree', 'blog_id')
->index('idx_cinecturlink2_cat_id', 'btree', 'cat_id')
->index('idx_cinecturlink2_user_id', 'btree', 'user_id')
->index('idx_cinecturlink2_type', 'btree', 'link_type');
$si = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); $s->{My::CATEGORY_TABLE_NAME}
$changes = $si->synchronize($s); ->cat_id('bigint', 0, false)
->blog_id('varchar', 32, false)
->cat_title('varchar', 255, false)
->cat_desc('varchar', 255, false)
->cat_creadt('timestamp', 0, false, 'now()')
->cat_upddt('timestamp', 0, false, 'now()')
->cat_pos('smallint', 0, false, "'0'")
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); ->primary('pk_cinecturlink2_cat', 'cat_id')
$s = dcCore::app()->blog->settings->cinecturlink2; ->index('idx_cinecturlink2_cat_blog_id', 'btree', 'blog_id')
$s->put('cinecturlink2_active', true, 'boolean', 'Enable cinecturlink2', false, true); ->unique('uk_cinecturlink2_cat_title', 'cat_title', 'blog_id');
$s->put('cinecturlink2_widthmax', 100, 'integer', 'Maximum width of picture', false, true);
$s->put('cinecturlink2_folder', 'cinecturlink', 'string', 'Public folder of pictures', false, true);
$s->put('cinecturlink2_triggeronrandom', false, 'boolean', 'Open link in new window', false, true);
$s->put('cinecturlink2_public_active', false, 'boolean', 'Enable cinecturlink2', false, true);
$s->put('cinecturlink2_public_title', '', 'string', 'Title of public page', false, true);
$s->put('cinecturlink2_public_description', '', 'string', 'Description of public page', false, true);
$s->put('cinecturlink2_public_nbrpp', 20, 'integer', 'Number of entries per page on public page', false, true);
$s->put('cinecturlink2_public_caturl', 'c2cat', 'string', 'Part of URL for a category list', false, true);
return true; (new Structure(dcCore::app()->con, dcCore::app()->prefix))->synchronize($s);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); $s = My::settings();
$s->put('avtive', true, 'boolean', 'Enable cinecturlink2', false, true);
$s->put('widthmax', 100, 'integer', 'Maximum width of picture', false, true);
$s->put('folder', 'cinecturlink', 'string', 'Public folder of pictures', false, true);
$s->put('triggeronrandom', false, 'boolean', 'Open link in new window', false, true);
$s->put('public_active', false, 'boolean', 'Enable cinecturlink2', false, true);
$s->put('public_title', '', 'string', 'Title of public page', false, true);
$s->put('public_description', '', 'string', 'Description of public page', false, true);
$s->put('public_nbrpp', 20, 'integer', 'Number of entries per page on public page', false, true);
$s->put('public_caturl', 'c2cat', 'string', 'Part of URL for a category list', false, true);
return true;
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return false;
}
}
private static function upgradeSettings(): void
{
if (version_compare((string) dcCore::app()->getVersion(My::id()), '2.0', '<')) {
$ids = [
'active',
'widthmax',
'folder',
'triggeronrandom',
'public_active',
'public_title',
'public_description',
'public_nbrpp',
'public_caturl',
];
foreach ($ids as $id) {
$sql = new UpdateStatement();
$sql
->ref(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME)
->column('setting_id')
->value($id)
->where('setting_id = ' . $sql->quote('cinecturlink2_' . $id))
->and('setting_ns = ' . $sql->quote(My::id()))
->update();
}
}
}
} }
return false;

View file

@ -10,712 +10,52 @@
* @copyright Jean-Christian Denis * @copyright 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_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
}
dcPage::check(dcCore::app()->auth->makePermissions([ namespace Dotclear\Plugin\cinecturlink2;
dcAuth::PERMISSION_CONTENT_ADMIN,
]));
$linkid = $_REQUEST['linkid'] ?? ''; use Dotclear\Core\Process;
$linktitle = $_POST['linktitle'] ?? '';
$linkdesc = $_POST['linkdesc'] ?? '';
$linkauthor = $_POST['linkauthor'] ?? '';
$linkurl = $_POST['linkurl'] ?? '';
$linkcat = $_POST['linkcat'] ?? null;
$linklang = $_POST['linklang'] ?? dcCore::app()->auth->getInfo('user_lang');
$linkimage = $_POST['linkimage'] ?? '';
$linknote = $_POST['linknote'] ?? '';
$catid = $_REQUEST['catid'] ?? '';
$cattitle = $_POST['cattitle'] ?? '';
$catdesc = $_POST['catdesc'] ?? '';
$redir = $_REQUEST['redir'] ?? '';
$part = $_REQUEST['part'] ?? 'links';
$entries = $_POST['entries'] ?? [];
$headers = '';
$breadcrumb = [
__('Plugins') => '',
__('My cinecturlink') => dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'links']),
];
if (!in_array($part, ['links', 'link', 'cats', 'cat', 'dellinks', 'updlinksnote', 'updlinkscat'])) {
$part = 'links';
}
if (!is_array($entries)) {
$entries == [];
}
try { class Manage extends Process
$C2 = new cinecturlink2(); {
$categories = $C2->getCategories(); public static function init(): bool
$categories_combo = ['-' => '']; {
while ($categories->fetch()) { return self::status(match ($_REQUEST['part'] ?? 'links') {
$cat_title = html::escapeHTML($categories->cat_title); 'links' => ManageLinks::init(),
$categories_combo[$cat_title] = $categories->cat_id; 'link' => ManageLink::init(),
} 'cats' => ManageCats::init(),
} catch (Exception $e) { 'cat' => ManageCat::init(),
dcCore::app()->error->add($e->getMessage()); default => false,
} });
if ($part == 'dellinks') {
try {
// delete group of links
if (!empty($entries)) {
foreach ($entries as $id) {
$C2->delLink($id);
}
dcAdminNotices::addSuccessNotice(
__('Links successfully deleted.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'links']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
$breadcrumb[__('Delete links')] = '';
}
// get list of secleted links
if (in_array($part, ['updlinksnote', 'updlinkscat'])) {
try {
$links = $C2->getLinks(['link_id' => $entries]);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
if ($part == 'updlinksnote') {
try {
// update group of links note
if (!empty($entries) && isset($_POST['newlinknote'])) {
while ($links->fetch()) {
if (in_array($links->link_id, $entries)) {
$cur = dcCore::app()->con->openCursor($C2->table);
$cur->link_note = (int) $_POST['newlinknote'];
$C2->updLink($links->link_id, $cur);
}
}
dcAdminNotices::addSuccessNotice(
__('Links successfully updated.')
);
if (!empty($_POST['redir'])) {
http::redirect($redir);
} else {
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'links']);
}
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
$breadcrumb[__('Update links rating')] = '';
}
if ($part == 'updlinkscat') {
try {
// update group of links category
if (!empty($entries) && !empty($_POST['newcatid'])) {
while ($links->fetch()) {
if (in_array($links->link_id, $entries)) {
$cur = dcCore::app()->con->openCursor($C2->table);
$cur->cat_id = (int) $_POST['newcatid'];
$C2->updLink($links->link_id, $cur);
}
}
dcAdminNotices::addSuccessNotice(
__('Links successfully updated.')
);
if (!empty($_POST['redir'])) {
http::redirect($redir);
} else {
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'links']);
}
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
$breadcrumb[__('Update links category')] = '';
}
if ($part == 'links') {
$action_combo = [
__('Delete') => 'dellinks',
__('Change category') => 'updlinkscat',
__('Change rating') => 'updlinksnote',
];
$c2link_filter = new adminGenericFilterV2('c2link');
$c2link_filter->add('part', 'links');
$c2link_filter->add(dcAdminFilters::getPageFilter());
$c2link_filter->add(dcAdminFilters::getSearchFilter());
$c2link_filter->add(dcAdminFilters::getSelectFilter(
'catid',
__('Category:'),
$categories_combo,
'cat_id'
));
$params = $c2link_filter->params();
$params['link_type'] = 'cinecturlink';
$params['no_content'] = true;
$links_list = null;
try {
$links = $C2->getLinks($params);
$links_counter = $C2->getLinks($params, true)->f(0);
$links_list = new adminlistCinecturlink2($links, $links_counter);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
} }
$breadcrumb[__('My cinecturlink')] = ''; public static function process(): bool
$headers .= $c2link_filter->js(dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'links'])) . {
dcPage::jsFilterControl($c2link_filter->show()) . if (!self::status()) {
dcPage::jsLoad(dcPage::getPF('cinecturlink2/js/c2links.js')); return false;
}
if ($part == 'link') {
$langs_combo = l10n::getISOcodes(true);
$notes_combo = range(0, 20);
$media_combo = $tmp_media_combo = $dir = null;
try {
$allowed_media = ['png', 'jpg', 'gif', 'bmp', 'jpeg'];
dcCore::app()->media = new dcMedia();
dcCore::app()->media->chdir(dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_folder);
dcCore::app()->media->getDir();
$dir = & dcCore::app()->media->dir;
foreach ($dir['files'] as $file) {
if (!in_array(files::getExtension($file->relname), $allowed_media)) {
continue;
}
$tmp_media_combo[$file->media_title] = $file->file_url;
}
if (!empty($tmp_media_combo)) {
$media_combo = array_merge(['-' => ''], $tmp_media_combo);
}
} catch (Exception $e) {
//dcCore::app()->error->add($e->getMessage());
}
if (!empty($_POST['save'])) {
try {
cinecturlink2::makePublicDir(
DC_ROOT . '/' . dcCore::app()->blog->settings->system->public_path,
dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_folder
);
if (empty($linktitle)) {
throw new Exception(__('You must provide a title.'));
}
if (empty($linkauthor)) {
throw new Exception(__('You must provide an author.'));
}
if (!preg_match('/https?:\/\/.+/', $linkimage)) {
throw new Exception(__('You must provide a link to an image.'));
}
$cur = dcCore::app()->con->openCursor($C2->table);
$cur->link_title = $linktitle;
$cur->link_desc = $linkdesc;
$cur->link_author = $linkauthor;
$cur->link_url = $linkurl;
$cur->cat_id = $linkcat == '' ? null : $linkcat;
$cur->link_lang = $linklang;
$cur->link_img = $linkimage;
$cur->link_note = $linknote;
// create a link
if (empty($linkid)) {
$exists = $C2->getLinks(['link_title' => $linktitle], true)->f(0);
if ($exists) {
throw new Exception(__('Link with same name already exists.'));
}
$linkid = $C2->addLink($cur);
dcAdminNotices::addSuccessNotice(
__('Link successfully created.')
);
// update a link
} else {
$exists = $C2->getLinks(['link_id' => $linkid], true)->f(0);
if (!$exists) {
throw new Exception(__('Unknown link.'));
}
$C2->updLink($linkid, $cur);
dcAdminNotices::addSuccessNotice(
__('Link successfully updated.')
);
}
dcCore::app()->adminurl->redirect(
'admin.plugin.cinecturlink2',
[
'part' => 'link',
'linkid' => $linkid,
'redir' => $redir,
]
);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
if (!empty($_POST['delete']) && !empty($linkid)) {
try {
$C2->delLink($linkid);
dcAdminNotices::addSuccessNotice(
__('Link successfully deleted.')
);
if (!empty($_POST['redir'])) {
http::redirect($redir);
} else {
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'links']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
if (!empty($linkid)) {
$link = $C2->getLinks(['link_id' => $linkid]);
if (!$link->isEmpty()) {
$linktitle = $link->link_title;
$linkdesc = $link->link_desc;
$linkauthor = $link->link_author;
$linkurl = $link->link_url;
$linkcat = $link->cat_id;
$linklang = $link->link_lang;
$linkimage = $link->link_img;
$linknote = $link->link_note;
}
}
$breadcrumb[(empty($linkid) ? __('New link') : __('Edit link'))] = '';
$headers .= dcPage::jsVars(['dotclear.c2_lang' => dcCore::app()->auth->getInfo('user_lang')]) .
dcPage::jsLoad(dcPage::getPF('cinecturlink2/js/c2link.js'));
}
if ($part == 'cats') {
try {
// reorder categories
if (!empty($_POST['save'])) {
$catorder = [];
if (empty($_POST['im_order']) && !empty($_POST['order'])) {
$catorder = $_POST['order'];
asort($catorder);
$catorder = array_keys($catorder);
} elseif (!empty($_POST['im_order'])) {
$catorder = $_POST['im_order'];
if (substr($catorder, -1) == ',') {
$catorder = substr($catorder, 0, strlen($catorder) - 1);
}
$catorder = explode(',', $catorder);
}
$i = 0;
foreach ($catorder as $id) {
$i++;
$cur = dcCore::app()->con->openCursor($C2->cat_table);
$cur->cat_pos = $i;
$C2->updCategory($id, $cur);
}
dcAdminNotices::addSuccessNotice(
__('Categories successfully reordered.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'cats']);
}
// delete categories
if (!empty($_POST['delete']) && !empty($_POST['items_selected'])) {
foreach ($_POST['items_selected'] as $id) {
$C2->delCategory($id);
}
dcAdminNotices::addSuccessNotice(
__('Categories successfully deleted.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'cats']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
$breadcrumb[__('Categories')] = '';
dcCore::app()->auth->user_prefs->addWorkspace('accessibility');
if (!dcCore::app()->auth->user_prefs->accessibility->nodragdrop) {
$headers .= dcPage::jsLoad('js/jquery/jquery-ui.custom.js') .
dcPage::jsLoad('js/jquery/jquery.ui.touch-punch.js') .
dcPage::jsLoad(dcPage::getPF('cinecturlink2/js/c2cats.js'));
}
}
if ($part == 'cat') {
try {
// create category
if (!empty($_POST['save']) && empty($catid) && !empty($cattitle) && !empty($catdesc)) {
$exists = $C2->getCategories(['cat_title' => $cattitle], true)->f(0);
if ($exists) {
throw new Exception(__('Category with same name already exists.'));
}
$cur = dcCore::app()->con->openCursor($C2->cat_table);
$cur->cat_title = $cattitle;
$cur->cat_desc = $catdesc;
$catid = $C2->addCategory($cur);
dcAdminNotices::addSuccessNotice(
__('Category successfully created.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'cats']);
}
// update category
if (!empty($_POST['save']) && !empty($catid) && !empty($cattitle) && !empty($catdesc)) {
$exists = $C2->getCategories(['cat_title' => $cattitle, 'exclude_cat_id' => $catid], true)->f(0);
if ($exists) {
throw new Exception(__('Category with same name already exists.'));
}
$cur = dcCore::app()->con->openCursor($C2->cat_table);
$cur->cat_title = $cattitle;
$cur->cat_desc = $catdesc;
$C2->updCategory($catid, $cur);
dcAdminNotices::addSuccessNotice(
__('Category successfully updated.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'cats']);
}
// delete category
if (!empty($_POST['delete']) && !empty($catid)) {
$C2->delCategory($catid);
dcAdminNotices::addSuccessNotice(
__('Category successfully deleted.')
);
dcCore::app()->adminurl->redirect('admin.plugin.cinecturlink2', ['part' => 'cats']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
$breadcrumb[__('Categories')] = dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'cats']);
$breadcrumb[(empty($catid) ? __('New category') : __('Edit category'))] = '';
}
echo
'<html><head><title>' . __('Cinecturlink 2') . '</title>' .
$headers .
'</head><body>' .
dcPage::breadcrumb($breadcrumb) .
dcPage::notices();
if (!empty($redir)) {
echo '<p><a class="back" href="' . $redir . '">' . __('Back') . ' </a></p>';
}
if (!empty($title)) {
echo '<h3>' . $title . '</h3>';
}
if ($part == 'updlinksnote') {
if ($links->isEmpty()) {
echo '<p>' . __('There is no link') . '</p>';
} else {
echo '<h4>' . __('Links') . '</h4><ul>';
while ($links->fetch()) {
echo '<li><strong>' . $links->link_title . '</strong> - ' . $links->link_note . '/20</li>';
}
echo '</ul>';
echo '<h4>' . __('Rating') . '</h4>
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '">' .
'<p><label for="newlinknote" class="ib">' . __('New rating:') . '</label> ' .
form::number('newlinknote', [
'min' => 0,
'max' => 20,
'default' => 10,
]) . '/20' . '</p>' .
'<p>' .
'<input type="submit" value="' . __('Save') . ' (s)" accesskey="s" name="save" /> ' .
'<a id="post-cancel" href="' . (
$redir ? $redir :
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'links'])
) . '" class="button" accesskey="c">' . __('Cancel') . ' (c)</a> ';
foreach ($entries as $id) {
echo form::hidden(['entries[]'], $id);
}
echo
form::hidden('part', 'updlinksnote') .
form::hidden('redir', $redir) .
dcCore::app()->formNonce() . '</p>' .
'</form>';
}
}
if ($part == 'updlinkscat') {
if ($links->isEmpty()) {
echo '<p>' . __('There is no link') . '</p>';
} else {
echo '<h4>' . __('Links') . '</h4><ul>';
while ($links->fetch()) {
echo '<li><strong>' . $links->link_title . '</strong> - ' . ($links->cat_title ?? __('no categories')) . '</li>';
}
echo '</ul>';
echo '<h4>' . __('Category') . '</h4>
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '">' .
'<p><label for="newcatid" class="ib">' . __('New category:') . '</label> ' .
form::combo('newcatid', $categories_combo, $catid) . '</p>' .
'<input type="submit" value="' . __('Save') . ' (s)" accesskey="s" name="save" /> ' .
'<a id="post-cancel" href="' . (
$redir ? $redir :
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'links'])
) . '" class="button" accesskey="c">' . __('Cancel') . ' (c)</a> ';
foreach ($entries as $id) {
echo form::hidden(['entries[]'], $id);
}
echo
form::hidden('part', 'updlinkscat') .
form::hidden('redir', $redir) .
dcCore::app()->formNonce() . '</p>' .
'</form>';
}
}
if ($part == 'links') {
$links_redir = dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', $c2link_filter->values());
echo
'<p class="top-add"><a class="button add" href="' .
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'link', 'redir' => $links_redir]) .
'">' . __('New Link') . '</a> <a class="button add" href="' .
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'cats', 'redir' => $links_redir]) .
'">' . __('Edit categories') . ' </a></p>';
if ($links->isEmpty() && !$c2link_filter->show()) {
echo '<p>' . __('There is no link') . '</p>';
} else {
$c2link_filter->display(
'admin.plugin.cinecturlink2',
form::hidden('p', 'cinecturlink2') . form::hidden('part', 'links')
);
$links_list->display(
$c2link_filter->page,
$c2link_filter->nb,
'<form action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '" method="post" id="form-entries">' .
'%s' .
'<div class="two-cols">' .
'<p class="col checkboxes-helpers"></p>' .
'<p class="col right"><label for="action" class="classic">' . __('Selected links action:') . '</label> ' .
form::combo('part', $action_combo) .
'<input id="do-action" type="submit" value="' . __('ok') . '" disabled /></p>' .
dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.cinecturlink2', array_diff_key($c2link_filter->values(), ['part' => ''])) .
form::hidden(['redir'], $links_redir) .
dcCore::app()->formNonce() .
'</div>' .
'</form>',
$c2link_filter->show(),
$links_redir
);
}
}
if ($part == 'link') {
echo '
<form id="newlinkform" method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '">
<div class="two-cols clearfix">
<div class="col70">
<p><label for="linktitle">' . __('Title:') . ' ' .
form::field('linktitle', 60, 255, html::escapeHTML($linktitle), 'maximal') .
'</label></p>
<p><label for="linkdesc">' . __('Description:') . ' ' .
form::field('linkdesc', 60, 255, html::escapeHTML($linkdesc), 'maximal') .
'</label></p>
<p><label for="linkauthor">' . __('Author:') . ' ' .
form::field('linkauthor', 60, 255, html::escapeHTML($linkauthor), 'maximal') .
'</label></p>
<p><label for="linkurl">' . __('Details URL:') . ' ' .
form::field('linkurl', 60, 255, html::escapeHTML($linkurl), 'maximal') . '</label>' .
'<a class="modal hidden-if-no-js" href="http://google.com" id="newlinksearch">' .
__('Search with Google') . '</a>' .
'</p>
<p><label for="linkimage">' . __('Image URL:') . ' ' .
form::field('linkimage', 60, 255, html::escapeHTML($linkimage), 'maximal') . '</label>' .
'<a class="modal hidden-if-no-js"" href="http://amazon.com" id="newimagesearch">' .
__('Search with Amazon') . '</a>' .
'</p>';
if (empty($media_combo)) {
echo
'<p class="form-note">' . __('There is no image in cinecturlink media path.') . '</p>';
} else {
echo '
<p><label for="newimageselect">' . __('or select from repository:') . ' ' .
form::combo('newimageselect', $media_combo, '', 'maximal') .
'</label></p>' .
'<p class="form-note"><a href="' .
dcCore::app()->adminurl->get('admin.media', ['d' => (string) dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_folder]) . '">' .
__('Go to media manager to add image to cinecturlink path.') .
'<a></p>';
}
echo '
</div>
<div class="col30">
<p><label for="linkcat">' . __('Category:') . '</label> ' .
form::combo('linkcat', $categories_combo, $linkcat) .
'</p>
<p><label for="linklang">' . __('Lang:') . '</label> ' .
form::combo('linklang', $langs_combo, $linklang) .
'</p>
<p><label for="linknote">' . __('Rating:') . '</label> ' .
form::number('linknote', [
'min' => 0,
'max' => 20,
'default' => $linknote,
]) . '/20' . '</p>
</div></div>
<p class="border-top">' .
'<input type="submit" value="' . __('Save') . ' (s)" accesskey="s" name="save" /> ' .
'<a id="post-cancel" href="' .
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'links']) .
'" class="button" accesskey="c">' . __('Cancel') . ' (c)</a> ' .
'<input type="submit" class="delete" value="' . __('Delete') . '" name="delete" />' .
form::hidden('linkid', $linkid) .
form::hidden('part', 'link') .
form::hidden('redir', $redir) .
dcCore::app()->formNonce() . '
</p>
</form>';
}
if ($part == 'cats') {
echo
'<p class="top-add"><a class="button add" href="' .
dcCore::app()->adminurl->get(
'admin.plugin.cinecturlink2',
[
'part' => 'cat',
'redir' => dcCore::app()->adminurl->get(
'admin.plugin.cinecturlink2',
[
'part' => 'cats',
'redir' => $redir,
]
),
]
) .
'">' . __('New Category') . ' </a></p>';
if ($categories->isEmpty()) {
echo '<p>' . __('There is no category') . '</p>';
} else {
echo '
<form id="c2items" method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '">
<div class="table-outer">
<table class="dragable">
<caption>' . __('Categories list') . '</caption>
<thead><tr>
<th colspan="3" scope="col">' . __('name') . '</th>
<th scope="col">' . __('description') . '</th>
</tr></thead>
<tbody id="c2itemslist">';
$i = 0;
while ($categories->fetch()) {
$id = $categories->cat_id;
echo
'<tr class="line" id="l_' . $i . '">' .
'<td class="handle minimal">' .
form::number(['order[' . $id . ']'], [
'min' => 1,
'max' => $categories->count(),
'default' => $i + 1,
'class' => 'position',
'extra_html' => 'title="' . sprintf(__('position of %s'), html::escapeHTML($categories->cat_title)) . '"',
]) .
form::hidden(['dynorder[]', 'dynorder-' . $i], $id) . '</td>
<td class="minimal">' . form::checkbox(['items_selected[]', 'ims-' . $i], $id) . '</td>
<td class="nowrap"><a title="' . __('Edit') . '" href="' .
dcCore::app()->adminurl->get(
'admin.plugin.cinecturlink2',
[
'part' => 'cat',
'catid' => $id,
'redir' => dcCore::app()->adminurl->get(
'admin.plugin.cinecturlink2',
[
'part' => 'cats',
'redir' => $redir,
]
),
]
) .
'">' . html::escapeHTML($categories->cat_title) . '</a></td>
<td class="maximal">' . html::escapeHTML($categories->cat_desc) . '</td>
</tr>';
$i++;
} }
echo ' return self::status(match ($_REQUEST['part'] ?? 'links') {
</tbody> 'links' => ManageLinks::process(),
</table> 'link' => ManageLink::process(),
</div> 'cats' => ManageCats::process(),
<p class="form-note">' . __('Check to delete') . '</p> 'cat' => ManageCat::process(),
<p class="border-top">' . default => false,
'<input type="submit" value="' . __('Save order') . ' (s)" accesskey="s" name="save" /> ' . });
'<a id="post-cancel" href="' .
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'cats']) .
'" class="button" accesskey="c">' . __('Cancel') . ' (c)</a> ' .
'<input type="submit" class="delete" value="' . __('Delete selection') . '" name="delete" />' .
form::hidden('im_order', '') .
form::hidden('part', 'cats') .
dcCore::app()->formNonce() . '</p>' .
'</form>';
} }
}
if ($part == 'cat') { public static function render(): void
if (!empty($catid)) { {
$category = $C2->getCategories(['cat_id' => $catid]); if (!self::status()) {
if (!$category->isEmpty()) { return;
$cattitle = $category->cat_title;
$catdesc = $category->cat_desc;
} }
}
if ($catid) { match ($_REQUEST['part'] ?? 'links') {
$links = $C2->getLinks(['cat_id' => $catid], true)->f(0); 'links' => ManageLinks::render(),
echo '<p class="info">' . ( 'link' => ManageLink::render(),
empty($links) ? 'cats' => ManageCats::render(),
__('No link uses this category.') : 'cat' => ManageCat::render(),
sprintf(__('A link uses this category.', '%s links use this category.', $links), $links) default => false,
) . '</p>'; };
} }
echo '
<form method="post" action="' . dcCore::app()->adminurl->get('admin.plugin.cinecturlink2') . '">
<p><label for="cattitle">' . __('Title:') . ' ' .
form::field('cattitle', 60, 64, $cattitle, 'maximal') .
'</label></p>
<p><label for="catdesc">' . __('Description:') . ' ' .
form::field('catdesc', 60, 64, $catdesc, 'maximal') .
'</label></p>
<p class="border-top">' .
'<input type="submit" value="' . __('Save') . ' (s)" accesskey="s" name="save" /> ' .
'<a id="post-cancel" href="' .
dcCore::app()->adminurl->get('admin.plugin.cinecturlink2', ['part' => 'cats']) .
'" class="button" accesskey="c">' . __('Cancel') . ' (c)</a> ' .
(!empty($catid) ? ' <input type="submit" class="delete" value="' . __('Delete') . '" name="delete" />' : '') .
form::hidden('catid', $catid) .
form::hidden('part', 'cat') .
dcCore::app()->formNonce() . '</p>' .
'</form>';
} }
dcPage::helpBlock('cinecturlink2');
echo '</body></html>';

212
src/ManageCat.php Normal file
View file

@ -0,0 +1,212 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Core\Backend\{
Notices,
Page
};
use Dotclear\Core\Process;
use Dotclear\Helper\Html\Form\{
Form,
Input,
Label,
Link,
Note,
Para,
Submit
};
use Dotclear\Helper\Html\Html;
use Exception;
class ManageCat extends Process
{
private static string $module_redir = '';
private static int $catid = 0;
private static string $cattitle = '';
private static string $catdesc = '';
public static function init(): bool
{
return self::status(My::checkContext(My::MANAGE) && ($_REQUEST['part'] ?? 'links') == 'cat');
}
public static function process(): bool
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'cat') {
return false;
}
$utils = new Utils();
self::$module_redir = $_REQUEST['redir'] ?? '';
self::$catid = (int) ($_REQUEST['catid'] ?? 0);
self::$cattitle = $_POST['cattitle'] ?? '';
self::$catdesc = $_POST['catdesc'] ?? '';
try {
// create category
if (!empty($_POST['save']) && empty(self::$catid) && !empty(self::$cattitle) && !empty(self::$catdesc)) {
$exists = $utils->getCategories(['cat_title' => self::$cattitle], true)->f(0);
if ($exists) {
throw new Exception(__('Category with same name already exists.'));
}
$cur = dcCore::app()->con->openCursor($utils->cat_table);
$cur->setField('cat_title', self::$cattitle);
$cur->setField('cat_desc', self::$catdesc);
$catid = $utils->addCategory($cur);
Notices::addSuccessNotice(
__('Category successfully created.')
);
My::redirect(['part' => 'cats']);
}
// update category
if (!empty($_POST['save']) && !empty(self::$catid) && !empty(self::$cattitle) && !empty(self::$catdesc)) {
$exists = $utils->getCategories(['cat_title' => self::$cattitle, 'exclude_cat_id' => self::$catid], true)->f(0);
if ($exists) {
throw new Exception(__('Category with same name already exists.'));
}
$cur = dcCore::app()->con->openCursor($C2->cat_table);
$cur->setField('cat_title', self::$cattitle);
$cur->setField('cat_desc', self::$catdesc);
$utils->updCategory(self::$catid, $cur);
Notices::addSuccessNotice(
__('Category successfully updated.')
);
My::redirect(['part' => 'cats']);
}
// delete category
if (!empty($_POST['delete']) && !empty(self::$catid)) {
$utils->delCategory(self::$catid);
Notices::addSuccessNotice(
__('Category successfully deleted.')
);
My::redirect(['part' => 'cats']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
return true;
}
public static function render(): void
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'cat') {
return;
}
$utils = new Utils();
if (!empty(self::$catid)) {
$category = $utils->getCategories(['cat_id' => self::$catid]);
if (!$category->isEmpty()) {
self::$cattitle = (string) $category->f('cat_title');
self::$catdesc = (string) $category->f('cat_desc');
}
}
Page::openModule(My::name());
echo
Page::breadcrumb([
__('Plugins') => '',
My::name() => My::manageUrl(),
(empty(self::$catid) ? __('New category') : __('Edit category')) => '',
]) .
Notices::getNotices();
if (!empty(self::$module_redir)) {
echo (new Para())
->items([
(new Link())
->class('back')
->href(self::$module_redir)
->text(__('Back')),
])
->render();
}
if (self::$catid) {
$links = (int) $utils->getLinks(['cat_id' => self::$catid], true)->f(0);
echo (new Note())
->class('info')
->text(
empty($links) ?
__('No link uses this category.') :
sprintf(__('A link uses this category.', '%s links use this category.', $links), $links)
)
->render();
}
echo (new Form('newcatform'))
->method('post')
->action(My::manageUrl())
->fields([
(new Para())
->items([
(new Label(__('Title:'), Label::OUTSIDE_LABEL_BEFORE))
->for('cattitle'),
(new Input('cattitle'))
->size(65)
->maxlenght(64)
->value(Html::escapeHTML(self::$cattitle)),
]),
(new Para())
->items([
(new Label(__('Description:'), Label::OUTSIDE_LABEL_BEFORE))
->for('catdesc'),
(new Input('catdesc'))
->size(65)
->maxlenght(64)
->value(Html::escapeHTML(self::$catdesc)),
]),
(new Para())
->class('border-top')
->separator(' ')
->items([
(new Submit('save'))
->value(__('Save') . ' (s)')
->accesskey('s'),
(new Link())
->class('button')
->href(My::manageUrl(['part' => 'links']))
->title(__('Cancel'))
->text(__('Cancel') . ' (c)')
->accesskey('c'),
(new Submit('delete'))
->class('delete')
->value(__('Delete') . ' (d)')
->accesskey('d'),
... My::hiddenFields([
'catid' => self::$catid,
'part' => 'cat',
'redir' => self::$module_redir,
]),
]),
])
->render();
Page::helpBlock(My::id());
Page::closeModule();
}
}

269
src/ManageCats.php Normal file
View file

@ -0,0 +1,269 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Core\Backend\{
Notices,
Page
};
use Dotclear\Core\Process;
use Dotclear\Helper\Html\Form\{
Checkbox,
Div,
Form,
Hidden,
Label,
Link,
Note,
Number,
Para,
Submit,
Table, Thead, Tbody, Th, Tr, Td, Caption
};
use Dotclear\Helper\Html\Html;
use Exception;
class ManageCats extends Process
{
private static string $module_redir = '';
public static function init(): bool
{
return self::status(My::checkContext(My::MANAGE) && ($_REQUEST['part'] ?? 'links') == 'cats');
}
public static function process(): bool
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'cats') {
return false;
}
self::$module_redir = $_REQUEST['redir'] ?? '';
try {
$utils = new Utils();
// reorder categories
if (!empty($_POST['save'])) {
$catorder = [];
if (empty($_POST['im_order']) && !empty($_POST['order'])) {
$catorder = $_POST['order'];
asort($catorder);
$catorder = array_keys($catorder);
} elseif (!empty($_POST['im_order'])) {
$catorder = $_POST['im_order'];
if (substr($catorder, -1) == ',') {
$catorder = substr($catorder, 0, strlen($catorder) - 1);
}
$catorder = explode(',', $catorder);
}
$i = 0;
foreach ($catorder as $id) {
$i++;
$cur = dcCore::app()->con->openCursor($utils->cat_table);
$cur->setField('cat_pos', $i);
$utils->updCategory((int) $id, $cur);
}
Notices::addSuccessNotice(
__('Categories successfully reordered.')
);
My::redirect(['part' => 'cats']);
}
// delete categories
if (!empty($_POST['delete']) && !empty($_POST['items_selected'])) {
foreach ($_POST['items_selected'] as $id) {
$utils->delCategory((int) $id);
}
Notices::addSuccessNotice(
__('Categories successfully deleted.')
);
My::redirect(['part' => 'cats']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
return true;
}
public static function render(): void
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'cats') {
return;
}
$categories = (new Utils())->getCategories();
$items = [];
$i = 0;
while ($categories->fetch()) {
$id = $categories->f('cat_id');
$items[] = (new Tr('l_' . $i))
->class('line')
->items([
(new Td())
->class('handle minimal')
->items([
(new Number(['order[' . $id . ']']))
->min(1)
->max($categories->count())
->value($i + 1)
->class('position')
->title(Html::escapeHTML(sprintf(__('position of %s'), (string) $categories->f('cat_title')))),
(new Hidden(['dynorder[]', 'dynorder-' . $i], $id)),
]),
(new Td())
->class('minimal')
->items([
(new Checkbox(['items_selected[]', 'ims-' . $i]))
->value($id),
]),
(new Td())
->class('nowrap')
->items([
(new Link())
->href(My::manageUrl([
'part' => 'cat',
'catid' => $id,
'redir' => My::manageUrl([
'part' => 'cats',
'redir' => self::$module_redir,
]),
]))
->title(__('Edit'))
->text(Html::escapeHTML((string) $categories->f('cat_title'))),
]),
(new Td())
->class('maximal')
->text(Html::escapeHTML((string) $categories->f('cat_desc'))),
]);
$i++;
}
Page::openModule(
My::name(),
(!dcCore::app()->auth->user_prefs?->get('accessibility')->get('nodragdrop') ?
Page::jsLoad('js/jquery/jquery-ui.custom.js') .
Page::jsLoad('js/jquery/jquery.ui.touch-punch.js') .
My::jsLoad('c2cats')
: '')
);
echo
Page::breadcrumb([
__('Plugins') => '',
My::name() => My::manageUrl(),
__('Categories') => '',
]) .
Notices::getNotices();
if (!empty(self::$module_redir)) {
echo (new Para())
->items([
(new Link())
->class('back')
->href(self::$module_redir)
->text(__('Back')),
])
->render();
}
echo (new Para())
->class('top-add')
->separator(' ')
->items([
(new Link())
->class('button add')
->href(My::manageUrl(['part' => 'cat', 'redir' => My::manageUrl(['part' => 'cats'])]))
->text(__('New Link')),
])
->render();
if ($categories->isEmpty()) {
echo (new Note())
->class('info')
->text(__('There is no category'))
->render();
} else {
echo (new Div())
->items([
(new Form('c2items'))
->action(My::manageUrl())
->method('post')
->fields([
(new Div())
->class('table-outer')
->items([
(new Table())
->class('dragable')
->items([
(new Thead())
->items([
(new Caption(__('Categories list'))),
(new Tr())
->items([
(new Th())
->text(__('Name'))
->scope('col')
->colspan(3),
(new Th())
->text(__('Description'))
->scope('col'),
]),
]),
(new Tbody('c2itemslist'))
->items($items),
]),
]),
(new Note())
->class('form-note')
->text(__('Check to delete')),
(new Para())
->class('border-top')
->separator(' ')
->items([
(new Submit('save'))
->value(__('Save order') . ' (s)')
->accesskey('s'),
(new Link())
->class('button')
->href(My::manageUrl(['part' => 'cats']))
->title(__('Cancel'))
->text(__('Cancel') . ' (c)')
->accesskey('c'),
(new Submit('delete'))
->class('delete')
->value(__('Delete') . ' (d)')
->accesskey('d'),
... My::hiddenFields([
'im_order' => '',
'part' => 'cats',
'redir' => self::$module_redir,
]),
]),
]),
])
->render();
}
Page::helpBlock(My::id());
Page::closeModule();
}
}

357
src/ManageLink.php Normal file
View file

@ -0,0 +1,357 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Core\Backend\{
Notices,
Page
};
use Dotclear\Core\Process;
use Dotclear\Helper\Html\Form\{
Div,
Form,
Input,
Label,
Link,
Note,
Number,
Para,
Select,
Submit
};
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\Network\Http;
use Exception;
class ManageLink extends Process
{
private static string $module_redir = '';
private static int $linkid = 0;
private static string $linktitle = '';
private static string $linkdesc = '';
private static string $linkauthor = '';
private static string $linkurl = '';
private static ?string $linkcat = '';
private static string $linklang = '';
private static string $linkimage = '';
private static string $linknote = '';
public static function init(): bool
{
return self::status(My::checkContext(My::MANAGE) && ($_REQUEST['part'] ?? 'links') == 'link');
}
public static function process(): bool
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'link') {
return false;
}
$utils = new Utils();
self::$module_redir = $_REQUEST['redir'] ?? '';
self::$linkid = (int) ($_REQUEST['linkid'] ?? 0);
self::$linktitle = $_POST['linktitle'] ?? '';
self::$linkdesc = $_POST['linkdesc'] ?? '';
self::$linkauthor = $_POST['linkauthor'] ?? '';
self::$linkurl = $_POST['linkurl'] ?? '';
self::$linkcat = $_POST['linkcat'] ?? null;
self::$linklang = $_POST['linklang'] ?? dcCore::app()->auth->getInfo('user_lang');
self::$linkimage = $_POST['linkimage'] ?? '';
self::$linknote = $_POST['linknote'] ?? '';
if (!empty($_POST['save'])) {
try {
Utils::makePublicDir(
DC_ROOT . '/' . dcCore::app()->blog->settings->system->get('public_path'),
My::settings()->folder
);
if (empty(self::$linktitle)) {
throw new Exception(__('You must provide a title.'));
}
if (empty(self::$linkauthor)) {
throw new Exception(__('You must provide an author.'));
}
if (!preg_match('/https?:\/\/.+/', self::$linkimage)) {
//throw new Exception(__('You must provide a link to an image.'));
}
$cur = dcCore::app()->con->openCursor($utils->table);
$cur->setField('link_title', self::$linktitle);
$cur->setField('link_desc', self::$linkdesc);
$cur->setField('link_author', self::$linkauthor);
$cur->setField('link_url', self::$linkurl);
$cur->setField('cat_id', self::$linkcat == '' ? null : self::$linkcat);
$cur->setField('link_lang', self::$linklang);
$cur->setField('link_img', self::$linkimage);
$cur->setField('link_note', self::$linknote);
// create a link
if (empty(self::$linkid)) {
$exists = $utils->getLinks(['link_title' => self::$linktitle], true)->f(0);
if ($exists) {
throw new Exception(__('Link with same name already exists.'));
}
self::$linkid = $utils->addLink($cur);
Notices::addSuccessNotice(
__('Link successfully created.')
);
// update a link
} else {
$exists = $utils->getLinks(['link_id' => self::$linkid], true)->f(0);
if (!$exists) {
throw new Exception(__('Unknown link.'));
}
$utils->updLink(self::$linkid, $cur);
Notices::addSuccessNotice(
__('Link successfully updated.')
);
}
My::redirect(
[
'part' => 'link',
'linkid' => self::$linkid,
'redir' => self::$module_redir,
]
);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
if (!empty($_POST['delete']) && !empty(self::$linkid)) {
try {
$utils->delLink(self::$linkid);
Notices::addSuccessNotice(
__('Link successfully deleted.')
);
if (!empty($_POST['redir'])) {
Http::redirect(self::$module_redir);
} else {
My::redirect(['part' => 'links']);
}
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
if (!empty(self::$linkid)) {
$link = $utils->getLinks(['link_id' => self::$linkid]);
if (!$link->isEmpty()) {
self::$linktitle = (string) $link->f('link_title');
self::$linkdesc = (string) $link->f('link_desc');
self::$linkauthor = (string) $link->f('link_author');
self::$linkurl = (string) $link->f('link_url');
self::$linkcat = (string) $link->f('cat_id');
self::$linklang = (string) $link->f('link_lang');
self::$linkimage = (string) $link->f('link_img');
self::$linknote = (string) $link->f('link_note');
}
}
return true;
}
public static function render(): void
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'link') {
return;
}
$mc = Combo::mediaCombo();
Page::openModule(
My::name(),
Page::jsVars(['dotclear.c2_lang' => dcCore::app()->auth->getInfo('user_lang')]) .
My::jsLoad('c2link')
);
echo
Page::breadcrumb([
__('Plugins') => '',
My::name() => My::manageUrl(),
(empty(self::$linkid) ? __('New link') : __('Edit link')) => '',
]) .
Notices::getNotices();
if (!empty(self::$module_redir)) {
echo (new Para())
->items([
(new Link())
->class('back')
->href(self::$module_redir)
->text(__('Back')),
])
->render();
}
echo (new Div())
->items([
(new Form('newlinkform'))
->action(My::manageUrl())
->method('post')
->fields([
(new Div())
->class('two-cols clearfix')
->items([
(new Div())
->class('col70')
->items([
(new Para())
->items([
(new Label(__('Title:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linktitle'),
(new Input('linktitle'))
->size(65)
->maxlenght(255)
->value(Html::escapeHTML(self::$linktitle)),
]),
(new Para())
->items([
(new Label(__('Description:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linkdesc'),
(new Input('linkdesc'))
->size(65)
->maxlenght(255)
->value(Html::escapeHTML(self::$linkdesc)),
]),
(new Para())
->items([
(new Label(__('Author:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linkauthor'),
(new Input('linkauthor'))
->size(65)
->maxlenght(255)
->value(Html::escapeHTML(self::$linkauthor)),
]),
(new Para())
->items([
(new Label(__('Details URL:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linkurl'),
(new Input('linkurl'))
->size(65)
->maxlenght(255)
->value(Html::escapeHTML(self::$linkurl)),
(new Link('newlinksearch'))
->class('modal hidden-if-no-js')
->href('http://google.com')
->title(__('Search with Google'))
->text(__('Search with Google')),
]),
(new Para())
->items([
(new Label(__('Image URL:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linkimage'),
(new Input('linkimage'))
->size(65)
->maxlenght(255)
->value(Html::escapeHTML(self::$linkimage)),
(new Link('newimagesearch'))
->class('modal hidden-if-no-js')
->href('http://amazon.com')
->title(__('Search with Amazon'))
->text(__('Search with Amazon')),
]),
...(
empty($mc) ?
[(new Note())
->class('form-note')
->text(__('There is no image in cinecturlink media path.'))] :
[(new Para())
->items([
(new Label(__('or select from repository:'), Label::OUTSIDE_LABEL_BEFORE))
->for('newimageselect'),
(new Select('newimageselect'))
->items($mc)
->default(''),
]),
(new Para())
->class('form-note')
->items([
(new Link())
->class('modal hidden-if-no-js')
->href(dcCore::app()->adminurl->get('admin.media', ['d' => (string) My::settings()->folder]))
->title(__('Media manager'))
->text(__('Go to media manager to add image to cinecturlink path.')),
]),
]
),
]),
(new Div())
->class('col30')
->items([
(new Para())
->items([
(new Label(__('Category:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linkcat'),
(new Select('linkcat'))
->items(Combo::categoriesCombo())
->default(self::$linkcat),
]),
(new Para())
->items([
(new Label(__('Lang:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linklang'),
(new Select('linklang'))
->items(Combo::langsCombo())
->default(self::$linklang),
]),
(new Para())
->items([
(new Label(__('Rating:'), Label::OUTSIDE_LABEL_BEFORE))
->for('linknote'),
(new Number('linknote'))
->min(0)
->max(20)
->value(self::$linknote),
]),
]),
]),
(new Para())
->class('border-top')
->separator(' ')
->items([
(new Submit('save'))
->value(__('Save') . ' (s)')
->accesskey('s'),
(new Link())
->class('button')
->href(My::manageUrl(['part' => 'links']))
->title(__('Cancel'))
->text(__('Cancel') . ' (c)')
->accesskey('c'),
(new Submit('delete'))
->class('delete')
->value(__('Delete') . ' (d)')
->accesskey('d'),
... My::hiddenFields([
'linkid' => self::$linkid,
'part' => 'link',
'redir' => self::$module_redir,
]),
]),
]),
])
->render();
Page::helpBlock(My::id());
Page::closeModule();
}
}

192
src/ManageLinks.php Normal file
View file

@ -0,0 +1,192 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Core\Backend\Action\Actions;
use Dotclear\Core\Backend\Filter\{
Filters,
FiltersLibrary
};
use Dotclear\Core\Backend\Listing\Listing;
use Dotclear\Core\Backend\{
Notices,
Page
};
use Dotclear\Core\Process;
use Dotclear\Helper\Html\Form\{
Div,
Form,
Hidden,
Label,
Link,
Para,
Select,
Submit,
Text
};
use Exception;
class ManageLinks extends Process
{
private static Actions $module_action;
private static Filters $module_filter;
private static Listing $module_listing;
private static int $module_counter = 0;
private static ?bool $module_rendered = null;
public static function init(): bool
{
return self::status(My::checkContext(My::MANAGE) && ($_REQUEST['part'] ?? 'links') == 'links');
}
public static function process(): bool
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'links') {
return false;
}
self::$module_action = new BackendActionsLinks(My::manageUrl(['part' => 'links'], '&'));
if (self::$module_action->process()) {
self::$module_rendered = true;
return true;
}
self::$module_filter = new Filters(My::id());
self::$module_filter->add('part', 'links');
self::$module_filter->add(FiltersLibrary::getPageFilter());
self::$module_filter->add(FiltersLibrary::getSearchFilter());
self::$module_filter->add(FiltersLibrary::getSelectFilter(
'catid',
__('Category:'),
Combo::categoriesCombo(),
'cat_id'
));
$params = self::$module_filter->params();
$params['link_type'] = 'cinecturlink';
$params['no_content'] = true;
try {
$utils = new Utils();
$links = $utils->getLinks($params);
self::$module_counter = (int) $utils->getLinks($params, true)->f(0);
self::$module_listing = new BackendListingLinks($links, self::$module_counter);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
return true;
}
public static function render(): void
{
if (!self::status() || ($_REQUEST['part'] ?? 'links') != 'links') {
return;
}
if (self::$module_rendered) {
self::$module_action->render();
return;
}
$from_redir = $_REQUEST['redir'] ?? '';
$this_redir = My::manageUrl(self::$module_filter->values());
Page::openModule(
My::name(),
self::$module_filter->js(My::manageUrl(['part' => 'links'])) .
//Page::jsFilterControl(self::$module_filter->show()) .
My::jsLoad('c2links')
);
echo
Page::breadcrumb([
__('Plugins') => '',
My::name() => '',
__('Manage links') => '',
]) .
Notices::getNotices();
if (!empty($from_redir)) {
echo (new Para())
->items([
(new Link())
->class('back')
->href($from_redir)
->text(__('Back')),
])
->render();
}
echo (new Para())
->class('top-add')
->separator(' ')
->items([
(new Link())
->class('button add')
->href(My::manageUrl(['part' => 'link', 'redir' => $this_redir]))
->text(__('New Link')),
(new Link())
->class('button add')
->href(My::manageUrl(['part' => 'cats', 'redir' => $this_redir]))
->text(__('Edit categories')),
])
->render();
if (self::$module_counter) {
self::$module_filter->display(
'admin.plugin.' . My::id(),
(new Hidden('p', My::id()))->render() . (new Hidden('part', 'links'))->render()
);
}
self::$module_listing->display(
self::$module_filter,
(new Form('form-entries'))
->action(My::manageUrl())
->method('post')
->fields([
(new Text('', '%s')),
(new Div())
->class('two-cols')
->items([
(new Para())
->class('col checkboxes-helpers'),
(new Para())
->class('col right')
->separator('&nbsp;')
->items([
(new Label(__('Selected links action:'), Label::OUTSIDE_LABEL_BEFORE))
->for('action'),
(new Select('action'))
->items(self::$module_action->getCombo()),
(new Submit('do-action'))
->value(__('ok')),
... My::hiddenFields(self::$module_filter->values(true)),
]),
]),
])
->render(),
$this_redir
);
Page::helpBlock(My::id());
Page::closeModule();
}
}

39
src/My.php Normal file
View file

@ -0,0 +1,39 @@
<?php
/**
* @brief cinecturlink2, 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);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Module\MyPlugin;
class My extends MyPlugin
{
public const CINECTURLINK_TABLE_NAME = \initCinecturlink2::CINECTURLINK_TABLE_NAME;
public const CATEGORY_TABLE_NAME = \initCinecturlink2::CATEGORY_TABLE_NAME;
public const ALLOWED_MEDIA_EXTENSION = ['png', 'jpg', 'gif', 'bmp', 'jpeg'];
public static function checkCustomContext(int $context): ?bool
{
if (in_array($context, [My::MENU, My::BACKEND])) {
return defined('DC_CONTEXT_ADMIN')
&& !is_null(dcCore::app()->blog)
&& dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
dcCore::app()->auth::PERMISSION_CONTENT_ADMIN,
]), dcCore::app()->blog->id);
}
return null;
}
}

View file

@ -10,42 +10,45 @@
* @copyright Jean-Christian Denis * @copyright 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;
}
class cinecturlink2ActivityReportBehaviors namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Plugin\activityReport\ActivityReport;
class PluginActivityReport
{ {
public static function add() public static function add()
{ {
dcCore::app()->activityReport->addGroup('cinecturlink2', __('Plugin cinecturlink2')); ActivityReport::instance()->addGroup('cinecturlink2', __('Plugin cinecturlink2'));
// from BEHAVIOR cinecturlink2AfterAddLink in cinecturlink2/inc/class.cinecturlink2.php // from BEHAVIOR cinecturlink2AfterAddLink in cinecturlink2/inc/class.cinecturlink2.php
dcCore::app()->activityReport->addAction( ActivityReport::instance()->addAction(
'cinecturlink2', 'cinecturlink2',
'create', 'create',
__('link creation'), __('link creation'),
__('A new cineturlink named "%s" was added by "%s"'), __('A new cineturlink named "%s" was added by "%s"'),
'cinecturlink2AfterAddLink', 'cinecturlink2AfterAddLink',
['cinecturlink2ActivityReportBehaviors', 'addLink'] [self::class, 'addLink']
); );
// from BEHAVIOR cinecturlink2AfterUpdLink in cinecturlink2/inc/class.cinecturlink2.php // from BEHAVIOR cinecturlink2AfterUpdLink in cinecturlink2/inc/class.cinecturlink2.php
dcCore::app()->activityReport->addAction( ActivityReport::instance()->addAction(
'cinecturlink2', 'cinecturlink2',
'update', 'update',
__('updating link'), __('updating link'),
__('Cinecturlink named "%s" has been updated by "%s"'), __('Cinecturlink named "%s" has been updated by "%s"'),
'cinecturlink2AfterUpdLink', 'cinecturlink2AfterUpdLink',
['cinecturlink2ActivityReportBehaviors', 'updLink'] [self::class, 'updLink']
); );
// from BEHAVIOR cinecturlink2BeforeDelLink in cinecturlink2/inc/class.cinecturlink2.php // from BEHAVIOR cinecturlink2BeforeDelLink in cinecturlink2/inc/class.cinecturlink2.php
dcCore::app()->activityReport->addAction( ActivityReport::instance()->addAction(
'cinecturlink2', 'cinecturlink2',
'delete', 'delete',
__('link deletion'), __('link deletion'),
__('Cinecturlink named "%s" has been deleted by "%s"'), __('Cinecturlink named "%s" has been deleted by "%s"'),
'cinecturlink2BeforeDelLink', 'cinecturlink2BeforeDelLink',
['cinecturlink2ActivityReportBehaviors', 'delLink'] [self::class, 'delLink']
); );
} }
@ -55,30 +58,30 @@ class cinecturlink2ActivityReportBehaviors
$cur->link_title, $cur->link_title,
dcCore::app()->auth->getInfo('user_cn'), dcCore::app()->auth->getInfo('user_cn'),
]; ];
dcCore::app()->activityReport->addLog('cinecturlink2', 'create', $logs); ActivityReport::instance()->addLog('cinecturlink2', 'create', $logs);
} }
public static function updLink($cur, $id) public static function updLink($cur, $id)
{ {
$C2 = new cinecturlink2(); $C2 = new Utils();
$rs = $C2->getLinks(['link_id' => $id]); $rs = $C2->getLinks(['link_id' => $id]);
$logs = [ $logs = [
$rs->link_title, $rs->link_title,
dcCore::app()->auth->getInfo('user_cn'), dcCore::app()->auth->getInfo('user_cn'),
]; ];
dcCore::app()->activityReport->addLog('cinecturlink2', 'update', $logs); ActivityReport::instance()->addLog('cinecturlink2', 'update', $logs);
} }
public static function delLink($id) public static function delLink($id)
{ {
$C2 = new cinecturlink2(); $C2 = new Utils();
$rs = $C2->getLinks(['link_id' => $id]); $rs = $C2->getLinks(['link_id' => $id]);
$logs = [ $logs = [
$rs->link_title, $rs->link_title,
dcCore::app()->auth->getInfo('user_cn'), dcCore::app()->auth->getInfo('user_cn'),
]; ];
dcCore::app()->activityReport->addLog('cinecturlink2', 'delete', $logs); ActivityReport::instance()->addLog('cinecturlink2', 'delete', $logs);
} }
} }

View file

@ -10,17 +10,21 @@
* @copyright Jean-Christian Denis * @copyright 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
*/ */
class sitemapsCinecturlink2 declare(strict_types=1);
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
class PluginSitemaps
{ {
public static function sitemapsDefineParts($map_parts) public static function sitemapsDefineParts($map_parts)
{ {
$map_parts->offsetSet(__('Cinecturlink'), 'cinecturlink2'); $map_parts->offsetSet(My::name(), My::id());
} }
public static function sitemapsURLsCollect($sitemaps) public static function sitemapsURLsCollect($sitemaps)
{ {
dcCore::app()->blog->settings->addNamespace('sitemaps');
if (dcCore::app()->plugins->moduleExists('cinecturlink2') if (dcCore::app()->plugins->moduleExists('cinecturlink2')
&& dcCore::app()->blog->settings->sitemaps->sitemaps_cinecturlink2_url && dcCore::app()->blog->settings->sitemaps->sitemaps_cinecturlink2_url
) { ) {
@ -30,11 +34,10 @@ class sitemapsCinecturlink2
$sitemaps->addEntry($base, $prio, $freq); $sitemaps->addEntry($base, $prio, $freq);
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); $C2 = new Utils();
$C2 = new cinecturlink2();
$cats = $C2->getCategories(); $cats = $C2->getCategories();
while ($cats->fetch()) { while ($cats->fetch()) {
$sitemaps->addEntry($base . '/' . dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl . '/' . urlencode($cats->cat_title), $prio, $freq); $sitemaps->addEntry($base . '/' . dcCore::app()->blog->settings->cinecturlink2->public_caturl . '/' . urlencode($cats->cat_title), $prio, $freq);
} }
} }
} }

View file

@ -10,34 +10,42 @@
* @copyright Jean-Christian Denis * @copyright 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;
} namespace Dotclear\Plugin\cinecturlink2;
Clearbricks::lib()->autoload([ use dcCore;
'cinecturlink2' => __DIR__ . '/inc/class.cinecturlink2.php', use Dotclear\Core\Process;
'cinecturlink2Context' => __DIR__ . '/inc/lib.cinecturlink2.context.php',
'adminlistCinecturlink2' => __DIR__ . '/inc/lib.cinecturlink2.list.php', class Prepend extends Process
'sitemapsCinecturlink2' => __DIR__ . '/inc/lib.sitemaps.cinecturlink2.php', {
'cinecturlink2ActivityReportBehaviors' => __DIR__ . '/inc/lib.cinecturlink2.activityreport.php', public static function init(): bool
]); {
return self::status(My::checkContext(My::PREPEND));
dcCore::app()->url->register( }
'cinecturlink2',
'cinecturlink', public static function process(): bool
'^cinecturlink(?:/(.+))?$', {
['urlCinecturlink2', 'c2Page'] if (!self::status()) {
); return false;
}
dcCore::app()->addBehavior(
'sitemapsDefineParts', dcCore::app()->url->register(
['sitemapsCinecturlink2', 'sitemapsDefineParts'] My::id(),
); 'cinecturlink',
dcCore::app()->addBehavior( '^cinecturlink(?:/(.+))?$',
'sitemapsURLsCollect', [FrontendUrl::class, 'c2Page']
['sitemapsCinecturlink2', 'sitemapsURLsCollect'] );
);
dcCore::app()->addBehaviors([
if (defined('ACTIVITY_REPORT_V2')) { 'sitemapsDefineParts' => [PluginSitemaps::class, 'sitemapsDefineParts'],
cinecturlink2ActivityReportBehaviors::add(); 'sitemapsURLsCollect' => [PluginSitemaps::class, 'sitemapsURLsCollect'],
]);
if (defined('ACTIVITY_REPORT_V2')) {
PluginActivityReport::add();
}
return true;
}
} }

View file

@ -10,116 +10,71 @@
* @copyright Jean-Christian Denis * @copyright 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_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use Dotclear\Core\Process;
use Dotclear\Plugin\Uninstaller\Uninstaller;
class Uninstall extends Process
{
public static function init(): bool
{
return self::status(My::checkContext(My::UNINSTALL));
}
public static function process(): bool
{
if (!self::status() || !dcCore::app()->plugins->moduleExists('Uninstaller')) {
return false;
}
Uninstaller::instance()
->addUserAction(
'settings',
'delete_all',
My::id()
)
->addUserAction(
My::id() . 'DeletePostsMeta',
'delete_all',
My::id()
)
->addUserAction(
'tables',
'delete',
My::CINECTURLINK_TABLE_NAME,
)
->addUserAction(
'tables',
'delete',
My::CATEGORY_TABLE_NAME,
)
->addUserAction(
'plugins',
'delete',
My::id()
)
->addUserAction(
'versions',
'delete',
My::id()
)
->addDirectAction(
'plugins',
'delete',
My::id()
)
->addDirectAction(
'versions',
'delete',
My::id()
)
;
return false;
}
} }
$this->addUserAction(
/* type */
'settings',
/* action */
'delete_all',
/* ns */
'cinecturlink2',
/* desc */
__('delete all settings')
);
$this->addUserAction(
/* type */
'tables',
/* action */
'delete',
/* ns */
initCinecturlink2::CINECTURLINK_TABLE_NAME,
/* desc */
sprintf(__('delete %s table'), 'cinecturlink2')
);
$this->addUserAction(
/* type */
'tables',
/* action */
'delete',
/* ns */
initCinecturlink2::CATEGORY_TABLE_NAME,
/* desc */
sprintf(__('delete %s table'), 'cinecturlink2_cat')
);
$this->addUserAction(
/* type */
'versions',
/* action */
'delete',
/* ns */
'cinecturlink2',
/* desc */
__('delete the version number')
);
$this->addUserAction(
/* type */
'plugins',
/* action */
'delete',
/* ns */
'cinecturlink2',
/* desc */
__('delete plugin files')
);
$this->addDirectAction(
/* type */
'settings',
/* action */
'delete_all',
/* ns */
'cinecturlink2',
/* desc */
sprintf(__('delete all %s settings'), 'cinecturlink2')
);
$this->addDirectAction(
/* type */
'tables',
/* action */
'delete',
/* ns */
initCinecturlink2::CINECTURLINK_TABLE_NAME,
/* desc */
sprintf(__('delete %s table'), 'cinecturlink2')
);
$this->addDirectAction(
/* type */
'tables',
/* action */
'delete',
/* ns */
initCinecturlink2::CATEGORY_TABLE_NAME,
/* desc */
sprintf(__('delete %s table'), 'cinecturlink2_cat')
);
$this->addDirectAction(
/* type */
'versions',
/* action */
'delete',
/* ns */
'cinecturlink2',
/* desc */
sprintf(__('delete %s version number'), 'cinecturlink2')
);
$this->addDirectAction(
/* type */
'plugins',
/* action */
'delete',
/* ns */
'cinecturlink2',
/* description */
sprintf(__('delete %s plugin files'), 'cinecturlink2')
);

View file

@ -10,84 +10,132 @@
* @copyright Jean-Christian Denis * @copyright 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;
} namespace Dotclear\Plugin\cinecturlink2;
use dcCore;
use dcAuth;
use Dotclear\Database\{
AbstractHandler,
Cursor,
MetaRecord
};
use Dotclear\Database\Statement\{
DeleteStatement,
JoinStatement,
SelectStatement,
UpdateStatement
};
use Dotclear\Helper\File\Files;
use Dotclear\Helper\Text;
use Exception;
/** /**
* @ingroup DC_PLUGIN_CINECTURLINK2 * @ingroup DC_PLUGIN_CINECTURLINK2
* @brief Share media you like - main methods. * @brief Share media you like - main methods.
* @since 2.6 * @since 2.6
*/ */
class cinecturlink2 class Utils
{ {
/** @var dbLayer dbLayer instance */ /** @var AbstractHandler AbstractHandler instance */
public $con; public $con;
/** @var string Cinecturlink table name */ /** @var string Cinecturlink table name */
public $table; public $table;
/** @var string Cinecturlink category table name */ /** @var string Cinecturlink category table name */
public $cat_table; public $cat_table;
/** @var string Blog ID */ /** @var string Blog ID */
public $blog; public $blog;
/** /**
* Contructor * Contructor.
*/ */
public function __construct() public function __construct()
{ {
dcCore::app()->blog->settings->addNamespace('cinecturlink2');
$this->con = dcCore::app()->con; $this->con = dcCore::app()->con;
$this->table = dcCore::app()->prefix . initCinecturlink2::CINECTURLINK_TABLE_NAME; $this->table = dcCore::app()->prefix . My::CINECTURLINK_TABLE_NAME;
$this->cat_table = dcCore::app()->prefix . initCinecturlink2::CATEGORY_TABLE_NAME; $this->cat_table = dcCore::app()->prefix . My::CATEGORY_TABLE_NAME;
$this->blog = dcCore::app()->con->escape(dcCore::app()->blog->id); $this->blog = (string) dcCore::app()->blog?->id;
} }
/** /**
* Get links * Get links.
* *
* @param array $params Query params * @param array $params Query params
* @param boolean $count_only Count only result * @param bool $count_only Count only result
* @return record record instance * @return MetaRecord MetaRecord instance
*/ */
public function getLinks($params = [], $count_only = false) public function getLinks(array $params = [], bool $count_only = false): MetaRecord
{ {
if ($count_only) { $sql = new SelectStatement();
$strReq = 'SELECT count(L.link_id) ';
} else {
$content_req = '';
if (!empty($params['columns']) && is_array($params['columns'])) {
$content_req .= implode(', ', $params['columns']) . ', ';
}
$strReq = 'SELECT L.link_id, L.blog_id, L.cat_id, L.user_id, L.link_type, ' . if ($count_only) {
$content_req . $sql->column($sql->count($sql->unique('L.link_id')));
'L.link_creadt, L.link_upddt, L.link_note, L.link_count, ' . } else {
'L.link_title, L.link_desc, L.link_author, ' . if (!empty($params['columns']) && is_array($params['columns'])) {
'L.link_lang, L.link_url, L.link_img, ' . $sql->columns($params['columns']);
'U.user_name, U.user_firstname, U.user_displayname, U.user_email, ' . }
'U.user_url, ' . $sql->columns([
'C.cat_title, C.cat_desc '; 'L.link_id',
'L.blog_id',
'L.cat_id',
'L.user_id',
'L.link_type',
'L.link_creadt',
'L.link_upddt',
'L.link_note',
'L.link_count',
'L.link_title',
'L.link_desc',
'L.link_author',
'L.link_lang',
'L.link_url',
'L.link_img',
'U.user_name',
'U.user_firstname',
'U.user_displayname',
'U.user_email',
'U.user_url',
'C.cat_title',
'C.cat_desc',
]);
} }
$strReq .= 'FROM ' . $this->table . ' L ' . $sql
'INNER JOIN ' . dcCore::app()->prefix . dcAuth::USER_TABLE_NAME . ' U ON U.user_id = L.user_id ' . ->from($sql->as($this->table, 'L'), false, true)
'LEFT OUTER JOIN ' . $this->cat_table . ' C ON L.cat_id = C.cat_id '; ->join(
(new JoinStatement())
->inner()
->from($sql->as(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME, 'U'))
->on('U.user_id = L.user_id')
->statement()
)
->join(
(new JoinStatement())
->left()
->from($sql->as($this->cat_table, 'C'))
->on('L.cat_id = C.cat_id')
->statement()
);
if (!empty($params['join'])) {
$sql->join($params['join']);
}
if (!empty($params['from'])) { if (!empty($params['from'])) {
$strReq .= $params['from'] . ' '; $sql->from($params['from']);
} }
$strReq .= "WHERE L.blog_id = '" . $this->blog . "' "; $sql->where('L.blog_id = ' . $sql->quote(dcCore::app()->blog->id));
if (isset($params['link_type'])) { if (isset($params['link_type'])) {
if (is_array($params['link_type']) && !empty($params['link_type'])) { if (is_array($params['link_type']) && !empty($params['link_type'])) {
$strReq .= 'AND L.link_type ' . $this->con->in($params['link_type']); $sql->and('L.link_type' . $sql->in($params['link_type']));
} elseif ($params['link_type'] != '') { } elseif ($params['link_type'] != '') {
$strReq .= "AND L.link_type = '" . $this->con->escape($params['link_type']) . "' "; $sql->and('L.link_type = ' . $sql->quote($params['link_type']));
} }
} else { } else {
$strReq .= "AND L.link_type = 'cinecturlink' "; $sql->and('L.link_type = ' . $sql->quote('cinecturlink'));
} }
if (!empty($params['link_id'])) { if (!empty($params['link_id'])) {
@ -96,7 +144,7 @@ class cinecturlink2
} else { } else {
$params['link_id'] = [(int) $params['link_id']]; $params['link_id'] = [(int) $params['link_id']];
} }
$strReq .= 'AND L.link_id ' . $this->con->in($params['link_id']); $sql->and('L.link_id' . $sql->in($params['link_id']));
} }
if (!empty($params['cat_id'])) { if (!empty($params['cat_id'])) {
@ -109,54 +157,57 @@ class cinecturlink2
} else { } else {
$params['cat_id'] = [(int) $params['cat_id']]; $params['cat_id'] = [(int) $params['cat_id']];
} }
$strReq .= 'AND L.cat_id ' . $this->con->in($params['cat_id']); $sql->and('L.cat_id' . $sql->in($params['cat_id']));
} }
if (!empty($params['cat_title'])) { if (!empty($params['cat_title'])) {
$strReq .= "AND C.cat_title = '" . $this->con->escape($params['cat_title']) . "' "; $sql->and('C.cat_title = ' . $sql->quote($params['cat_title']));
} }
if (!empty($params['link_title'])) { if (!empty($params['link_title'])) {
$strReq .= "AND L.link_title = '" . $this->con->escape($params['link_title']) . "' "; $sql->and('L.link_title = ' . $sql->quote($params['link_title']));
} }
if (!empty($params['link_lang'])) { if (!empty($params['link_lang'])) {
$strReq .= "AND L.link_lang = '" . $this->con->escape($params['link_lang']) . "' "; $sql->and('L.link_lang = ' . $sql->quote($params['link_lang']));
} }
if (!empty($params['q'])) { if (!empty($params['q']) && is_string($params['q'])) {
$q = $this->con->escape(str_replace('*', '%', strtolower($params['q']))); $params['q'] = (string) str_replace('*', '%', strtolower($params['q']));
$strReq .= "AND LOWER(L.link_title) LIKE '%" . $q . "%' "; $words = Text::splitWords($params['q']);
}
if (!empty($params['where'])) { if (!empty($words)) {
$strReq .= $params['where'] . ' '; foreach ($words as $i => $w) {
$words[$i] = $sql->like('LOWER(L.link_title)', '%' . $sql->escape($w) . '%');
}
$sql->and($words);
}
} }
if (!empty($params['sql'])) { if (!empty($params['sql'])) {
$strReq .= $params['sql'] . ' '; $sql->sql($params['sql']);
} }
if (!$count_only) { if (!$count_only) {
if (!empty($params['order'])) { if (!empty($params['order'])) {
$strReq .= 'ORDER BY ' . $this->con->escape($params['order']) . ' '; $sql->order($sql->escape($params['order']));
} else { } else {
$strReq .= 'ORDER BY L.link_upddt DESC '; $sql->order('L.link_upddt DESC');
} }
} }
if (!$count_only && !empty($params['limit'])) { if (!$count_only && !empty($params['limit'])) {
$strReq .= $this->con->limit($params['limit']); $sql->limit($params['limit']);
} }
return $this->con->select($strReq); return $sql->select() ?? MetaRecord::newFromArray([]);
} }
/** /**
* Add link * Add link.
* *
* @param cursor $cur cursor instance * @param Cursor $cur Cursor instance
*/ */
public function addLink(cursor $cur) public function addLink(Cursor $cur): int
{ {
$this->con->writeLock($this->table); $this->con->writeLock($this->table);
@ -193,28 +244,29 @@ class cinecturlink2
# --BEHAVIOR-- cinecturlink2AfterAddLink # --BEHAVIOR-- cinecturlink2AfterAddLink
dcCore::app()->callBehavior('cinecturlink2AfterAddLink', $cur); dcCore::app()->callBehavior('cinecturlink2AfterAddLink', $cur);
return $cur->link_id; return (int) $cur->link_id;
} }
/** /**
* Update link * Update link.
* *
* @param integer $id Link ID * @param int $id Link ID
* @param cursor $cur cursor instance * @param Cursor $cur Cursor instance
* @param boolean $behavior Call related behaviors * @param bool $behavior Call related behaviors
*/ */
public function updLink($id, cursor $cur, $behavior = true) public function updLink(int $id, Cursor $cur, bool $behavior = true): void
{ {
$id = (int) $id;
if (empty($id)) { if (empty($id)) {
throw new Exception(__('No such link ID')); throw new Exception(__('No such link ID'));
} }
$cur->link_upddt = date('Y-m-d H:i:s'); $cur->link_upddt = date('Y-m-d H:i:s');
$cur->update('WHERE link_id = ' . $id . " AND blog_id = '" . $this->blog . "' "); $sql = new UpdateStatement();
$this->trigger(); $sql
->where('blog_id = ' . $sql->quote($this->blog))
->and('link_id = ' . $id)
->update($cur);
if ($behavior) { if ($behavior) {
# --BEHAVIOR-- cinecturlink2AfterUpdLink # --BEHAVIOR-- cinecturlink2AfterUpdLink
@ -223,14 +275,12 @@ class cinecturlink2
} }
/** /**
* Delete link * Delete link.
* *
* @param integer $id Link ID * @param int $id Link ID
*/ */
public function delLink($id) public function delLink(int $id): void
{ {
$id = (int) $id;
if (empty($id)) { if (empty($id)) {
throw new Exception(__('No such link ID')); throw new Exception(__('No such link ID'));
} }
@ -238,56 +288,67 @@ class cinecturlink2
# --BEHAVIOR-- cinecturlink2BeforeDelLink # --BEHAVIOR-- cinecturlink2BeforeDelLink
dcCore::app()->callBehavior('cinecturlink2BeforeDelLink', $id); dcCore::app()->callBehavior('cinecturlink2BeforeDelLink', $id);
$this->con->execute( $sql = new DeleteStatement();
'DELETE FROM ' . $this->table . ' ' . $sql
'WHERE link_id = ' . $id . ' ' . ->from($this->table)
"AND blog_id = '" . $this->blog . "' " ->where('blog_id = ' . $sql->quote($this->blog))
); ->and('link_id = ' . $id)
->delete();
$this->trigger(); $this->trigger();
} }
/** /**
* Get next link ID * Get next link ID.
* *
* @return integer Next link ID * @return int Next link ID
*/ */
private function getNextLinkId() private function getNextLinkId(): int
{ {
return $this->con->select( $sql = new SelectStatement();
'SELECT MAX(link_id) FROM ' . $this->table . ' '
)->f(0) + 1; return $sql
->column($sql->max('link_id'))
->from($this->table)
->select()
->f(0) + 1;
} }
/** /**
* Get categories * Get categories.
* *
* @param array $params Query params * @param array $params Query params
* @param boolean $count_only Count only result * @param bool $count_only Count only result
* @return record record instance * @return MetaRecord Record instance
*/ */
public function getCategories($params = [], $count_only = false) public function getCategories(array $params = [], bool $count_only = false): MetaRecord
{ {
if ($count_only) { $sql = new SelectStatement();
$strReq = 'SELECT count(C.cat_id) ';
} else {
$content_req = '';
if (!empty($params['columns']) && is_array($params['columns'])) {
$content_req .= implode(', ', $params['columns']) . ', ';
}
$strReq = 'SELECT C.cat_id, C.blog_id, C.cat_title, C.cat_desc, ' . if ($count_only) {
$content_req . $sql->column($sql->count($sql->unique('C.cat_id')));
'C.cat_pos, C.cat_creadt, C.cat_upddt '; } else {
if (!empty($params['columns']) && is_array($params['columns'])) {
$sql->columns($params['columns']);
}
$sql->columns([
'C.cat_id',
'C.blog_id',
'C.cat_title',
'C.cat_desc',
'C.cat_pos',
'C.cat_creadt',
'C.cat_upddt',
]);
} }
$strReq .= 'FROM ' . $this->cat_table . ' C '; $sql->from($sql->as($this->cat_table, 'C'));
if (!empty($params['from'])) { if (!empty($params['from'])) {
$strReq .= $params['from'] . ' '; $sql->from($params['from']);
} }
$strReq .= "WHERE C.blog_id = '" . $this->blog . "' "; $sql->where('C.blog_id = ' . $sql->quote(dcCore::app()->blog->id));
if (!empty($params['cat_id'])) { if (!empty($params['cat_id'])) {
if (is_array($params['cat_id'])) { if (is_array($params['cat_id'])) {
@ -299,7 +360,7 @@ class cinecturlink2
} else { } else {
$params['cat_id'] = [(int) $params['cat_id']]; $params['cat_id'] = [(int) $params['cat_id']];
} }
$strReq .= 'AND C.cat_id ' . $this->con->in($params['cat_id']); $sql->and('C.cat_id ' . $sql->in($params['cat_id']));
} }
if (isset($params['exclude_cat_id']) && $params['exclude_cat_id'] !== '') { if (isset($params['exclude_cat_id']) && $params['exclude_cat_id'] !== '') {
@ -312,39 +373,40 @@ class cinecturlink2
} else { } else {
$params['exclude_cat_id'] = [(int) $params['exclude_cat_id']]; $params['exclude_cat_id'] = [(int) $params['exclude_cat_id']];
} }
$strReq .= 'AND C.cat_id NOT ' . $this->con->in($params['exclude_cat_id']); $sql->and('C.cat_id NOT ' . $sql->in($params['exclude_cat_id']));
} }
if (!empty($params['cat_title'])) { if (!empty($params['cat_title'])) {
$strReq .= "AND C.cat_title = '" . $this->con->escape($params['cat_title']) . "' "; $sql->and('C.cat_title = ' . $sql->quote($params['cat_title']));
} }
if (!empty($params['sql'])) { if (!empty($params['sql'])) {
$strReq .= $params['sql'] . ' '; $sql->sql($params['sql']);
} }
if (!$count_only) { if (!$count_only) {
if (!empty($params['order'])) { if (!empty($params['order'])) {
$strReq .= 'ORDER BY ' . $this->con->escape($params['order']) . ' '; $sql->order($sql->escape($params['order']));
} else { } else {
$strReq .= 'ORDER BY cat_pos ASC '; $sql->order('cat_pos ASC');
} }
} }
if (!$count_only && !empty($params['limit'])) { if (!$count_only && !empty($params['limit'])) {
$strReq .= $this->con->limit($params['limit']); $sql->limit($params['limit']);
} }
return $this->con->select($strReq); return $sql->select() ?? MetaRecord::newFromArray([]);
} }
/** /**
* Add category * Add category.
* *
* @param cursor $cur cursor instance * @param Cursor $cur Cursor instance
* @return integer New category ID *
* @return int New category ID
*/ */
public function addCategory(cursor $cur) public function addCategory(Cursor $cur): int
{ {
$this->con->writeLock($this->cat_table); $this->con->writeLock($this->cat_table);
@ -370,99 +432,115 @@ class cinecturlink2
} }
$this->trigger(); $this->trigger();
return $cur->cat_id; return (int) $cur->cat_id;
} }
/** /**
* Update category * Update category.
* *
* @param integer $id Category ID * @param int $id Category ID
* @param cursor $cur cursor instance * @param Cursor $cur Cursor instance
*/ */
public function updCategory($id, cursor $cur) public function updCategory(int $id, Cursor $cur): void
{ {
$id = (int) $id;
if (empty($id)) { if (empty($id)) {
throw new Exception(__('No such category ID')); throw new Exception(__('No such category ID'));
} }
$cur->cat_upddt = date('Y-m-d H:i:s'); $cur->cat_upddt = date('Y-m-d H:i:s');
$cur->update('WHERE cat_id = ' . $id . " AND blog_id = '" . $this->blog . "' "); $sql = new UpdateStatement();
$sql
->where('blog_id = ' . $sql->quote($this->blog))
->and('cat_id = ' . $id)
->update($cur);
$this->trigger(); $this->trigger();
} }
/** /**
* Delete category * Delete category.
* *
* @param integer $id Category ID * @param int $id Category ID
*/ */
public function delCategory($id) public function delCategory(int $id): void
{ {
$id = (int) $id;
if (empty($id)) { if (empty($id)) {
throw new Exception(__('No such category ID')); throw new Exception(__('No such category ID'));
} }
$this->con->execute( $sql = new DeleteStatement();
'DELETE FROM ' . $this->cat_table . ' ' . $sql
'WHERE cat_id = ' . $id . ' ' . ->from($this->cat_table)
"AND blog_id = '" . $this->blog . "' " ->where('blog_id = ' . $sql->quote($this->blog))
); ->and('cat_id = ' . $id)
->delete();
# Update link cat to NULL # Update link cat to NULL
$cur = $this->con->openCursor($this->table); $cur = $this->con->openCursor($this->table);
$cur->cat_id = null; $cur->setField('cat_id', null);
$cur->link_upddt = date('Y-m-d H:i:s'); $cur->setField('link_upddt', date('Y-m-d H:i:s'));
$cur->update('WHERE cat_id = ' . $id . " AND blog_id = '" . $this->blog . "' ");
$sql = new UpdateStatement();
$sql
->where('blog_id = ' . $sql->quote($this->blog))
->and('cat_id = ' . $id)
->update($cur);
$this->trigger(); $this->trigger();
} }
/** /**
* Get next category ID * Get next category ID.
* *
* @return integer Next category ID * @return int Next category ID
*/ */
private function getNextCatId() private function getNextCatId(): int
{ {
return $this->con->select( $sql = new SelectStatement();
'SELECT MAX(cat_id) FROM ' . $this->cat_table . ' '
)->f(0) + 1; return $sql
->column($sql->max('cat_id'))
->from($this->cat_table)
->select()
->f(0) + 1;
} }
/** /**
* Get next category position * Get next category position.
* *
* @return integer Next category position * @return int Next category position
*/ */
private function getNextCatPos() private function getNextCatPos(): int
{ {
return $this->con->select( $sql = new SelectStatement();
'SELECT MAX(cat_pos) FROM ' . $this->cat_table . ' ' .
"WHERE blog_id = '" . $this->blog . "' " return $sql
)->f(0) + 1; ->column($sql->max('cat_pos'))
->from($this->cat_table)
->where('blog_id = ' . $sql->quote($this->blog))
->select()
->f(0) + 1;
} }
/** /**
* Trigger event * Trigger event.
*/ */
private function trigger() private function trigger(): void
{ {
dcCore::app()->blog->triggerBlog(); dcCore::app()->blog->triggerBlog();
} }
/** /**
* Check if a directory exists and is writable * Check if a directory exists and is writable.
* *
* @param string $root Root * @param string $root Root
* @param string $folder Folder to create into root folder * @param string $folder Folder to create into root folder
* @param boolean $throw Throw exception or not * @param bool $throw Throw exception or not
* @return boolean True if exists and writable *
* @return bool True if exists and writable
*/ */
public static function makePublicDir($root, $folder, $throw = false) public static function makePublicDir(string $root, string $folder, bool $throw = false): bool
{ {
if (!is_dir($root . '/' . $folder)) { if (!is_dir($root . '/' . $folder)) {
if (!is_dir($root) || !is_writable($root) || !mkdir($root . '/' . $folder)) { if (!is_dir($root) || !is_writable($root) || !mkdir($root . '/' . $folder)) {
@ -478,14 +556,14 @@ class cinecturlink2
} }
/** /**
* Get list of public directories * Get list of public directories.
* *
* @return array Directories * @return array<string,string> Directories
*/ */
public static function getPublicDirs() public static function getPublicDirs(): array
{ {
$dirs = []; $dirs = [];
$all = files::getDirList(dcCore::app()->blog->public_path); $all = Files::getDirList(dcCore::app()->blog->public_path);
foreach ($all['dirs'] as $dir) { foreach ($all['dirs'] as $dir) {
$dir = substr($dir, strlen(dcCore::app()->blog->public_path) + 1); $dir = substr($dir, strlen(dcCore::app()->blog->public_path) + 1);
$dirs[$dir] = $dir; $dirs[$dir] = $dir;

View file

@ -10,31 +10,23 @@
* @copyright Jean-Christian Denis * @copyright 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;
}
dcCore::app()->addBehavior( namespace Dotclear\Plugin\cinecturlink2;
'initWidgets',
['cinecturlink2Widget', 'adminLinks']
);
dcCore::app()->addBehavior(
'initWidgets',
['cinecturlink2Widget', 'adminCats']
);
class cinecturlink2Widget use dcCore;
use Dotclear\Helper\Html\Html;
use Dotclear\Plugin\widgets\WidgetsStack;
use Dotclear\Plugin\widgets\WidgetsElement;
class Widgets
{ {
public static function adminLinks($w) public static function initLinks(WidgetsStack $w): void
{ {
$C2 = new cinecturlink2(); $categories_combo = array_merge(
Combo::categoriesCombo(),
$categories_combo = ['' => '', __('Uncategorized') => 'null']; [__('Uncategorized') => 'null']
$categories = $C2->getCategories(); );
while ($categories->fetch()) {
$cat_title = html::escapeHTML($categories->cat_title);
$categories_combo[$cat_title] = $categories->cat_id;
}
$sortby_combo = [ $sortby_combo = [
__('Update date') => 'link_upddt', __('Update date') => 'link_upddt',
@ -52,7 +44,7 @@ class cinecturlink2Widget
->create( ->create(
'cinecturlink2links', 'cinecturlink2links',
__('My cinecturlink'), __('My cinecturlink'),
['cinecturlink2Widget', 'publicLinks'], [self::class, 'parseLinks'],
null, null,
__('Show selection of cinecturlinks') __('Show selection of cinecturlinks')
) )
@ -122,13 +114,13 @@ class cinecturlink2Widget
->addOffline(); ->addOffline();
} }
public static function adminCats($w) public static function initCats(WidgetsStack $w): void
{ {
$w $w
->create( ->create(
'cinecturlink2cats', 'cinecturlink2cats',
__('List of categories of cinecturlink'), __('List of categories of cinecturlink'),
['cinecturlink2Widget', 'publicCats'], [self::class, 'parseCats'],
null, null,
__('List of categories of cinecturlink') __('List of categories of cinecturlink')
) )
@ -153,18 +145,16 @@ class cinecturlink2Widget
->addOffline(); ->addOffline();
} }
public static function publicLinks($w) public static function parseLinks(WidgetsElement $w): string
{ {
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); if (!My::settings()->avtive
if (!dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_active
|| !$w->checkHomeOnly(dcCore::app()->url->type) || !$w->checkHomeOnly(dcCore::app()->url->type)
) { ) {
return null; return '';
} }
$C2 = new cinecturlink2(); $C2 = new Utils();
$aprams = []; $params = [];
if ($w->category) { if ($w->category) {
if ($w->category == 'null') { if ($w->category == 'null') {
@ -181,7 +171,7 @@ class cinecturlink2Widget
$big_rs = $C2->getLinks($params); $big_rs = $C2->getLinks($params);
if ($big_rs->isEmpty()) { if ($big_rs->isEmpty()) {
return null; return '';
} }
$ids = []; $ids = [];
@ -207,21 +197,21 @@ class cinecturlink2Widget
$rs = $C2->getLinks($params); $rs = $C2->getLinks($params);
if ($rs->isEmpty()) { if ($rs->isEmpty()) {
return null; return '';
} }
$widthmax = (int) dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_widthmax; $widthmax = (int) My::settings()->widthmax;
$style = $widthmax ? ' style="width:' . $widthmax . 'px;"' : ''; $style = $widthmax ? ' style="width:' . $widthmax . 'px;"' : '';
$entries = []; $entries = [];
while ($rs->fetch()) { while ($rs->fetch()) {
$url = $rs->link_url; $url = $rs->link_url;
$img = $rs->link_img; $img = $rs->link_img;
$title = html::escapeHTML($rs->link_title); $title = Html::escapeHTML($rs->link_title);
$author = html::escapeHTML($rs->link_author); $author = Html::escapeHTML($rs->link_author);
$cat = html::escapeHTML($rs->cat_title); $cat = Html::escapeHTML($rs->cat_title);
$note = $w->shownote ? ' <em>(' . $rs->link_note . '/20)</em>' : ''; $note = $w->shownote ? ' <em>(' . $rs->link_note . '/20)</em>' : '';
$desc = $w->showdesc ? '<br /><em>' . html::escapeHTML($rs->link_desc) . '</em>' : ''; $desc = $w->showdesc ? '<br /><em>' . Html::escapeHTML($rs->link_desc) . '</em>' : '';
$lang = $rs->link_lang ? ' hreflang="' . $rs->link_lang . '"' : ''; $lang = $rs->link_lang ? ' hreflang="' . $rs->link_lang . '"' : '';
$count = abs((int) $rs->link_count); $count = abs((int) $rs->link_count);
@ -240,7 +230,7 @@ class cinecturlink2Widget
try { try {
$cur = dcCore::app()->con->openCursor($C2->table); $cur = dcCore::app()->con->openCursor($C2->table);
$cur->link_count = ($count + 1); $cur->link_count = ($count + 1);
$C2->updLink($rs->link_id, $cur, false); $C2->updLink((int) $rs->link_id, $cur, false);
} catch (Exception $e) { } catch (Exception $e) {
} }
} }
@ -249,43 +239,41 @@ class cinecturlink2Widget
|| $w->sortby == 'COUNTER' || $w->sortby == 'COUNTER'
) { ) {
shuffle($entries); shuffle($entries);
if (dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_triggeronrandom) { if (My::settings()->triggeronrandom) {
dcCore::app()->blog->triggerBlog(); dcCore::app()->blog->triggerBlog();
} }
} }
return $w->renderDiv( return $w->renderDiv(
$w->content_only, (bool) $w->content_only,
'cinecturlink2list ' . $w->class, 'cinecturlink2list ' . $w->class,
'', '',
($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . implode(' ', $entries) . ($w->title ? $w->renderTitle(Html::escapeHTML($w->title)) : '') . implode(' ', $entries) .
( (
$w->showpagelink && dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_active ? $w->showpagelink && My::settings()->public_active ?
'<p><a href="' . dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . '" title="' . __('view all links') . '">' . __('More links') . '</a></p>' : '' '<p><a href="' . dcCore::app()->blog->url . dcCore::app()->url->getBase(My::id()) . '" title="' . __('view all links') . '">' . __('More links') . '</a></p>' : ''
) )
); );
} }
public static function publicCats($w) public static function parseCats(WidgetsElement $w): string
{ {
dcCore::app()->blog->settings->addNamespace('cinecturlink2'); if (!My::settings()->avtive
|| !My::settings()->public_active
if (!dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_active
|| !dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_active
|| !$w->checkHomeOnly(dcCore::app()->url->type) || !$w->checkHomeOnly(dcCore::app()->url->type)
) { ) {
return null; return '';
} }
$C2 = new cinecturlink2(); $C2 = new Utils();
$rs = $C2->getCategories([]); $rs = $C2->getCategories([]);
if ($rs->isEmpty()) { if ($rs->isEmpty()) {
return null; return '';
} }
$res = []; $res = [];
$res[] = '<li><a href="' . $res[] = '<li><a href="' .
dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . dcCore::app()->blog->url . dcCore::app()->url->getBase(My::id()) .
'" title="' . __('view all links') . '">' . __('all links') . '" title="' . __('view all links') . '">' . __('all links') .
'</a>' . ($w->shownumlink ? ' (' . ($C2->getLinks([], true)->f(0)) . ')' : '') . '</a>' . ($w->shownumlink ? ' (' . ($C2->getLinks([], true)->f(0)) . ')' : '') .
'</li>'; '</li>';
@ -293,20 +281,20 @@ class cinecturlink2Widget
while ($rs->fetch()) { while ($rs->fetch()) {
$res[] = '<li><a href="' . $res[] = '<li><a href="' .
dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . '/' . dcCore::app()->blog->url . dcCore::app()->url->getBase('cinecturlink2') . '/' .
dcCore::app()->blog->settings->cinecturlink2->cinecturlink2_public_caturl . '/' . My::settings()->public_caturl . '/' .
urlencode($rs->cat_title) . urlencode($rs->cat_title) .
'" title="' . __('view links of this category') . '">' . '" title="' . __('view links of this category') . '">' .
html::escapeHTML($rs->cat_title) . Html::escapeHTML($rs->cat_title) .
'</a>' . ($w->shownumlink ? ' (' . '</a>' . ($w->shownumlink ? ' (' .
($C2->getLinks(['cat_id' => $rs->cat_id], true)->f(0)) . ')' : '') . ($C2->getLinks(['cat_id' => $rs->cat_id], true)->f(0)) . ')' : '') .
'</li>'; '</li>';
} }
return $w->renderDiv( return $w->renderDiv(
$w->content_only, (bool) $w->content_only,
'cinecturlink2cat ' . $w->class, 'cinecturlink2cat ' . $w->class,
'', '',
($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . ($w->title ? $w->renderTitle(Html::escapeHTML($w->title)) : '') .
'<ul>' . implode(' ', $res) . '</ul>' '<ul>' . implode(' ', $res) . '</ul>'
); );
} }