Skip to content

Commit 75982c5

Browse files
authored
Merge pull request dokuwiki#4489 from dokuwiki/extension-base
ExtensionManager: get base from plugin classes. fixes dokuwiki#4484
2 parents 3892623 + a1ef4d6 commit 75982c5

File tree

5 files changed

+81
-12
lines changed

5 files changed

+81
-12
lines changed

lib/plugins/extension/Extension.php

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ class Extension
2525
512 => 'CSS/JS-only',
2626
];
2727

28+
/** @var string[] List of plugin component file base names */
29+
public const COMPONENT_FILES = [
30+
'syntax',
31+
'admin',
32+
'action',
33+
'render',
34+
'helper',
35+
'remote',
36+
'auth',
37+
'cli',
38+
];
39+
2840
/** @var string "plugin"|"template" */
2941
protected string $type = self::TYPE_PLUGIN;
3042

@@ -117,7 +129,7 @@ protected function initFromDirectory($dir, $type = null, $base = null)
117129
} elseif (isset($this->localInfo['base'])) {
118130
$this->base = $this->localInfo['base'];
119131
} else {
120-
$this->base = basename($dir);
132+
$this->base = $this->getBaseFromClass($dir) ?: basename($dir);
121133
}
122134
}
123135

@@ -769,6 +781,28 @@ protected function readLocalInfo()
769781
$this->localInfo = array_filter($this->localInfo); // remove all falsy keys
770782
}
771783

784+
/**
785+
* Try to determine the extension's base name from a plugin class name
786+
*
787+
* We use this as a fallback for old plugins without an info file
788+
*
789+
* @param string $dir The directory where the extension is located
790+
* @return string
791+
*/
792+
protected function getBaseFromClass($dir)
793+
{
794+
foreach (Extension::COMPONENT_FILES as $type) {
795+
$file = $dir . '/' . $type . '.php';
796+
if (!is_readable($file)) continue;
797+
$class = $this->getClassNameFromFile($file);
798+
if ($class === null) continue;
799+
if (preg_match('/' . $type . '_plugin_(\w+)/', $class, $matches)) {
800+
return $matches[1];
801+
}
802+
}
803+
return '';
804+
}
805+
772806
/**
773807
* Fetches the remote info from the repository
774808
*
@@ -845,6 +879,39 @@ protected function idToTypeBase($id)
845879
return [$type, $base];
846880
}
847881

882+
/**
883+
* Extract the class name from a file
884+
*
885+
* @param string $filePath
886+
* @return string|null
887+
*/
888+
protected function getClassNameFromFile($filePath)
889+
{
890+
$code = file_get_contents($filePath);
891+
$tokens = token_get_all($code);
892+
893+
for ($i = 0, $count = count($tokens); $i < $count; $i++) {
894+
if (is_array($tokens[$i]) && $tokens[$i][0] === T_CLASS) {
895+
// Skip whitespace/comments after T_CLASS
896+
$j = $i + 1;
897+
while (
898+
isset($tokens[$j]) &&
899+
is_array($tokens[$j]) &&
900+
in_array($tokens[$j][0], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])
901+
) {
902+
$j++;
903+
}
904+
905+
// The next token should be the class name
906+
if (isset($tokens[$j]) && is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) {
907+
return $tokens[$j][1]; // Return class name
908+
}
909+
}
910+
}
911+
912+
return null; // No class found
913+
}
914+
848915
/**
849916
* @return string
850917
*/

lib/plugins/extension/Installer.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public function installExtension(Extension $extension)
9494
if (!$url) {
9595
throw new Exception('error_nourl', [$extension->getId()]);
9696
}
97-
$this->installFromUrl($url);
97+
$this->installFromUrl($url, $extension->getBase());
9898
}
9999

100100
/**
@@ -127,14 +127,12 @@ public function installFromUpload($field)
127127
throw new Exception('msg_upload_failed', [$_FILES[$field]['error']]);
128128
}
129129

130+
$tmpbase = $this->fileToBase($_FILES[$field]['name']) ?: 'upload';
130131
$tmp = $this->mkTmpDir();
131-
if (!move_uploaded_file($_FILES[$field]['tmp_name'], "$tmp/upload.archive")) {
132+
if (!move_uploaded_file($_FILES[$field]['tmp_name'], "$tmp/$tmpbase.archive")) {
132133
throw new Exception('msg_upload_failed', ['move failed']);
133134
}
134-
$this->installFromArchive(
135-
"$tmp/upload.archive",
136-
$this->fileToBase($_FILES[$field]['name']),
137-
);
135+
$this->installFromArchive("$tmp/$tmpbase.archive");
138136
}
139137

140138
/**
@@ -149,8 +147,7 @@ public function installFromUpload($field)
149147
*/
150148
public function installFromArchive($archive, $base = null)
151149
{
152-
if ($base === null) $base = $this->fileToBase($archive);
153-
$target = $this->mkTmpDir() . '/' . $base;
150+
$target = $this->mkTmpDir() . '/' . ($base ?? $this->fileToBase($archive));
154151
$this->extractArchive($archive, $target);
155152
$extensions = $this->findExtensions($target, $base);
156153
foreach ($extensions as $extension) {
@@ -433,7 +430,7 @@ public static function ensurePermissions(Extension $extension)
433430
protected function fileToBase($file)
434431
{
435432
$base = PhpString::basename($file);
436-
$base = preg_replace('/\.(tar\.gz|tar\.bz|tar\.bz2|tar|tgz|tbz|zip)$/', '', $base);
433+
$base = preg_replace('/\.(tar\.gz|tar\.bz|tar\.bz2|tar|tgz|tbz|zip|archive)$/', '', $base);
437434
return preg_replace('/\W+/', '', $base);
438435
}
439436

@@ -487,7 +484,6 @@ protected function findExtensions($dir, $base = null)
487484
if (count($files) === 1 && is_dir($files[0])) {
488485
$dir = $files[0];
489486
}
490-
$base ??= PhpString::basename($dir);
491487
return [Extension::createFromDirectory($dir, null, $base)];
492488
}
493489

lib/plugins/extension/_test/InstallerTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function provideFindExtensionsData()
2828
'plgsub6' => ['plgsub6', ['plugin6' => 'plugin']],
2929
'plugin1' => ['plugin1', ['plugin1' => 'plugin']],
3030
'plugin2' => ['plugin2', ['plugin2' => 'plugin']],
31+
'plugin3' => ['plugin3', ['foobar' => 'plugin']],
3132
'template1' => ['template1', ['template1' => 'template']],
3233
'tplfoo5' => ['tplfoo5', ['template5' => 'template']],
3334
'tplsub3' => ['tplsub3', ['template3' => 'template']],
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
class syntax_plugin_foobar extends DokuWiki_Plugin {
4+
5+
}

lib/plugins/extension/cli.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ protected function cmdInstall($extensions)
206206

207207
try {
208208
if (preg_match("/^https?:\/\//i", $extname)) {
209-
$installer->installFromURL($extname, true);
209+
$installer->installFromURL($extname);
210210
} else {
211211
$installer->installFromId($extname);
212212
}

0 commit comments

Comments
 (0)