From a54b6f395dbef03e679357e9e93891d4b4749ba1 Mon Sep 17 00:00:00 2001
From: Moritz Strohm <strohm@data-quest.de>
Date: Fri, 3 May 2024 14:06:50 +0000
Subject: [PATCH] functions.php: added studip_interpolate, closes #3555

Closes #3555

Merge request studip/studip!2442
---
 lib/functions.php                | 31 +++++++++++++++++++++++++++++++
 tests/unit/lib/FunctionsTest.php | 20 +++++++++++++++++++-
 2 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/lib/functions.php b/lib/functions.php
index 90d4499c529..b68658a25ff 100644
--- a/lib/functions.php
+++ b/lib/functions.php
@@ -1859,3 +1859,34 @@ function xml_escape($string)
     $string = preg_replace('/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string);
     return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
 }
+
+/**
+ * This function mimics the functionality of the $gettextInterpolate function in JavaScript.
+ * This makes it easier to format text in translatable strings.
+ *
+ * Note that the behavior of this function is simplified in comparison with $gettextInterpolate:
+ * - All placeholders that have a value are replaced with the string value of that value.
+ *   Numbers must be pre-formatted before added to the parameters.
+ * - All placeholders that have no replacements in the parameters array are output.
+ *
+ * @param string $gettext_string The translation string to be interpolated.
+ *
+ * @param array $parameters The parameters that replace the placeholders in the translation string.
+ *     Array keys are the names of the placeholders while array values are the values that are
+ *     placed inside the string.
+ *
+ * @return string The interpolated translation string.
+ */
+function studip_interpolate(string $gettext_string, array $parameters) : string
+{
+    return preg_replace_callback(
+        '/%\{\s*(\w+)\s*\}/',
+        function ($match) use ($parameters): string {
+            if (!isset($parameters[$match[1]])) {
+                throw new Exception('The parameter for the placeholder ' . $match[1] . ' is missing.');
+            }
+            return $parameters[$match[1]];
+        },
+        $gettext_string
+    );
+}
diff --git a/tests/unit/lib/FunctionsTest.php b/tests/unit/lib/FunctionsTest.php
index 9a92f1a2755..670d00c74b8 100644
--- a/tests/unit/lib/FunctionsTest.php
+++ b/tests/unit/lib/FunctionsTest.php
@@ -80,11 +80,29 @@ class FunctionsTest extends \Codeception\Test\Unit
     public function testTrailsControllerExtractActionAndArgs()
     {
         $controller = new Trails_Controller(null);
-        list($action, $args, $format) = $controller->extract_action_and_args('foo/bar//42.html');
+        [$action, $args, $format] = $controller->extract_action_and_args('foo/bar//42.html');
 
         $this->assertEquals('foo', $action);
         $this->assertEquals(['bar', '', '42'], $args);
         $this->assertEquals('html', $format);
 
     }
+
+    /**
+     * @covers ::studip_interpolate
+     */
+    public function testStudipInterpolate()
+    {
+        $this->assertEquals(
+            '12bar34',
+            studip_interpolate('12%{foo}34', ['foo' => 'bar'])
+        );
+        $this->assertEquals(
+            'foo',
+            studip_interpolate('%{ bar }', ['bar' => 'foo'])
+        );
+
+        $this->expectException(Exception::class);
+        studip_interpolate('%{foo}', []);
+    }
 }
-- 
GitLab