From 5801f5128b41c02d67aa36f857ded9ef7ee7251d Mon Sep 17 00:00:00 2001 From: Anna Dabrowska Date: Mon, 21 Oct 2024 13:17:26 +0200 Subject: [PATCH] Insert relative media references when applicable --- _test/FileTest.php | 37 +++++++++++++++++++ _test/GeneralTest.php | 84 +++++++++++++++++++++++++++++++++++++++++++ action.php | 2 +- helper.php | 74 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 _test/FileTest.php create mode 100644 _test/GeneralTest.php create mode 100644 helper.php diff --git a/_test/FileTest.php b/_test/FileTest.php new file mode 100644 index 0000000..67047b7 --- /dev/null +++ b/_test/FileTest.php @@ -0,0 +1,37 @@ + [ 'foo:bar', 'pasted:11223333-4455.png', 'pasted:11223333-4455.png'], + 'same top ns - relative' => [ 'foo:bar', 'foo:pasted:20241008-181825.png', '.:pasted:20241008-181825.png'], + 'one ns up' => ['foo:v1:bar', 'foo:pasted:11223333-4455.png', '..:pasted:11223333-4455.png'], + 'two ns up' => ['foo:bar:v1:baz', 'foo:pasted:11223333-4455.png', '..:..:pasted:11223333-4455.png'], + 'page with ns, media ref in root - absolute' => ['a:b', 'c', ':c'], + ]; + } + + /** + * @dataProvider provideIds + * @param string $page + * @param string $media + * @param string $expected + */ + public function testResolveID(string $page, string $media, string $expected) + { + $this->assertSame($expected, \helper_plugin_imgpaste::createRelativeID($page, $media)); + } +} diff --git a/_test/GeneralTest.php b/_test/GeneralTest.php new file mode 100644 index 0000000..71cf59d --- /dev/null +++ b/_test/GeneralTest.php @@ -0,0 +1,84 @@ +assertFileExists($file); + + $info = confToHash($file); + + $this->assertArrayHasKey('base', $info); + $this->assertArrayHasKey('author', $info); + $this->assertArrayHasKey('email', $info); + $this->assertArrayHasKey('date', $info); + $this->assertArrayHasKey('name', $info); + $this->assertArrayHasKey('desc', $info); + $this->assertArrayHasKey('url', $info); + + $this->assertEquals('imgpaste', $info['base']); + $this->assertRegExp('/^https?:\/\//', $info['url']); + $this->assertTrue(mail_isvalid($info['email'])); + $this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']); + $this->assertTrue(false !== strtotime($info['date'])); + } + + /** + * Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in + * conf/metadata.php. + */ + public function testPluginConf(): void + { + $conf_file = __DIR__ . '/../conf/default.php'; + $meta_file = __DIR__ . '/../conf/metadata.php'; + + if (!file_exists($conf_file) && !file_exists($meta_file)) { + self::markTestSkipped('No config files exist -> skipping test'); + } + + if (file_exists($conf_file)) { + include($conf_file); + } + if (file_exists($meta_file)) { + include($meta_file); + } + + $this->assertEquals( + gettype($conf), + gettype($meta), + 'Both ' . DOKU_PLUGIN . 'imgpaste/conf/default.php and ' . DOKU_PLUGIN . 'imgpaste/conf/metadata.php have to exist and contain the same keys.' + ); + + if ($conf !== null && $meta !== null) { + foreach ($conf as $key => $value) { + $this->assertArrayHasKey( + $key, + $meta, + 'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'imgpaste/conf/metadata.php' + ); + } + + foreach ($meta as $key => $value) { + $this->assertArrayHasKey( + $key, + $conf, + 'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'imgpaste/conf/default.php' + ); + } + } + } +} diff --git a/action.php b/action.php index 419df06..54bbc55 100644 --- a/action.php +++ b/action.php @@ -78,7 +78,7 @@ public function handleAjaxUpload(Doku_Event $event) header('Content-Type: application/json'); echo json_encode([ 'message' => $lang['uploadsucc'], - 'id' => $result, + 'id' => \helper_plugin_imgpaste::createRelativeId($INPUT->post->str('id'), $result), 'mime' => $type, 'ext' => $mimetypes[$type], 'url' => ml($result), diff --git a/helper.php b/helper.php new file mode 100644 index 0000000..e434a9b --- /dev/null +++ b/helper.php @@ -0,0 +1,74 @@ + + */ +class helper_plugin_imgpaste extends Plugin +{ + /** + * Create a relative ID from a given reference ID and a full ID to link to + * + * PHP rewrite of the original Javascript written by Andreas Gohr + * in /lib/scripts/linkwiz.js + * + * Both IDs are expected to be clean, e.g., the result of a clean ID function. + * No relative paths, leading colons, or similar things are allowed. As long as + * pages have a common prefix, a relative link is constructed. + * + * @param string $ref The ID of a page the link is used on + * @param string $id The ID to link to + * @return string The relative ID + */ + public static function createRelativeID($ref, $id) { + // Split the reference and target IDs into namespaces + $sourceNs = explode(':', $ref); + array_pop($sourceNs); // Remove the page part, keep only the namespace + $targetNs = explode(':', $id); + $targetPage = array_pop($targetNs); // Remove the page part of the target ID + $relativeID = []; + + // Find the common prefix length + $commonPrefixLength = 0; + while ($commonPrefixLength < count($sourceNs) && + $commonPrefixLength < count($targetNs) && + $sourceNs[$commonPrefixLength] === $targetNs[$commonPrefixLength]) { + $commonPrefixLength++; + } + + if (count($sourceNs) > 0) { + if ($commonPrefixLength > 0) { + if ($commonPrefixLength === count($sourceNs) && $commonPrefixLength === count($targetNs)) { + // Both pages are in the same namespace + } elseif ($commonPrefixLength < count($sourceNs)) { + // Add '..' for each missing namespace from common to the target + $relativeID = array_merge( + $relativeID, + array_fill(0, count($sourceNs) - $commonPrefixLength, '..') + ); + } else { + // Target is below common prefix, add '.' + $relativeID[] = '.'; + } + } elseif (count($targetNs) === 0) { + // Target is in the root namespace, but source is not, make it absolute + $relativeID[] = ''; + } + + // Add any remaining parts of the target namespace + $relativeID = array_merge($relativeID, array_slice($targetNs, $commonPrefixLength)); + } else { + // Source is in the root namespace, just use target as is + $relativeID = $targetNs; + } + + // Add the target page to the relative ID + $relativeID[] = $targetPage; + + return implode(':', $relativeID); + } +}