aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaria Carolin Chabowski <laria@laria.me>2020-09-25 21:18:18 +0200
committerLaria Carolin Chabowski <laria@laria.me>2020-09-25 21:28:55 +0200
commit378881378aab5454c84cb1fecbbcc675f64dc27f (patch)
treef8bbe239c2a87cc61bec05b987099e4401dd2693
parent78c0350b3b7fc025ba565e19bfa195b68e95bb88 (diff)
downloadratatoeskr-cms-378881378aab5454c84cb1fecbbcc675f64dc27f.tar.gz
ratatoeskr-cms-378881378aab5454c84cb1fecbbcc675f64dc27f.tar.bz2
ratatoeskr-cms-378881378aab5454c84cb1fecbbcc675f64dc27f.zip
Refactor textprocessors
They are now managed by TextprocessorRepository and are instances of Textprocessor. This replaces the global $textprocessors variable.
-rw-r--r--ratatoeskr/backend.php26
-rw-r--r--ratatoeskr/frontend.php7
-rw-r--r--ratatoeskr/sys/Env.php37
-rw-r--r--ratatoeskr/sys/models.php31
-rw-r--r--ratatoeskr/sys/plugin_api.php8
-rw-r--r--ratatoeskr/sys/textprocessors.php75
-rw-r--r--ratatoeskr/sys/textprocessors/HtmlProcessor.php20
-rw-r--r--ratatoeskr/sys/textprocessors/LegacyTextprocessor.php32
-rw-r--r--ratatoeskr/sys/textprocessors/MarkdownProcessor.php22
-rw-r--r--ratatoeskr/sys/textprocessors/PlainTextProcessor.php22
-rw-r--r--ratatoeskr/sys/textprocessors/Textprocessor.php19
-rw-r--r--ratatoeskr/sys/textprocessors/TextprocessorRepository.php76
12 files changed, 302 insertions, 73 deletions
diff --git a/ratatoeskr/backend.php b/ratatoeskr/backend.php
index df1ea5b..1b898ea 100644
--- a/ratatoeskr/backend.php
+++ b/ratatoeskr/backend.php
@@ -10,6 +10,7 @@
*/
use r7r\cms\sys\Esc;
+use r7r\cms\sys\Env;
require_once(dirname(__FILE__) . "/sys/models.php");
require_once(dirname(__FILE__) . "/sys/pwhash.php");
@@ -139,12 +140,13 @@ function build_backend_subactions()
/**
* @var \ste\STECore $ste
* @var array $translation
- * @var array $textprocessors
* @var Settings $ratatoeskr_settings
* @var array $languages
* @var array $articleeditor_plugins
*/
- global $ste, $translation, $textprocessors, $ratatoeskr_settings, $languages, $articleeditor_plugins;
+ global $ste, $translation, $ratatoeskr_settings, $languages, $articleeditor_plugins;
+
+ $textprocessors = Env::getGlobal()->textprocessors();
list($article, $editlang) = array_slice($url_next, 0);
if (!isset($editlang)) {
@@ -164,9 +166,9 @@ function build_backend_subactions()
$ste->vars["submenu"] = isset($article) ? "articles" : "newarticle";
$ste->vars["textprocessors"] = [];
- foreach ($textprocessors as $txtproc => $properties) {
- if ($properties[1]) {
- $ste->vars["textprocessors"][] = $txtproc;
+ foreach ($textprocessors->all() as $name => $textprocessor) {
+ if ($textprocessor->showInBackend()) {
+ $ste->vars["textprocessors"][] = $name;
}
}
@@ -190,12 +192,12 @@ function build_backend_subactions()
} else {
$inputs["article_status"] = (int) $_POST["article_status"];
}
- if (!isset($textprocessors[@$_POST["content_txtproc"]])) {
+ if ($textprocessors->getTextprocessor(@$_POST["content_txtproc"]) === null) {
$fail_reasons[] = $translation["unknown_txtproc"];
} else {
$inputs["content_txtproc"] = $_POST["content_txtproc"];
}
- if (!isset($textprocessors[@$_POST["excerpt_txtproc"]])) {
+ if ($textprocessors->getTextprocessor(@$_POST["excerpt_txtproc"]) === null) {
$fail_reasons[] = $translation["unknown_txtproc"];
} else {
$inputs["excerpt_txtproc"] = $_POST["excerpt_txtproc"];
@@ -1216,7 +1218,9 @@ function build_backend_subactions()
]),
"admin" => url_action_subactions([
"settings" => function (&$data, $url_now, &$url_next) {
- global $ste, $translation, $languages, $ratatoeskr_settings, $textprocessors;
+ global $ste, $translation, $languages, $ratatoeskr_settings;
+
+ $textprocessors = Env::getGlobal()->textprocessors();
$url_next = [];
@@ -1225,9 +1229,9 @@ function build_backend_subactions()
$ste->vars["pagetitle"] = $translation["menu_settings"];
$ste->vars["textprocessors"] = [];
- foreach ($textprocessors as $txtproc => $properties) {
- if ($properties[1]) {
- $ste->vars["textprocessors"][] = $txtproc;
+ foreach ($textprocessors->all() as $name => $textprocessor) {
+ if ($textprocessor->showInBackend()) {
+ $ste->vars["textprocessors"][] = $name;
}
}
diff --git a/ratatoeskr/frontend.php b/ratatoeskr/frontend.php
index eb62378..696d446 100644
--- a/ratatoeskr/frontend.php
+++ b/ratatoeskr/frontend.php
@@ -9,6 +9,7 @@
* See "ratatoeskr/licenses/ratatoeskr" for more information.
*/
+use r7r\cms\sys\Env;
use r7r\cms\sys\Esc;
require_once(dirname(__FILE__) . "/sys/utils.php");
@@ -103,6 +104,8 @@ function article_transform_ste($article, $lang)
{
global $rel_path_to_root;
+ $textprocessors = Env::getGlobal()->textprocessors();
+
$languages = [];
$a_section = $article->get_section();
foreach ($article->title as $language => $_) {
@@ -114,8 +117,8 @@ function article_transform_ste($article, $lang)
"urlname" => $article->urlname,
"fullurl" => Esc::esc("$rel_path_to_root/$lang/{$a_section->name}/{$article->urlname}"),
"title" => Esc::esc($article->title[$lang]->text),
- "text" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->text[$lang]->text), $article->text[$lang]->texttype),
- "excerpt" => textprocessor_apply(str_replace("%root%", $rel_path_to_root, $article->excerpt[$lang]->text), $article->excerpt[$lang]->texttype),
+ "text" => $textprocessors->mustApply(str_replace("%root%", $rel_path_to_root, $article->text[$lang]->text), $article->text[$lang]->texttype),
+ "excerpt" => $textprocessors->mustApply(str_replace("%root%", $rel_path_to_root, $article->excerpt[$lang]->text), $article->excerpt[$lang]->texttype),
"custom" => $article->custom,
"status" => $article->status,
"section" => section_transform_ste($a_section, $lang),
diff --git a/ratatoeskr/sys/Env.php b/ratatoeskr/sys/Env.php
new file mode 100644
index 0000000..cfe1598
--- /dev/null
+++ b/ratatoeskr/sys/Env.php
@@ -0,0 +1,37 @@
+<?php
+
+
+namespace r7r\cms\sys;
+
+use r7r\cms\sys\textprocessors\TextprocessorRepository;
+
+/**
+ * Env holds several global global objects. It's basically a DI container.
+ */
+class Env
+{
+ /** @var self|null */
+ private static $globalInstance = null;
+
+ private $lazyLoaded = [];
+
+ private function lazy(string $ident, callable $callback)
+ {
+ if (!isset($this->lazyLoaded[$ident])) {
+ $this->lazyLoaded[$ident] = $callback();
+ }
+ return $this->lazyLoaded[$ident];
+ }
+
+ public static function getGlobal(): self
+ {
+ self::$globalInstance = self::$globalInstance ?? new self();
+
+ return self::$globalInstance;
+ }
+
+ public function textprocessors(): TextprocessorRepository
+ {
+ return $this->lazy("textprocessors", [TextprocessorRepository::class, 'buildDefault']);
+ }
+}
diff --git a/ratatoeskr/sys/models.php b/ratatoeskr/sys/models.php
index 9f81fcf..caf14ad 100644
--- a/ratatoeskr/sys/models.php
+++ b/ratatoeskr/sys/models.php
@@ -9,6 +9,9 @@
* See "ratatoeskr/licenses/ratatoeskr" for more information.
*/
+use r7r\cms\sys\textprocessors\TextprocessorRepository;
+use r7r\cms\sys\Env;
+
require_once(dirname(__FILE__) . "/db.php");
require_once(dirname(__FILE__) . "/utils.php");
require_once(dirname(__FILE__) . "/../libs/kses.php");
@@ -691,6 +694,16 @@ class Translation
$this->text = $text;
$this->texttype = $texttype;
}
+
+ /**
+ * Applies a textprocessor to the text according to texttype.
+ * @param TextprocessorRepository $textprocessors
+ * @return string
+ */
+ public function applyTextprocessor(TextprocessorRepository $textprocessors): string
+ {
+ return $textprocessors->apply((string)$this->text, (string)$this->texttype);
+ }
}
/*
@@ -1192,22 +1205,20 @@ class Comment extends BySQLRowEnabled
return $rv;
}
- /*
- * Function: htmlize_comment_text
- * Creates the HTML representation of a comment text. It applys the page's comment textprocessor on it
+ /**
+ * Creates the HTML representation of a comment text. It applies the page's comment textprocessor on it
* and filters some potentially harmful tags using kses.
*
- * Parameters:
- * $text - Text to HTMLize.
- *
- * Returns:
- * HTML code.
+ * @param string $text Text to HTMLize.
+ * @return string HTML code.
*/
- public static function htmlize_comment_text($text)
+ public static function htmlize_comment_text($text, ?TextprocessorRepository $textprocessors = null)
{
global $ratatoeskr_settings;
- return kses(textprocessor_apply($text, $ratatoeskr_settings["comment_textprocessor"]), [
+ $textprocessors = $textprocessors ?? Env::getGlobal()->textprocessors();
+
+ return kses($textprocessors->mustApply($text, $ratatoeskr_settings["comment_textprocessor"]), [
"a" => ["href" => 1, "hreflang" => 1, "title" => 1, "rel" => 1, "rev" => 1],
"b" => [],
"i" => [],
diff --git a/ratatoeskr/sys/plugin_api.php b/ratatoeskr/sys/plugin_api.php
index c286fdc..b85ce57 100644
--- a/ratatoeskr/sys/plugin_api.php
+++ b/ratatoeskr/sys/plugin_api.php
@@ -10,6 +10,8 @@
*/
use r7r\ste\STECore;
+use r7r\cms\sys\Env;
+use r7r\cms\sys\textprocessors\LegacyTextprocessor;
require_once(dirname(__FILE__) . "/models.php");
require_once(dirname(__FILE__) . "/textprocessors.php");
@@ -50,6 +52,9 @@ abstract class RatatoeskrPlugin
{
private $id;
+ /** @var Env */
+ private $env;
+
/** @var PluginKVStorage The Key-Value-Storage for the Plugin */
protected $kvstorage;
@@ -70,6 +75,7 @@ abstract class RatatoeskrPlugin
global $ste, $rel_path_to_root;
$this->id = $id;
+ $this->env = Env::getGlobal();
$this->kvstorage = new PluginKVStorage($id);
$this->ste = $ste;
$this->rel_path_to_root = $rel_path_to_root;
@@ -151,7 +157,7 @@ abstract class RatatoeskrPlugin
*/
final protected function register_textprocessor($name, $fx, $visible_in_backend=true)
{
- textprocessor_register($name, $fx, $visible_in_backend);
+ $this->env->textprocessors()->register($name, new LegacyTextprocessor($fx, (bool)$visible_in_backend));
}
/**
diff --git a/ratatoeskr/sys/textprocessors.php b/ratatoeskr/sys/textprocessors.php
index f195ef7..da52043 100644
--- a/ratatoeskr/sys/textprocessors.php
+++ b/ratatoeskr/sys/textprocessors.php
@@ -9,74 +9,51 @@
* See "ratatoeskr/licenses/ratatoeskr" for more information.
*/
-use Michelf\Markdown;
+use r7r\cms\sys\Env;
+use r7r\cms\sys\textprocessors\LegacyTextprocessor;
+use r7r\cms\sys\textprocessors\TextprocessorRepository;
require_once(dirname(__FILE__) . "/utils.php");
-/*
- * Function: textprocessor_register
+/**
* Register a textprocessor.
*
- * Parameters:
- * $name - The name of the textprocessor
- * $fx - The textprocessor function (function($input), returns HTML)
- * $visible_in_backend - Should this textprocessor be visible in the backend? Defaults to True.
+ * @deprecated Use {@see TextprocessorRepository::register()} of the global {@see TextprocessorRepository} as returned by {@see Env::textprocessors()}.
+ *
+ * @param string $name The name of the textprocessor
+ * @param callable $fx The textprocessor function (function($input), returns HTML)
+ * @param bool $visible_in_backend Should this textprocessor be visible in the backend? Defaults to True.
*/
function textprocessor_register($name, $fx, $visible_in_backend=true)
{
- global $textprocessors;
- $textprocessors[$name] = [$fx, $visible_in_backend];
+ Env::getGlobal()->textprocessors()->register($name, new LegacyTextprocessor($fx, $visible_in_backend));
}
-/*
- * Function: textprocessor_apply
+/**
* Apply a textprocessor on a text.
*
- * Parameters:
- * $text - The input text.
- * $textprocessor - The name of the textprocessor.
+ * @param string $text The input text.
+ * @param string $name The name of the textprocessor.
*
- * Returns:
- * HTML
+ * @return string HTML
+ * @throws Exception If the textprocessor is unknown
+ * @deprecated Use {@see TextprocessorRepository::mustApply()} of the global {@see TextprocessorRepository} as returned by {@see Env::textprocessors()}.
*/
-function textprocessor_apply($text, $textprocessor)
+function textprocessor_apply($text, $name)
{
- global $textprocessors;
- if (!isset($textprocessors[$textprocessor])) {
- throw new Exception("Unknown Textprocessor: $textprocessor");
- }
-
- $fx = @$textprocessors[$textprocessor][0];
- if (!is_callable($fx)) {
- throw new Exception("Invalid Textprocessor: $textprocessor");
- }
-
- return call_user_func($fx, $text);
+ return Env::getGlobal()->textprocessors()->mustApply((string)$text, (string)$name);
}
-/*
- * Function: textprocessor_apply_translation
- * Applys a textprocessor automatically on a <Translation> object. The used textprocessor is determined by the $texttype property.
+/**
+ * Applies a textprocessor automatically on a {@see Translation} object.
*
- * Parameters:
- * $translationobj - The <Translation> object.
+ * The used textprocessor is determined by the {@see Translation::$texttype} property.
*
- * Returns:
- * HTML
+ * @param Translation $translationobj
+ * @return string HTML
+ * @deprecated Use {@see Translation::applyTextprocessor()} instead
*/
-function textprocessor_apply_translation($translationobj)
+function textprocessor_apply_translation(Translation $translationobj)
{
- return textprocessor_apply($translationobj->text, $translationobj->texttype);
-}
-
-if (!isset($textprocessors)) {
- $textprocessors = [
- "Markdown" => [Closure::fromCallable([Markdown::class, "defaultTransform"]), true],
- "Plain Text" => [function ($text) {
- return str_replace(["\r\n", "\n"], ["<br />", "<br />"], htmlesc($text));
- }, true],
- "HTML" => [function ($text) {
- return $text;
- }, true]
- ];
+ return $translationobj->applyTextprocessor(Env::getGlobal()->textprocessors());
}
diff --git a/ratatoeskr/sys/textprocessors/HtmlProcessor.php b/ratatoeskr/sys/textprocessors/HtmlProcessor.php
new file mode 100644
index 0000000..c3f691b
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/HtmlProcessor.php
@@ -0,0 +1,20 @@
+<?php
+
+
+namespace r7r\cms\sys\textprocessors;
+
+/**
+ * A simple textprocessor that assumes the input already is HTML.
+ */
+class HtmlProcessor implements Textprocessor
+{
+ public function apply(string $input): string
+ {
+ return $input;
+ }
+
+ public function showInBackend(): bool
+ {
+ return true;
+ }
+}
diff --git a/ratatoeskr/sys/textprocessors/LegacyTextprocessor.php b/ratatoeskr/sys/textprocessors/LegacyTextprocessor.php
new file mode 100644
index 0000000..e7e5cc2
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/LegacyTextprocessor.php
@@ -0,0 +1,32 @@
+<?php
+
+
+namespace r7r\cms\sys\textprocessors;
+
+/**
+ * LegacyTextprocessor is used to wrap an old-style textprocessor into an Textprocessor object.
+ */
+class LegacyTextprocessor implements Textprocessor
+{
+ /** @var callable */
+ private $fx;
+
+ /** @var bool */
+ private $visible_in_backend;
+
+ public function __construct(callable $fx, $visible_in_backend)
+ {
+ $this->fx = $fx;
+ $this->visible_in_backend = (bool)$visible_in_backend;
+ }
+
+ public function apply(string $input): string
+ {
+ return (string)call_user_func($this->fx, $input);
+ }
+
+ public function showInBackend(): bool
+ {
+ return $this->visible_in_backend;
+ }
+}
diff --git a/ratatoeskr/sys/textprocessors/MarkdownProcessor.php b/ratatoeskr/sys/textprocessors/MarkdownProcessor.php
new file mode 100644
index 0000000..15f2f48
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/MarkdownProcessor.php
@@ -0,0 +1,22 @@
+<?php
+
+
+namespace r7r\cms\sys\textprocessors;
+
+use Michelf\Markdown;
+
+/**
+ * A textprocessor that uses markdown to generate HTML.
+ */
+class MarkdownProcessor implements Textprocessor
+{
+ public function apply(string $input): string
+ {
+ return Markdown::defaultTransform($input);
+ }
+
+ public function showInBackend(): bool
+ {
+ return true;
+ }
+}
diff --git a/ratatoeskr/sys/textprocessors/PlainTextProcessor.php b/ratatoeskr/sys/textprocessors/PlainTextProcessor.php
new file mode 100644
index 0000000..c8f13f6
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/PlainTextProcessor.php
@@ -0,0 +1,22 @@
+<?php
+
+
+namespace r7r\cms\sys\textprocessors;
+
+use r7r\cms\sys\Esc;
+
+/**
+ * A textprocessor that simply escapes the input string.
+ */
+class PlainTextProcessor implements Textprocessor
+{
+ public function apply(string $input): string
+ {
+ return Esc::esc($input, Esc::HTML_WITH_BR);
+ }
+
+ public function showInBackend(): bool
+ {
+ return true;
+ }
+}
diff --git a/ratatoeskr/sys/textprocessors/Textprocessor.php b/ratatoeskr/sys/textprocessors/Textprocessor.php
new file mode 100644
index 0000000..90c1347
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/Textprocessor.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace r7r\cms\sys\textprocessors;
+
+/**
+ * Interface Textprocessor.
+ *
+ * A textprocessor turns an input into HTML.
+ */
+interface Textprocessor
+{
+ public function apply(string $input): string;
+
+ /**
+ * Should this textprocessor be available to the user in the backend?
+ * @return bool
+ */
+ public function showInBackend(): bool;
+}
diff --git a/ratatoeskr/sys/textprocessors/TextprocessorRepository.php b/ratatoeskr/sys/textprocessors/TextprocessorRepository.php
new file mode 100644
index 0000000..5d918c0
--- /dev/null
+++ b/ratatoeskr/sys/textprocessors/TextprocessorRepository.php
@@ -0,0 +1,76 @@
+<?php
+
+
+namespace r7r\cms\sys\textprocessors;
+
+use Exception;
+
+class TextprocessorRepository
+{
+ /** @var Textprocessor[] */
+ private $textprocessors = [];
+
+
+ /**
+ * Builds a repository with the default textprocessors prepopulated.
+ * @return self
+ */
+ public static function buildDefault(): self
+ {
+ $repo = new self();
+
+ $repo->register("Markdown", new MarkdownProcessor());
+ $repo->register("Plain Text", new PlainTextProcessor());
+ $repo->register("HTML", new HtmlProcessor());
+
+ return $repo;
+ }
+
+ public function register(string $name, Textprocessor $textprocessor): void
+ {
+ $this->textprocessors[$name] = $textprocessor;
+ }
+
+ public function getTextprocessor(string $name): ?Textprocessor
+ {
+ return $this->textprocessors[$name] ?? null;
+ }
+
+ /**
+ * @return Textprocessor[]
+ */
+ public function all(): array
+ {
+ return $this->textprocessors;
+ }
+
+ /**
+ * Apply a textprocessor to the input text.
+ *
+ * @param string $input The input text
+ * @param string $name The name of the textprocessor
+ * @return string|null Will return null, if the textprocessor was not found
+ */
+ public function apply(string $input, string $name): ?string
+ {
+ $textprocessor = $this->getTextprocessor($name);
+ return $textprocessor === null ? null : $textprocessor->apply($input);
+ }
+
+ /**
+ * Like {@see TextprocessorRepository::apply()}, but will throw an exception instead of returning null, if the textprocessor was not found.
+ *
+ * @param string $input The input text
+ * @param string $name The name of the textprocessor
+ * @return string
+ * @throws Exception
+ */
+ public function mustApply(string $input, string $name): string
+ {
+ $out = $this->apply($input, $name);
+ if ($out === null) {
+ throw new Exception("Unknown Textprocessor: $name");
+ }
+ return $out;
+ }
+}