From adc711f877776e965647ee58318512fd88132bcf Mon Sep 17 00:00:00 2001 From: Jean-Christian Denis Date: Mon, 21 Aug 2023 16:55:06 +0200 Subject: [PATCH] upgrade to dotclear 2.27 --- js/posts.js | 7 +- locales/fr/main.lang.php | 306 ++++++++-------- locales/fr/main.po | 318 ++++++++-------- src/Backend.php | 392 ++------------------ src/BackendBehaviors.php | 326 ++++++++++++++++ src/Combo.php | 48 +++ src/Config.php | 464 ++++++++++++++--------- src/Frontend.php | 591 +++--------------------------- src/FrontendBehaviors.php | 102 ++++++ src/FrontendTemplate.php | 205 +++++++++++ src/FrontendUrl.php | 211 +++++++++++ src/FrontendUtils.php | 53 +++ src/ImportExportBehaviors.php | 70 ++++ src/Install.php | 183 ++++----- src/LinksListing.php | 222 ++++++----- src/Logs.php | 257 +++++++------ src/Manage.php | 290 +++++++-------- src/ManageLinks.php | 163 ++++++++ src/My.php | 38 ++ src/Prepend.php | 157 ++++---- src/Service.php | 147 +++++--- src/Service/ServiceBilbolinks.php | 51 ++- src/Service/ServiceBitly.php | 62 ++-- src/Service/ServiceCustom.php | 104 ++++-- src/Service/ServiceDefault.php | 75 ++-- src/Service/ServiceIsgd.php | 21 +- src/Service/ServiceLocal.php | 191 ++++++---- src/Service/ServiceYourls.php | 88 +++-- src/Services/ServiceGoogl.php | 84 ----- src/Services/ServiceShortto.php | 58 --- src/Services/ServiceSupr.php | 124 ------- src/Services/ServiceTrim.php | 127 ------- src/Uninstall.php | 151 ++++---- src/Utils.php | 59 ++- src/Widgets.php | 112 +++--- src/Wiki.php | 39 +- 36 files changed, 3157 insertions(+), 2739 deletions(-) create mode 100644 src/BackendBehaviors.php create mode 100644 src/Combo.php create mode 100644 src/FrontendBehaviors.php create mode 100644 src/FrontendTemplate.php create mode 100644 src/FrontendUrl.php create mode 100644 src/FrontendUtils.php create mode 100644 src/ImportExportBehaviors.php create mode 100644 src/ManageLinks.php create mode 100644 src/My.php delete mode 100644 src/Services/ServiceGoogl.php delete mode 100644 src/Services/ServiceShortto.php delete mode 100644 src/Services/ServiceSupr.php delete mode 100644 src/Services/ServiceTrim.php diff --git a/js/posts.js b/js/posts.js index 4576328..04df616 100644 --- a/js/posts.js +++ b/js/posts.js @@ -1,7 +1,10 @@ -$(function(){ +/*global $, dotclear */ +'use strict'; + +$(() => { /* toogle admin form sidebar */ $('#kUtRL h5').toggleWithLegend( $('#kUtRL').children().not('h5'), - {cookie:'dcx_kUtRL_admin_form_sidebar',legend_click:true} + {user_pref:'dcx_kUtRL_admin_form_sidebar',legend_click:true} ); }); \ No newline at end of file diff --git a/locales/fr/main.lang.php b/locales/fr/main.lang.php index 1fe4215..6cf4017 100644 --- a/locales/fr/main.lang.php +++ b/locales/fr/main.lang.php @@ -9,155 +9,157 @@ # DOT NOT MODIFY THIS FILE ! # -l10n::$locales['Links shortener'] = 'Réducteur de liens'; -l10n::$locales['Short link'] = 'Lien court'; -l10n::$locales['Long link'] = 'Lien long'; -l10n::$locales['Service'] = 'Service'; -l10n::$locales['Hash'] = 'Hash'; -l10n::$locales['links per page'] = 'liens par page'; -l10n::$locales['Create short link'] = 'Créer un lien court'; -l10n::$locales['Custom short link:'] = 'Lien court personnalisé :'; -l10n::$locales['never followed'] = 'jamais suivi'; -l10n::$locales['followed one time'] = 'suivi une fois'; -l10n::$locales['followed %s times'] = 'suivi %s fois'; -l10n::$locales['Delete short link'] = 'Effacer un lien court'; -l10n::$locales['No enough right'] = 'Privilèges insuffisants'; -l10n::$locales['Posts short links have been created.'] = 'Les liens courts des billets ont été créé.'; -l10n::$locales['Disabled'] = 'Désactiver'; -l10n::$locales['Enable plugin'] = 'Activer le plugin'; -l10n::$locales['Behaviors'] = 'Comportements'; -l10n::$locales['Allow short link for external URL'] = 'Autoriser les liens court sur des URLs externes'; -l10n::$locales['Not only link started with this blog URL could be shortened.'] = 'Ne pas limiter la création de liens courts aux liens commençant par l\'URL du blog.'; -l10n::$locales['Passive mode'] = 'Mode passif'; -l10n::$locales['If this extension is disabled and the passive mode is enabled, "kutrl" tags (like EntryKurl) will display long urls instead of nothing on templates.'] = 'Si cette extension est désactivée et que le mode passif est activé, les balises "kutrl" (comme EntryKutrl) afficheront les liens longs au lieu de rien.'; -l10n::$locales['Active mode'] = 'Mode actif'; -l10n::$locales['If the active mode is enabled, all know default template tags (like EntryURL) will display short urls instead of long ones on templates.'] = 'Si le mode actif est acitvé, les balises de thème (comme EntryURL) afficheront les liens court au lieu des longs.'; -l10n::$locales['You can disable URL shortening for a specific template tag by adding attribute disable_kutrl="1" to it .'] = 'Vous pouvez désactiver le raccourcissement pour un tag de template spécifique en lui ajoutant l\'attribue disable_kutrl="1"'; -l10n::$locales['We strongly discourage using active mode as it crashes public post form and complex url if theme is not customize for kUtRL.'] = 'Nous décourageons fortement l\'utilisation du mode actif car il casse les formulaires en pages publiques et les liens complexe si le thème n\'est pas personnalisé pour utiliser kUtRL.'; -l10n::$locales['Create short link for new entries'] = 'Créer un lien court pour les nouveaux billets'; -l10n::$locales['This can be changed on page of creation/edition of an entry.'] = 'Ceci peut être changé sur la page d\'édition / création d\'un billet.'; -l10n::$locales['Default services'] = 'Services par défaut'; -l10n::$locales['Administration:'] = 'Administration :'; -l10n::$locales['Service to use in this admin page and on edit page of an entry.'] = 'Service à utiliser sur cette page d\'administration ou sur la page d\'édition d\'un billet.'; -l10n::$locales['Extensions:'] = 'Extensions :'; -l10n::$locales['Service to use on third part plugins.'] = 'Service à utiliser par les plugins tiers'; -l10n::$locales['Templates:'] = 'Templates :'; -l10n::$locales['Shorten links automatically when using template value like "EntryKutrl".'] = 'Réduit automatiquement les liens des templates utilisant les balises telles que "EntryKutrl".'; -l10n::$locales['Contents:'] = 'Contenus :'; -l10n::$locales['Shorten links automatically found in contents using wiki synthax.'] = 'Réduit automatiquement les liens des contenus utilisant la syntax wiki.'; -l10n::$locales['List of services you can use to shorten links with pkugin kUtRL.'] = 'Liste des services que vous pouvez utiliser pour réduire des liens à l\'aide du plugin kUtRL.'; -l10n::$locales['Failed to test %s API.'] = 'Impossible de tester l\'API %s.'; -l10n::$locales['%s API is well configured and runing.'] = 'L\'API %s est correctement configurée et est fonctionnelle.'; -l10n::$locales['Failed to test service %s: %s'] = 'Impossible de tester le service %s : %s'; -l10n::$locales['homepage'] = 'page d\'accueil'; -l10n::$locales['Learn more about %s.'] = 'En savoir plus à propos de %s.'; -l10n::$locales['Failed to verify protected field.'] = 'Impossible de vérifier le champs de protection.'; -l10n::$locales['Service is not well configured.'] = 'Le service n\'est pas correctement configuré.'; -l10n::$locales['This string is not a valid URL.'] = 'Cette chaine n\'est pas un lien valide.'; -l10n::$locales['This link is too short.'] = 'Ce lien est trop court.'; -l10n::$locales['This type of link is not allowed.'] = 'Ce type de lien n\'est pas autorisé.'; -l10n::$locales['Short links are limited to this blog URL.'] = 'Les liens courts sont limités à l\'URL de ce blog.'; -l10n::$locales['This link is already a short link.'] = 'Ce lien est dèjà un lien court.'; -l10n::$locales['Short link for %s is %s'] = 'Le lien court pour %s est %s'; -l10n::$locales['Failed to create short link.'] = 'Impossible de créer le lien court.'; -l10n::$locales['New public short URL'] = 'Nouvelle URL courte'; -l10n::$locales['Confirm by writing "%s" in next field:'] = 'Confirmez en écrivant "%s" dans le champs suivant :'; -l10n::$locales['Shorten link'] = 'Réduire un lien'; -l10n::$locales['Top of short links'] = 'Top des liens courts'; -l10n::$locales['Text: (Use wildcard %rank%, %hash%, %url%, %count%, %counttext%)'] = 'Texte : (Ustiliser les jokers %rank%, %hash%, %url%, %count%, %counttext%)'; -l10n::$locales['URL length (if truncate)'] = 'Longueur de l\'URL (si tronqué)'; -l10n::$locales['All'] = 'Tous'; -l10n::$locales['Mini URL'] = 'Mini URL'; -l10n::$locales['Custom URL'] = 'URL personnalisé'; -l10n::$locales['Semi-custom'] = 'Semi-personnalisé'; -l10n::$locales['Semi-custom prefix: (only if you want limit to a particular prefix)'] = 'Préfixe des liens semi-personnalisé : (Seulement si vous voulez limiter à un préfixe particulier)'; -l10n::$locales['Sort by:'] = 'Trier par :'; -l10n::$locales['Rank'] = 'Rang'; -l10n::$locales['Limit:'] = 'Limite :'; -l10n::$locales['Hide no followed links'] = 'Cacher les liens non suivis'; -l10n::$locales['Long link:'] = 'Lien long :'; -l10n::$locales['Rewrite "%s" in next field to show that you are not a robot:'] = 'Recopier "%s" dans le champs suivant pour montrer que vous n\'êtes pas une machine :'; -l10n::$locales['Shorten'] = 'Raccourir'; -l10n::$locales['Plugin kUtRL'] = 'Extension kUtRL'; -l10n::$locales['Short link creation'] = 'Création de lien court'; -l10n::$locales['New short link of type "%s" and hash "%s" was created.'] = 'Un nouveau lien court de type "%s" et de hash "%s" a été créé.'; -l10n::$locales['No short link matches the filter'] = 'Aucun lien correspondant au filtre'; -l10n::$locales['No short link'] = 'Pas de lien court'; -l10n::$locales['List of %s links matching the filter.'] = 'Liste des %s liens correspondant au filtre.'; -l10n::$locales['List of links (%s)'] = 'Listes des liens (%s)'; -l10n::$locales['There is nothing to configure for this service.'] = 'Il n\'y a rien à configurer pour ce service.'; -l10n::$locales['%s (Shorten with %s)'] = '%s (réduit avec %s)'; -l10n::$locales['New short URL'] = 'Nouvelle URL courte'; -l10n::$locales['Url of the service:'] = 'URL du service :'; -l10n::$locales['This is the root URL of the "bilbolinks" service you want to use. Ex: "http://tux-pla.net/".'] = 'Ceci est l\'URL du service bilbolinks que vous souhaitez utiliser. Ex: "http://tux-pla.net/".'; -l10n::$locales['Service is unavailable.'] = 'Le service n\'est pas disponible.'; -l10n::$locales['Service rate limit exceeded.'] = 'La limitation d\'envoie au service est atteinte.'; -l10n::$locales['API Key:'] = 'Clé API :'; -l10n::$locales['This is your personnal %s API key. You can find it on your account page.'] = 'C\'est votre clé personnelle de l\'API %s. Vous pouvez la trouver sur la page de votre compte.'; -l10n::$locales['Failed to call service.'] = 'Impossible d\'appeler le service.'; -l10n::$locales['You can set a configurable service.'] = 'Vous pouvez configurer un service particulier.'; -l10n::$locales['It consists on a simple query to an URL with only one param.'] = 'Il effectue une simple requête à une URL avec un seul paramètre.'; -l10n::$locales['It must respond with a http code 200 on success.'] = 'Il doit répondre avec un code HTTP de 200 en cas de succès'; -l10n::$locales['It must returned the short URL (or only hash) in clear text.'] = 'Il doit retourner l\'URL courte (ou seulement le hash) en texte clair.'; -l10n::$locales['API URL:'] = 'URL de l\'API:'; -l10n::$locales['Full path to API of the URL shortener. ex: "http://is.gd/api.php"'] = 'Chemin complet vers l\'API. ex: "http://is.gd.php"'; -l10n::$locales['Short URL domain:'] = 'Domaine des URLs courtes:'; -l10n::$locales['Common part of the short URL. ex: "http://is.gd/"'] = 'Partie commune aux URLs courtes. ex: "http://is.gd/"'; -l10n::$locales['API URL param:'] = 'Paramètre de l\'URL'; -l10n::$locales['Param of the query. ex: "longurl"'] = 'Paramètre de la raquête. ex: "longurl"'; -l10n::$locales['Encode URL'] = 'Encoder l\'URL à raccourcir'; -l10n::$locales['This service is set to:'] = 'Ce service est règlé comme suit:'; -l10n::$locales['Full API URL:'] = 'URL complet vers l\'API:'; -l10n::$locales['Query param:'] = 'Paramètre de la requête:'; -l10n::$locales['Encode URL:'] = 'Encodage des URLs à raccourcir:'; -l10n::$locales['Settings:'] = 'Paramètres :'; -l10n::$locales['Allowed protocols:'] = 'Protocoles autorisés :'; -l10n::$locales['Use comma seperated list like: "http:,https:,ftp:"'] = 'Utiliser une virgule pour séparer la liste des protocoles. Ex: "http:,https:,ftp:"'; -l10n::$locales['Enable public page for visitors to shorten links'] = 'Activer la page publique pour que les visiteurs puissent réduire des liens'; -l10n::$locales['CSS:'] = 'CSS :'; -l10n::$locales['You can add here special cascading style sheet. Body of page has class "dc-kutrl" and widgets have class "shortenkutrlwidget" and "rankkutrlwidget".'] = 'Vous pouvez ajouter des styles ici. La balise "body" a la class "dc-kutrl" et les widgets ont les class "shortenkutrlwidget" et "rankkutrlwidget".'; -l10n::$locales['Enable special 404 error public page for unknow urls'] = 'Activer la page spéciale d\'erreur 404 pour les liens inconnus'; -l10n::$locales['If this is not activated, the default 404 page of the theme will be display.'] = 'Si cette option est désactivée, la page d\'erreur 404 par défaut du thème sera utilisée.'; -l10n::$locales['Note:'] = 'Note :'; -l10n::$locales['This service use your own Blog to shorten and serve URL.'] = 'Ce service utilise votre propre blog pour réduire et servir des liens.'; -l10n::$locales['This means that with this service short links start with "%s".'] = 'Cela signifie qu\'avec ce service vos liens courts commencent par "%s".'; -l10n::$locales['You can use Dotclear\'s plugin called myUrlHandlers to change short links prefix on your blog.'] = 'Vous pouvez utiliser l\'extension myUrlHandlers pour Dotclear afin de changer le prefix de vos liens courts depuis votre blog.'; -l10n::$locales['We recommand that you use a rewrite engine in order to remove \'index.php\' from your blog\'s URL.'] = 'Nous vous recommandons d\'utiliser la réécriture d\'URL pour supprimer \'index.php de l\'URL de votre blog.'; -l10n::$locales['You can find more about this on the Dotclear\'s documentation.'] = 'Vous trouverez plus d\'information à ce sujet dans la documentation Dotclear.'; -l10n::$locales['There are two templates delivered with kUtRL, if you do not use default theme, you may adapt them to yours.'] = 'Il y a deux templates livrés avec kUtRL, si vous n\'utilisez pas le thème par défaut, vous devrez peut-être les adapter au votre.'; -l10n::$locales['Files are in plugin directory /default-templates, just copy them into your theme and edit them.'] = 'Les fichiers sont dans le répertoire /default-templates du plugin, copiez les dans votre thème et modifiez les.'; -l10n::$locales['Custom short link is already taken.'] = 'Le lien court personnalisé est déjà pris.'; -l10n::$locales['Custom short link is not valid.'] = 'Le lien court personnalisé n\'est pas valide.'; -l10n::$locales['Failed to save link.'] = 'Impossible d\'enregistrer le lien.'; -l10n::$locales['Login:'] = 'Identifiant :'; -l10n::$locales['This is your login to sign up to %s'] = 'C\'est votre identifiant pour vous connecter sur %s'; -l10n::$locales['An error occured with code %s and message "%s"'] = 'Une erreur est survenu avec le code "%s" et le message "%s"'; -l10n::$locales['This is your login to sign up to tr.im.'] = 'Ceci est votre login d\'inscription sur tr.im.'; -l10n::$locales['This is your password to sign up to tr.im.'] = 'Ceci est votre mot de passe d\'inscription sur tr.im.'; -l10n::$locales['Prevent service rate limit.'] = 'Prévention de la limitation d\'envoie du service.'; -l10n::$locales['Authentication to service failed.'] = 'Authentification au service échoué.'; -l10n::$locales['Unreadable service response.'] = 'La réponse du service n\'est pas lisible.'; -l10n::$locales['This is the URL of the YOURLS service you want to use. Ex: "http://www.smaller.org/api.php".'] = 'Ceci est l\'URL du service YOURLS que vous voulez utiliser. Ex: "http://www.smaller.org/api.php".'; -l10n::$locales['This is your user name to sign up to this YOURLS service.'] = 'Ceci est votre nom d\'utilisateur pour vous connecter à ce service YOURLS.'; -l10n::$locales['This is your password to sign up to this YOURLS service.'] = 'Ceci est votre mot de passe pour vous connecter à ce service YOURLS.'; -l10n::$locales['There is nothing to shorten.'] = 'I n\'y a rien à réduire.'; -l10n::$locales['This service does not allowed custom hash.'] = 'Ce service n\'accepte pas les liens court personnalisés.'; -l10n::$locales['This link is not a valid URL.'] = 'Ce lien n\'est pas valide.'; -l10n::$locales['This custom short url is already taken.'] = 'Ce lien court personnalisé est déjà pris.'; -l10n::$locales['Failed to create short link. This could be caused by a service failure.'] = 'Impossible de créé un lien court. Ceci peut être causé par un problème du service.'; -l10n::$locales['Service:'] = 'Service :'; -l10n::$locales['Links successfully deleted'] = 'Liens supprimés avec succès'; -l10n::$locales['New link'] = 'Nouveau lien'; -l10n::$locales['You must set an admin service.'] = 'Vous devez définir un service admin.'; -l10n::$locales['Shorten link using service "%s"'] = 'Raccourcir un lien en utilisant le service "%s"'; -l10n::$locales['Only if you want a custom short link.'] = 'Uniquement si vous souhaitez un lien court personnalisé.'; -l10n::$locales['You can use "bob!!" if you want a semi-custom link, it starts with "bob" and "!!" will be replaced by an increment value.'] = 'Vous pouvez utiliser "bob!!" si vous souhaitez un lien semi-personnalisé, il commencera par "bob" et "!!" sera remplacé par une valeur incrémentale.'; -l10n::$locales['Delete selected short links'] = 'Effacer les liens court sélectionnés'; -l10n::$locales['Configuration successfully saved'] = 'Configuration sauvegardée avec succès'; -l10n::$locales['Plugin activation'] = 'Activation'; -l10n::$locales['URL not found'] = 'Lien non trouvé'; -l10n::$locales['The URL you are looking for does not exist.'] = 'Le liens que vous recherchez n\'existe pas.'; -l10n::$locales['Create your own short URL'] = 'Créer votre propre lien court'; -l10n::$locales['Publish history'] = 'Publier l\'historique'; -l10n::$locales['This publish all short links on your bit.ly public page.'] = 'Ceci publie tous vos liens sur votre page public bit.ly'; -l10n::$locales['Use, create and serve short url on your blog'] = 'Utiliser, créer et servir des liens court sur votre blog'; +use Dotclear\Helper\L10n; + +L10n::$locales['Links shortener'] = 'Réducteur de liens'; +L10n::$locales['Long link:'] = 'Lien long :'; +L10n::$locales['Shorten'] = 'Raccourir'; +L10n::$locales['URL not found'] = 'Lien non trouvé'; +L10n::$locales['The URL you are looking for does not exist.'] = 'Le liens que vous recherchez n\'existe pas.'; +L10n::$locales['Create your own short URL'] = 'Créer votre propre lien court'; +L10n::$locales['Plugin kUtRL'] = 'Extension kUtRL'; +L10n::$locales['Short link creation'] = 'Création de lien court'; +L10n::$locales['New short link of type "%s" and hash "%s" was created.'] = 'Un nouveau lien court de type "%s" et de hash "%s" a été créé.'; +L10n::$locales['Hash'] = 'Hash'; +L10n::$locales['Service'] = 'Service'; +L10n::$locales['links per page'] = 'liens par page'; +L10n::$locales['Create short link'] = 'Créer un lien court'; +L10n::$locales['Custom short link:'] = 'Lien court personnalisé :'; +L10n::$locales['never followed'] = 'jamais suivi'; +L10n::$locales['followed one time'] = 'suivi une fois'; +L10n::$locales['followed %s times'] = 'suivi %s fois'; +L10n::$locales['Delete short link'] = 'Effacer un lien court'; +L10n::$locales['Short link'] = 'Lien court'; +L10n::$locales['No enough right'] = 'Privilèges insuffisants'; +L10n::$locales['Posts short links have been created.'] = 'Les liens courts des billets ont été créé.'; +L10n::$locales['Long link'] = 'Lien long'; +L10n::$locales['Disabled'] = 'Désactiver'; +L10n::$locales['Failed to test %s API.'] = 'Impossible de tester l\'API %s.'; +L10n::$locales['%s API is well configured and runing.'] = 'L\'API %s est correctement configurée et est fonctionnelle.'; +L10n::$locales['Failed to test service %s: %s'] = 'Impossible de tester le service %s : %s'; +L10n::$locales['homepage'] = 'page d\'accueil'; +L10n::$locales['Learn more about %s.'] = 'En savoir plus à propos de %s.'; +L10n::$locales['Enable plugin'] = 'Activer le plugin'; +L10n::$locales['Behaviors'] = 'Comportements'; +L10n::$locales['Allow short link for external URL'] = 'Autoriser les liens court sur des URLs externes'; +L10n::$locales['Not only link started with this blog URL could be shortened.'] = 'Ne pas limiter la création de liens courts aux liens commençant par l\'URL du blog.'; +L10n::$locales['Passive mode'] = 'Mode passif'; +L10n::$locales['If this extension is disabled and the passive mode is enabled, "kutrl" tags (like EntryKurl) will display long urls instead of nothing on templates.'] = 'Si cette extension est désactivée et que le mode passif est activé, les balises "kutrl" (comme EntryKutrl) afficheront les liens longs au lieu de rien.'; +L10n::$locales['Active mode'] = 'Mode actif'; +L10n::$locales['If the active mode is enabled, all know default template tags (like EntryURL) will display short urls instead of long ones on templates.'] = 'Si le mode actif est acitvé, les balises de thème (comme EntryURL) afficheront les liens court au lieu des longs.'; +L10n::$locales['You can disable URL shortening for a specific template tag by adding attribute disable_kutrl="1" to it .'] = 'Vous pouvez désactiver le raccourcissement pour un tag de template spécifique en lui ajoutant l\'attribue disable_kutrl="1"'; +L10n::$locales['We strongly discourage using active mode as it crashes public post form and complex url if theme is not customize for kUtRL.'] = 'Nous décourageons fortement l\'utilisation du mode actif car il casse les formulaires en pages publiques et les liens complexe si le thème n\'est pas personnalisé pour utiliser kUtRL.'; +L10n::$locales['Create short link for new entries'] = 'Créer un lien court pour les nouveaux billets'; +L10n::$locales['This can be changed on page of creation/edition of an entry.'] = 'Ceci peut être changé sur la page d\'édition / création d\'un billet.'; +L10n::$locales['Default services'] = 'Services par défaut'; +L10n::$locales['Administration:'] = 'Administration :'; +L10n::$locales['Service to use in this admin page and on edit page of an entry.'] = 'Service à utiliser sur cette page d\'administration ou sur la page d\'édition d\'un billet.'; +L10n::$locales['Extensions:'] = 'Extensions :'; +L10n::$locales['Service to use on third part plugins.'] = 'Service à utiliser par les plugins tiers'; +L10n::$locales['Templates:'] = 'Templates :'; +L10n::$locales['Shorten links automatically when using template value like "EntryKutrl".'] = 'Réduit automatiquement les liens des templates utilisant les balises telles que "EntryKutrl".'; +L10n::$locales['Contents:'] = 'Contenus :'; +L10n::$locales['Shorten links automatically found in contents using wiki synthax.'] = 'Réduit automatiquement les liens des contenus utilisant la syntax wiki.'; +L10n::$locales['List of services you can use to shorten links with pkugin kUtRL.'] = 'Liste des services que vous pouvez utiliser pour réduire des liens à l\'aide du plugin kUtRL.'; +L10n::$locales['New public short URL'] = 'Nouvelle URL courte'; +L10n::$locales['Confirm by writing "%s" in next field:'] = 'Confirmez en écrivant "%s" dans le champs suivant :'; +L10n::$locales['Failed to verify protected field.'] = 'Impossible de vérifier le champs de protection.'; +L10n::$locales['Service is not well configured.'] = 'Le service n\'est pas correctement configuré.'; +L10n::$locales['This string is not a valid URL.'] = 'Cette chaine n\'est pas un lien valide.'; +L10n::$locales['This link is too short.'] = 'Ce lien est trop court.'; +L10n::$locales['This type of link is not allowed.'] = 'Ce type de lien n\'est pas autorisé.'; +L10n::$locales['Short links are limited to this blog URL.'] = 'Les liens courts sont limités à l\'URL de ce blog.'; +L10n::$locales['This link is already a short link.'] = 'Ce lien est dèjà un lien court.'; +L10n::$locales['Short link for %s is %s'] = 'Le lien court pour %s est %s'; +L10n::$locales['Failed to create short link.'] = 'Impossible de créer le lien court.'; +L10n::$locales['No short link matches the filter'] = 'Aucun lien correspondant au filtre'; +L10n::$locales['No short link'] = 'Pas de lien court'; +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['There is nothing to shorten.'] = 'Il n\'y a rien à réduire.'; +L10n::$locales['This service does not allowed custom hash.'] = 'Ce service n\'accepte pas les liens court personnalisés.'; +L10n::$locales['This link is not a valid URL.'] = 'Ce lien n\'est pas valide.'; +L10n::$locales['This custom short url is already taken.'] = 'Ce lien court personnalisé est déjà pris.'; +L10n::$locales['Failed to create short link. This could be caused by a service failure.'] = 'Impossible de créé un lien court. Ceci peut être causé par un problème du service.'; +L10n::$locales['New short URL'] = 'Nouvelle URL courte'; +L10n::$locales['New link'] = 'Nouveau lien'; +L10n::$locales['You must set an admin service.'] = 'Vous devez définir un service admin.'; +L10n::$locales['Only if you want a custom short link.'] = 'Uniquement si vous souhaitez un lien court personnalisé.'; +L10n::$locales['You can use "bob!!" if you want a semi-custom link, it starts with "bob" and "!!" will be replaced by an increment value.'] = 'Vous pouvez utiliser "bob!!" si vous souhaitez un lien semi-personnalisé, il commencera par "bob" et "!!" sera remplacé par une valeur incrémentale.'; +L10n::$locales['Shorten link using service "%s"'] = 'Raccourcir un lien en utilisant le service "%s"'; +L10n::$locales['Service:'] = 'Service :'; +L10n::$locales['Links successfully deleted'] = 'Liens supprimés avec succès'; +L10n::$locales['Delete selected short links'] = 'Effacer les liens court sélectionnés'; +L10n::$locales['Url of the service:'] = 'URL du service :'; +L10n::$locales['This is the root URL of the "bilbolinks" service you want to use. Ex: "http://tux-pla.net/".'] = 'Ceci est l\'URL du service bilbolinks que vous souhaitez utiliser. Ex: "http://tux-pla.net/".'; +L10n::$locales['Service is unavailable.'] = 'Le service n\'est pas disponible.'; +L10n::$locales['Service rate limit exceeded.'] = 'La limitation d\'envoie au service est atteinte.'; +L10n::$locales['API Key:'] = 'Clé API :'; +L10n::$locales['This is your personnal %s API key. You can find it on your account page.'] = 'C\'est votre clé personnelle de l\'API %s. Vous pouvez la trouver sur la page de votre compte.'; +L10n::$locales['Failed to call service.'] = 'Impossible d\'appeler le service.'; +L10n::$locales['You can set a configurable service.'] = 'Vous pouvez configurer un service particulier.'; +L10n::$locales['It consists on a simple query to an URL with only one param.'] = 'Il effectue une simple requête à une URL avec un seul paramètre.'; +L10n::$locales['It must respond with a http code 200 on success.'] = 'Il doit répondre avec un code HTTP de 200 en cas de succès'; +L10n::$locales['It must returned the short URL (or only hash) in clear text.'] = 'Il doit retourner l\'URL courte (ou seulement le hash) en texte clair.'; +L10n::$locales['API URL:'] = 'URL de l\'API:'; +L10n::$locales['Full path to API of the URL shortener. ex: "http://is.gd/api.php"'] = 'Chemin complet vers l\'API. ex: "http://is.gd.php"'; +L10n::$locales['Short URL domain:'] = 'Domaine des URLs courtes:'; +L10n::$locales['Common part of the short URL. ex: "http://is.gd/"'] = 'Partie commune aux URLs courtes. ex: "http://is.gd/"'; +L10n::$locales['API URL param:'] = 'Paramètre de l\'URL'; +L10n::$locales['Param of the query. ex: "longurl"'] = 'Paramètre de la raquête. ex: "longurl"'; +L10n::$locales['Encode URL'] = 'Encoder l\'URL à raccourcir'; +L10n::$locales['There is nothing to configure for this service.'] = 'Il n\'y a rien à configurer pour ce service.'; +L10n::$locales['Full API URL:'] = 'URL complet vers l\'API:'; +L10n::$locales['Query param:'] = 'Paramètre de la requête:'; +L10n::$locales['Encode URL:'] = 'Encodage des URLs à raccourcir:'; +L10n::$locales['Settings:'] = 'Paramètres :'; +L10n::$locales['Allowed protocols:'] = 'Protocoles autorisés :'; +L10n::$locales['Use comma seperated list like: "http:,https:,ftp:"'] = 'Utiliser une virgule pour séparer la liste des protocoles. Ex: "http:,https:,ftp:"'; +L10n::$locales['Enable public page for visitors to shorten links'] = 'Activer la page publique pour que les visiteurs puissent réduire des liens'; +L10n::$locales['CSS:'] = 'CSS :'; +L10n::$locales['You can add here special cascading style sheet. Body of page has class "dc-kutrl" and widgets have class "shortenkutrlwidget" and "rankkutrlwidget".'] = 'Vous pouvez ajouter des styles ici. La balise "body" a la class "dc-kutrl" et les widgets ont les class "shortenkutrlwidget" et "rankkutrlwidget".'; +L10n::$locales['Enable special 404 error public page for unknow urls'] = 'Activer la page spéciale d\'erreur 404 pour les liens inconnus'; +L10n::$locales['If this is not activated, the default 404 page of the theme will be display.'] = 'Si cette option est désactivée, la page d\'erreur 404 par défaut du thème sera utilisée.'; +L10n::$locales['Note:'] = 'Note :'; +L10n::$locales['This service use your own Blog to shorten and serve URL.'] = 'Ce service utilise votre propre blog pour réduire et servir des liens.'; +L10n::$locales['This means that with this service short links start with "%s".'] = 'Cela signifie qu\'avec ce service vos liens courts commencent par "%s".'; +L10n::$locales['You can use Dotclear\'s plugin called myUrlHandlers to change short links prefix on your blog.'] = 'Vous pouvez utiliser l\'extension myUrlHandlers pour Dotclear afin de changer le prefix de vos liens courts depuis votre blog.'; +L10n::$locales['We recommand that you use a rewrite engine in order to remove \'index.php\' from your blog\'s URL.'] = 'Nous vous recommandons d\'utiliser la réécriture d\'URL pour supprimer \'index.php de l\'URL de votre blog.'; +L10n::$locales['You can find more about this on the Dotclear\'s documentation.'] = 'Vous trouverez plus d\'information à ce sujet dans la documentation Dotclear.'; +L10n::$locales['There are two templates delivered with kUtRL, if you do not use default theme, you may adapt them to yours.'] = 'Il y a deux templates livrés avec kUtRL, si vous n\'utilisez pas le thème par défaut, vous devrez peut-être les adapter au votre.'; +L10n::$locales['Files are in plugin directory /default-templates, just copy them into your theme and edit them.'] = 'Les fichiers sont dans le répertoire /default-templates du plugin, copiez les dans votre thème et modifiez les.'; +L10n::$locales['Custom short link is already taken.'] = 'Le lien court personnalisé est déjà pris.'; +L10n::$locales['Custom short link is not valid.'] = 'Le lien court personnalisé n\'est pas valide.'; +L10n::$locales['Failed to save link.'] = 'Impossible d\'enregistrer le lien.'; +L10n::$locales['This is the URL of the YOURLS service you want to use. Ex: "http://www.smaller.org/api.php".'] = 'Ceci est l\'URL du service YOURLS que vous voulez utiliser. Ex: "http://www.smaller.org/api.php".'; +L10n::$locales['Login:'] = 'Identifiant :'; +L10n::$locales['This is your user name to sign up to this YOURLS service.'] = 'Ceci est votre nom d\'utilisateur pour vous connecter à ce service YOURLS.'; +L10n::$locales['This is your password to sign up to this YOURLS service.'] = 'Ceci est votre mot de passe pour vous connecter à ce service YOURLS.'; +L10n::$locales['Authentication to service failed.'] = 'Authentification au service échoué.'; +L10n::$locales['Unreadable service response.'] = 'La réponse du service n\'est pas lisible.'; +L10n::$locales['Shorten link'] = 'Réduire un lien'; +L10n::$locales['Top of short links'] = 'Top des liens courts'; +L10n::$locales['Text: (Use wildcard %rank%, %hash%, %url%, %count%, %counttext%)'] = 'Texte : (Ustiliser les jokers %rank%, %hash%, %url%, %count%, %counttext%)'; +L10n::$locales['URL length (if truncate)'] = 'Longueur de l\'URL (si tronqué)'; +L10n::$locales['All'] = 'Tous'; +L10n::$locales['Mini URL'] = 'Mini URL'; +L10n::$locales['Custom URL'] = 'URL personnalisé'; +L10n::$locales['Semi-custom'] = 'Semi-personnalisé'; +L10n::$locales['Semi-custom prefix: (only if you want limit to a particular prefix)'] = 'Préfixe des liens semi-personnalisé : (Seulement si vous voulez limiter à un préfixe particulier)'; +L10n::$locales['Sort by:'] = 'Trier par :'; +L10n::$locales['Rank'] = 'Rang'; +L10n::$locales['Limit:'] = 'Limite :'; +L10n::$locales['Hide no followed links'] = 'Cacher les liens non suivis'; +L10n::$locales['Rewrite "%s" in next field to show that you are not a robot:'] = 'Recopier "%s" dans le champs suivant pour montrer que vous n\'êtes pas une machine :'; +L10n::$locales['%s (Shorten with %s)'] = '%s (réduit avec %s)'; +L10n::$locales['List of links (%s)'] = 'Listes des liens (%s)'; +L10n::$locales['This service is set to:'] = 'Ce service est règlé comme suit:'; +L10n::$locales['This is your login to sign up to %s'] = 'C\'est votre identifiant pour vous connecter sur %s'; +L10n::$locales['An error occured with code %s and message "%s"'] = 'Une erreur est survenu avec le code "%s" et le message "%s"'; +L10n::$locales['This is your login to sign up to tr.im.'] = 'Ceci est votre login d\'inscription sur tr.im.'; +L10n::$locales['This is your password to sign up to tr.im.'] = 'Ceci est votre mot de passe d\'inscription sur tr.im.'; +L10n::$locales['Prevent service rate limit.'] = 'Prévention de la limitation d\'envoie du service.'; +L10n::$locales['Configuration successfully saved'] = 'Configuration sauvegardée avec succès'; +L10n::$locales['Publish history'] = 'Publier l\'historique'; +L10n::$locales['This publish all short links on your bit.ly public page.'] = 'Ceci publie tous vos liens sur votre page public bit.ly'; +L10n::$locales['Use, create and serve short url on your blog'] = 'Utiliser, créer et servir des liens court sur votre blog'; diff --git a/locales/fr/main.po b/locales/fr/main.po index 71de2d1..79d61b5 100644 --- a/locales/fr/main.po +++ b/locales/fr/main.po @@ -1,10 +1,10 @@ msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" -"Project-Id-Version: kUtRL 2022.11.12\n" +"Project-Id-Version: kUtRL 2022.08.21\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2022-11-20T16:20:38+00:00\n" -"Last-Translator: Jean-Crhistian Denis\n" +"PO-Revision-Date: 2023-08-21T14:43:14+00:00\n" +"Last-Translator: Jean-Christain Denis\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" @@ -13,18 +13,36 @@ msgstr "" msgid "Links shortener" msgstr "Réducteur de liens" -msgid "Short link" -msgstr "Lien court" +msgid "Long link:" +msgstr "Lien long :" -msgid "Long link" -msgstr "Lien long" +msgid "Shorten" +msgstr "Raccourir" -msgid "Service" -msgstr "Service" +msgid "URL not found" +msgstr "Lien non trouvé" + +msgid "The URL you are looking for does not exist." +msgstr "Le liens que vous recherchez n'existe pas." + +msgid "Create your own short URL" +msgstr "Créer votre propre lien court" + +msgid "Plugin kUtRL" +msgstr "Extension kUtRL" + +msgid "Short link creation" +msgstr "Création de lien court" + +msgid "New short link of type \"%s\" and hash \"%s\" was created." +msgstr "Un nouveau lien court de type \"%s\" et de hash \"%s\" a été créé." msgid "Hash" msgstr "Hash" +msgid "Service" +msgstr "Service" + msgid "links per page" msgstr "liens par page" @@ -46,15 +64,36 @@ msgstr "suivi %s fois" msgid "Delete short link" msgstr "Effacer un lien court" +msgid "Short link" +msgstr "Lien court" + msgid "No enough right" msgstr "Privilèges insuffisants" msgid "Posts short links have been created." msgstr "Les liens courts des billets ont été créé." +msgid "Long link" +msgstr "Lien long" + msgid "Disabled" msgstr "Désactiver" +msgid "Failed to test %s API." +msgstr "Impossible de tester l'API %s." + +msgid "%s API is well configured and runing." +msgstr "L'API %s est correctement configurée et est fonctionnelle." + +msgid "Failed to test service %s: %s" +msgstr "Impossible de tester le service %s : %s" + +msgid "homepage" +msgstr "page d'accueil" + +msgid "Learn more about %s." +msgstr "En savoir plus à propos de %s." + msgid "Enable plugin" msgstr "Activer le plugin" @@ -121,20 +160,11 @@ msgstr "Réduit automatiquement les liens des contenus utilisant la syntax wiki. msgid "List of services you can use to shorten links with pkugin kUtRL." msgstr "Liste des services que vous pouvez utiliser pour réduire des liens à l'aide du plugin kUtRL." -msgid "Failed to test %s API." -msgstr "Impossible de tester l'API %s." +msgid "New public short URL" +msgstr "Nouvelle URL courte" -msgid "%s API is well configured and runing." -msgstr "L'API %s est correctement configurée et est fonctionnelle." - -msgid "Failed to test service %s: %s" -msgstr "Impossible de tester le service %s : %s" - -msgid "homepage" -msgstr "page d'accueil" - -msgid "Learn more about %s." -msgstr "En savoir plus à propos de %s." +msgid "Confirm by writing \"%s\" in next field:" +msgstr "Confirmez en écrivant \"%s\" dans le champs suivant :" msgid "Failed to verify protected field." msgstr "Impossible de vérifier le champs de protection." @@ -163,69 +193,6 @@ msgstr "Le lien court pour %s est %s" msgid "Failed to create short link." msgstr "Impossible de créer le lien court." -msgid "New public short URL" -msgstr "Nouvelle URL courte" - -msgid "Confirm by writing \"%s\" in next field:" -msgstr "Confirmez en écrivant \"%s\" dans le champs suivant :" - -msgid "Shorten link" -msgstr "Réduire un lien" - -msgid "Top of short links" -msgstr "Top des liens courts" - -msgid "Text: (Use wildcard %rank%, %hash%, %url%, %count%, %counttext%)" -msgstr "Texte : (Ustiliser les jokers %rank%, %hash%, %url%, %count%, %counttext%)" - -msgid "URL length (if truncate)" -msgstr "Longueur de l'URL (si tronqué)" - -msgid "All" -msgstr "Tous" - -msgid "Mini URL" -msgstr "Mini URL" - -msgid "Custom URL" -msgstr "URL personnalisé" - -msgid "Semi-custom" -msgstr "Semi-personnalisé" - -msgid "Semi-custom prefix: (only if you want limit to a particular prefix)" -msgstr "Préfixe des liens semi-personnalisé : (Seulement si vous voulez limiter à un préfixe particulier)" - -msgid "Sort by:" -msgstr "Trier par :" - -msgid "Rank" -msgstr "Rang" - -msgid "Limit:" -msgstr "Limite :" - -msgid "Hide no followed links" -msgstr "Cacher les liens non suivis" - -msgid "Long link:" -msgstr "Lien long :" - -msgid "Rewrite \"%s\" in next field to show that you are not a robot:" -msgstr "Recopier \"%s\" dans le champs suivant pour montrer que vous n'êtes pas une machine :" - -msgid "Shorten" -msgstr "Raccourir" - -msgid "Plugin kUtRL" -msgstr "Extension kUtRL" - -msgid "Short link creation" -msgstr "Création de lien court" - -msgid "New short link of type \"%s\" and hash \"%s\" was created." -msgstr "Un nouveau lien court de type \"%s\" et de hash \"%s\" a été créé." - msgid "No short link matches the filter" msgstr "Aucun lien correspondant au filtre" @@ -235,18 +202,51 @@ msgstr "Pas de lien court" 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 "List of links. (%s)" +msgstr "Liste des liens. (%s)" -msgid "There is nothing to configure for this service." -msgstr "Il n'y a rien à configurer pour ce service." +msgid "There is nothing to shorten." +msgstr "Il n'y a rien à réduire." -msgid "%s (Shorten with %s)" -msgstr "%s (réduit avec %s)" +msgid "This service does not allowed custom hash." +msgstr "Ce service n'accepte pas les liens court personnalisés." + +msgid "This link is not a valid URL." +msgstr "Ce lien n'est pas valide." + +msgid "This custom short url is already taken." +msgstr "Ce lien court personnalisé est déjà pris." + +msgid "Failed to create short link. This could be caused by a service failure." +msgstr "Impossible de créé un lien court. Ceci peut être causé par un problème du service." msgid "New short URL" msgstr "Nouvelle URL courte" +msgid "New link" +msgstr "Nouveau lien" + +msgid "You must set an admin service." +msgstr "Vous devez définir un service admin." + +msgid "Only if you want a custom short link." +msgstr "Uniquement si vous souhaitez un lien court personnalisé." + +msgid "You can use \"bob!!\" if you want a semi-custom link, it starts with \"bob\" and \"!!\" will be replaced by an increment value." +msgstr "Vous pouvez utiliser \"bob!!\" si vous souhaitez un lien semi-personnalisé, il commencera par \"bob\" et \"!!\" sera remplacé par une valeur incrémentale." + +msgid "Shorten link using service \"%s\"" +msgstr "Raccourcir un lien en utilisant le service \"%s\"" + +msgid "Service:" +msgstr "Service :" + +msgid "Links successfully deleted" +msgstr "Liens supprimés avec succès" + +msgid "Delete selected short links" +msgstr "Effacer les liens court sélectionnés" + msgid "Url of the service:" msgstr "URL du service :" @@ -301,8 +301,8 @@ msgstr "Paramètre de la raquête. ex: \"longurl\"" msgid "Encode URL" msgstr "Encoder l'URL à raccourcir" -msgid "This service is set to:" -msgstr "Ce service est règlé comme suit:" +msgid "There is nothing to configure for this service." +msgstr "Il n'y a rien à configurer pour ce service." msgid "Full API URL:" msgstr "URL complet vers l'API:" @@ -370,9 +370,75 @@ msgstr "Le lien court personnalisé n'est pas valide." msgid "Failed to save link." msgstr "Impossible d'enregistrer le lien." +msgid "This is the URL of the YOURLS service you want to use. Ex: \"http://www.smaller.org/api.php\"." +msgstr "Ceci est l'URL du service YOURLS que vous voulez utiliser. Ex: \"http://www.smaller.org/api.php\"." + msgid "Login:" msgstr "Identifiant :" +msgid "This is your user name to sign up to this YOURLS service." +msgstr "Ceci est votre nom d'utilisateur pour vous connecter à ce service YOURLS." + +msgid "This is your password to sign up to this YOURLS service." +msgstr "Ceci est votre mot de passe pour vous connecter à ce service YOURLS." + +msgid "Authentication to service failed." +msgstr "Authentification au service échoué." + +msgid "Unreadable service response." +msgstr "La réponse du service n'est pas lisible." + +msgid "Shorten link" +msgstr "Réduire un lien" + +msgid "Top of short links" +msgstr "Top des liens courts" + +msgid "Text: (Use wildcard %rank%, %hash%, %url%, %count%, %counttext%)" +msgstr "Texte : (Ustiliser les jokers %rank%, %hash%, %url%, %count%, %counttext%)" + +msgid "URL length (if truncate)" +msgstr "Longueur de l'URL (si tronqué)" + +msgid "All" +msgstr "Tous" + +msgid "Mini URL" +msgstr "Mini URL" + +msgid "Custom URL" +msgstr "URL personnalisé" + +msgid "Semi-custom" +msgstr "Semi-personnalisé" + +msgid "Semi-custom prefix: (only if you want limit to a particular prefix)" +msgstr "Préfixe des liens semi-personnalisé : (Seulement si vous voulez limiter à un préfixe particulier)" + +msgid "Sort by:" +msgstr "Trier par :" + +msgid "Rank" +msgstr "Rang" + +msgid "Limit:" +msgstr "Limite :" + +msgid "Hide no followed links" +msgstr "Cacher les liens non suivis" + +msgid "Rewrite \"%s\" in next field to show that you are not a robot:" +msgstr "Recopier \"%s\" dans le champs suivant pour montrer que vous n'êtes pas une machine :" + +msgid "%s (Shorten with %s)" +msgstr "%s (réduit avec %s)" + +msgid "List of links (%s)" +msgstr "Listes des liens (%s)" + +msgid "This service is set to:" +msgstr "Ce service est règlé comme suit:" + msgid "This is your login to sign up to %s" msgstr "C'est votre identifiant pour vous connecter sur %s" @@ -388,75 +454,9 @@ msgstr "Ceci est votre mot de passe d'inscription sur tr.im." msgid "Prevent service rate limit." msgstr "Prévention de la limitation d'envoie du service." -msgid "Authentication to service failed." -msgstr "Authentification au service échoué." - -msgid "Unreadable service response." -msgstr "La réponse du service n'est pas lisible." - -msgid "This is the URL of the YOURLS service you want to use. Ex: \"http://www.smaller.org/api.php\"." -msgstr "Ceci est l'URL du service YOURLS que vous voulez utiliser. Ex: \"http://www.smaller.org/api.php\"." - -msgid "This is your user name to sign up to this YOURLS service." -msgstr "Ceci est votre nom d'utilisateur pour vous connecter à ce service YOURLS." - -msgid "This is your password to sign up to this YOURLS service." -msgstr "Ceci est votre mot de passe pour vous connecter à ce service YOURLS." - -msgid "There is nothing to shorten." -msgstr "I n'y a rien à réduire." - -msgid "This service does not allowed custom hash." -msgstr "Ce service n'accepte pas les liens court personnalisés." - -msgid "This link is not a valid URL." -msgstr "Ce lien n'est pas valide." - -msgid "This custom short url is already taken." -msgstr "Ce lien court personnalisé est déjà pris." - -msgid "Failed to create short link. This could be caused by a service failure." -msgstr "Impossible de créé un lien court. Ceci peut être causé par un problème du service." - -msgid "Service:" -msgstr "Service :" - -msgid "Links successfully deleted" -msgstr "Liens supprimés avec succès" - -msgid "New link" -msgstr "Nouveau lien" - -msgid "You must set an admin service." -msgstr "Vous devez définir un service admin." - -msgid "Shorten link using service \"%s\"" -msgstr "Raccourcir un lien en utilisant le service \"%s\"" - -msgid "Only if you want a custom short link." -msgstr "Uniquement si vous souhaitez un lien court personnalisé." - -msgid "You can use \"bob!!\" if you want a semi-custom link, it starts with \"bob\" and \"!!\" will be replaced by an increment value." -msgstr "Vous pouvez utiliser \"bob!!\" si vous souhaitez un lien semi-personnalisé, il commencera par \"bob\" et \"!!\" sera remplacé par une valeur incrémentale." - -msgid "Delete selected short links" -msgstr "Effacer les liens court sélectionnés" - msgid "Configuration successfully saved" msgstr "Configuration sauvegardée avec succès" -msgid "Plugin activation" -msgstr "Activation" - -msgid "URL not found" -msgstr "Lien non trouvé" - -msgid "The URL you are looking for does not exist." -msgstr "Le liens que vous recherchez n'existe pas." - -msgid "Create your own short URL" -msgstr "Créer votre propre lien court" - msgid "Publish history" msgstr "Publier l'historique" diff --git a/src/Backend.php b/src/Backend.php index 4cd24f1..84badd8 100644 --- a/src/Backend.php +++ b/src/Backend.php @@ -10,371 +10,59 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return null; -} +declare(strict_types=1); -dcCore::app()->blog->settings->addNamespace(basename(__DIR__)); +namespace Dotclear\Plugin\kUtRL; -require_once __DIR__ . '/_widgets.php'; +use dcCore; +use Dotclear\Core\Process; -# Plugin menu -dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem( - __('Links shortener'), - dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), - urldecode(dcPage::getPF(basename(__DIR__) . '/icon.svg')), - preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/', $_SERVER['REQUEST_URI']), - dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id) -); - -# Admin behaviors -if (dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) { - dcCore::app()->addBehavior('adminDashboardFavoritesV2', ['adminKutrl', 'antispamDashboardFavoritesV2']); - dcCore::app()->addBehavior('adminColumnsListsV2', ['adminKutrl', 'adminColumnsListsV2']); - dcCore::app()->addBehavior('adminFiltersListsV2', ['adminKutrl', 'adminFiltersListsV2']); - dcCore::app()->addBehavior('adminPostHeaders', ['adminKutrl', 'adminPostHeaders']); - dcCore::app()->addBehavior('adminPostFormItems', ['adminKutrl', 'adminPostFormItems']); - dcCore::app()->addBehavior('adminAfterPostUpdate', ['adminKutrl', 'adminAfterPostUpdate']); // update existing short url - dcCore::app()->addBehavior('adminAfterPostUpdate', ['adminKutrl', 'adminAfterPostCreate']); // create new short url - dcCore::app()->addBehavior('adminAfterPostCreate', ['adminKutrl', 'adminAfterPostCreate']); - dcCore::app()->addBehavior('adminBeforePostDelete', ['adminKutrl', 'adminBeforePostDelete']); - dcCore::app()->addBehavior('adminPostsActions', ['adminKutrl', 'adminPostsActions']); -} - -dcCore::app()->addBehavior('exportFullV2', ['backupKutrl', 'exportFullV2']); -dcCore::app()->addBehavior('exportSingleV2', ['backupKutrl', 'exportSingleV2']); -dcCore::app()->addBehavior('importInitV2', ['backupKutrl', 'importInitV2']); -dcCore::app()->addBehavior('importSingleV2', ['backupKutrl', 'importSingleV2']); -dcCore::app()->addBehavior('importFullV2', ['backupKutrl', 'importFullV2']); - -# Admin behaviors class -class adminKutrl +/** + * Backend prepend. + */ +class Backend extends Process { - public static function sortbyCombo() + public static function init(): bool { - return [ - __('Date') => 'kut_dt', - __('Short link') => 'kut_hash', - __('Long link') => 'kut_url', - __('Service') => 'kut_service', - ]; + return self::status(My::checkContext(My::BACKEND)); } - public static function antispamDashboardFavoritesV2(dcFavorites $favs) + public static function process(): bool { - $favs->register( - 'kUtRL', - [ - 'title' => __('Links shortener'), - 'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), - 'small-icon' => dcPage::getPF(basename(__DIR__) . '/icon.png'), - 'large-icon' => dcPage::getPF(basename(__DIR__) . '/icon-b.png'), - 'permissions' => dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), - ] - ); - } - - public static function adminColumnsListsV2($cols) - { - $cols['kUtRL'] = [ - __('Links shortener'), - [ - 'kut_hash' => [true, __('Hash')], - 'kut_dt' => [true, __('Date')], - 'kut_service' => [true, __('Service')], - ], - ]; - } - - public static function adminFiltersListsV2($sorts) - { - $sorts['kUtRL'] = [ - __('Links shortener'), - self::sortbyCombo(), - 'kut_dt', - 'desc', - [__('links per page'), 30], - ]; - } - - public static function adminPostHeaders() - { - return dcPage::jsModuleLoad(basename(__DIR__) . '/js/posts.js'); - } - - public static function adminPostFormItems($main_items, $sidebar_items, $post) - { - $s = dcCore::app()->blog->settings->get(basename(__DIR__)); - - if (!$s->get('active') || !$s->get('active')) { - return null; - } - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; + if (!self::status()) { + return false; } - if ($post) { - $post_url = $post->getURL(); - $rs = $kut->isKnowUrl($post_url); - } else { - $post_url = ''; - $rs = false; + // sidebar menu + My::addBackendMenuItem(); + + # Admin behaviors + if (My::settings()->get('active')) { + dcCore::app()->addBehaviors([ + 'adminDashboardFavoritesV2' => [BackendBehaviors::class, 'antispamDashboardFavoritesV2'], + 'adminColumnsListsV2' => [BackendBehaviors::class, 'adminColumnsListsV2'], + 'adminFiltersListsV2' => [BackendBehaviors::class, 'adminFiltersListsV2'], + 'adminPostHeaders' => [BackendBehaviors::class, 'adminPostHeaders'], + 'adminPostFormItems' => [BackendBehaviors::class, 'adminPostFormItems'], + 'adminAfterPostUpdate' => [BackendBehaviors::class, 'adminAfterPostUpdate'], // update existing short url + 'adminAfterPostUpdate' => [BackendBehaviors::class, 'adminAfterPostCreate'], // create new short url + 'adminAfterPostCreate' => [BackendBehaviors::class, 'adminAfterPostCreate'], + 'adminBeforePostDelete' => [BackendBehaviors::class, 'adminBeforePostDelete'], + 'adminPostsActions' => [BackendBehaviors::class, 'adminPostsActions'], + ]); } - $ret = '
' . __('Short link') . '
' . - form::hidden(['kutrl_old_post_url'], $post_url); + dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initShorten']); + dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initRank']); - if (!$rs) { - if (empty($_POST['kutrl_old_post_url']) && $s->get('admin_entry_default')) { - $chk = true; - } else { - $chk = !empty($_POST['kutrl_create']); - } - $ret .= '

'; + dcCore::app()->addBehaviors([ + 'exportFullV2' => [ImportExportBehaviors::class, 'exportFullV2'], + 'exportSingleV2' => [ImportExportBehaviors::class, 'exportSingleV2'], + 'importInitV2' => [ImportExportBehaviors::class, 'importInitV2'], + 'importSingleV2' => [ImportExportBehaviors::class, 'importSingleV2'], + 'importFullV2' => [ImportExportBehaviors::class, 'importFullV2'], + ]); - if ($kut->allow_custom_hash) { - $ret .= '

' . - '

'; - } - } else { - $count = $rs->counter; - if ($count == 0) { - $title = __('never followed'); - } elseif ($count == 1) { - $title = __('followed one time'); - } else { - $title = sprintf(__('followed %s times'), $count); - } - $href = $kut->url_base . $rs->hash; - - $ret .= '

' . - '

' . $href . '

'; - } - $ret .= '
'; - - $sidebar_items['options-box']['items']['kUtRL'] = $ret; - } - - public static function adminAfterPostUpdate($cur, $post_id) - { - # Create: see adminAfterPostCreate - if (!empty($_POST['kutrl_create']) || !dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) { - return null; - } - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; - } - if (empty($_POST['kutrl_old_post_url'])) { - return null; - } - - $old_post_url = $_POST['kutrl_old_post_url']; - - if (!($rs = $kut->isKnowUrl($old_post_url))) { - return null; - } - - $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); - if ($rs->isEmpty()) { - return null; - } - $title = html::escapeHTML($rs->post_title); - $new_post_url = $rs->getURL(); - - # Delete - if (!empty($_POST['kutrl_delete'])) { - $kut->remove($old_post_url); - # Update - } else { - if ($old_post_url == $new_post_url) { - return null; - } - - $kut->remove($old_post_url); - - $rs = $kut->hash($new_post_url, '');//$custom); // better to update (not yet implemented) - $url = $kut->url_base . $rs->hash; - - # ex: Send new url to messengers - if (!empty($rs)) { - dcCore::app()->callBehavior('adminAfterKutrlCreate', $rs, $title); - } - } - } - - public static function adminAfterPostCreate($cur, $post_id) - { - if (empty($_POST['kutrl_create']) || !dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) { - return null; - } - - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; - } - - $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); - if ($rs->isEmpty()) { - return null; - } - $title = html::escapeHTML($rs->post_title); - - $custom = !empty($_POST['kutrl_create_custom']) && $kut->allow_custom_hash ? - $_POST['kutrl_create_custom'] : null; - - $rs = $kut->hash($rs->getURL(), $custom); - $url = $kut->url_base . $rs->hash; - - # ex: Send new url to messengers - if (!empty($rs)) { - dcCore::app()->callBehavior('adminAfterKutrlCreate', $rs, $title); - } - } - - public static function adminBeforePostDelete($post_id) - { - if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) { - return null; - } - - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; - } - - $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); - if ($rs->isEmpty()) { - return null; - } - - $kut->remove($rs->getURL()); - } - - public static function adminPostsActions(dcPostsActions $pa) - { - if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('active') - || !dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { - return null; - } - - $pa->addAction( - [__('Links shortener') => [__('Create short link') => 'kutrl_create']], - ['adminKutrl', 'callbackCreate'] - ); - $pa->addAction( - [__('Links shortener') => [__('Delete short link') => 'kutrl_delete']], - ['adminKutrl', 'callbackDelete'] - ); - } - - public static function callbackCreate(dcPostsActions $pa, ArrayObject $post) - { - # No entry - $posts_ids = $pa->getIDs(); - if (empty($posts_ids)) { - throw new Exception(__('No entry selected')); - } - - # No right - if (!dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { - throw new Exception(__('No enough right')); - } - - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; - } - - # retrieve posts info and create hash - $posts = dcCore::app()->blog->getPosts(['post_id' => $posts_ids]); - while ($posts->fetch()) { - $kut->hash($posts->getURL()); - } - - dcAdminNotices::addSuccessNotice(__('Posts short links have been created.')); - $pa->redirect(true); - } - - public static function callbackDelete(dcPostsActions $pa, ArrayObject $post) - { - # No entry - $posts_ids = $pa->getIDs(); - if (empty($posts_ids)) { - throw new Exception(__('No entry selected')); - } - - # No right - if (!dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { - throw new Exception(__('No enough right')); - } - - if (null === ($kut = kUtRL::quickPlace('admin'))) { - return null; - } - - # retrieve posts info and create hash - $posts = dcCore::app()->blog->getPosts(['post_id' => $posts_ids]); - while ($posts->fetch()) { - $kut->remove($posts->getURL()); - } - - dcAdminNotices::addSuccessNotice(__('Posts short links have been created.')); - $pa->redirect(true); - } -} - -# Import/export behaviors for Import/export plugin -class backupKutrl -{ - public static function exportSingleV2($exp, $blog_id) - { - $exp->export( - 'kutrl', - 'SELECT kut_id, blog_id, kut_service, kut_type, ' . - 'kut_hash, kut_url, kut_dt, kut_password, kut_counter ' . - 'FROM ' . dcCore::app()->prefix . initkUtRL::KURL_TABLE_NAME . ' ' . - "WHERE blog_id = '" . $blog_id . "' " - ); - } - - public static function exportFullV2($exp) - { - $exp->exportTable('kutrl'); - } - - public static function importInitV2($bk) - { - $bk->cur_kutrl = dcCore::app()->con->openCursor(dcCore::app()->prefix . initkUtRL::KURL_TABLE_NAME); - $bk->kutrl = new kutrlLog(); - } - - public static function importSingleV2($line, $bk) - { - if ($line->__name == 'kutrl') { - # Do nothing if str/type exists ! - if (false === $bk->kutrl->select($line->kut_url, $line->kut_hash, $line->kut_type, $line->kut_service)) { - $bk->kutrl->insert($line->kut_url, $line->kut_hash, $line->kut_type, $line->kut_service); - } - } - } - - public static function importFullV2($line, $bk) - { - if ($line->__name == 'kutrl') { - $bk->cur_kutrl->clean(); - $bk->cur_kutrl->kut_id = (int) $line->kut_id; - $bk->cur_kutrl->blog_id = (string) $line->blog_id; - $bk->cur_kutrl->kut_service = (string) $line->kut_service; - $bk->cur_kutrl->kut_type = (string) $line->kut_type; - $bk->cur_kutrl->kut_hash = (string) $line->kut_hash; - $bk->cur_kutrl->kut_url = (string) $line->kut_url; - $bk->cur_kutrl->kut_dt = (string) $line->miniurl_dt; - $bk->cur_kutrl->kut_counter = (int) $line->kut_counter; - $bk->cur_kutrl->kut_password = (string) $line->kut_password; - $bk->cur_kutrl->insert(); - } + return true; } } diff --git a/src/BackendBehaviors.php b/src/BackendBehaviors.php new file mode 100644 index 0000000..e409358 --- /dev/null +++ b/src/BackendBehaviors.php @@ -0,0 +1,326 @@ +register( + My::id(), + [ + 'title' => My::name(), + 'url' => My::manageUrl(), + 'small-icon' => My::icons(), + 'large-icon' => My::icons(), + 'permissions' => dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_ADMIN]), + ] + ); + } + + public static function adminColumnsListsV2(ArrayObject $cols): void + { + $cols[My::id()] = [ + My::name(), + [ + 'kut_hash' => [true, __('Hash')], + 'kut_dt' => [true, __('Date')], + 'kut_service' => [true, __('Service')], + ], + ]; + } + + public static function adminFiltersListsV2(ArrayObject $sorts): void + { + $sorts[My::id()] = [ + My::name(), + Combo::sortbyCombo(), + 'kut_dt', + 'desc', + [__('links per page'), 30], + ]; + } + + public static function adminPostHeaders(): string + { + return My::jsLoad('posts'); + } + + public static function adminPostFormItems(ArrayObject $main_items, ArrayObject $sidebar_items, ?MetaRecord $post): void + { + $s = My::settings(); + + if (!$s->get('active') + || !$s->get('active') + || null === ($kut = Utils::quickPlace('admin')) + ) { + return; + } + + $post_url = ''; + $rs = false; + if ($post) { + $post_url = $post->getURL(); + $rs = $kut->isKnowUrl($post_url); + } + + $items = []; + + if (!$rs) { + $chk = !empty($_POST['kutrl_create']); + if (empty($_POST['kutrl_old_post_url']) && $s->get('admin_entry_default')) { + $chk = true; + } + + $items[] = (new Para()) + ->items([ + (new Checkbox('kutrl_create', $chk)) + ->value(1), + (new Label(__('Create short link'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('kutrl_create'), + ]); + + if ($kut->allow_custom_hash) { + $items[] = (new Para()) + ->class('classic') + ->items([ + (new Label(__('Custom short link:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_create_custom'), + (new Input('kutrl_create_custom')) + ->size(32) + ->maxlenght(32) + ->class('maximal') + ->value(''), + ]); + } + } else { + $count = $rs->counter; + if ($count == 0) { + $title = __('never followed'); + } elseif ($count == 1) { + $title = __('followed one time'); + } else { + $title = sprintf(__('followed %s times'), $count); + } + $href = $kut->url_base . $rs->hash; + + $items[] = (new Para()) + ->items([ + (new Checkbox('kutrl_delete', !empty($_POST['kutrl_delete']))) + ->value(1), + (new Label(__('Delete short link'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('kutrl_delete'), + ]); + + $items[] = (new Para()) + ->items([ + (new Link()) + ->href($href) + ->title($title) + ->text($href), + ]); + } + + $sidebar_items['options-box']['items'][My::id()] = (new Div(My::id())) + ->items([ + (new Text('h5', __('Short link'))), + (new Hidden('kutrl_old_post_url', $post_url)), + ... $items, + ]) + ->render(); + } + + public static function adminAfterPostUpdate(Cursor $cur, string|int $post_id): void + { + # Create: see adminAfterPostCreate + if (!empty($_POST['kutrl_create']) + || !My::settings()->get('active') + || null === ($kut = Utils::quickPlace('admin')) + || empty($_POST['kutrl_old_post_url']) + ) { + return; + } + + $old_post_url = $_POST['kutrl_old_post_url']; + if (!($rs = $kut->isKnowUrl($old_post_url))) { + return; + } + + $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); + if ($rs->isEmpty()) { + return; + } + $title = Html::escapeHTML($rs->post_title); + $new_post_url = $rs->getURL(); + + # Delete + if (!empty($_POST['kutrl_delete'])) { + $kut->remove($old_post_url); + # Update + } else { + if ($old_post_url == $new_post_url) { + return; + } + + $kut->remove($old_post_url); + + $rs = $kut->hash($new_post_url, '');//$custom); // better to update (not yet implemented) + $url = $kut->url_base . $rs->hash; + + # ex: Send new url to messengers + if (!empty($rs)) { + dcCore::app()->callBehavior('adminAfterKutrlCreate', $rs, $title); + } + } + } + + public static function adminAfterPostCreate(Cursor $cur, int $post_id): void + { + if (empty($_POST['kutrl_create']) + || !My::settings()->get('active') + || null === ($kut = Utils::quickPlace('admin')) + ) { + return; + } + + $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); + if ($rs->isEmpty()) { + return; + } + $title = Html::escapeHTML($rs->post_title); + + $custom = !empty($_POST['kutrl_create_custom']) && $kut->allow_custom_hash ? + $_POST['kutrl_create_custom'] : null; + + $rs = $kut->hash($rs->getURL(), $custom); + $url = $kut->url_base . $rs->hash; + + # ex: Send new url to messengers + if (!empty($rs)) { + dcCore::app()->callBehavior('adminAfterKutrlCreate', $rs, $title); + } + } + + public static function adminBeforePostDelete(string|int $post_id): void + { + if (!My::settings()->get('active') + || null === ($kut = Utils::quickPlace('admin')) + ) { + return; + } + + $rs = dcCore::app()->blog->getPosts(['post_id' => $post_id]); + if ($rs->isEmpty()) { + return; + } + + $kut->remove($rs->getURL()); + } + + public static function adminPostsActions(ActionsPosts $pa): void + { + if (!My::settings()->get('active') + || !dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { + return; + } + + $pa->addAction( + [My::name() => [__('Create short link') => 'kutrl_create']], + [self::class, 'callbackCreate'] + ); + $pa->addAction( + [My::name() => [__('Delete short link') => 'kutrl_delete']], + [self::class, 'callbackDelete'] + ); + } + + public static function callbackCreate(ActionsPosts $pa, ArrayObject $post): void + { + # No entry + $posts_ids = $pa->getIDs(); + if (empty($posts_ids)) { + throw new Exception(__('No entry selected')); + } + + # No right + if (!dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { + throw new Exception(__('No enough right')); + } + + if (null === ($kut = Utils::quickPlace('admin'))) { + return; + } + + # retrieve posts info and create hash + $posts = dcCore::app()->blog->getPosts(['post_id' => $posts_ids]); + while ($posts->fetch()) { + $kut->hash($posts->getURL()); + } + + Notices::addSuccessNotice(__('Posts short links have been created.')); + $pa->redirect(true); + } + + public static function callbackDelete(ActionsPosts $pa, ArrayObject $post): void + { + # No entry + $posts_ids = $pa->getIDs(); + if (empty($posts_ids)) { + throw new Exception(__('No entry selected')); + } + + # No right + if (!dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { + throw new Exception(__('No enough right')); + } + + if (null === ($kut = Utils::quickPlace('admin'))) { + return; + } + + # retrieve posts info and create hash + $posts = dcCore::app()->blog->getPosts(['post_id' => $posts_ids]); + while ($posts->fetch()) { + $kut->remove($posts->getURL()); + } + + Notices::addSuccessNotice(__('Posts short links have been created.')); + $pa->redirect(true); + } +} diff --git a/src/Combo.php b/src/Combo.php new file mode 100644 index 0000000..73cabf3 --- /dev/null +++ b/src/Combo.php @@ -0,0 +1,48 @@ + + */ + public static function sortbyCombo(): array + { + return [ + __('Date') => 'kut_dt', + __('Short link') => 'kut_hash', + __('Long link') => 'kut_url', + __('Service') => 'kut_service', + ]; + } + + /** + * @return array + */ + public static function ServicesCombo(bool $with_none = false): array + { + $services_combo = []; + foreach (Utils::getServices() as $service_id => $service) { + $o = new $service(); + $services_combo[__($o->name)] = $o->id; + } + if ($with_none) { + $services_combo = array_merge([__('Disabled') => ''], $services_combo); + } + + return $services_combo; + } +} diff --git a/src/Config.php b/src/Config.php index 1b6072f..7234109 100644 --- a/src/Config.php +++ b/src/Config.php @@ -10,186 +10,320 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; -} +declare(strict_types=1); -# Check user perms -dcPage::check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN])); +namespace Dotclear\Plugin\kUtRL; -# Settings -$s = dcCore::app()->blog->settings->get(basename(__DIR__)); +use dcCore; +use Dotclear\Core\Backend\Notices; +use Dotclear\Core\Process; +use Dotclear\Helper\Html\Form\{ + Checkbox, + Div, + Label, + Link, + Note, + Para, + Select, + Text +}; +use Exception; -# Default values -$img_green = 'ok'; -$img_red = 'fail'; +/** + * Backend module configuration. + */ +class Config extends Process +{ + public static function init(): bool + { + return self::status(My::checkContext(My::CONFIG)); + } -$services_combo = []; -foreach (kUtRL::getServices() as $service_id => $service) { - $o = new $service(); - $services_combo[__($o->name)] = $o->id; -} -$ext_services_combo = array_merge([__('Disabled') => ''], $services_combo); -$lst_services_combo = array_merge(['-' => ''], $services_combo); - -$s_active = (bool) $s->get('active'); -$s_plugin_service = (string) $s->get('plugin_service'); -$s_admin_service = (string) $s->get('admin_service'); -$s_tpl_service = (string) $s->get('tpl_service'); -$s_wiki_service = (string) $s->get('wiki_service'); -$s_allow_external_url = (bool) $s->get('allow_external_url'); -$s_tpl_passive = (bool) $s->get('tpl_passive'); -$s_tpl_active = (bool) $s->get('tpl_active'); -$s_admin_entry_default = (string) $s->get('admin_entry_default'); - -if (!empty($_POST['save'])) { - try { - # settings - $s_active = !empty($_POST['s_active']); - $s_admin_service = (string) $_POST['s_admin_service']; - $s_plugin_service = (string) $_POST['s_plugin_service']; - $s_tpl_service = (string) $_POST['s_tpl_service']; - $s_wiki_service = (string) $_POST['s_wiki_service']; - $s_allow_external_url = !empty($_POST['s_allow_external_url']); - $s_tpl_passive = !empty($_POST['s_tpl_passive']); - $s_tpl_active = !empty($_POST['s_tpl_active']); - $s_admin_entry_default = !empty($_POST['s_admin_entry_default']); - - $s->put('active', $s_active); - $s->put('plugin_service', $s_plugin_service); - $s->put('admin_service', $s_admin_service); - $s->put('tpl_service', $s_tpl_service); - $s->put('wiki_service', $s_wiki_service); - $s->put('allow_external_url', $s_allow_external_url); - $s->put('tpl_passive', $s_tpl_passive); - $s->put('tpl_active', $s_tpl_active); - $s->put('admin_entry_default', $s_admin_entry_default); - - # services - foreach (kUtRL::getServices() as $service_id => $service) { - $o = new $service(); - $o->saveSettings(); + public static function process(): bool + { + if (!self::status()) { + return false; } - dcCore::app()->blog->triggerBlog(); + // no action + if (empty($_POST['save'])) { + return true; + } - dcAdminNotices::addSuccessNotice( - __('Configuration successfully updated.') - ); + # Settings + $s = My::settings(); - dcCore::app()->adminurl->redirect( - 'admin.plugins', - ['module' => basename(__DIR__), 'conf' => 1, 'chk' => 1, 'redir' => dcCore::app()->admin->list->getRedir()] - ); - } catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); - } -} + $s_active = (bool) $s->get('active'); + $s_plugin_service = (string) $s->get('plugin_service'); + $s_admin_service = (string) $s->get('admin_service'); + $s_tpl_service = (string) $s->get('tpl_service'); + $s_wiki_service = (string) $s->get('wiki_service'); + $s_allow_external_url = (bool) $s->get('allow_external_url'); + $s_tpl_passive = (bool) $s->get('tpl_passive'); + $s_tpl_active = (bool) $s->get('tpl_active'); + $s_admin_entry_default = (string) $s->get('admin_entry_default'); -echo ' -

' . __('Settings') . '

-
-
' . __('Activation') . '
-

-
+ if (!empty($_POST['save'])) { + try { + # settings + $s_active = !empty($_POST['s_active']); + $s_admin_service = (string) $_POST['s_admin_service']; + $s_plugin_service = (string) $_POST['s_plugin_service']; + $s_tpl_service = (string) $_POST['s_tpl_service']; + $s_wiki_service = (string) $_POST['s_wiki_service']; + $s_allow_external_url = !empty($_POST['s_allow_external_url']); + $s_tpl_passive = !empty($_POST['s_tpl_passive']); + $s_tpl_active = !empty($_POST['s_tpl_active']); + $s_admin_entry_default = !empty($_POST['s_admin_entry_default']); -
-
' . __('Behaviors') . '
-

-

' . __('Not only link started with this blog URL could be shortened.') . '

-

-

' . __('If this extension is disabled and the passive mode is enabled, "kutrl" tags (like EntryKurl) will display long urls instead of nothing on templates.') . '

-

-

' . __('If the active mode is enabled, all know default template tags (like EntryURL) will display short urls instead of long ones on templates.') . '
' . -__('You can disable URL shortening for a specific template tag by adding attribute disable_kutrl="1" to it . ') . '

-

' . __('We strongly discourage using active mode as it crashes public post form and complex url if theme is not customize for kUtRL.') . '

-

-

' . __('This can be changed on page of creation/edition of an entry.') . '

-
+ $s->put('active', $s_active); + $s->put('plugin_service', $s_plugin_service); + $s->put('admin_service', $s_admin_service); + $s->put('tpl_service', $s_tpl_service); + $s->put('wiki_service', $s_wiki_service); + $s->put('allow_external_url', $s_allow_external_url); + $s->put('tpl_passive', $s_tpl_passive); + $s->put('tpl_active', $s_tpl_active); + $s->put('admin_entry_default', $s_admin_entry_default); -
-
' . __('Default services') . '
-

-

' . __('Service to use in this admin page and on edit page of an entry.') . '

-

-

' . __('Service to use on third part plugins.') . '

-

-

' . __('Shorten links automatically when using template value like "EntryKutrl".') . '

-

-

' . __('Shorten links automatically found in contents using wiki synthax.') . '

-
-
+ # services + foreach (Utils::getServices() as $service_id => $service) { + $o = new $service(); + $o->saveSettings(); + } -
-

' . __('Services') . '

-

' . __('List of services you can use to shorten links with pkugin kUtRL.') . '

-'; + dcCore::app()->blog->triggerBlog(); -foreach (kUtRL::getServices() as $service_id => $service) { - $o = new $service(); + Notices::addSuccessNotice( + __('Configuration successfully updated.') + ); - echo '
' . $o->name . '
'; - - if (!empty($_REQUEST['chk'])) { - $img_chk = $img_red . ' ' . sprintf(__('Failed to test %s API.'), $o->name); - - try { - if ($o->testService()) { - $img_chk = $img_green . ' ' . sprintf(__('%s API is well configured and runing.'), $o->name); + dcCore::app()->admin->url->redirect( + 'admin.plugins', + ['module' => My::id(), 'conf' => 1, 'chk' => 1, 'redir' => dcCore::app()->admin->list->getRedir()] + ); + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); } - } catch (Exception $e) { - dcCore::app()->error->add(sprintf(__('Failed to test service %s: %s'), $o->name, $e->getMessage())); } - echo sprintf('

%s

', $img_chk) . $o->error->toHTML(); - } - if ($o->home != '') { - echo '

' . sprintf(__('Learn more about %s.'), $o->name) . '

'; - } - $o->settingsForm(); - echo '
'; + return true; + } + + public static function render(): void + { + if (!self::status()) { + return; + } + + # Default values + $img_green = 'ok'; + $img_red = 'fail'; + + # Settings + $s = My::settings(); + + $s_active = (bool) $s->get('active'); + $s_plugin_service = (string) $s->get('plugin_service'); + $s_admin_service = (string) $s->get('admin_service'); + $s_tpl_service = (string) $s->get('tpl_service'); + $s_wiki_service = (string) $s->get('wiki_service'); + $s_allow_external_url = (bool) $s->get('allow_external_url'); + $s_tpl_passive = (bool) $s->get('tpl_passive'); + $s_tpl_active = (bool) $s->get('tpl_active'); + $s_admin_entry_default = (bool) $s->get('admin_entry_default'); + + $chk_admin_service = ''; + $chk_plugin_service = ''; + $chk_tpl_service = ''; + $chk_wiki_service = ''; + if (!empty($_REQUEST['chk'])) { + if (null !== ($o = Utils::quickPlace($s_admin_service))) { + $chk_admin_service = ($o->testService() ? $img_green : $img_red) . ' '; + } + if (null !== ($o = Utils::quickPlace($s_plugin_service))) { + $chk_plugin_service = ($o->testService() ? $img_green : $img_red) . ' '; + } + if (null !== ($o = Utils::quickPlace($s_tpl_service))) { + $chk_tpl_service = ($o->testService() ? $img_green : $img_red) . ' '; + } + if (null !== ($o = Utils::quickPlace($s_wiki_service))) { + $chk_wiki_service = ($o->testService() ? $img_green : $img_red) . ' '; + } + } + + $i_config = []; + foreach (Utils::getServices() as $service_id => $service) { + $o = new $service(); + + $s_items = []; + + if (!empty($_REQUEST['chk'])) { + $img_chk = $img_red . ' ' . sprintf(__('Failed to test %s API.'), $o->name); + + try { + if ($o->testService()) { + $img_chk = $img_green . ' ' . sprintf(__('%s API is well configured and runing.'), $o->name); + } + } catch (Exception $e) { + dcCore::app()->error->add(sprintf(__('Failed to test service %s: %s'), $o->name, $e->getMessage())); + } + $s_items[] = (new Text(null, sprintf('

%s

', $img_chk) . $o->error->toHTML())); + } + + if ($o->home != '') { + $s_items[] = (new Para()) + ->items([ + (new Link()) + ->href($o->home) + ->title(__('homepage')) + ->text(sprintf(__('Learn more about %s.'), $o->name)), + ]); + } + + $i_config[] = (new Text('hr')); + $i_config[] = (new Div('settings-' . $service_id)) + ->items([ + (new Text('h5', $o->name)), + ... $s_items, + $o->settingsForm(), + ]); + } + + echo (new Div()) + ->class('fieldset') + ->items([ + (new text('h4', __('Settings'))), + (new Div('setting-plugin')) + ->items([ + (new Text('h5', __('Activation'))), + (new Para()) + ->items([ + (new Checkbox('s_active', $s_active)) + ->value(1), + (new Label(__('Enable plugin'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('s_active'), + ]), + ]), + (new Text('hr')), + + (new Div('setting-option')) + ->items([ + (new Text('h5', __('Behaviors'))), + (new Para()) + ->items([ + (new Checkbox('s_allow_external_url', $s_allow_external_url)) + ->value(1), + (new Label(__('Allow short link for external URL'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('s_allow_external_url'), + ]), + (new Note()) + ->class('form-note') + ->text(__('Not only link started with this blog URL could be shortened.')), + (new Para()) + ->items([ + (new Checkbox('s_tpl_passive', $s_tpl_passive)) + ->value(1), + (new Label(__('Passive mode'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('s_tpl_passive'), + ]), + (new Note()) + ->class('form-note') + ->text(__('If this extension is disabled and the passive mode is enabled, "kutrl" tags (like EntryKurl) will display long urls instead of nothing on templates.')), + (new Para()) + ->items([ + (new Checkbox('s_tpl_active', $s_tpl_active)) + ->value(1), + (new Label(__('Active mode'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('s_tpl_active'), + ]), + (new Note()) + ->class('form-note') + ->text(__('If the active mode is enabled, all know default template tags (like EntryURL) will display short urls instead of long ones on templates.')), + (new Note()) + ->class('form-note') + ->text(__('You can disable URL shortening for a specific template tag by adding attribute disable_kutrl="1" to it . ')), + (new Note()) + ->class('warning') + ->text(__('We strongly discourage using active mode as it crashes public post form and complex url if theme is not customize for kUtRL.')), + (new Para()) + ->items([ + (new Checkbox('s_admin_entry_default', $s_admin_entry_default)) + ->value(1), + (new Label(__('Create short link for new entries'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('s_admin_entry_default'), + ]), + (new Note()) + ->class('form-note') + ->text(__('This can be changed on page of creation/edition of an entry.')), + ]), + (new Text('hr')), + + (new Div('setting-service')) + ->items([ + (new Text('h5', __('Default services'))), + (new Para()) + ->items([ + (new Label($chk_admin_service . __('Administration:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('s_admin_service'), + (new Select('s_admin_service')) + ->items(Combo::servicesCombo()) + ->default($s_admin_service), + ]), + (new Note()) + ->class('form-note') + ->text(__('Service to use in this admin page and on edit page of an entry.')), + (new Para()) + ->items([ + (new Label($chk_plugin_service . __('Extensions:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('s_plugin_service'), + (new Select('s_plugin_service')) + ->items(Combo::servicesCombo()) + ->default($s_plugin_service), + ]), + (new Note()) + ->class('form-note') + ->text(__('Service to use on third part plugins.')), + (new Para()) + ->items([ + (new Label($chk_tpl_service . __('Templates:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('s_tpl_service'), + (new Select('s_tpl_service')) + ->items(Combo::servicesCombo()) + ->default($s_tpl_service), + ]), + (new Note()) + ->class('form-note') + ->text(__('Shorten links automatically when using template value like "EntryKutrl".')), + (new Para()) + ->items([ + (new Label($chk_wiki_service . __('Contents:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('s_wiki_service'), + (new Select('s_wiki_service')) + ->items(Combo::servicesCombo()) + ->default($s_wiki_service), + ]), + (new Note()) + ->class('form-note') + ->text(__('Shorten links automatically found in contents using wiki synthax.')), + ]), + ]) + ->render() . + + (new Div()) + ->class('fieldset') + ->items([ + (new text('h4', __('Settings'))), + (new Note()) + ->class('info') + ->text(__('List of services you can use to shorten links with pkugin kUtRL.')), + ... $i_config, + ]) + ->render(); + } } - -echo'
'; diff --git a/src/Frontend.php b/src/Frontend.php index 8748e86..1f610f0 100644 --- a/src/Frontend.php +++ b/src/Frontend.php @@ -10,567 +10,66 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -require_once __DIR__ . '/_widgets.php'; +namespace Dotclear\Plugin\kUtRL; -dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates'); +use dcCore; -dcCore::app()->addBehavior('publicBeforeDocumentV2', ['pubKutrl', 'publicBeforeDocumentV2']); -dcCore::app()->addBehavior('publicHeadContent', ['pubKutrl', 'publicHeadContent']); -dcCore::app()->addBehavior('publicBeforeContentFilterV2', ['pubKutrl', 'publicBeforeContentFilterV2']); -dcCore::app()->addBehavior('templateBeforeValueV2', ['pubKutrl', 'templateBeforeValueV2']); -dcCore::app()->addBehavior('templateAfterValueV2', ['pubKutrl', 'templateAfterValueV2']); +use Dotclear\Core\Process; -dcCore::app()->tpl->addBlock('kutrlPageIf', ['tplKutrl', 'pageIf']); -dcCore::app()->tpl->addBlock('kutrlMsgIf', ['tplKutrl', 'pageMsgIf']); - -dcCore::app()->tpl->addValue('kutrlPageURL', ['tplKutrl', 'pageURL']); -dcCore::app()->tpl->addValue('kutrlMsg', ['tplKutrl', 'pageMsg']); -dcCore::app()->tpl->addValue('kutrlHumanField', ['tplKutrl', 'humanField']); -dcCore::app()->tpl->addValue('kutrlHumanFieldProtect', ['tplKutrl', 'humanFieldProtect']); - -dcCore::app()->tpl->addBlock('AttachmentKutrlIf', ['tplKutrl', 'AttachmentKutrlIf']); -dcCore::app()->tpl->addValue('AttachmentKutrl', ['tplKutrl', 'AttachmentKutrl']); -dcCore::app()->tpl->addBlock('MediaKutrlIf', ['tplKutrl', 'MediaKutrlIf']); -dcCore::app()->tpl->addValue('MediaKutrl', ['tplKutrl', 'MediaKutrl']); -dcCore::app()->tpl->addBlock('EntryAuthorKutrlIf', ['tplKutrl', 'EntryAuthorKutrlIf']); -dcCore::app()->tpl->addValue('EntryAuthorKutrl', ['tplKutrl', 'EntryAuthorKutrl']); -dcCore::app()->tpl->addBlock('EntryKutrlIf', ['tplKutrl', 'EntryKutrlIf']); -dcCore::app()->tpl->addValue('EntryKutrl', ['tplKutrl', 'EntryKutrl']); -dcCore::app()->tpl->addBlock('CommentAuthorKutrlIf', ['tplKutrl', 'CommentAuthorKutrlIf']); -dcCore::app()->tpl->addValue('CommentAuthorKutrl', ['tplKutrl', 'CommentAuthorKutrl']); -dcCore::app()->tpl->addBlock('CommentPostKutrlIf', ['tplKutrl', 'CommentPostKutrlIf']); -dcCore::app()->tpl->addValue('CommentPostKutrl', ['tplKutrl', 'CommentPostKutrl']); - -class urlKutrl extends dcUrlHandlers +/** + * Frontend prepend. + */ +class Frontend extends Process { - # Redirect !!! local !!! service only - public static function redirectUrl($args) + public static function init(): bool { - # Not active, go to default 404 - if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('active')) { - self::p404(); - - return null; - } - # Not a valid url, go to kutrl 404 - if (!preg_match('#^(|(/(.*?)))$#', $args, $m)) { - self::kutrl404(); - - return null; - } - - $args = $m[3] ?? ''; - dcCore::app()->ctx->kutrl_msg = ''; - dcCore::app()->ctx->kutrl_hmf = hmfKutrl::create(); - dcCore::app()->ctx->kutrl_hmfp = hmfKutrl::protect(dcCore::app()->ctx->kutrl_hmf); - - $kut = new localKutrlService(); - - # Nothing on url - if ($m[1] == '/') { - dcCore::app()->ctx->kutrl_msg = 'No link given.'; - } - # find suffix on redirect url - $suffix = ''; - if (preg_match('@^([^?/#]+)(.*?)$@', $args, $more)) { - $args = $more[1]; - $suffix = $more[2]; - } - # No arg, go to kurtl page - if ($args == '') { - self::pageKutrl($kut); - - return null; - } - # Not find, go to kutrl 404 - if (false === ($url = $kut->getUrl($args))) { - //dcCore::app()->ctx->kutrl_msg = 'Failed to find short link.'; - //self::pageKutrl($kut); - self::kutrl404(); - - return null; - } - # Removed (empty url), go to kutrl 404 - if (!$url) { - self::kutrl404(); - - return null; - } - - dcCore::app()->blog->triggerBlog(); - http::redirect($url . $suffix); - - return null; + return self::status(My::checkContext(My::FRONTEND)); } - private static function pageKutrl($kut) + public static function process(): bool { - $s = dcCore::app()->blog->settings->get(basename(__DIR__)); - - # Not active, go to default 404 - if (!$s->get('active')) { - self::p404(); - - return null; - } - # Public page not active, go to kutrl 404 - if (!$s->get('srv_local_public')) { - self::kutrl404(); - - return null; - } - # Validation form - $url = !empty($_POST['longurl']) ? trim(dcCore::app()->con->escape($_POST['longurl'])) : ''; - if (!empty($url)) { - $hmf = !empty($_POST['hmf']) ? $_POST['hmf'] : '!'; - $hmfu = !empty($_POST['hmfp']) ? hmfKutrl::unprotect($_POST['hmfp']) : '?'; - - $err = false; - if (!$err) { - if ($hmf != $hmfu) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('Failed to verify protected field.'); - } - } - if (!$err) { - if (!$kut->testService()) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('Service is not well configured.'); - } - } - if (!$err) { - if (!$kut->isValidUrl($url)) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('This string is not a valid URL.'); - } - } - if (!$err) { - if (!$kut->isLongerUrl($url)) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('This link is too short.'); - } - } - if (!$err) { - if (!$kut->isProtocolUrl($url)) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('This type of link is not allowed.'); - } - } - - if (!$err) { - if (!$kut->allow_external_url && !$kut->isBlogUrl($url)) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('Short links are limited to this blog URL.'); - } - } - if (!$err) { - if ($kut->isServiceUrl($url)) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('This link is already a short link.'); - } - } - if (!$err) { - if (false !== ($rs = $kut->isKnowUrl($url))) { - $err = true; - - $url = $rs->url; - $new_url = $kut->url_base . $rs->hash; - - dcCore::app()->ctx->kutrl_msg = sprintf( - __('Short link for %s is %s'), - html::escapeHTML($url), - '' . $new_url . '' - ); - } - } - if (!$err) { - if (false === ($rs = $kut->hash($url))) { - $err = true; - dcCore::app()->ctx->kutrl_msg = __('Failed to create short link.'); - } else { - $url = $rs->url; - $new_url = $kut->url_base . $rs->hash; - - dcCore::app()->ctx->kutrl_msg = sprintf( - __('Short link for %s is %s'), - html::escapeHTML($url), - '' . $new_url . '' - ); - dcCore::app()->blog->triggerBlog(); - - # ex: Send new url to messengers - if (!empty($rs)) { - dcCore::app()->callBehavior('publicAfterKutrlCreate', $rs, __('New public short URL')); - } - } - } + if (!self::status()) { + return false; } - dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates'); - self::serveDocument('kutrl.html'); + dcCore::app()->tpl->setPath( + dcCore::app()->tpl->getPath(), + My::path() . DIRECTORY_SEPARATOR . 'default-templates' + ); + dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initShorten']); + dcCore::app()->addBehavior('initWidgets', [Widgets::class, 'initRank']); - return null; - } + dcCore::app()->addBehaviors([ + 'publicBeforeDocumentV2' => [FrontendBehaviors::class, 'publicBeforeDocumentV2'], + 'publicHeadContent' => [FrontendBehaviors::class, 'publicHeadContent'], + 'publicBeforeContentFilterV2' => [FrontendBehaviors::class, 'publicBeforeContentFilterV2'], + 'templateBeforeValueV2' => [FrontendBehaviors::class, 'templateBeforeValueV2'], + 'templateAfterValueV2' => [FrontendBehaviors::class, 'templateAfterValueV2'], + ]); - protected static function kutrl404() - { - if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('srv_local_404_active')) { - self::p404(); + dcCore::app()->tpl->addBlock('kutrlPageIf', [FrontendTemplate::class, 'pageIf']); + dcCore::app()->tpl->addBlock('kutrlMsgIf', [FrontendTemplate::class, 'pageMsgIf']); - return null; - } + dcCore::app()->tpl->addValue('kutrlPageURL', [FrontendTemplate::class, 'pageURL']); + dcCore::app()->tpl->addValue('kutrlMsg', [FrontendTemplate::class, 'pageMsg']); + dcCore::app()->tpl->addValue('kutrlHumanField', [FrontendTemplate::class, 'humanField']); + dcCore::app()->tpl->addValue('kutrlHumanFieldProtect', [FrontendTemplate::class, 'humanFieldProtect']); - dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates'); + dcCore::app()->tpl->addBlock('AttachmentKutrlIf', [FrontendTemplate::class, 'AttachmentKutrlIf']); + dcCore::app()->tpl->addValue('AttachmentKutrl', [FrontendTemplate::class, 'AttachmentKutrl']); + dcCore::app()->tpl->addBlock('MediaKutrlIf', [FrontendTemplate::class, 'MediaKutrlIf']); + dcCore::app()->tpl->addValue('MediaKutrl', [FrontendTemplate::class, 'MediaKutrl']); + dcCore::app()->tpl->addBlock('EntryAuthorKutrlIf', [FrontendTemplate::class, 'EntryAuthorKutrlIf']); + dcCore::app()->tpl->addValue('EntryAuthorKutrl', [FrontendTemplate::class, 'EntryAuthorKutrl']); + dcCore::app()->tpl->addBlock('EntryKutrlIf', [FrontendTemplate::class, 'EntryKutrlIf']); + dcCore::app()->tpl->addValue('EntryKutrl', [FrontendTemplate::class, 'EntryKutrl']); + dcCore::app()->tpl->addBlock('CommentAuthorKutrlIf', [FrontendTemplate::class, 'CommentAuthorKutrlIf']); + dcCore::app()->tpl->addValue('CommentAuthorKutrl', [FrontendTemplate::class, 'CommentAuthorKutrl']); + dcCore::app()->tpl->addBlock('CommentPostKutrlIf', [FrontendTemplate::class, 'CommentPostKutrlIf']); + dcCore::app()->tpl->addValue('CommentPostKutrl', [FrontendTemplate::class, 'CommentPostKutrl']); - header('Content-Type: text/html; charset=UTF-8'); - http::head(404, 'Not Found'); - dcCore::app()->url->type = '404'; - dcCore::app()->ctx->current_tpl = 'kutrl404.html'; - dcCore::app()->ctx->content_type = 'text/html'; - - echo dcCore::app()->tpl->getData(dcCore::app()->ctx->current_tpl); - - # --BEHAVIOR-- publicAfterDocument - dcCore::app()->callBehavior('publicAfterDocumentV2'); - exit; - } -} - -class pubKutrl -{ - # List of template tag which content URL that can be shortenn - public static $know_tags = [ - 'AttachmentURL', - 'CategoryURL', - 'MediaURL', - 'EntryAuthorURL', - 'EntryURL', - 'EntryCategoryURL', - 'CommentAuthorURL', - 'CommentPostURL', - ]; - - # Disable URL shoretning on filtered tag - public static function templateBeforeValueV2($tag, $attr) - { - if (!empty($attr['disable_kutrl']) && in_array($tag, pubKutrl::$know_tags)) { - return 'ctx->__set("disable_kutrl", true); ?>'; - } - - return null; - } - - # Re unable it after tag - public static function templateAfterValueV2($tag, $attr) - { - if (!empty($attr['disable_kutrl']) && in_array($tag, pubKutrl::$know_tags)) { - return 'ctx->__set("disable_kutrl", false); ?>'; - } - - return null; - } - - # Replace long urls on the fly (on filter) for default tags - public static function publicBeforeContentFilterV2($tag, $args) - { - # Unknow tag - if (!in_array($tag, pubKutrl::$know_tags)) { - return null; - } - # URL shortening is disabled by tag attribute - if (true !== dcCore::app()->ctx->__get('disable_kutrl')) { - # kUtRL is not activated - if (!dcCore::app()->blog->settings->get(basename(__DIR__))->get('active') - || !dcCore::app()->blog->settings->get(basename(__DIR__))->get('tpl_active') - ) { - return null; - } - - # Oups - if (!dcCore::app()->ctx->exists('kutrl')) { - return null; - } - # Existing - if (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->isKnowUrl($args[0]))) { - $args[0] = dcCore::app()->ctx->kutrl->url_base . $kutrl_rs->hash; - # New - } elseif (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->hash($args[0]))) { - $args[0] = dcCore::app()->ctx->kutrl->url_base . $kutrl_rs->hash; - - # ex: Send new url to messengers - if (!empty($kutrl_rs)) { - dcCore::app()->callBehavior('publicAfterKutrlCreate', $kutrl_rs, __('New public short URL')); - } - } - } - } - - public static function publicBeforeDocumentV2() - { - $s = dcCore::app()->blog->settings->get(basename(__DIR__)); - - # Passive : all kutrl tag return long url - dcCore::app()->ctx->kutrl_passive = (bool) $s->get('tpl_passive'); - - if (!$s->get('active') || !$s->get('tpl_service')) { - return null; - } - if (null === ($kut = kUtRL::quickPlace('tpl'))) { - return null; - } - dcCore::app()->ctx->kutrl = $kut; - } - - public static function publicHeadContent($_) - { - $css = dcCore::app()->blog->settings->get(basename(__DIR__))->get('srv_local_css'); - if ($css) { - echo - "\n \n" . - "\n"; - } - } -} - -class tplKutrl -{ - public static function pageURL($attr) - { - $f = dcCore::app()->tpl->getFilters($attr); - - return 'blog->url.dcCore::app()->url->getBase("kutrl")') . '; ?>'; - } - - public static function pageIf($attr, $content) - { - $operator = isset($attr['operator']) ? self::getOperator($attr['operator']) : '&&'; - - if (isset($attr['is_active'])) { - $sign = (bool) $attr['is_active'] ? '' : '!'; - $if[] = $sign . 'dcCore::app()->blog->settings->get("' . basename(__DIR__) . '")->get("srv_local_public")'; - } - if (empty($if)) { - return $content; - } - - return - '\n" . - $content . - "\n"; - } - - public static function pageMsgIf($attr, $content) - { - $operator = isset($attr['operator']) ? self::getOperator($attr['operator']) : '&&'; - - if (isset($attr['has_message'])) { - $sign = (bool) $attr['has_message'] ? '!' : '='; - $if[] = '"" ' . $sign . '= dcCore::app()->ctx->kutrl_msg'; - } - if (empty($if)) { - return $content; - } - - return - '\n" . - $content . - "\n"; - } - - public static function pageMsg($attr) - { - return 'ctx->kutrl_msg; ?>'; - } - - public static function humanField($attr) - { - return "ctx->kutrl_hmf); ?>"; - } - - public static function humanFieldProtect($attr) - { - return - '' . - 'formNonce(); ?>'; - } - - public static function AttachmentKutrlIf($attr, $content) - { - return self::genericKutrlIf('$attach_f->file_url', $attr, $content); - } - - public static function AttachmentKutrl($attr) - { - return self::genericKutrl('$attach_f->file_url', $attr); - } - - public static function MediaKutrlIf($attr, $content) - { - return self::genericKutrlIf('dcCore::app()->ctx->file_url', $attr, $content); - } - - public static function MediaKutrl($attr) - { - return self::genericKutrl('dcCore::app()->ctx->file_url', $attr); - } - - public static function EntryAuthorKutrlIf($attr, $content) - { - return self::genericKutrlIf('dcCore::app()->ctx->posts->user_url', $attr, $content); - } - - public static function EntryAuthorKutrl($attr) - { - return self::genericKutrl('dcCore::app()->ctx->posts->user_url', $attr); - } - - public static function EntryKutrlIf($attr, $content) - { - return self::genericKutrlIf('dcCore::app()->ctx->posts->getURL()', $attr, $content); - } - - public static function EntryKutrl($attr) - { - return self::genericKutrl('dcCore::app()->ctx->posts->getURL()', $attr); - } - - public static function CommentAuthorKutrlIf($attr, $content) - { - return self::genericKutrlIf('dcCore::app()->ctx->comments->getAuthorURL()', $attr, $content); - } - - public static function CommentAuthorKutrl($attr) - { - return self::genericKutrl('dcCore::app()->ctx->comments->getAuthorURL()', $attr); - } - - public static function CommentPostKutrlIf($attr, $content) - { - return self::genericKutrlIf('dcCore::app()->ctx->comments->getPostURL()', $attr, $content); - } - - public static function CommentPostKutrl($attr) - { - return self::genericKutrl('dcCore::app()->ctx->comments->getPostURL()', $attr); - } - - protected static function genericKutrlIf($str, $attr, $content) - { - $operator = isset($attr['operator']) ? self::getOperator($attr['operator']) : '&&'; - - if (isset($attr['is_active'])) { - $sign = (bool) $attr['is_active'] ? '' : '!'; - $if[] = $sign . 'dcCore::app()->ctx->exists("kutrl")'; - } - if (isset($attr['passive_mode'])) { - $sign = (bool) $attr['passive_mode'] ? '' : '!'; - $if[] = $sign . 'dcCore::app()->ctx->kutrl_passive'; - } - if (isset($attr['has_kutrl'])) { - $sign = (bool) $attr['has_kutrl'] ? '!' : '='; - $if[] = '(dcCore::app()->ctx->exists("kutrl") && false ' . $sign . '== dcCore::app()->ctx->kutrl->select(' . $str . ',null,null,"kutrl"))'; - } - if (empty($if)) { - return $content; - } - - return - '\n" . - $content . - "\n"; - } - - protected static function genericKutrl($str, $attr) - { - $f = dcCore::app()->tpl->getFilters($attr); - - return - "ctx->preview) { \n" . - ' echo ' . sprintf($f, $str) . '; ' . - "} else { \n" . - # Disable - "if (!dcCore::app()->ctx->exists('kutrl')) { \n" . - # Passive mode - ' if (dcCore::app()->ctx->kutrl_passive) { ' . - ' echo ' . sprintf($f, $str) . '; ' . - " } \n" . - "} else { \n" . - # Existing - ' if (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->isKnowUrl(' . $str . '))) { ' . - ' echo ' . sprintf($f, 'dcCore::app()->ctx->kutrl->url_base.$kutrl_rs->hash') . '; ' . - " } \n" . - # New - ' elseif (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->hash(' . $str . '))) { ' . - ' echo ' . sprintf($f, 'dcCore::app()->ctx->kutrl->url_base.$kutrl_rs->hash') . '; ' . - - # ex: Send new url to messengers - ' if (!empty($kutrl_rs)) { ' . - " dcCore::app()->callBehavior('publicAfterKutrlCreate',\$kutrl_rs,__('New public short URL')); " . - " } \n" . - - " } \n" . - " unset(\$kutrl_rs); \n" . - "} \n" . - "} \n" . - "?>\n"; - } - - protected static function getOperator($op) - { - switch (strtolower($op)) { - case 'or': - case '||': - return '||'; - case 'and': - case '&&': - default: - return '&&'; - } - } -} - -class hmfKutrl -{ - public static $chars = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'; - - public static function create($len = 6) - { - $res = ''; - $chars = self::$chars; - for ($i = 0; $i < $len; $i++) { - $res .= $chars[rand(0, strlen($chars) - 1)]; - } - - return $res; - } - - public static function protect($str) - { - $res = ''; - $chars = self::$chars; - for ($i = 0; $i < strlen($str); $i++) { - $res .= $chars[rand(0, strlen($chars) - 1)] . $str[$i]; - } - - return $res; - } - - public static function unprotect($str) - { - $res = ''; - for ($i = 0; $i < strlen($str); $i++) { - $i++; - $res .= $str[$i]; - } - - return $res; + return true; } } diff --git a/src/FrontendBehaviors.php b/src/FrontendBehaviors.php new file mode 100644 index 0000000..d10d404 --- /dev/null +++ b/src/FrontendBehaviors.php @@ -0,0 +1,102 @@ +ctx->__set("disable_kutrl", true); ?>'; + } + + return null; + } + + # Re unable it after tag + public static function templateAfterValueV2(string $tag, ArrayObject $attr): ?string + { + if (!empty($attr['disable_kutrl']) && in_array($tag, My::USED_TAGS)) { + return 'ctx->__set("disable_kutrl", false); ?>'; + } + + return null; + } + + # Replace long urls on the fly (on filter) for default tags + public static function publicBeforeContentFilterV2(string $tag, array $args): ?string + { + # Unknow tag + if (!in_array($tag, My::USED_TAGS)) { + return null; + } + # URL shortening is disabled by tag attribute + if (true !== dcCore::app()->ctx->__get('disable_kutrl')) { + # plugin is not activated + if (!My::settings()->get('active') + || !My::settings()->get('tpl_active') + || !dcCore::app()->ctx->exists('kutrl') + ) { + return null; + } + # Existing + if (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->isKnowUrl($args[0]))) { + $args[0] = dcCore::app()->ctx->kutrl->url_base . $kutrl_rs->hash; + # New + } elseif (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->hash($args[0]))) { + $args[0] = dcCore::app()->ctx->kutrl->url_base . $kutrl_rs->hash; + + # ex: Send new url to messengers + if (!empty($kutrl_rs)) { + dcCore::app()->callBehavior('publicAfterKutrlCreate', $kutrl_rs, __('New public short URL')); + } + } + } + } + + public static function publicBeforeDocumentV2(): void + { + $s = My::settings(); + + # Passive : all kutrl tag return long url + dcCore::app()->ctx->kutrl_passive = (bool) $s->get('tpl_passive'); + + if (!$s->get('active') + || !$s->get('tpl_service') + || null === ($kut = Utils::quickPlace('tpl')) + ) { + return; + } + + dcCore::app()->ctx->kutrl = $kut; + } + + public static function publicHeadContent($_): void + { + $css = My::settings()->get('srv_local_css'); + if (!empty($css)) { + echo + "\n \n" . + "\n"; + } + } +} diff --git a/src/FrontendTemplate.php b/src/FrontendTemplate.php new file mode 100644 index 0000000..b864f0c --- /dev/null +++ b/src/FrontendTemplate.php @@ -0,0 +1,205 @@ +tpl->getFilters($attr); + + return 'blog->url.dcCore::app()->url->getBase("kutrl")') . '; ?>'; + } + + public static function pageIf(ArrayObject $attr, string $content): string + { + $operator = isset($attr['operator']) ? dcTemplate::getOperator($attr['operator']) : '&&'; + + if (isset($attr['is_active'])) { + $sign = (bool) $attr['is_active'] ? '' : '!'; + $if[] = $sign . 'dcCore::app()->blog->settings->get("' . My::id() . '")->get("srv_local_public")'; + } + if (empty($if)) { + return $content; + } + + return + '\n" . + $content . + "\n"; + } + + public static function pageMsgIf(ArrayObject$attr, string $content): string + { + $operator = isset($attr['operator']) ? dcTemplate::getOperator($attr['operator']) : '&&'; + + if (isset($attr['has_message'])) { + $sign = (bool) $attr['has_message'] ? '!' : '='; + $if[] = '"" ' . $sign . '= dcCore::app()->ctx->kutrl_msg'; + } + if (empty($if)) { + return $content; + } + + return + '\n" . + $content . + "\n"; + } + + public static function pageMsg(ArrayObject$attr): string + { + return 'ctx->kutrl_msg; ?>'; + } + + public static function humanField(ArrayObject $attr): string + { + return "ctx->kutrl_hmf); ?>"; + } + + public static function humanFieldProtect(ArrayObject $attr): string + { + return + '' . + 'formNonce(); ?>'; + } + + public static function AttachmentKutrlIf(ArrayObject$attr, string $content): string + { + return self::genericKutrlIf('$attach_f->file_url', $attr, $content); + } + + public static function AttachmentKutrl(ArrayObject $attr): string + { + return self::genericKutrl('$attach_f->file_url', $attr); + } + + public static function MediaKutrlIf(ArrayObject$attr, string $content): string + { + return self::genericKutrlIf('dcCore::app()->ctx->file_url', $attr, $content); + } + + public static function MediaKutrl(ArrayObject $attr): string + { + return self::genericKutrl('dcCore::app()->ctx->file_url', $attr); + } + + public static function EntryAuthorKutrlIf(ArrayObject$attr, string $content): string + { + return self::genericKutrlIf('dcCore::app()->ctx->posts->user_url', $attr, $content); + } + + public static function EntryAuthorKutrl(ArrayObject $attr): string + { + return self::genericKutrl('dcCore::app()->ctx->posts->user_url', $attr); + } + + public static function EntryKutrlIf(ArrayObject $attr, string $content): string + { + return self::genericKutrlIf('dcCore::app()->ctx->posts->getURL()', $attr, $content); + } + + public static function EntryKutrl(ArrayObject $attr): string + { + return self::genericKutrl('dcCore::app()->ctx->posts->getURL()', $attr); + } + + public static function CommentAuthorKutrlIf(ArrayObject $attr, string $content): string + { + return self::genericKutrlIf('dcCore::app()->ctx->comments->getAuthorURL()', $attr, $content); + } + + public static function CommentAuthorKutrl(ArrayObject $attr): string + { + return self::genericKutrl('dcCore::app()->ctx->comments->getAuthorURL()', $attr); + } + + public static function CommentPostKutrlIf(ArrayObject $attr, string $content): string + { + return self::genericKutrlIf('dcCore::app()->ctx->comments->getPostURL()', $attr, $content); + } + + public static function CommentPostKutrl(ArrayObject $attr): string + { + return self::genericKutrl('dcCore::app()->ctx->comments->getPostURL()', $attr); + } + + protected static function genericKutrlIf(string $str, ArrayObject $attr, string $content): string + { + $operator = isset($attr['operator']) ? dcTemplate::getOperator($attr['operator']) : '&&'; + + if (isset($attr['is_active'])) { + $sign = (bool) $attr['is_active'] ? '' : '!'; + $if[] = $sign . 'dcCore::app()->ctx->exists("kutrl")'; + } + if (isset($attr['passive_mode'])) { + $sign = (bool) $attr['passive_mode'] ? '' : '!'; + $if[] = $sign . 'dcCore::app()->ctx->kutrl_passive'; + } + if (isset($attr['has_kutrl'])) { + $sign = (bool) $attr['has_kutrl'] ? '!' : '='; + $if[] = '(dcCore::app()->ctx->exists("kutrl") && false ' . $sign . '== dcCore::app()->ctx->kutrl->select(' . $str . ',null,null,"kutrl"))'; + } + if (empty($if)) { + return $content; + } + + return + '\n" . + $content . + "\n"; + } + + protected static function genericKutrl(string $str, ArrayObject $attr): string + { + $f = dcCore::app()->tpl->getFilters($attr); + + return + "ctx->preview) { \n" . + ' echo ' . sprintf($f, $str) . '; ' . + "} else { \n" . + # Disable + "if (!dcCore::app()->ctx->exists('kutrl')) { \n" . + # Passive mode + ' if (dcCore::app()->ctx->kutrl_passive) { ' . + ' echo ' . sprintf($f, $str) . '; ' . + " } \n" . + "} else { \n" . + # Existing + ' if (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->isKnowUrl(' . $str . '))) { ' . + ' echo ' . sprintf($f, 'dcCore::app()->ctx->kutrl->url_base.$kutrl_rs->hash') . '; ' . + " } \n" . + # New + ' elseif (false !== ($kutrl_rs = dcCore::app()->ctx->kutrl->hash(' . $str . '))) { ' . + ' echo ' . sprintf($f, 'dcCore::app()->ctx->kutrl->url_base.$kutrl_rs->hash') . '; ' . + + # ex: Send new url to messengers + ' if (!empty($kutrl_rs)) { ' . + " dcCore::app()->callBehavior('publicAfterKutrlCreate',\$kutrl_rs,__('New public short URL')); " . + " } \n" . + + " } \n" . + " unset(\$kutrl_rs); \n" . + "} \n" . + "} \n" . + "?>\n"; + } +} diff --git a/src/FrontendUrl.php b/src/FrontendUrl.php new file mode 100644 index 0000000..c2a4de8 --- /dev/null +++ b/src/FrontendUrl.php @@ -0,0 +1,211 @@ +get('active')) { + self::p404(); + + return; + } + # Not a valid url, go to kutrl 404 + if (!preg_match('#^(|(/(.*?)))$#', $args, $m)) { + self::kutrl404(); + + return; + } + + $args = $m[3] ?? ''; + dcCore::app()->ctx->kutrl_msg = ''; + dcCore::app()->ctx->kutrl_hmf = FrontendUtils::create(); + dcCore::app()->ctx->kutrl_hmfp = FrontendUtils::protect(dcCore::app()->ctx->kutrl_hmf); + + $kut = new Service\ServiceLocal(); + + # Nothing on url + if ($m[1] == '/') { + dcCore::app()->ctx->kutrl_msg = 'No link given.'; + } + # find suffix on redirect url + $suffix = ''; + if (preg_match('@^([^?/#]+)(.*?)$@', $args, $more)) { + $args = $more[1]; + $suffix = $more[2]; + } + # No arg, go to kurtl page + if ($args == '') { + self::pageKutrl($kut); + + return; + } + # Not find, go to kutrl 404 + if (false === ($url = $kut->getUrl($args))) { + //dcCore::app()->ctx->kutrl_msg = 'Failed to find short link.'; + //self::pageKutrl($kut); + self::kutrl404(); + + return; + } + # Removed (empty url), go to kutrl 404 + if (!$url) { + self::kutrl404(); + + return; + } + + dcCore::app()->blog->triggerBlog(); + Http::redirect($url . $suffix); + } + + private static function pageKutrl(Service $kut): void + { + $s = My::settings(); + + # Not active, go to default 404 + if (!$s->get('active')) { + self::p404(); + + return; + } + # Public page not active, go to kutrl 404 + if (!$s->get('srv_local_public')) { + self::kutrl404(); + + return; + } + # Validation form + $url = !empty($_POST['longurl']) ? trim(dcCore::app()->con->escapeStr((string) $_POST['longurl'])) : ''; + if (!empty($url)) { + $hmf = !empty($_POST['hmf']) ? $_POST['hmf'] : '!'; + $hmfu = !empty($_POST['hmfp']) ? FrontendUtils::unprotect($_POST['hmfp']) : '?'; + + $err = false; + if (!$err) { + if ($hmf != $hmfu) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('Failed to verify protected field.'); + } + } + if (!$err) { + if (!$kut->testService()) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('Service is not well configured.'); + } + } + if (!$err) { + if (!$kut->isValidUrl($url)) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('This string is not a valid URL.'); + } + } + if (!$err) { + if (!$kut->isLongerUrl($url)) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('This link is too short.'); + } + } + if (!$err) { + if (!$kut->isProtocolUrl($url)) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('This type of link is not allowed.'); + } + } + + if (!$err) { + if (!$kut->allow_external_url && !$kut->isBlogUrl($url)) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('Short links are limited to this blog URL.'); + } + } + if (!$err) { + if ($kut->isServiceUrl($url)) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('This link is already a short link.'); + } + } + if (!$err) { + if (false !== ($rs = $kut->isKnowUrl($url))) { + $err = true; + + $url = $rs->url; + $new_url = $kut->url_base . $rs->hash; + + dcCore::app()->ctx->kutrl_msg = sprintf( + __('Short link for %s is %s'), + Html::escapeHTML($url), + '' . $new_url . '' + ); + } + } + if (!$err) { + if (false === ($rs = $kut->hash($url))) { + $err = true; + dcCore::app()->ctx->kutrl_msg = __('Failed to create short link.'); + } else { + $url = $rs->url; + $new_url = $kut->url_base . $rs->hash; + + dcCore::app()->ctx->kutrl_msg = sprintf( + __('Short link for %s is %s'), + Html::escapeHTML($url), + '' . $new_url . '' + ); + dcCore::app()->blog->triggerBlog(); + + # ex: Send new url to messengers + if (!empty($rs)) { + dcCore::app()->callBehavior('publicAfterKutrlCreate', $rs, __('New public short URL')); + } + } + } + } + + dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), My::path() . '/default-templates'); + self::serveDocument('kutrl.html'); + } + + protected static function kutrl404(): void + { + if (!My::settigns()->get('srv_local_404_active')) { + self::p404(); + + return; + } + + dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), My::path() . '/default-templates'); + + header('Content-Type: text/html; charset=UTF-8'); + Http::head(404, 'Not Found'); + dcCore::app()->url->type = '404'; + dcCore::app()->ctx->current_tpl = 'kutrl404.html'; + dcCore::app()->ctx->content_type = 'text/html'; + + echo dcCore::app()->tpl->getData(dcCore::app()->ctx->current_tpl); + + # --BEHAVIOR-- publicAfterDocumentV2 + dcCore::app()->callBehavior('publicAfterDocumentV2'); + exit; + } +} diff --git a/src/FrontendUtils.php b/src/FrontendUtils.php new file mode 100644 index 0000000..6593064 --- /dev/null +++ b/src/FrontendUtils.php @@ -0,0 +1,53 @@ +export( + My::TABLE_NAME, + 'SELECT kut_id, blog_id, kut_service, kut_type, ' . + 'kut_hash, kut_url, kut_dt, kut_password, kut_counter ' . + 'FROM ' . dcCore::app()->prefix . My::TABLE_NAME . ' ' . + "WHERE blog_id = '" . $blog_id . "' " + ); + } + + public static function exportFullV2($exp) + { + $exp->exportTable(My::TABLE_NAME); + } + + public static function importInitV2($bk) + { + $bk->cur_kutrl = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::TABLE_NAME); + $bk->kutrl = new Logs(); + } + + public static function importSingleV2($line, $bk) + { + if ($line->__name == My::TABLE_NAME) { + # Do nothing if str/type exists ! + if (false === $bk->kutrl->select($line->kut_url, $line->kut_hash, $line->kut_type, $line->kut_service)) { + $bk->kutrl->insert($line->kut_url, $line->kut_hash, $line->kut_type, $line->kut_service); + } + } + } + + public static function importFullV2($line, $bk) + { + if ($line->__name == My::TABLE_NAME) { + $bk->cur_kutrl->clean(); + $bk->cur_kutrl->kut_id = (int) $line->kut_id; + $bk->cur_kutrl->blog_id = (string) $line->blog_id; + $bk->cur_kutrl->kut_service = (string) $line->kut_service; + $bk->cur_kutrl->kut_type = (string) $line->kut_type; + $bk->cur_kutrl->kut_hash = (string) $line->kut_hash; + $bk->cur_kutrl->kut_url = (string) $line->kut_url; + $bk->cur_kutrl->kut_dt = (string) $line->miniurl_dt; + $bk->cur_kutrl->kut_counter = (int) $line->kut_counter; + $bk->cur_kutrl->kut_password = (string) $line->kut_password; + $bk->cur_kutrl->insert(); + } + } +} diff --git a/src/Install.php b/src/Install.php index b2892e2..dab7c48 100644 --- a/src/Install.php +++ b/src/Install.php @@ -10,94 +10,109 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; -} +declare(strict_types=1); -try { - // Compare versions - if (!dcCore::app()->newVersion( - basename(__DIR__), - dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version') - )) { - return null; +namespace Dotclear\Plugin\kUtRL; + +use dcCore; +use dcNamespace; +use Dotclear\Core\Process; +use Dotclear\Database\Structure; +use Exception; + +/** + * Module installation. + */ +class Install extends Process +{ + public static function init(): bool + { + return self::status(My::checkContext(My::INSTALL)); } - // Table - $t = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); - $t->{initkUtRL::KURL_TABLE_NAME} - ->kut_id('bigint', 0, false) - ->blog_id('varchar', 32, false) - ->kut_service('varchar', 32, false, "'kUtRL'") - ->kut_type('varchar', 32, false) - ->kut_hash('varchar', 32, false) - ->kut_url('text', 0, false) - ->kut_dt('timestamp', 0, false, 'now()') - ->kut_password('varchar', 32, true) - ->kut_counter('bigint', 0, false, 0) - - ->primary('pk_kutrl', 'kut_id') - ->index('idx_kut_blog_id', 'btree', 'blog_id') - ->index('idx_kut_hash', 'btree', 'kut_hash') - ->index('idx_kut_service', 'btree', 'kut_service') - ->index('idx_kut_type', 'btree', 'kut_type'); - - $ti = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); - $changes = $ti->synchronize($t); - - // upgrade version < 2022.12.22 : upgrade settings id and ns and array - $current = dcCore::app()->getVersion(basename(__DIR__)); - if ($current && version_compare($current, '2022.12.22', '<')) { - $record = dcCore::app()->con->select( - 'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' . - "WHERE setting_ns = 'kUtRL' " - ); - while ($record->fetch()) { - if (preg_match('/^kutrl_(.*?)$/', $record->setting_id, $match)) { - $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME); - // avoid the use of serialize function - if (in_array($record->setting_id, ['kutrl_srv_custom'])) { - $cur->setting_value = json_encode(@unserialize(base64_decode((string) $record->setting_value))); - } - $cur->setting_id = $match[1]; - $cur->setting_ns = basename(__DIR__); - $cur->update( - "WHERE setting_id = '" . $record->setting_id . "' and setting_ns = 'kUtRL' " . - 'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escape($record->blog_id) . "' ")) - ); - } + public static function process(): bool + { + if (!self::status()) { + return false; } - } else { - // Settings - $s = dcCore::app()->blog->settings->addNamespace(basename(__DIR__)); - $s->put('active', false, 'boolean', 'Enabled kutrl plugin', false, true); - $s->put('plugin_service', 'default', 'string', 'Service to use to shorten links on third part plugins', false, true); - $s->put('admin_service', 'local', 'string', 'Service to use to shorten links on admin', false, true); - $s->put('tpl_service', 'local', 'string', 'Service to use to shorten links on template', false, true); - $s->put('wiki_service', 'local', 'string', 'Service to use to shorten links on contents', false, true); - $s->put('allow_external_url', true, 'boolean', 'Limited short url to current blog\'s url', false, true); - $s->put('tpl_passive', true, 'boolean', 'Return long url on kutrl tags if kutrl is unactivate', false, true); - $s->put('tpl_active', false, 'boolean', 'Return short url on dotclear tags if kutrl is active', false, true); - $s->put('admin_entry_default', true, 'boolean', 'Create short link on new entry by default', false, true); - # Settings for "local" service - $local_css = ".shortenkutrlwidget input { border: 1px solid #CCCCCC; }\n" . - '.dc-kutrl input { border: 1px solid #CCCCCC; margin: 10px; }'; - $s->put('srv_local_protocols', 'http:,https:,ftp:,ftps:,irc:', 'string', 'Allowed kutrl local service protocols', false, true); - $s->put('srv_local_public', false, 'boolean', 'Enabled local service public page', false, true); - $s->put('srv_local_css', $local_css, 'string', 'Special CSS for kutrl local service', false, true); - $s->put('srv_local_404_active', false, 'boolean', 'Use special 404 page on unknow urls', false, true); - # Settings for "bilbolinks" service - $s->put('srv_bilbolinks_base', 'http://tux-pla.net/', 'string', 'URL of bilbolinks service', false, true); - # Settings for "YOURLS" service - $s->put('srv_yourls_base', '', 'string', 'URL of YOURLS service', false, true); - $s->put('srv_yourls_username', '', 'string', 'User name to YOURLS service', false, true); - $s->put('srv_yourls_password', '', 'string', 'User password to YOURLS service', false, true); + try { + // Table + $t = new Structure(dcCore::app()->con, dcCore::app()->prefix); + $t->{My::TABLE_NAME} + ->kut_id('bigint', 0, false) + ->blog_id('varchar', 32, false) + ->kut_service('varchar', 32, false, "'kUtRL'") + ->kut_type('varchar', 32, false) + ->kut_hash('varchar', 32, false) + ->kut_url('text', 0, false) + ->kut_dt('timestamp', 0, false, 'now()') + ->kut_password('varchar', 32, true) + ->kut_counter('bigint', 0, false, 0) + + ->primary('pk_kutrl', 'kut_id') + ->index('idx_kut_blog_id', 'btree', 'blog_id') + ->index('idx_kut_hash', 'btree', 'kut_hash') + ->index('idx_kut_service', 'btree', 'kut_service') + ->index('idx_kut_type', 'btree', 'kut_type'); + + (new Structure(dcCore::app()->con, dcCore::app()->prefix))->synchronize($t); + + // upgrade version < 2022.12.22 : upgrade settings id and ns and array + $current = dcCore::app()->getVersion(My::id()); + if ($current && version_compare($current, '2022.12.22', '<')) { + $record = dcCore::app()->con->select( + 'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' . + "WHERE setting_ns = 'kUtRL' " + ); + while ($record->fetch()) { + if (preg_match('/^kutrl_(.*?)$/', $record->setting_id, $match)) { + $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME); + // avoid the use of serialize function + if (in_array($record->setting_id, ['kutrl_srv_custom'])) { + $cur->setting_value = json_encode(@unserialize(base64_decode((string) $record->setting_value))); + } + $cur->setting_id = $match[1]; + $cur->setting_ns = basename(__DIR__); + $cur->update( + "WHERE setting_id = '" . $record->setting_id . "' and setting_ns = 'kUtRL' " . + 'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escapeStr((string) $record->blog_id) . "' ")) + ); + } + } + } else { + // Settings + $s = My::settings(); + + $s->put('active', false, 'boolean', 'Enabled kutrl plugin', false, true); + $s->put('plugin_service', 'default', 'string', 'Service to use to shorten links on third part plugins', false, true); + $s->put('admin_service', 'local', 'string', 'Service to use to shorten links on admin', false, true); + $s->put('tpl_service', 'local', 'string', 'Service to use to shorten links on template', false, true); + $s->put('wiki_service', 'local', 'string', 'Service to use to shorten links on contents', false, true); + $s->put('allow_external_url', true, 'boolean', 'Limited short url to current blog\'s url', false, true); + $s->put('tpl_passive', true, 'boolean', 'Return long url on kutrl tags if kutrl is unactivate', false, true); + $s->put('tpl_active', false, 'boolean', 'Return short url on dotclear tags if kutrl is active', false, true); + $s->put('admin_entry_default', true, 'boolean', 'Create short link on new entry by default', false, true); + # Settings for "local" service + $local_css = ".shortenkutrlwidget input { border: 1px solid #CCCCCC; }\n" . + '.dc-kutrl input { border: 1px solid #CCCCCC; margin: 10px; }'; + $s->put('srv_local_protocols', 'http:,https:,ftp:,ftps:,irc:', 'string', 'Allowed kutrl local service protocols', false, true); + $s->put('srv_local_public', false, 'boolean', 'Enabled local service public page', false, true); + $s->put('srv_local_css', $local_css, 'string', 'Special CSS for kutrl local service', false, true); + $s->put('srv_local_404_active', false, 'boolean', 'Use special 404 page on unknow urls', false, true); + # Settings for "bilbolinks" service + $s->put('srv_bilbolinks_base', 'http://tux-pla.net/', 'string', 'URL of bilbolinks service', false, true); + # Settings for "YOURLS" service + $s->put('srv_yourls_base', '', 'string', 'URL of YOURLS service', false, true); + $s->put('srv_yourls_username', '', 'string', 'User name to YOURLS service', false, true); + $s->put('srv_yourls_password', '', 'string', 'User password to YOURLS service', false, true); + } + + return true; + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + + return false; + } } - - return true; -} catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); } - -return false; diff --git a/src/LinksListing.php b/src/LinksListing.php index 9ffda50..3b65b76 100644 --- a/src/LinksListing.php +++ b/src/LinksListing.php @@ -10,121 +10,141 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -class kutrlLinkslist +declare(strict_types=1); + +namespace Dotclear\Plugin\kUtRL; + +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, +}; +use Dotclear\Helper\Html\Html; + +class LinksListing extends Listing { - protected $rs; - 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 = __('« prev.'); - $this->html_next = __('next »'); - } - - 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) + public function display(Filters $filter, string $enclose_block): void { if ($this->rs->isEmpty()) { - if ($filter) { - echo '

' . __('No short link matches the filter') . '

'; - } else { - echo '

' . __('No short link') . '

'; - } - } else { - $pager = new dcPager($page, $this->rs_count, $nb_per_page, 10); - $links = []; - if (isset($_REQUEST['entries'])) { - foreach ($_REQUEST['entries'] as $v) { - $links[(int) $v] = true; - } - } + echo (new Note()) + ->class('info') + ->text($filter->show() ? __('No short link matches the filter') : __('No short link')) + ->render(); - $cols = [ - 'kut_url' => '' . __('Link') . '', - 'kut_hash' => '' . __('Hash') . '', - 'kut_dt' => '' . __('Date') . '', - 'kut_service' => '' . __('Service') . '', - ]; - $cols = new ArrayObject($cols); - $this->userColumns('kUtRL', $cols); - - $html_block = '
' . - '' . - '' . - '' . - '' . implode(iterator_to_array($cols)) . '' . - '' . - '%s' . - '
' . ( - $filter ? - sprintf(__('List of %s links matching the filter.'), $this->rs_count) : - sprintf(__('List of links (%s)'), $this->rs_count) - ) . '
' . - '%s
'; - - if ($enclose_block) { - $html_block = sprintf($enclose_block, $html_block); - } - $blocks = explode('%s', $html_block); - - echo $pager->getLinks() . $blocks[0]; - - while ($this->rs->fetch()) { - echo $this->linkLine(isset($links[$this->rs->kut_id])); - } - - echo $blocks[1] . $blocks[2] . $pager->getLinks(); + return; } + + $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->nb, 10); + + $cols = new ArrayObject([ + 'kut_url' => (new Text('th', __('Link'))) + ->class('first') + ->extra('colspan="2"'), + 'kut_hash' => (new Text('th', __('Hash'))) + ->extra('scope="col"'), + 'kut_dt' => (new Text('th', __('Date'))) + ->extra('scope="col"'), + 'kut_service' => (new Text('th', __('Service'))) + ->extra('scope="col"'), + ]); + + $this->userColumns(My::id(), $cols); + + $lines = []; + while ($this->rs->fetch()) { + $lines[] = $this->linkLine(isset($links[$this->rs->kut_id])); + } + + echo + $pager->getLinks() . + sprintf( + $enclose_block, + (new Div()) + ->class('table-outer') + ->items([ + (new Para(null, 'table')) + ->items([ + (new Text( + 'caption', + $filter->show() ? + sprintf(__('List of %s links matching the filter.'), $this->rs_count) : + sprintf(__('List of links. (%s)'), $this->rs_count) + )), + (new Para(null, 'tr')) + ->items(iterator_to_array($cols)), + (new Para(null, 'tbody')) + ->items($lines), + ]), + ]) + ->render() + ) . + $pager->getLinks(); } - private function linkLine($checked) + private function linkLine(bool $checked): Para { $type = $this->rs->kut_type; $hash = $this->rs->kut_hash; - if (null !== ($o = kUtRL::quickService($type))) { - $type = '' . $o->name . ''; - $hash = '' . $hash . ''; + if (null !== ($o = Utils::quickService($type))) { + $type = (new Link()) + ->href($o->home) + ->title($o->name) + ->text($o->name) + ->render(); + $hash = (new Link()) + ->href($o->url_base . $hash) + ->title($o->url_base . $hash) + ->text($hash) + ->render(); } - $cols = [ - 'check' => '' . - form::checkbox(['entries[]'], $this->rs->kut_id, ['checked' => $checked]) . - '', - 'kut_url' => '' . - '' . $this->rs->kut_url . '' . - '', - 'kut_hash' => '' . - $hash . - '', - 'kut_dt' => '' . - dt::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->kut_dt, dcCore::app()->auth->getInfo('user_tz')) . - '', - 'kut_service' => '' . - $type . - '', - ]; + $cols = new ArrayObject([ + 'check' => (new Para(null, 'td')) + ->class('nowrap minimal') + ->items([ + (new Checkbox(['entries[]'], $checked)) + ->value($this->rs->kut_id), + ]), + 'kut_url' => (new Para(null, 'td')) + ->class('maximal') + ->items([ + (new Link()) + ->href($o->home) + ->title($this->rs->kut_url) + ->text($this->rs->kut_url), + ]), + 'kut_hash' => (new Text('td', $hash)) + ->class('nowrap'), + 'kut_dt' => (new Text('td', Html::escapeHTML(Date::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->kut_dt, dcCore::app()->auth->getInfo('user_tz'))))) + ->class('nowrap'), + 'kut_service' => (new Text('td', $type)) + ->class('nowrap'), + ]); - $cols = new ArrayObject($cols); - $this->userColumns('kUtRL', $cols); + $this->userColumns(My::id(), $cols); - return '' . implode(iterator_to_array($cols)) . '' . "\n"; + return + (new Para('p' . $this->rs->kut_id, 'tr')) + ->class('line') + ->items(iterator_to_array($cols)); } } diff --git a/src/Logs.php b/src/Logs.php index 1e3fa45..b22bb14 100644 --- a/src/Logs.php +++ b/src/Logs.php @@ -2,6 +2,8 @@ /** * @brief kUtRL, a plugin for Dotclear 2 * + * This file contents class to acces local short links records + * * @package Dotclear * @subpackage Plugin * @@ -10,36 +12,52 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -# This file contents class to acces local short links records +declare(strict_types=1); -class kutrlLog +namespace Dotclear\Plugin\kUtRL; + +use dcCore; +use Dotclear\Database\MetaRecord; +use Dotclear\Database\Statement\{ + DeleteStatement, + JoinStatement, + SelectStatement, + UpdateStatement +}; + +class Logs { public $table; - public $blog; public $con; public function __construct() { - $this->table = dcCore::app()->prefix . initkUtRL::KURL_TABLE_NAME; - $this->blog = dcCore::app()->con->escape(dcCore::app()->blog->id); + $this->table = dcCore::app()->prefix . My::TABLE_NAME; $this->con = dcCore::app()->con; } - public function nextId() + public function nextId(): int { - return $this->con->select( - 'SELECT MAX(kut_id) FROM ' . $this->table - )->f(0) + 1; + $sql = new SelectStatement(); + + return $sql + ->column($sql->max('kut_id')) + ->from($this->table) + ->select() + ->f(0) + 1; } - public function insert($url, $hash, $type, $service = 'kutrl') + /** + * @return false|array + */ + public function insert(string $url, string $hash, string $type, string $service = 'kutrl') { $cur = $this->con->openCursor($this->table); $this->con->writeLock($this->table); try { $cur->kut_id = $this->nextId(); - $cur->blog_id = $this->blog; + $cur->blog_id = dcCore::app()->blog->id; $cur->kut_url = (string) $url; $cur->kut_hash = (string) $hash; $cur->kut_type = (string) $type; @@ -64,45 +82,50 @@ class kutrlLog throw $e; } - return false; + return []; } - public function select($url = null, $hash = null, $type = null, $service = 'kutrl') + /** + * @return false|MetaRecord + */ + public function select(?string $url = null, ?string $hash = null, ?string $type = null, string $service = 'kutrl') { - //$this->con->writeLock($this->table); - - $req = 'SELECT kut_id as id, kut_hash as hash, kut_url as url, ' . - 'kut_type as type, kut_service as service, kut_counter as counter ' . - 'FROM ' . $this->table . ' ' . - "WHERE blog_id = '" . $this->blog . "' " . - "AND kut_service = '" . $this->con->escape($service) . "' "; + $sql = new SelectStatement(); + $sql + ->columns([ + $sql->as('kut_id', 'id'), + $sql->as('kut_hash', 'hash'), + $sql->as('kut_url', 'url'), + $sql->as('kut_type', 'type'), + $sql->as('kut_service', 'service'), + $sql->as('kut_counter', 'counter'), + ]) + ->from($this->table) + ->where('blog_id = ' . $sql->quote(dcCore::app()->blog->id)) + ->and('kut_service = ' . $sql->quote($service)) + ; if (null !== $url) { - $req .= "AND kut_url = '" . $this->con->escape($url) . "' "; + $sql->and('kut_url = ' . $sql->quote($url)); } if (null !== $hash) { - $req .= "AND kut_hash = '" . $this->con->escape($hash) . "' "; + $sql->and('kut_hash = ' . $sql->quote($hash)); } if (null !== $type) { - if (is_array($type)) { - $req .= "AND kut_type '" . $this->con->in($type) . "' "; - } else { - $req .= "AND kut_type = '" . $this->con->escape($type) . "' "; - } + $sql->and('kut_type = ' . $sql->quote($type)); } - $req .= 'ORDER BY kut_dt DESC ' . $this->con->limit(1); + $sql + ->order('kut_dt DESC') + ->limit(1); - $rs = $this->con->select($req); - //$this->con->unlock(); + $rs = $sql->select(); return $rs->isEmpty() ? false : $rs; } - public function clear($id) + public function clear(int $id): bool { - $id = (int) $id; - $cur = $this->con->openCursor($this->table); $this->con->writeLock($this->table); @@ -112,7 +135,7 @@ class kutrlLog $cur->kut_counter = 0; $cur->update( - "WHERE blog_id='" . $this->blog . "' " . + "WHERE blog_id='" . $this->con->escapeStr(dcCore::app()->blog->id) . "' " . "AND kut_id='" . $id . "' " ); $this->con->unlock(); @@ -127,29 +150,29 @@ class kutrlLog return false; } - public function delete($id) + public function delete(int $id): bool { - $id = (int) $id; + $sql = new DeleteStatement(); + $sql + ->from($this->table) + ->where('blog_id = ' . $sql->quote(dcCore::app()->blog->id)) + ->and('kut_id = ' . $id) + ->delete(); - return $this->con->execute( - 'DELETE FROM ' . $this->table . ' ' . - "WHERE blog_id='" . $this->blog . "' " . - "AND kut_id='" . $id . "' " - ); + return true; } - public function counter($id, $do = 'get') + public function counter(int $id, string $do = 'get'): int { - $id = (int) $id; + $sql = new SelectStatement(); + $rs = $sql + ->column('kut_counter') + ->from($this->table) + ->where('blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id)) + ->and('kut_id = ' . $id) + ->select(); - $rs = $this->con->select( - 'SELECT kut_counter ' . - 'FROM ' . $this->table . ' ' . - "WHERE blog_id='" . $this->blog . "' " . - "AND kut_id='" . $id . "' " - ); - - $counter = $rs->isEmpty() ? 0 : $rs->kut_counter; + $counter = $rs->isEmpty() ? 0 : (int) $rs->kut_counter; if ('get' == $do) { return $counter; @@ -161,94 +184,86 @@ class kutrlLog return 0; } - $cur = $this->con->openCursor($this->table); - $this->con->writeLock($this->table); - - $cur->kut_counter = (int) $counter; - $cur->update( - "WHERE blog_id='" . $this->blog . "' " . - "AND kut_id='" . $id . "'" - ); - $this->con->unlock(); + $sql = new UpdateStatement(); + $ret = $sql->ref($this->table) + ->column('kut_counter') + ->value($counter) + ->where('blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id)) + ->and('kut_id = ' . $id) + ->update(); return $counter; } - public function getLogs($p, $count_only = false) + public function getLogs(array $params, bool $count_only = false): MetaRecord { - if ($count_only) { - $r = 'SELECT count(S.kut_id) '; - } else { - $content_req = ''; + $sql = new SelectStatement(); - if (!empty($p['columns']) && is_array($p['columns'])) { - $content_req .= implode(', ', $p['columns']) . ', '; - } - $r = 'SELECT S.kut_id, S.kut_type, S.kut_hash, S.kut_url, ' . - $content_req . 'S.kut_dt '; - } - $r .= 'FROM ' . $this->table . ' S '; - if (!empty($p['from'])) { - $r .= $p['from'] . ' '; - } - $r .= "WHERE S.blog_id = '" . $this->blog . "' "; - if (isset($p['kut_service'])) { - $r .= "AND kut_service='" . $this->con->escape($p['kut_service']) . "' "; + if ($count_only) { + $sql->column($sql->count($sql->unique('S.kut_id'))); } else { - $r .= "AND kut_service='kutrl' "; - } - if (isset($p['kut_type'])) { - if (is_array($p['kut_type']) && !empty($p['kut_type'])) { - $r .= 'AND kut_type ' . $this->con->in($p['kut_type']); - } elseif ($p['kut_type'] != '') { - $r .= "AND kut_type = '" . $this->con->escape($p['kut_type']) . "' "; + if (!empty($params['columns']) && is_array($params['columns'])) { + $sql->columns($params['columns']); } + $sql->columns([ + 'S.kut_id', + 'S.kut_type', + 'S.kut_hash', + 'S.kut_url', + 'S.kut_dt', + 'S.kut_counter', + ]); } - if (isset($p['kut_id'])) { - if (is_array($p['kut_id']) && !empty($p['kut_id'])) { - $r .= 'AND kut_id ' . $this->con->in($p['kut_id']); - } elseif ($p['kut_id'] != '') { - $r .= "AND kut_id = '" . $this->con->escape($p['kut_id']) . "' "; - } + + $sql->from($sql->as($this->table, 'S')); + + if (!empty($params['from'])) { + $sql->from($params['from']); } - if (isset($p['kut_hash'])) { - if (is_array($p['kut_hash']) && !empty($p['kut_hash'])) { - $r .= 'AND kut_hash ' . $this->con->in($p['kut_hash']); - } elseif ($p['kut_hash'] != '') { - $r .= "AND kut_hash = '" . $this->con->escape($p['kut_hash']) . "' "; - } + + $sql->where('S.blog_id = ' . $sql->quote(dcCore::app()->blog->id)); + + if (isset($params['kut_service'])) { + $sql->and('kut_service = ' . $sql->quote($params['kut_service'])); + } else { + $sql->and("kut_service = 'kutrl' "); } - if (isset($p['kut_url'])) { - if (is_array($p['kut_url']) && !empty($p['kut_url'])) { - $r .= 'AND kut_url ' . $this->con->in($p['kut_url']); - } elseif ($p['kut_url'] != '') { - $r .= "AND kut_url = '" . $this->con->escape($p['kut_url']) . "' "; - } + if (isset($params['kut_type'])) { + $sql->and('kut_type ' . $sql->in($params['kut_type'])); } - if (!empty($p['kut_year'])) { - $r .= 'AND ' . $this->con->dateFormat('kut_dt', '%Y') . ' = ' . - "'" . sprintf('%04d', $p['kut_year']) . "' "; + if (isset($params['kut_id'])) { + $sql->and('kut_id ' . $sql->in($params['kut_id'])); } - if (!empty($p['kut_month'])) { - $r .= 'AND ' . $this->con->dateFormat('kut_dt', '%m') . ' = ' . - "'" . sprintf('%02d', $p['kut_month']) . "' "; + if (isset($params['kut_hash'])) { + $sql->and('kut_hash ' . $sql->in($params['kut_hash'])); } - if (!empty($p['kut_day'])) { - $r .= 'AND ' . $this->con->dateFormat('kut_dt', '%d') . ' = ' . - "'" . sprintf('%02d', $p['kut_day']) . "' "; + if (isset($params['kut_url'])) { + $sql->and('kut_url ' . $sql->in($params['kut_url'])); } - if (!empty($p['sql'])) { - $r .= $p['sql'] . ' '; + if (!empty($params['kut_year'])) { + $sql->and($sql->dateFormat('kut_dt', '%Y') . ' = ' . $sql->quote(sprintf('%04d', $params['kut_year']))); + } + if (!empty($params['kut_month'])) { + $sql->and($sql->dateFormat('kut_dt', '%m') . ' = ' . $sql->quote(sprintf('%02d', $params['kut_month']))); + } + if (!empty($params['kut_day'])) { + $sql->and($sql->dateFormat('kut_dt', '%d') . ' = ' . $sql->quote(sprintf('%02d', $params['kut_day']))); + } + if (!empty($params['sql'])) { + $sql->sql($params['sql']); } if (!$count_only) { - $r .= empty($p['order']) ? - 'ORDER BY kut_dt DESC ' : - 'ORDER BY ' . $this->con->escape($p['order']) . ' '; - } - if (!$count_only && !empty($p['limit'])) { - $r .= $this->con->limit($p['limit']); + if (!empty($params['order'])) { + $sql->order($sql->escape($params['order'])); + } else { + $sql->order('kut_dt DESC'); + } } - return $this->con->select($r); + if (!$count_only && !empty($params['limit'])) { + $sql->limit($params['limit']); + } + + return $sql->select(); } } diff --git a/src/Manage.php b/src/Manage.php index a8391c4..30fe2e4 100644 --- a/src/Manage.php +++ b/src/Manage.php @@ -10,29 +10,56 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; -} +declare(strict_types=1); -# Check user perms -dcPage::check(dcCore::app()->auth->makePermissions([ - dcAuth::PERMISSION_ADMIN, -])); +namespace Dotclear\Plugin\kUtRL; -$header = ''; -$part = $_REQUEST['part'] ?? 'links'; -$action = $_POST['action'] ?? ''; +use dcCore; +use Dotclear\Core\Backend\{ + Notices, + Page +}; +use Dotclear\Core\Process; +use Dotclear\Helper\Html\Form\{ + Div, + Form, + Input, + Label, + Note, + Para, + Submit, + Text, +}; +use Dotclear\Helper\Html\Html; -# link creation -if ($part == 'link') { - $kut = kUtRL::quickPlace('admin'); +class Manage extends Process +{ + public static function init(): bool + { + return self::status(($_REQUEST['part'] ?? 'links') === 'links' ? ManageLinks::init() : My::checkContext(My::MANAGE)); + } + + public static function process(): bool + { + if (!self::status()) { + return false; + } + + if (($_REQUEST['part'] ?? 'links') === 'links') { + return ManageLinks::process(); + } + + $kut = Utils::quickPlace('admin'); + + if (empty($_POST['save'])) { + return true; + } - if (!empty($_POST['save'])) { try { if (null === $kut) { throw new Exception('Unknow service'); } - $url = trim(dcCore::app()->con->escape($_POST['str'])); + $url = trim(dcCore::app()->con->escapeStr((string) $_POST['str'])); $hash = empty($_POST['custom']) ? null : $_POST['custom']; if (empty($url)) { @@ -66,9 +93,9 @@ if ($part == 'link') { $url = $rs->url; $new_url = $kut->url_base . $rs->hash; - dcAdminNotices::addSuccessNotice(sprintf( + Notices::addSuccessNotice(sprintf( __('Short link for %s is %s'), - '' . html::escapeHTML($url) . '', + '' . Html::escapeHTML($url) . '', '' . $new_url . '' )); } else { @@ -82,9 +109,9 @@ if ($part == 'link') { $url = $rs->url; $new_url = $kut->url_base . $rs->hash; - dcAdminNotices::addSuccessNotice(sprintf( + Notices::addSuccessNotice(sprintf( __('Short link for %s is %s'), - '' . html::escapeHTML($url) . '', + '' . Html::escapeHTML($url) . '', '' . $new_url . '' )); @@ -97,152 +124,91 @@ if ($part == 'link') { } catch (Exception $e) { dcCore::app()->error->add($e->getMessage()); } + + return true; } -# links -} else { - $services_combo = []; - foreach (kUtRL::getServices() as $service_id => $service) { - $o = new $service(); - $services_combo[__($o->name)] = $o->id; - } - $ext_services_combo = array_merge([__('Disabled') => ''], $services_combo); - $lst_services_combo = array_merge(['-' => ''], $services_combo); - - $log = new kutrlLog(); - - $kUtRL_filter = new adminGenericFilterV2('kUtRL'); - $kUtRL_filter->add('part', 'links'); - $kUtRL_filter->add(dcAdminFilters::getPageFilter()); - $kUtRL_filter->add(dcAdminFilters::getSelectFilter( - 'urlsrv', - __('Service:'), - $lst_services_combo, - 'kut_type' - )); - - $params = $kUtRL_filter->params(); - - try { - $list_all = $log->getLogs($params); - $list_counter = $log->getLogs($params, true)->f(0); - $list_current = new kutrlLinkslist($list_all, $list_counter); - } catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); - } - - $header = $kUtRL_filter->js(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['part' => 'links'])) . - dcPage::jsModuleLoad(basename(__DIR__) . '/js/admin.js'); - - if (!empty($_POST['deletelinks'])) { - try { - foreach ($_POST['entries'] as $id) { - $rs = $log->getLogs(['kut_id' => $id]); - if ($rs->isEmpty()) { - continue; - } - if (null === ($o = kUtRL::quickService($rs->kut_type))) { - continue; - } - $o->remove($rs->kut_url); - } - - dcCore::app()->blog->triggerBlog(); - - dcAdminNotices::addSuccessNotice( - __('Links successfully deleted') - ); - dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__), $kUtRL_filter->values()); - } catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); - } - } -} - -# display header -echo -'kUtRL, ' . __('Links shortener') . '' . -$header . -''; - -# display link creation -if ($part == 'link') { - echo - dcPage::breadcrumb([ - __('Plugins') => '', - __('Links shortener') => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), - __('New link') => '', - ]) . - dcPage::notices(); - - if (!isset($kut) || null === $kut) { - echo '

' . __('You must set an admin service.') . '

'; - } else { - echo ' -
-

' . sprintf(__('Shorten link using service "%s"'), $kut->name) . '

-
- '; + if (($_REQUEST['part'] ?? 'links') === 'links') { + ManageLinks::render(); + + return; + } + + $kut = Utils::quickPlace('admin'); + + Page::openModule(My::id()); + + echo + Page::breadcrumb([ + __('Plugins') => '', + My::name() => My::manageUrl(), + __('New link') => '', + ]) . + Notices::getNotices(); + + if (!isset($kut) || null === $kut) { + echo (new Para()) + ->text(__('You must set an admin service.')) + ->render(); + } else { + $fields = []; + + if ($kut->allow_custom_hash) { + $fields[] = (new Para()) + ->items([ + (new Label(__('Custom short link:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('custom'), + (new Input('custom')) + ->size(50) + ->maxlenght(32) + ->value(''), + ]); + $fields[] = (new Note()) + ->class('form-note') + ->text(__('Only if you want a custom short link.')); + + if ($kut->admin_service == 'local') { + $fields[] = (new Note()) + ->class('form-note') + ->text(__('You can use "bob!!" if you want a semi-custom link, it starts with "bob" and "!!" will be replaced by an increment value.')); + } + } + + echo (new Div()) + ->items([ + (new Text('h4', sprintf(__('Shorten link using service "%s"'), $kut->name))), + (new Form('create-link')) + ->method('post') + ->action(My::manageUrl()) + ->fields([ + (new Para()) + ->items([ + (new Label(__('Long link:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('str'), + (new Input('str')) + ->size(100) + ->maxlenght(255) + ->value(''), + ]), + ... $fields, + (new Submit('save')) + ->value(__('Save')), + ... My::hiddenFields([ + 'part' => 'link', + ]), + ]), + ]) + ->render(); + } + + Page::helpBlock(My::id()); + + Page::closeModule(); } -} else { - echo - dcPage::breadcrumb([ - __('Plugins') => '', - __('Links shortener') => '', - ]) . - dcPage::notices() . - - '

' . __('New Link') . '

'; - - $kUtRL_filter->display('admin.plugin.' . basename(__DIR__), form::hidden('p', basename(__DIR__)) . form::hidden('part', 'links')); - - $list_current->display( - $kUtRL_filter->value('page'), - $kUtRL_filter->nb, - '
- - %s - -
-
-

-
-

-

' . - dcCore::app()->adminurl->getHiddenFormFields('admin.plugin.' . basename(__DIR__), array_merge(['deletelinks' => 1], $kUtRL_filter->values(true))) . - dcCore::app()->formNonce() . ' -

-
-
', - $kUtRL_filter->show() - ); } - -# display footer -dcPage::helpBlock('kUtRL'); - -echo ''; diff --git a/src/ManageLinks.php b/src/ManageLinks.php new file mode 100644 index 0000000..de37869 --- /dev/null +++ b/src/ManageLinks.php @@ -0,0 +1,163 @@ +add('part', 'links'); + self::$kutrl_filter->add(FiltersLibrary::getPageFilter()); + self::$kutrl_filter->add(FiltersLibrary::getSelectFilter( + 'urlsrv', + __('Service:'), + array_merge(['-' => ''], Combo::servicesCombo()), + 'kut_type' + )); + + $params = self::$kutrl_filter->params(); + + try { + $list_all = $log->getLogs($params); + $list_counter = $log->getLogs($params, true)->f(0); + self::$kutrl_listing = new LinksListing($list_all, $list_counter); + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + } + + if (!empty($_POST['deletelinks'])) { + try { + foreach ($_POST['entries'] as $id) { + $rs = $log->getLogs(['kut_id' => $id]); + if ($rs->isEmpty()) { + continue; + } + if (null === ($o = Utils::quickService($rs->kut_type))) { + continue; + } + $o->remove($rs->kut_url); + } + + dcCore::app()->blog->triggerBlog(); + + Notices::addSuccessNotice(__('Links successfully deleted')); + My::redirect(self::$kutrl_filter->values()); + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + } + } + + return true; + } + + public static function render(): void + { + if (!self::status()) { + return; + } + + Page::openModule( + My::id(), + self::$kutrl_filter->js(My::manageUrl(['part' => 'links'])) . + My::jsLoad('admin') + ); + + echo + Page::breadcrumb([ + __('Plugins') => '', + My::name() => My::manageUrl(), + ]) . + Notices::getNotices() . + (new Para()) + ->class('top-add') + ->items([ + (new Link()) + ->class('button add') + ->href(My::manageUrl(['part' => 'link'])) + ->title(__('New Link')) + ->text(__('New Link')), + ]) + ->render(); + + self::$kutrl_filter->display( + 'admin.plugin.' . My::id(), + (new Hidden('p', My::id()))->render() . (new Hidden('part', 'links'))->render() + ); + + self::$kutrl_listing->display( + self::$kutrl_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(' ') + ->items([ + (new Submit('do-action')) + ->class('delete') + ->value(__('Delete selected short links')), + ... My::hiddenFields(array_merge(['deletelinks' => 1], self::$kutrl_filter->values(true))), + ]), + ]), + ])->render() + ); + + Page::helpBlock(My::id()); + + Page::closeModule(); + } +} diff --git a/src/My.php b/src/My.php new file mode 100644 index 0000000..db57e75 --- /dev/null +++ b/src/My.php @@ -0,0 +1,38 @@ +autoload([ - 'kUtRL' => $d . 'class.kutrl.php', - 'kutrlService' => $d . 'lib.kutrl.srv.php', - 'kutrlLog' => $d . 'lib.kutrl.log.php', - 'kutrlLinkslist' => $d . 'lib.kutrl.lst.php', -]); +use dcCore; +use Dotclear\Core\Process; -# Services -Clearbricks::lib()->autoload(['defaultKutrlService' => $d . 'services/class.default.service.php']); -dcCore::app()->addBehavior('kutrlService', function () { return ['default','defaultKutrlService']; }); -if (!defined('SHORTEN_SERVICE_DISABLE_CUSTOM')) { - Clearbricks::lib()->autoload(['customKutrlService' => $d . 'services/class.custom.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['custom','customKutrlService']; }); -} -if (!defined('SHORTEN_SERVICE_DISABLE_LOCAL')) { - Clearbricks::lib()->autoload(['localKutrlService' => $d . 'services/class.local.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['local','localKutrlService']; }); -} -if (!defined('SHORTEN_SERVICE_DISABLE_BILBOLINKS')) { - Clearbricks::lib()->autoload(['bilbolinksKutrlService' => $d . 'services/class.bilbolinks.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['bilbolinks','bilbolinksKutrlService']; }); -} -if (!defined('SHORTEN_SERVICE_DISABLE_BITLY')) { - Clearbricks::lib()->autoload(['bitlyKutrlService' => $d . 'services/class.bitly.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['bitly','bitlyKutrlService']; }); -} -//if (!defined('SHORTEN_SERVICE_DISABLE_GOOGL')) { -// Clearbricks::lib()->autoload(['googlKutrlService' => $d . 'services/class.googl.service.php']); -// dcCore::app()->addBehavior('kutrlService', function() { return ["googl","googlKutrlService"]; } ); -//} -if (!defined('SHORTEN_SERVICE_DISABLE_ISGD')) { - Clearbricks::lib()->autoload(['isgdKutrlService' => $d . 'services/class.isgd.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['isgd','isgdKutrlService']; }); -} -//if (!defined('SHORTEN_SERVICE_DISABLE_SHORTTO')) { -// Clearbricks::lib()->autoload(['shorttoKutrlService' => $d . 'services/class.shortto.service.php']); -// dcCore::app()->addBehavior('kutrlService', function() { return ["shortto","shorttoKutrlService"]; } ); -//} -//if (!defined('SHORTEN_SERVICE_DISABLE_TRIM')) { -// Clearbricks::lib()->autoload(['trimKutrlService' => $d . 'services/class.trim.service.php']); -// dcCore::app()->addBehavior('kutrlService', function() { return ["trim","trimKutrlService"]; } ); -//} -if (!defined('SHORTEN_SERVICE_DISABLE_YOURLS')) { - Clearbricks::lib()->autoload(['yourlsKutrlService' => $d . 'services/class.yourls.service.php']); - dcCore::app()->addBehavior('kutrlService', function () { return ['yourls','yourlsKutrlService']; }); -} -//if (!defined('SHORTEN_SERVICE_DISABLE_SUPR')) { -// Clearbricks::lib()->autoload(['suprKutrlService' => $d . 'services/class.supr.service.php']); -// dcCore::app()->addBehavior('kutrlService', function() { return ["supr","suprKutrlService"]; } ); -//} +/** + * Module prepend. + */ +class Prepend extends Process +{ + public static function init(): bool + { + return self::status(My::checkContext(My::PREPEND)); + } -# Shorten url passed through wiki functions -Clearbricks::lib()->autoload(['kutrlWiki' => $d . 'lib.wiki.kutrl.php']); -dcCore::app()->addBehavior('coreInitWikiPost', ['kutrlWiki','coreInitWiki']); -dcCore::app()->addBehavior('coreInitWikiComment', ['kutrlWiki','coreInitWiki']); -dcCore::app()->addBehavior('coreInitWikiSimpleComment', ['kutrlWiki','coreInitWiki']); + public static function process(): bool + { + if (!self::status()) { + return false; + } -# Public page -dcCore::app()->url->register('kutrl', 'go', '^go(/(.*?)|)$', ['urlKutrl', 'redirectUrl']); + # Set a URL shortener for quick get request + if (!defined('SHORTEN_SERVICE_NAME')) { + define('SHORTEN_SERVICE_NAME', 'Is.gd'); + } + if (!defined('SHORTEN_SERVICE_API')) { + define('SHORTEN_SERVICE_API', 'https://is.gd/api.php?'); + } + if (!defined('SHORTEN_SERVICE_BASE')) { + define('SHORTEN_SERVICE_BASE', 'https://is.gd/'); + } + if (!defined('SHORTEN_SERVICE_PARAM')) { + define('SHORTEN_SERVICE_PARAM', 'longurl'); + } + if (!defined('SHORTEN_SERVICE_ENCODE')) { + define('SHORTEN_SERVICE_ENCODE', false); + } -# Add kUtRL events on plugin activityReport -if (defined('ACTIVITY_REPORT_V2')) { - require_once $d . 'lib.kutrl.activityreport.php'; + # Services + dcCore::app()->addBehavior('kutrlService', fn () => ['default', Service\ServiceDefault::class]); + if (!defined('SHORTEN_SERVICE_DISABLE_CUSTOM')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['custom', Service\ServiceCustom::class]); + } + if (!defined('SHORTEN_SERVICE_DISABLE_LOCAL')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['local', Service\ServiceLocal::class]); + } + if (!defined('SHORTEN_SERVICE_DISABLE_BILBOLINKS')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['bilbolinks', Service\ServiceBilbolinks::class]); + } + if (!defined('SHORTEN_SERVICE_DISABLE_BITLY')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['bitly', Service\ServiceBitly::class]); + } + if (!defined('SHORTEN_SERVICE_DISABLE_ISGD')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['isgd', Service\ServiceIsgd::class]); + } + if (!defined('SHORTEN_SERVICE_DISABLE_YOURLS')) { + dcCore::app()->addBehavior('kutrlService', fn () => ['yourls', Service\ServiceYourls::class]); + } + + # Shorten url passed through wiki functions + dcCore::app()->addBehaviors([ + 'coreInitWikiPost' => [Wiki::class, 'coreInitWiki'], + 'coreInitWikiComment' => [Wiki::class, 'coreInitWiki'], + 'coreInitWikiSimpleComment' => [Wiki::class,'coreInitWiki'], + ]); + + # Public page + dcCore::app()->url->register( + 'kutrl', + 'go', + '^go(/(.*?)|)$', + [FrontendUrl::class, 'redirectUrl'] + ); + + # Add kUtRL events on plugin activityReport + if (defined('ACTIVITY_REPORT_V2')) { + require_once $d . 'lib.kutrl.activityreport.php'; + } + + return true; + } } diff --git a/src/Service.php b/src/Service.php index 7fdcd35..ac51573 100644 --- a/src/Service.php +++ b/src/Service.php @@ -2,6 +2,9 @@ /** * @brief kUtRL, a plugin for Dotclear 2 * + * Generic class for shorten link service + * A service class must extends this one + * * @package Dotclear * @subpackage Plugin * @@ -10,9 +13,20 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -# Generic class for shorten link service -# A service class must extends this one -class kutrlService +declare(strict_types=1); + +namespace Dotclear\Plugin\kUtRL; + +use dcCore; +use dcError; +use Dotclear\Database\MetaRecord; +use Dotclear\Helper\Html\Form\{ + Div, + Note +}; +use Dotclear\Helper\Network\HttpClient; + +class Service { public $error; public $settings; @@ -22,32 +36,32 @@ class kutrlService public function __construct() { - $this->settings = dcCore::app()->blog->settings->get(basename(dirname(__DIR__))); - $this->log = new kutrlLog(); + $this->settings = My::settings(); + $this->log = new Logs(); $this->error = new dcError(); //$this->error->setHTMLFormat('%s', "%s\n"); $this->init(); // Force setting - $allow_external_url = $this->settings->get('allow_external_url'); - $this->config['$allow_external_url'] = null === $allow_external_url ? + $allow_external_url = $this->settings?->get('allow_external_url'); + $this->config['allow_external_url'] = null === $allow_external_url ? true : $allow_external_url; $this->config = array_merge( [ - 'id' => 'undefined', - 'name' => 'undefined', - 'home' => '', + 'id' => 'undefined', + 'name' => 'undefined', + 'home' => '', 'allow_external_url' => true, 'allow_custom_hash' => false, 'allow_protocols' => ['http://'], - 'url_test' => 'http://github.com/JcDenis/kUtRL/releases', - 'url_api' => '', - 'url_base' => '', - 'url_min_len' => 0, + 'url_test' => 'http://github.com/JcDenis/kUtRL/releases', + 'url_api' => '', + 'url_base' => '', + 'url_min_len' => 0, ], $this->config ); @@ -66,52 +80,54 @@ class kutrlService } # Additionnal actions on child start - protected function init() + protected function init(): void { // } # Save settings from admin page - public function saveSettings() + public function saveSettings(): void { - return null; + // } # Settings form for admin page - public function settingsForm() + public function settingsForm(): Div { - echo - '

' . - __('There is nothing to configure for this service.') . - '

'; + return (new Div()) + ->items([ + (new Note()) + ->class('form-note') + ->text(__('There is nothing to configure for this service.')), + ]); } # Test if service is well configured - public function testService() + public function testService(): bool { - return null; + return true; } # Test if an url is valid - public function isValidUrl($url) + public function isValidUrl(string $url): bool { return (bool) filter_var($url, FILTER_VALIDATE_URL); } # Test if an url contents know prefix - public function isServiceUrl($url) + public function isServiceUrl(string $url): bool { return strpos($url, $this->url_base) === 0; } # Test if an url is long enoutgh - public function isLongerUrl($url) + public function isLongerUrl(string $url): bool { return (strlen($url) >= (int) $this->url_min_len); } # Test if an url protocol (eg: http://) is allowed - public function isProtocolUrl($url) + public function isProtocolUrl(string $url): bool { foreach ($this->allow_protocols as $protocol) { if (empty($protocol)) { @@ -126,7 +142,7 @@ class kutrlService } # Test if an url is from current blog - public function isBlogUrl($url) + public function isBlogUrl(string $url): bool { $base = dcCore::app()->blog->url; $url = substr($url, 0, strlen($base)); @@ -134,22 +150,34 @@ class kutrlService return $url == $base; } - # Test if an url is know - public function isKnowUrl($url) + /** + * Test if an url is know. + * + * @return false|MetaRecord + */ + public function isKnowUrl(string $url) { return $this->log->select($url, null, $this->id, 'kutrl'); } - # Test if an custom short url is know - public function isKnowHash($hash) + /** + * Test if an custom short url is know. + * + * @return false|MetaRecord + */ + public function isKnowHash(string $hash) { return $this->log->select(null, $hash, $this->id, 'kutrl'); } - # Create hash from url - public function hash($url, $hash = null) + /** + * Create hash from url. + * + * @return false|MetaRecord + */ + public function hash(string $url, ?string $hash = null) { - $url = trim(dcCore::app()->con->escape($url)); + $url = trim(dcCore::app()->con->escapeStr((string) $url)); if ('undefined' === $this->id) { return false; } @@ -183,41 +211,54 @@ class kutrlService return $rs; } - # Create a hash for a given url (and its custom hash) - public function createHash($url, $hash = null) + /** + * Create a hash for a given url (and its custom hash). + * + * @return false|ArrayObject + */ + public function createHash(string $url, ?string $hash = null) { return false; } - # Remove an url from list of know urls - public function remove($url) + /** + * Remove an url from list of know urls. + */ + public function remove(string $url): bool { if (!($rs = $this->isKnowUrl($url))) { return false; } $this->deleteUrl($url); - $this->log->delete($rs->id); + $this->log->delete((int) $rs->id); return true; } - # Delete url on service (second argument really delete urls) - public function deleteUrl($url, $delete = false) - { - return null; - } - - # Retrieve long url from hash - public function getUrl($hash) + /** + * Delete url on service (second argument really delete urls). + */ + public function deleteUrl(string $url, bool $delete = false): bool { return false; } - # Post request - public static function post($server, $data, $verbose = true, $get = false, $headers = []) + /** + * Retrieve long url from hash. + * + * @return false|string + */ + public function getUrl(string $hash) { - $url = (string) $server; - $client = netHttp::initClient($url, $url); + return false; + } + + /** + * Post request. + */ + public static function post(string $url, $data, bool $verbose = true, bool $get = false, $headers = []) + { + $client = HttpClient::initClient($url, $url); $client->setUserAgent('kUtRL - https://github.com/JcDenis/kUtRL'); $client->setPersistReferers(false); diff --git a/src/Service/ServiceBilbolinks.php b/src/Service/ServiceBilbolinks.php index 572f413..7eb56ed 100644 --- a/src/Service/ServiceBilbolinks.php +++ b/src/Service/ServiceBilbolinks.php @@ -10,11 +10,21 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class bilbolinksKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Helper\Html\Form\{ + Div, + Input, + label, + Note, + Para +}; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceBilbolinks extends Service { protected $config = [ 'id' => 'bilbolinks', @@ -22,7 +32,7 @@ class bilbolinksKutrlService extends kutrlService 'home' => 'http://www.tux-planet.fr/bilbobox/', ]; - protected function init() + protected function init(): void { $base = (string) $this->settings->get('srv_bilbolinks_base'); if (!empty($base) && substr($base, -1, 1) != '/') { @@ -33,7 +43,7 @@ class bilbolinksKutrlService extends kutrlService $this->config['url_min_len'] = 25; } - public function saveSettings() + public function saveSettings(): void { $base = ''; if (!empty($_POST['kutrl_srv_bilbolinks_base'])) { @@ -45,19 +55,26 @@ class bilbolinksKutrlService extends kutrlService $this->settings->put('srv_bilbolinks_base', $base); } - public function settingsForm() + public function settingsForm(): Div { - echo - '

' . - '

' . - __('This is the root URL of the "bilbolinks" service you want to use. Ex: "http://tux-pla.net/".') . - '

'; + return (new Div()) + ->items([ + (new Para()) + ->items([ + (new Label(__('Url of the service:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_bilbolinks_base'), + (new Input('kutrl_srv_bilbolinks_base')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_bilbolinks_base')), + ]), + (new Note()) + ->class('form-note') + ->text(__('This is the root URL of the "bilbolinks" service you want to use. Ex: "http://tux-pla.net/".')), + ]); } - public function testService() + public function testService(): bool { if (empty($this->url_base)) { $this->error->add(__('Service is not well configured.')); @@ -75,7 +92,7 @@ class bilbolinksKutrlService extends kutrlService return true; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $arg = ['longurl' => $url]; diff --git a/src/Service/ServiceBitly.php b/src/Service/ServiceBitly.php index a08b83a..bf4383d 100644 --- a/src/Service/ServiceBitly.php +++ b/src/Service/ServiceBitly.php @@ -10,20 +10,30 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class bitlyKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Helper\Html\Form\{ + Div, + Input, + label, + Note, + Para +}; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceBitly extends Service { protected $config = [ - 'id' => 'bitly', - 'name' => 'bit.ly', - 'home' => 'https://bit.ly', + 'id' => 'bitly', + 'name' => 'bit.ly', + 'home' => 'https://bit.ly', - 'url_api' => 'https://api-ssl.bitly.com/v4/', - 'url_base' => 'https://bit.ly/', - 'url_min_len' => 25, + 'url_api' => 'https://api-ssl.bitly.com/v4/', + 'url_base' => 'https://bit.ly/', + 'url_min_len' => 25, 'allow_protocols' => ['http://', 'https://'], ]; @@ -32,28 +42,36 @@ class bitlyKutrlService extends kutrlService 'apiKey' => '', ]; - protected function init() + protected function init(): void { $this->args['apiKey'] = $this->settings->get('srv_bitly_apikey'); } - public function saveSettings() + public function saveSettings(): void { $this->settings->put('srv_bitly_apikey', $_POST['kutrl_srv_bitly_apikey']); } - public function settingsForm() + public function settingsForm(): Div { - echo - '

' . - '

' . - sprintf(__('This is your personnal %s API key. You can find it on your account page.'), $this->config['name']) . - '

'; + return (new Div()) + ->items([ + (new Para()) + ->items([ + (new Label(__('API Key:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_bitly_apikey'), + (new Input('kutrl_srv_bitly_apikey')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_bitly_apikey')), + ]), + (new Note()) + ->class('form-note') + ->text(sprintf(__('This is your personnal %s API key. You can find it on your account page.'), $this->config['name'])), + ]); } - public function testService() + public function testService(): bool { if (empty($this->args['apiKey'])) { $this->error->add(__('Service is not well configured.')); @@ -71,7 +89,7 @@ class bitlyKutrlService extends kutrlService return true; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $args = json_encode(['domain' => 'bit.ly', 'long_url' => $url]); diff --git a/src/Service/ServiceCustom.php b/src/Service/ServiceCustom.php index 6df5b3f..4a98645 100644 --- a/src/Service/ServiceCustom.php +++ b/src/Service/ServiceCustom.php @@ -10,18 +10,29 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class customKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Helper\Html\Form\{ + Checkbox, + Div, + Input, + Label, + Note, + Para +}; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceCustom extends Service { protected $config = [ 'id' => 'custom', 'name' => 'Custom', ]; - protected function init() + protected function init(): void { $config = json_decode((string) $this->settings->get('srv_custom'), true); if (!is_array($config)) { @@ -36,7 +47,7 @@ class customKutrlService extends kutrlService $this->config['url_min_length'] = strlen($this->url_base) + 2; } - public function saveSettings() + public function saveSettings(): void { $config = [ 'url_api' => $_POST['kutrl_srv_custom_url_api'], @@ -47,7 +58,7 @@ class customKutrlService extends kutrlService $this->settings->put('srv_custom', json_encode($config)); } - public function settingsForm() + public function settingsForm(): Div { $default = [ 'url_api' => '', @@ -61,30 +72,63 @@ class customKutrlService extends kutrlService } $config = array_merge($default, $config); - echo - '

' . __('You can set a configurable service.') . '
' . - __('It consists on a simple query to an URL with only one param.') . '
' . - __('It must respond with a http code 200 on success.') . '
' . - __('It must returned the short URL (or only hash) in clear text.') . '

' . - '

' . - '

' . __('Full path to API of the URL shortener. ex: "http://is.gd/api.php"') . '

' . - '

' . - '

' . __('Common part of the short URL. ex: "http://is.gd/"') . '

' . - '

' . - '

' . __('Param of the query. ex: "longurl"') . '

' . - '

'; + return (new Div()) + ->items([ + (new Para()) + ->text( + __('You can set a configurable service.') . '
' . + __('It consists on a simple query to an URL with only one param.') . '
' . + __('It must respond with a http code 200 on success.') . '
' . + __('It must returned the short URL (or only hash) in clear text.') + ), + (new Para()) + ->items([ + (new Label(__('API URL:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_custom_url_api'), + (new Input('kutrl_srv_custom_url_api')) + ->size(50) + ->maxlenght(255) + ->value((string) $config['url_api']), + ]), + (new Note()) + ->class('form-note') + ->text(__('Full path to API of the URL shortener. ex: "http://is.gd/api.php"')), + (new Para()) + ->items([ + (new Label(__('Short URL domain:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_custom_url_base'), + (new Input('kutrl_srv_custom_url_base')) + ->size(50) + ->maxlenght(255) + ->value((string) $config['url_base']), + ]), + (new Note()) + ->class('form-note') + ->text(__('Common part of the short URL. ex: "http://is.gd/"')), + (new Para()) + ->items([ + (new Label(__('API URL param:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_custom_url_param'), + (new Input('kutrl_srv_custom_url_param')) + ->size(50) + ->maxlenght(255) + ->value((string) $config['url_param']), + ]), + (new Note()) + ->class('form-note') + ->text(__('Param of the query. ex: "longurl"')), + (new Para()) + ->items([ + (new Checkbox('kutrl_srv_custom_url_encode', (bool) $config['url_encode'])) + ->value(1), + (new Label(__('Encode URL'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('kutrl_srv_custom_url_encode'), + ]), + ]); } - public function testService() + public function testService(): bool { if (empty($this->url_api)) { return false; @@ -100,7 +144,7 @@ class customKutrlService extends kutrlService return true; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $enc = $this->url_encode ? urlencode($url) : $url; $arg = [$this->url_param => $enc]; diff --git a/src/Service/ServiceDefault.php b/src/Service/ServiceDefault.php index 9214825..72422bb 100644 --- a/src/Service/ServiceDefault.php +++ b/src/Service/ServiceDefault.php @@ -10,55 +10,70 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); + +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Helper\Html\Form\{ + Div, + Note, + Para, + Text +}; +use Dotclear\Plugin\kUtRL\Service; # nb: "default" ne veut pas dire service par défaut # mais service simple et rapide configuré par des constantes # cela permet de configurer ces constantes dans le fichier # config de Dotclear pour une plateforme complète. -class defaultKutrlService extends kutrlService +class ServiceDefault extends Service { - protected function init() + protected function init(): void { $this->config = [ - 'id' => 'default', - 'name' => 'Default', - 'home' => '', + 'id' => 'default', + 'name' => 'Default', + 'home' => '', 'url_api' => SHORTEN_SERVICE_API, 'url_base' => SHORTEN_SERVICE_BASE, 'url_min_len' => strlen(SHORTEN_SERVICE_BASE) + 2, - 'url_param' => SHORTEN_SERVICE_PARAM, - 'url_encode' => SHORTEN_SERVICE_ENCODE, + 'url_param' => SHORTEN_SERVICE_PARAM, + 'url_encode' => SHORTEN_SERVICE_ENCODE, ]; } - public function settingsForm() + public function settingsForm(): Div { - echo - '

' . - __('There is nothing to configure for this service.') . - '

' . - '

' . __('This service is set to:') . '

' . - '
' . - '
' . __('Service name:') . '
' . - '
' . SHORTEN_SERVICE_NAME . '
' . - '
' . __('Full API URL:') . '
' . - '
' . SHORTEN_SERVICE_API . '
' . - '
' . __('Query param:') . '
' . - '
' . SHORTEN_SERVICE_PARAM . '
' . - '
' . __('Short URL domain:') . '
' . - '
' . SHORTEN_SERVICE_BASE . '
' . - '
' . __('Encode URL:') . '
' . - '
' . (SHORTEN_SERVICE_ENCODE ? __('yes') : __('no')) . '
' . - '
'; + return (new Div()) + ->items([ + (new Note()) + ->class('form-note') + ->text(__('There is nothing to configure for this service.')), + (new Para()) + ->text(__('There is nothing to configure for this service.')), + (new Text( + '', + '
' . + '
' . __('Service name:') . '
' . + '
' . SHORTEN_SERVICE_NAME . '
' . + '
' . __('Full API URL:') . '
' . + '
' . SHORTEN_SERVICE_API . '
' . + '
' . __('Query param:') . '
' . + '
' . SHORTEN_SERVICE_PARAM . '
' . + '
' . __('Short URL domain:') . '
' . + '
' . SHORTEN_SERVICE_BASE . '
' . + '
' . __('Encode URL:') . '
' . + '
' . (SHORTEN_SERVICE_ENCODE ? __('yes') : __('no')) . '
' . + '
' + )), + ]); } - public function testService() + public function testService(): bool { $url = $this->url_encode ? urlencode($this->url_test) : $this->url_test; $arg = [$this->url_param => urlencode($this->url_test)]; @@ -72,7 +87,7 @@ class defaultKutrlService extends kutrlService return true; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $enc = $this->url_encode ? urlencode($url) : $url; $arg = [$this->url_param => $url]; diff --git a/src/Service/ServiceIsgd.php b/src/Service/ServiceIsgd.php index 9de12ad..e875d93 100644 --- a/src/Service/ServiceIsgd.php +++ b/src/Service/ServiceIsgd.php @@ -10,23 +10,26 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return; -} +declare(strict_types=1); -class isgdKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceIsgd extends Service { protected $config = [ - 'id' => 'isgd', - 'name' => 'is.gd', - 'home' => 'http://is.gd/', + 'id' => 'isgd', + 'name' => 'is.gd', + 'home' => 'http://is.gd/', 'url_api' => 'http://is.gd/api.php', 'url_base' => 'http://is.gd/', 'url_min_length' => 25, ]; - public function testService() + public function testService(): bool { $arg = ['longurl' => urlencode($this->url_test)]; if (!self::post($this->url_api, $arg, true, true)) { @@ -38,7 +41,7 @@ class isgdKutrlService extends kutrlService return true; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $arg = ['longurl' => $url]; diff --git a/src/Service/ServiceLocal.php b/src/Service/ServiceLocal.php index 80bd24d..4748313 100644 --- a/src/Service/ServiceLocal.php +++ b/src/Service/ServiceLocal.php @@ -10,21 +10,36 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class localKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use dcCore; +use Dotclear\Helper\Html\Form\{ + Checkbox, + Div, + Input, + Label, + Note, + Para, + Text, + Textarea +}; +use Dotclear\Helper\Html\Html; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceLocal extends Service { protected $config = [ - 'id' => 'local', - 'name' => 'kUtRL', - 'home' => 'https://github.com/JcDenis/kUtRL', + 'id' => 'local', + 'name' => 'kUtRL', + 'home' => 'https://github.com/JcDenis/kUtRL', 'allow_custom_hash' => true, ]; - protected function init() + protected function init(): void { $protocols = (string) $this->settings->get('srv_local_protocols'); $this->config['allow_protocols'] = empty($protocols) ? [] : explode(',', $protocols); @@ -33,7 +48,7 @@ class localKutrlService extends kutrlService $this->config['url_min_len'] = strlen($this->url_base) + 2; } - public function saveSettings() + public function saveSettings(): void { $this->settings->put('srv_local_protocols', $_POST['kutrl_srv_local_protocols'], 'string'); $this->settings->put('srv_local_public', isset($_POST['kutrl_srv_local_public']), 'boolean'); @@ -41,64 +56,96 @@ class localKutrlService extends kutrlService $this->settings->put('srv_local_404_active', isset($_POST['kutrl_srv_local_404_active']), 'boolean'); } - public function settingsForm() + public function settingsForm(): Div { - echo - '
' . + return (new Div()) + ->items([ + (new Div()) + ->class('two-cols') + ->items([ + (new Div()) + ->class('col') + ->items([ + (new Text('b', __('Settings:'))), + (new Para()) + ->items([ + (new Label(__('Allowed protocols:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_local_protocols'), + (new Input('kutrl_srv_local_protocols')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_local_protocols')), + ]), + (new Note()) + ->class('form-note') + ->text(__('Use comma seperated list like: "http:,https:,ftp:"')), + (new Para()) + ->items([ + (new Checkbox('kutrl_srv_local_public', (bool) $this->settings->get('srv_local_public'))) + ->value(1), + (new Label(__('Enable public page for visitors to shorten links'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('kutrl_srv_local_public'), + ]), + (new Para('style-area')) + ->class('area') + ->items([ + (new Label(__('CSS:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_local_css'), + (new Textarea('kutrl_srv_local_css', Html::escapeHTML($this->settings->get('srv_local_css')))) + ->cols(50) + ->rows(3), + ]), + (new Note()) + ->class('form-note') + ->text(__('You can add here special cascading style sheet. Body of page has class "dc-kutrl" and widgets have class "shortenkutrlwidget" and "rankkutrlwidget".')), + (new Para()) + ->items([ + (new Checkbox('kutrl_srv_local_404_active', (bool) $this->settings->get('srv_local_404_active'))) + ->value(1), + (new Label(__('Enable special 404 error public page for unknow urls'), Label::OUTSIDE_LABEL_AFTER)) + ->class('classic') + ->for('kutrl_srv_local_404_active'), + ]), + (new Note()) + ->class('form-note') + ->text(__('If this is not activated, the default 404 page of the theme will be display.')), + ]), - '

' . __('Settings:') . '

' . - '

' . - - '

' . - __('Use comma seperated list like: "http:,https:,ftp:"') . - '

' . - - '

' . - - '

' . - form::textarea('kutrl_srv_local_css', 50, 3, html::escapeHTML($this->settings->get('srv_local_css')), '', '2') . - '

' . - '

' . __('You can add here special cascading style sheet. Body of page has class "dc-kutrl" and widgets have class "shortenkutrlwidget" and "rankkutrlwidget".') . '

' . - - '

' . - '

' . __('If this is not activated, the default 404 page of the theme will be display.') . '

' . - - '
' . - - '

' . __('Note:') . '

' . - '

' . - __('This service use your own Blog to shorten and serve URL.') . '
' . - sprintf(__('This means that with this service short links start with "%s".'), $this->url_base) . - '

' . - '

' . - __("You can use Dotclear's plugin called myUrlHandlers to change short links prefix on your blog."); - - if (preg_match('/index\.php/', $this->url_base)) { - echo - '

' . - __("We recommand that you use a rewrite engine in order to remove 'index.php' from your blog's URL.") . - '
' . - __("You can find more about this on the Dotclear's documentation.") . - '

'; - } - echo - '

' . - '

' . __('There are two templates delivered with kUtRL, if you do not use default theme, you may adapt them to yours.') . '
' . - __('Files are in plugin directory /default-templates, just copy them into your theme and edit them.') . '

' . - - '

'; + (new Div()) + ->class('col') + ->items([ + (new Text('b', __('Note:'))), + (new Text( + 'p', + __('This service use your own Blog to shorten and serve URL.') . '
' . + sprintf(__('This means that with this service short links start with "%s".'), $this->url_base) + )), + (new Text( + 'p', + __("You can use Dotclear's plugin called myUrlHandlers to change short links prefix on your blog.") . + ( + preg_match('/index\.php/', $this->url_base) ? + ' ' . + __("We recommand that you use a rewrite engine in order to remove 'index.php' from your blog's URL.") . + '
' . + __("You can find more about this on the Dotclear's documentation.") . + '' + : '' + ) + )), + (new Text( + 'p', + __('There are two templates delivered with kUtRL, if you do not use default theme, you may adapt them to yours.') . '
' . + __('Files are in plugin directory /default-templates, just copy them into your theme and edit them.') + )), + ]), + ]), + (new Text('br', ''))->class('clear'), + ]); } - public function testService() + public function testService(): bool { $ap = $this->allow_protocols; if (!empty($ap)) { @@ -109,7 +156,7 @@ class localKutrlService extends kutrlService return false; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { # Create response object $rs = new ArrayObject(); @@ -121,12 +168,12 @@ class localKutrlService extends kutrlService $type = 'localnormal'; $rs->hash = $this->next($this->last('localnormal')); - # Mixed custom link + # Mixed custom link } elseif (preg_match('/^([A-Za-z0-9]{2,})\!\!$/', $hash, $m)) { $type = 'localmix'; $rs->hash = $m[1] . $this->next(-1, $m[1]); - # Custom link + # Custom link } elseif (preg_match('/^[A-Za-z0-9\.\-\_]{2,}$/', $hash)) { if (false !== $this->log->select(null, $hash, null, 'local')) { $this->error->add(__('Custom short link is already taken.')); @@ -136,7 +183,7 @@ class localKutrlService extends kutrlService $type = 'localcustom'; $rs->hash = $hash; - # Wrong char in custom hash + # Wrong char in custom hash } else { $this->error->add(__('Custom short link is not valid.')); @@ -215,7 +262,7 @@ class localKutrlService extends kutrlService return implode($id); } - public function getUrl($hash) + public function getUrl(string $hash) { if (false === ($rs = $this->log->select(null, $hash, null, 'local'))) { return false; @@ -223,20 +270,20 @@ class localKutrlService extends kutrlService if (!$rs->url) { //previously removed url return false; } - $this->log->counter($rs->id, 'up'); + $this->log->counter((int) $rs->id, 'up'); return $rs->url; } - public function deleteUrl($url, $delete = false) + public function deleteUrl(string $url, bool $delete = false): bool { if (false === ($rs = $this->log->select($url, null, null, 'local'))) { return false; } if ($delete) { - $this->log->delete($rs->id); + $this->log->delete((int) $rs->id); } else { - $this->log->clear($rs->id, ''); + $this->log->clear((int) $rs->id); } return true; diff --git a/src/Service/ServiceYourls.php b/src/Service/ServiceYourls.php index d354557..e5f5071 100644 --- a/src/Service/ServiceYourls.php +++ b/src/Service/ServiceYourls.php @@ -10,11 +10,21 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class yourlsKutrlService extends kutrlService +namespace Dotclear\Plugin\kUtRL\Service; + +use ArrayObject; +use Dotclear\Helper\Html\Form\{ + Div, + Input, + Label, + Note, + Para +}; +use Dotclear\Plugin\kUtRL\Service; + +class ServiceYourls extends Service { protected $config = [ 'id' => 'yourls', @@ -29,7 +39,7 @@ class yourlsKutrlService extends kutrlService 'action' => 'shorturl', ]; - protected function init() + protected function init(): void { $this->args['username'] = $this->settings->get('srv_yourls_username'); $this->args['password'] = $this->settings->get('srv_yourls_password'); @@ -42,38 +52,58 @@ class yourlsKutrlService extends kutrlService $this->config['url_min_len'] = strlen($base) + 3; } - public function saveSettings() + public function saveSettings(): void { $this->settings->put('srv_yourls_username', $_POST['kutrl_srv_yourls_username']); $this->settings->put('srv_yourls_password', $_POST['kutrl_srv_yourls_password']); $this->settings->put('srv_yourls_base', $_POST['kutrl_srv_yourls_base']); } - public function settingsForm() + public function settingsForm(): Div { - echo - '

' . - '

' . - __('This is the URL of the YOURLS service you want to use. Ex: "http://www.smaller.org/api.php".') . - '

' . - '

' . - '

' . - __('This is your user name to sign up to this YOURLS service.') . - '

' . - '

' . - '

' . - __('This is your password to sign up to this YOURLS service.') . - '

'; + return (new Div()) + ->items([ + (new Para()) + ->items([ + (new Label(__('Url of the service:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_yourls_base'), + (new Input('kutrl_srv_yourls_base')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_yourls_base')), + (new Note()) + ->class('form-note') + ->text(__('This is the URL of the YOURLS service you want to use. Ex: "http://www.smaller.org/api.php".')), + ]), + (new Para()) + ->items([ + (new Label(__('Login:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_yourls_username'), + (new Input('kutrl_srv_yourls_username')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_yourls_username')), + (new Note()) + ->class('form-note') + ->text(__('This is your user name to sign up to this YOURLS service.')), + ]), + (new Para()) + ->items([ + (new Label(__('Password:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('kutrl_srv_yourls_password'), + (new Input('kutrl_srv_yourls_password')) + ->size(50) + ->maxlenght(255) + ->value((string) $this->settings->get('srv_yourls_password')), + (new Note()) + ->class('form-note') + ->text(__('This is your password to sign up to this YOURLS service.')), + ]), + + ]); } - public function testService() + public function testService(): bool { if (empty($this->url_api)) { $this->error->add(__('Service is not well configured.')); @@ -99,7 +129,7 @@ class yourlsKutrlService extends kutrlService return false; } - public function createHash($url, $hash = null) + public function createHash(string $url, ?string $hash = null) { $args = array_merge($this->args, ['url' => $url]); diff --git a/src/Services/ServiceGoogl.php b/src/Services/ServiceGoogl.php deleted file mode 100644 index ba787d7..0000000 --- a/src/Services/ServiceGoogl.php +++ /dev/null @@ -1,84 +0,0 @@ - '', - ]; - private $headers = ['Content-Type: application/json']; - - protected function init() - { - $this->url_base = 'http://goo.gl/'; - $this->url_min_length = 20; - } - - public function testService() - { - $args = $this->args; - $args['shortUrl'] = $this->url_base . 'PLovn'; - if (!($response = self::post($this->url_api, $args, true, true, $this->headers))) { - $this->error->add(__('Failed to call service.')); - - return false; - } - - $rsp = json_decode($response); - - if (empty($rsp->status)) { - $this->error->add(__('An error occured')); - - return false; - } - - return true; - } - - public function createHash($url, $hash = null) - { - $args = $this->args; - $args['longUrl'] = $url; - $args = json_encode($args); - - if (!($response = self::post($this->url_api, $args, true, false, $this->headers))) { - $this->error->add(__('Failed to call service.')); - - return false; - } - - $rsp = json_decode($response); - - if (empty($rsp->id)) { - $this->error->add(__('An error occured')); - - return false; - } - - $rs = new ArrayObject(); - $rs->hash = str_replace($this->url_base, '', $rsp->id); - $rs->url = $rsp->longUrl; - $rs->type = $this->id; - - return $rs; - } -} diff --git a/src/Services/ServiceShortto.php b/src/Services/ServiceShortto.php deleted file mode 100644 index 3cd7f60..0000000 --- a/src/Services/ServiceShortto.php +++ /dev/null @@ -1,58 +0,0 @@ - 'shortto', - 'name' => 'short.to', - 'home' => 'http://short.to', - - 'url_api' => 'http://short.to/s.txt', - 'url_base' => 'http://short.to/', - 'url_min_len' => 25, - ]; - - public function testService() - { - $arg = ['url' => urlencode($this->url_test)]; - if (!self::post($this->url_api, $arg, true, true)) { - $this->error->add(__('Service is unavailable.')); - - return false; - } - - return true; - } - - public function createHash($url, $hash = null) - { - $arg = ['url' => $url]; - - if (!($response = self::post($this->url_api, $arg, true, true))) { - $this->error->add(__('Service is unavailable.')); - - return false; - } - - $rs = new ArrayObject(); - $rs->hash = str_replace($this->url_base, '', $response); - $rs->url = $url; - $rs->type = $this->id; - - return $rs; - } -} diff --git a/src/Services/ServiceSupr.php b/src/Services/ServiceSupr.php deleted file mode 100644 index c0f000d..0000000 --- a/src/Services/ServiceSupr.php +++ /dev/null @@ -1,124 +0,0 @@ - 'supr', - 'name' => 'su.pr StumbleUpon', - 'home' => 'http://su.pr', - - 'url_api' => 'http://su.pr/api/', - 'url_base' => 'http://su.pr/', - 'url_min_len' => 23, - ]; - - private $args = [ - 'version' => '1.0', - 'format' => 'xml', - 'login' => '', - 'apiKey' => '', - ]; - - protected function init() - { - $this->args['login'] = $this->settings->get('srv_supr_login'); - $this->args['apiKey'] = $this->settings->get('srv_supr_apikey'); - } - - public function saveSettings() - { - $this->settings->put('srv_supr_login', $_POST['kutrl_srv_supr_login']); - $this->settings->put('srv_supr_apikey', $_POST['kutrl_srv_supr_apikey']); - } - - public function settingsForm() - { - echo - '

' . - '

' . - sprintf(__('This is your login to sign up to %s'), $this->config['name']) . - '

' . - '

' . - '

' . - sprintf(__('This is your personnal %s API key. You can find it on your account page.'), $this->config['name']) . - '

'; - } - - public function testService() - { - if (empty($this->args['login']) || empty($this->args['apiKey'])) { - $this->error->add(__('Service is not well configured.')); - - return false; - } - - $args = $this->args; - $arg['longUrl'] = $this->url_test; - if (!($response = self::post($this->url_api . 'shorten', $args, true))) { - $this->error->add(__('Failed to call service.')); - - return false; - } - - $rsp = simplexml_load_string($response); - - $status = (string) $rsp->statusCode; - if ($status != 'OK') { - $err_no = (int) $rsp->errorCode; - $err_msg = (int) $rsp->errorMessage; - $this->error->add(sprintf(__('An error occured with code %s and message "%s"'), $err_no, $err_msg)); - - return false; - } - - return true; - } - - public function createHash($url, $hash = null) - { - $args = $this->args; - $args['longUrl'] = $url; - - if (!($response = self::post($this->url_api . 'shorten', $args, true))) { - $this->error->add(__('Failed to call service.')); - - return false; - } - - $rsp = simplexml_load_string($response); - - $status = (string) $rsp->statusCode; - if ($status != 'OK') { - $err_no = (int) $rsp->errorCode; - $err_msg = (int) $rsp->errorMessage; - $this->error->add(sprintf(__('An error occured with code %s and message "%s"'), $err_no, $err_msg)); - - return false; - } - - $rs = new ArrayObject(); - $rs->hash = (string) $rsp->results[0]->nodeKeyVal->hash; - $rs->url = (string) $rsp->results[0]->nodeKeyVal->nodeKey; - $rs->type = $this->id; - - return $rs; - } -} diff --git a/src/Services/ServiceTrim.php b/src/Services/ServiceTrim.php deleted file mode 100644 index 325166d..0000000 --- a/src/Services/ServiceTrim.php +++ /dev/null @@ -1,127 +0,0 @@ - 'trim', - 'name' => 'tr.im', - 'home' => 'http://tr.im', - - 'url_api' => 'http://api.tr.im/v1/', - 'url_base' => 'http://tr.im/', - 'url_min_len' => 25, - ]; - - private $args = [ - 'username' => '', - 'password' => '', - ]; - - private $api_rate_time = 0; - - protected function init() - { - $this->args['username'] = $this->settings->get('srv_trim_username'); - $this->args['password'] = $this->settings->get('srv_trim_password'); - - $this->api_rate_time = (int) $this->settings->get('srv_trim_apiratetime'); - } - - public function saveSettings() - { - $this->settings->put('srv_trim_username', $_POST['kutrl_srv_trim_username']); - $this->settings->put('srv_trim_password', $_POST['kutrl_srv_trim_password']); - } - - public function settingsForm() - { - echo - '

' . - '

' . - __('This is your login to sign up to tr.im.') . - '

' . - '

' . - '

' . - __('This is your password to sign up to tr.im.') . - '

'; - } - - public function testService() - { - if (empty($this->args['username']) || empty($this->args['password'])) { - $this->error->add(__('Service is not well configured.')); - - return false; - } - if (time() < $this->api_rate_time + 300) { // bloc service within 5min on API rate limit - $this->error->add(__('Prevent service rate limit.')); - - return false; - } - if (!($rsp = self::post($this->url_api . 'verify.xml', $this->args, true, true))) { - $this->error->add(__('Service is unavailable.')); - - return false; - } - $r = simplexml_load_string($rsp); - - if ($r['code'] == 200) { - return true; - } - $this->error->add(__('Authentication to service failed.')); - - return false; - } - - public function createHash($url, $hash = null) - { - $arg = $this->args; - $arg['url'] = $url; - - if (!($rsp = self::post($this->url_api . 'trim_url.xml', $arg, true, true))) { - $this->error->add(__('Service is unavailable.')); - - return false; - } - - $r = simplexml_load_string($rsp); - - # API rate limit - if ($r['code'] == 425) { - $this->settings->put('srv_trim_apiratetime', time()); - - $this->error->add(__('Service rate limit exceeded.')); - - return false; - } - if (isset($r->trimpath)) { - $rs = new ArrayObject(); - $rs->hash = $r->trimpath; - $rs->url = $url; - $rs->type = $this->id; - - return $rs; - } - $this->error->add(__('Unreadable service response.')); - - return false; - } -} diff --git a/src/Uninstall.php b/src/Uninstall.php index fccd2ab..1dca400 100644 --- a/src/Uninstall.php +++ b/src/Uninstall.php @@ -10,86 +10,73 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; +declare(strict_types=1); + +namespace Dotclear\Plugin\kUtRL; + +use dcCore; +use Dotclear\Core\Process; +use Dotclear\Plugin\Uninstaller\Uninstaller; + +/** + * Plugin Uninstaller actions. + */ +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( + 'tables', + 'delete', + My::TABLE_NAME, + ) + ->addUserAction( + 'plugins', + 'delete', + My::id() + ) + ->addUserAction( + 'versions', + 'delete', + My::id() + ) + ->addDirectAction( + 'settings', + 'delete_all', + My::id() + ) + ->addDirectAction( + 'tables', + 'delete', + My::TABLE_NAME + ) + ->addDirectAction( + 'plugins', + 'delete', + My::id() + ) + ->addDirectAction( + 'versions', + 'delete', + My::id() + ) + ; + + return false; + } } - -$this->addUserAction( - /* type */ - 'settings', - /* action */ - 'delete_all', - /* ns */ - basename(__DIR__), - /* description */ - __('delete all settings') -); - -$this->addUserAction( - /* type */ - 'tables', - /* action */ - 'delete', - /* ns */ - initkUtRL::KURL_TABLE_NAME, - /* description */ - __('delete table') -); - -$this->addUserAction( - /* type */ - 'plugins', - /* action */ - 'delete', - /* ns */ - basename(__DIR__), - /* description */ - __('delete plugin files') -); - -$this->addUserAction( - /* type */ - 'versions', - /* action */ - 'delete', - /* ns */ - basename(__DIR__), - /* description */ - __('delete the version number') -); - -# Delete only dc version and plugin files from pluginsBeforeDelete -# Keep table - -$this->addDirectAction( - /* type */ - 'settings', - /* action */ - 'delete_all', - /* ns */ - basename(__DIR__), - /* description */ - sprintf(__('delete all %s settings'), basename(__DIR__)) -); - -$this->addDirectAction( - /* type */ - 'versions', - /* action */ - 'delete', - /* ns */ - basename(__DIR__), - /* description */ - sprintf(__('delete %s version number'), basename(__DIR__)) -); - -$this->addDirectAction( - /* type */ - 'plugins', - /* action */ - 'delete', - /* ns */ - basename(__DIR__), - /* description */ - sprintf(__('delete %s plugin files'), basename(__DIR__)) -); diff --git a/src/Utils.php b/src/Utils.php index c315429..3ee1e1c 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -2,6 +2,8 @@ /** * @brief kUtRL, a plugin for Dotclear 2 * + * Generic class to play easily with services + * * @package Dotclear * @subpackage Plugin * @@ -10,15 +12,21 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -# Generic class to play easily with services -class kUtRL +namespace Dotclear\Plugin\kUtRL; + +use dcCore; +use Exception; + +class Utils { - # Load services list from behavior - public static function getServices() + /** + * Load services list from behavior. + * + * @return array The services list + */ + public static function getServices(): ?array { $list = dcCore::app()->getBehaviors('kutrlService'); @@ -37,9 +45,14 @@ class kUtRL return $services; } - # Silently try to load a service according to its id - # Return null on error else service on success - public static function quickService($id = '') + /** + * Silently try to load a service according to its id. + * + * @param string $id The service ID + * + * @return Service The service instance or null on error; + */ + public static function quickService(string $id = ''): ?Service { try { if (empty($id)) { @@ -55,15 +68,20 @@ class kUtRL return null; } - # Silently try to load a service according to its place - # Return null on error else service on success - public static function quickPlace($place = 'plugin') + /** + * Silently try to load a service according to its place. + * + * @param string The execution context + * + * @return Service The service or null on error + */ + public static function quickPlace(string $place = 'plugin'): ?Service { try { if (!in_array($place, ['tpl', 'wiki', 'admin', 'plugin'])) { return null; } - $id = dcCore::app()->blog->settings->get(basename(dirname(__DIR__)))->get($place . '_service'); + $id = My::settings()->get($place . '_service'); if (!empty($id)) { return self::quickService($id); } @@ -73,9 +91,16 @@ class kUtRL return null; } - # Silently try to reduce url (using 'plugin' place) - # return long url on error else short url on success - public static function quickReduce($url, $custom = null, $place = 'plugin') + /** + * Silently try to reduce url (using 'plugin' place). + * + * @param string $url The long URL + * @param string $cutom The custom short URI + * @param string $place The context + * + * @return string The short url on success else the long url + */ + public static function quickReduce(string $url, ?string $custom = null, string $place = 'plugin'): string { try { $srv = self::quickPlace($place); diff --git a/src/Widgets.php b/src/Widgets.php index 353ed95..80f5111 100644 --- a/src/Widgets.php +++ b/src/Widgets.php @@ -10,22 +10,32 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -dcCore::app()->addBehavior('initWidgets', ['widgetKutrl', 'adminShorten']); -dcCore::app()->addBehavior('initWidgets', ['widgetKutrl', 'adminRank']); +namespace Dotclear\Plugin\kUtRL; -class widgetKutrl +use dcCore; +use Dotclear\Helper\Html\Form\{ + Form, + Hidden, + Input, + Label, + Para, + Submit +}; +use Dotclear\Helper\Html\Html; +use Dotclear\Plugin\widgets\WidgetsStack; +use Dotclear\Plugin\widgets\WidgetsElement; + +class Widgets { - public static function adminShorten($w) + public static function initShorten(WidgetsStack $w): void { $w ->create( 'shortenkutrl', - __('Links shortener'), - ['widgetKutrl', 'publicShorten'] + My::name(), + [self::class, 'parseShorten'] ) ->addTitle(__('Shorten link')) ->addHomeOnly() @@ -34,13 +44,13 @@ class widgetKutrl ->addOffline(); } - public static function adminRank($w) + public static function initRank(WidgetsStack $w): void { $w ->create( 'rankkutrl', __('Top of short links'), - ['widgetKutrl', 'publicRank'] + [self::class, 'parseRank'] ) ->addTitle(__('Top of short links')) ->setting( @@ -112,49 +122,65 @@ class widgetKutrl ->addOffline(); } - public static function publicShorten($w) + public static function parseShorten(WidgetsElement $w): string { - $s = dcCore::app()->blog->settings->get(basename(__DIR__)); + $s = My::settings(); if (!$s->get('active') || !$s->get('srv_local_public') || !$w->checkHomeOnly(dcCore::app()->url->type) || dcCore::app()->url->type == 'kutrl') { - return null; + return ''; } - $hmf = hmfKutrl::create(); - $hmfp = hmfKutrl::protect($hmf); + $hmf = FrontendUtils::create(); + $hmfp = FrontendUtils::protect($hmf); return $w->renderDiv( - $w->content_only, + (bool) $w->content_only, 'shortenkutrlwidget ' . $w->class, '', - ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . - '
' . - '

' . - '

' . - '

' . - form::hidden('hmfp', $hmfp) . - dcCore::app()->formNonce() . - '

' . - '
' + ($w->title ? $w->renderTitle(Html::escapeHTML($w->title)) : '') . + (new Form(['shortenkutrlwidget'])) + ->method('post') + ->action(dcCore::app()->blog->url . dcCore::app()->url->getBase('kutrl')) + ->fields([ + (new Para()) + ->items([ + (new Label(__('Long link:'), Label::OUTSIDE_LABEL_BEFORE)) + ->for('longurl'), + (new Input('longurl')) + ->size(20) + ->maxlenght(255) + ->value(''), + ]), + (new Para()) + ->items([ + (new Label(sprintf(__('Rewrite "%s" in next field to show that you are not a robot:'), $hmf), Label::OUTSIDE_LABEL_BEFORE)) + ->for('hmf'), + (new Input('hmf')) + ->size(20) + ->maxlenght(255) + ->value(''), + ]), + (new Para()) + ->items([ + (new Submit('submiturl')) + ->value(__('Shorten')), + (new Hidden('hmfp', $hmfp)), + dcCore::app()->formNonce(false), + ]), + ]) + ->render() ); } - public static function publicRank($w) + public static function parseRank(WidgetsElement $w): string { - $s = dcCore::app()->blog->settings->get(basename(__DIR__)); + $s = My::settings(); if (!$s->get('active') || !$w->checkHomeOnly(dcCore::app()->url->type)) { - return null; + return ''; } $type = in_array($w->type, ['localnormal', 'localmix', 'localcustom']) ? @@ -165,7 +191,7 @@ class widgetKutrl $more = ''; if ($w->type == 'localmix' && '' != $w->mixprefix) { - $more = "AND kut_hash LIKE '" . dcCore::app()->con->escape($w->mixprefix) . "%' "; + $more = "AND kut_hash LIKE '" . dcCore::app()->con->escapeStr((string) $w->mixprefix) . "%' "; } $order = ($w->sortby && in_array($w->sortby, ['kut_dt', 'kut_counter', 'kut_hash'])) ? @@ -177,14 +203,14 @@ class widgetKutrl $rs = dcCore::app()->con->select( 'SELECT kut_counter, kut_hash ' . - 'FROM ' . dcCore::app()->prefix . initkUtRL::KURL_TABLE_NAME . ' ' . - "WHERE blog_id='" . dcCore::app()->con->escape(dcCore::app()->blog->id) . "' " . + 'FROM ' . dcCore::app()->prefix . My::TABLE_NAME . ' ' . + "WHERE blog_id='" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " . "AND kut_service = 'local' " . $type . $hide . $more . 'ORDER BY ' . $order . $limit ); if ($rs->isEmpty()) { - return null; + return ''; } $content = ''; @@ -225,14 +251,14 @@ class widgetKutrl } if (empty($content)) { - return null; + return ''; } return $w->renderDiv( - $w->content_only, + (bool) $w->content_only, 'lastblogupdate ' . $w->class, '', - ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . + ($w->title ? $w->renderTitle(Html::escapeHTML($w->title)) : '') . sprintf('
    %s
', $content) ); } diff --git a/src/Wiki.php b/src/Wiki.php index 0d42259..8c4cc1e 100644 --- a/src/Wiki.php +++ b/src/Wiki.php @@ -2,6 +2,8 @@ /** * @brief kUtRL, a plugin for Dotclear 2 * + * This file contents class to shorten url pass through wiki + * * @package Dotclear * @subpackage Plugin * @@ -10,40 +12,44 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -# This file contents class to shorten url pass through wiki +declare(strict_types=1); -if (!defined('DC_RC_PATH')) { - return null; -} +namespace Dotclear\Plugin\kUtRL; -class kutrlWiki +use dcCore; +use Dotclear\Helper\Html\WikiToHtml; + +class Wiki { - public static function coreInitWiki($wiki2xhtml) + public static function coreInitWiki(WikiToHtml $wiki2xhtml): void { # Do nothing on comment preview and post preview if (!empty($_POST['preview']) || isset(dcCore::app()->ctx) && dcCore::app()->ctx->preview - || !dcCore::app()->blog->settings->get(basename(dirname(__DIR__)))->get('active') + || !My::settings()?->get('active') ) { - return null; + return; } - if (null === ($kut = kUtRL::quickPlace('wiki'))) { - return null; + if (null === ($kut = Utils::quickPlace('wiki'))) { + return; } foreach ($kut->allow_protocols as $protocol) { $wiki2xhtml->registerFunction( 'url:' . $protocol, - ['kutrlWiki', 'transform'] + [self::class, 'transform'] ); } } - public static function transform($url, $content) + /** + * @return array + */ + public static function transform(string $url, string $content): ?array { - if (!dcCore::app()->blog->settings->get(basename(dirname(__DIR__)))->get('active')) { + if (!My::settings()?->get('active')) { return null; } - if (null === ($kut = kUtRL::quickPlace('wiki'))) { + if (null === ($kut = Utils::quickPlace('wiki'))) { return []; } # Test if long url exists @@ -64,10 +70,7 @@ class kutrlWiki $res['content'] = $res['url']; } - # ex: Send new url to messengers - if (!empty($rs)) { - dcCore::app()->callBehavior('wikiAfterKutrlCreate', $rs, __('New short URL')); - } + dcCore::app()->callBehavior('wikiAfterKutrlCreate', $rs, __('New short URL')); return $res; }