From 3d1b964812dcd3f9970000e10ed0b2cbf8f6c11b Mon Sep 17 00:00:00 2001 From: Matthew Barbour Date: Thu, 1 Aug 2019 11:20:09 -0500 Subject: [PATCH] Proposed extension info change to allow getting info for unloaded extensions --- core/_bootstrap.php | 1 + core/extension.php | 61 ++++++++++-- core/polyfills.php | 27 ++++++ core/send_event.php | 4 +- ext/ext_manager/main.php | 123 +++++++++++++++---------- ext/ext_manager/theme.php | 13 ++- ext/tips/info.php | 22 +++++ ext/tips/main.php | 8 -- themes/danbooru2/ext_manager.theme.php | 2 +- 9 files changed, 192 insertions(+), 69 deletions(-) create mode 100644 ext/tips/info.php diff --git a/core/_bootstrap.php b/core/_bootstrap.php index a003ed6e..a6d65ee3 100644 --- a/core/_bootstrap.php +++ b/core/_bootstrap.php @@ -26,6 +26,7 @@ $_tracer->begin("Opening files"); $_shm_files = array_merge( zglob("core/*.php"), zglob("core/{".ENABLED_MODS."}/*.php"), + zglob("ext/{".ENABLED_EXTS."}/info.php"), zglob("ext/{".ENABLED_EXTS."}/main.php") ); foreach ($_shm_files as $_shm_filename) { diff --git a/core/extension.php b/core/extension.php index 5c8c61fa..be7b8d24 100644 --- a/core/extension.php +++ b/core/extension.php @@ -89,18 +89,26 @@ abstract class Extension /** @var Themelet this theme's Themelet object */ public $theme; + public $info; + public function __construct() { - $this->theme = $this->get_theme_object(get_called_class()); + $class = get_called_class(); + $this->theme = $this->get_theme_object($class); + $this->info = ExtensionInfo::get_for_extension($class); } - public function is_live(): bool + public function is_supported(): bool { - global $database; - return ( - empty($this->db_support) || - in_array($database->get_driver_name(), $this->db_support) - ); + if($this->info!=null) { + return $this->info->supported; + } else { + global $database; + return ( + empty($this->db_support) || + in_array($database->get_driver_name(), $this->db_support) + ); + } } /** @@ -130,6 +138,45 @@ abstract class Extension } } +abstract class ExtensionInfo +{ + public $name; + public $authors; + public $link; + public $license; + public $version; + public $visibility; + public $description; + public $documentation; + public $supported; + public $db_support; + + public function __construct() + { + $this->supported = $this->is_supported(); + } + + public function is_supported(): bool + { + global $database; + return ( + empty($this->db_support) || + in_array($database->get_driver_name(), $this->db_support) + ); + } + + public static function get_for_extension(string $base): ?ExtensionInfo + { + $normal = $base.'Info'; + + if (class_exists($normal)) { + return new $normal(); + } else { + return null; + } + } +} + /** * Class FormatterExtension * diff --git a/core/polyfills.php b/core/polyfills.php index 680879f4..2741e5f9 100644 --- a/core/polyfills.php +++ b/core/polyfills.php @@ -801,4 +801,31 @@ function iterator_map(callable $callback, iterator $iter): Generator function iterator_map_to_array(callable $callback, iterator $iter): array { return iterator_to_array(iterator_map($callback, $iter)); +} + + +function get_class_from_file(string $file): string +{ + $fp = fopen($file, 'r'); + $class = $buffer = ''; + $i = 0; + while (!$class) { + if (feof($fp)) break; + + $buffer .= fread($fp, 512); + $tokens = token_get_all($buffer); + + if (strpos($buffer, '{') === false) continue; + + for (;$iis_live()) { + if (!$extension->is_supported()) { continue; } @@ -93,7 +93,7 @@ function ext_is_live(string $ext_name): bool if (class_exists($ext_name)) { /** @var Extension $ext */ $ext = new $ext_name(); - return $ext->is_live(); + return $ext->is_supported(); } return false; } diff --git a/ext/ext_manager/main.php b/ext/ext_manager/main.php index 39c7f572..2af52b42 100644 --- a/ext/ext_manager/main.php +++ b/ext/ext_manager/main.php @@ -12,12 +12,12 @@ * extensions and read their documentation */ -function __extman_extcmp(ExtensionInfo $a, ExtensionInfo $b): int +function __extman_extcmp(ExtensionManagerInfo $a, ExtensionManagerInfo $b): int { return strcmp($a->name, $b->name); } -class ExtensionInfo +class ExtensionManagerInfo { public $ext_name; public $name; @@ -28,59 +28,88 @@ class ExtensionInfo public $version; public $visibility; public $enabled; + public $supported; public function __construct($main) { $matches = []; - $lines = file($main); - $number_of_lines = count($lines); preg_match("#ext/(.*)/main.php#", $main, $matches); $this->ext_name = $matches[1]; $this->name = $this->ext_name; $this->enabled = $this->is_enabled($this->ext_name); - $this->authors = []; - for ($i = 0; $i < $number_of_lines; $i++) { - $line = $lines[$i]; - if (preg_match("/Name: (.*)/", $line, $matches)) { - $this->name = $matches[1]; - } elseif (preg_match("/Visibility: (.*)/", $line, $matches)) { - $this->visibility = $matches[1]; - } elseif (preg_match("/Link: (.*)/", $line, $matches)) { - $this->link = $matches[1]; - if ($this->link[0] == "/") { - $this->link = make_link(substr($this->link, 1)); - } - } elseif (preg_match("/Version: (.*)/", $line, $matches)) { - $this->version = $matches[1]; - } elseif (preg_match("/Authors?: (.*)/", $line, $matches)) { - $author_list = explode(',', $matches[1]); - foreach ($author_list as $author) { - if (preg_match("/(.*) [<\(](.*@.*)[>\)]/", $author, $matches)) { - $this->authors[] = new ExtensionAuthor($matches[1], $matches[2]); - } else { - $this->authors[] = new ExtensionAuthor($author, null); + if(file_exists("ext/{$this->ext_name}/info.php")) { + include_once "ext/{$this->ext_name}/info.php"; + $class = get_class_from_file("ext/{$this->ext_name}/info.php"); + $info = new $class(); + + $this->name = $info->name; + $this->link = $info->link; + foreach ($info->authors as $key=>$value){ + $this->authors[] = new ExtensionAuthor($key, $value); + } + $this->description = $info->description; + $this->documentation = $info->documentation; + $this->version = $info->version; + $this->visibility = $info->visibility; + $this->supported = $info->supported; + } else { + $this->authors = []; + + $handle = fopen($main, "r"); + if ($handle === null) { + throw new Exception("Could not open extension file $main"); + } + try { + $line = fgets($handle); + + while ($line !== false) { + if (preg_match("/Name: (.*)/", $line, $matches)) { + $this->name = $matches[1]; + } elseif (preg_match("/Visibility: (.*)/", $line, $matches)) { + $this->visibility = $matches[1]; + } elseif (preg_match("/Link: (.*)/", $line, $matches)) { + $this->link = $matches[1]; + if ($this->link[0] == "/") { + $this->link = make_link(substr($this->link, 1)); + } + } elseif (preg_match("/Version: (.*)/", $line, $matches)) { + $this->version = $matches[1]; + } elseif (preg_match("/Authors?: (.*)/", $line, $matches)) { + $author_list = explode(',', $matches[1]); + foreach ($author_list as $author) { + if (preg_match("/(.*) [<\(](.*@.*)[>\)]/", $author, $matches)) { + $this->authors[] = new ExtensionAuthor($matches[1], $matches[2]); + } else { + $this->authors[] = new ExtensionAuthor($author, null); + } + } + } elseif (preg_match("/(.*)Description: ?(.*)/", $line, $matches)) { + $this->description = $matches[2]; + $start = $matches[1] . " "; + $start_len = strlen($start); + while (($line = fgets($handle)) !== false && + substr($line, 0, $start_len) == $start) { + $this->description .= " " . substr($line, $start_len); + } + continue; + } elseif (preg_match("/(.*)Documentation: ?(.*)/", $line, $matches)) { + $this->documentation = $matches[2]; + $start = $matches[1] . " "; + $start_len = strlen($start); + while (($line = fgets($handle)) !== false && + substr($line, 0, $start_len) == $start) { + $this->documentation .= " " . substr($line, $start_len); + } + $this->documentation = str_replace('$site', make_http(get_base_href()), $this->documentation); + continue; + } elseif (preg_match("/\*\//", $line, $matches)) { + break; } + $line = fgets($handle); } - } elseif (preg_match("/(.*)Description: ?(.*)/", $line, $matches)) { - $this->description = $matches[2]; - $start = $matches[1] . " "; - $start_len = strlen($start); - while (substr($lines[$i + 1], 0, $start_len) == $start) { - $this->description .= " " . substr($lines[$i + 1], $start_len); - $i++; - } - } elseif (preg_match("/(.*)Documentation: ?(.*)/", $line, $matches)) { - $this->documentation = $matches[2]; - $start = $matches[1] . " "; - $start_len = strlen($start); - while (substr($lines[$i + 1], 0, $start_len) == $start) { - $this->documentation .= " " . substr($lines[$i + 1], $start_len); - $i++; - } - $this->documentation = str_replace('$site', make_http(get_base_href()), $this->documentation); - } elseif (preg_match("/\*\//", $line, $matches)) { - break; + } finally { + fclose($handle); } } } @@ -142,8 +171,8 @@ class ExtManager extends Extension if ($event->page_matches("ext_doc")) { $ext = $event->get_arg(0); - if (file_exists("ext/$ext/main.php")) { - $info = new ExtensionInfo("ext/$ext/main.php"); + if (file_exists("ext/$ext/info.php")) { + $info = new ExtensionManagerInfo("ext/$ext/main.php"); $this->theme->display_doc($page, $info); } else { $this->theme->display_table($page, $this->get_extensions(false), false); @@ -196,7 +225,7 @@ class ExtManager extends Extension $exts = zglob("ext/{" . ENABLED_EXTS . "}/main.php"); } foreach ($exts as $main) { - $extensions[] = new ExtensionInfo($main); + $extensions[] = new ExtensionManagerInfo($main); } usort($extensions, "__extman_extcmp"); return $extensions; diff --git a/ext/ext_manager/theme.php b/ext/ext_manager/theme.php index 9a326ffc..fcf8b64a 100644 --- a/ext/ext_manager/theme.php +++ b/ext/ext_manager/theme.php @@ -29,8 +29,13 @@ class ExtManagerTheme extends Themelet $h_name = html_escape(empty($extension->name) ? $extension->ext_name : $extension->name); $h_description = html_escape($extension->description); $h_link = make_link("ext_doc/" . url_escape($extension->ext_name)); - $h_enabled = ($extension->enabled === true ? " checked='checked'" : ($extension->enabled === false ? "" : " disabled checked='checked'")); - $h_enabled_box = $editable ? "" : ""; + + $h_enabled = ($extension->enabled === true ? " checked='checked'" : ($extension->enabled === false ? "" : " checked='checked'")); + $h_disabled = ($extension->supported===false || $extension->enabled===null? " disabled ": " " ); + + //baseline_open_in_new_black_18dp.png + + $h_enabled_box = $editable ? "" : ""; $h_docs = ($extension->documentation ? "" : ""); //TODO: A proper "docs" symbol would be preferred here. $html .= " @@ -38,7 +43,7 @@ class ExtManagerTheme extends Themelet {$h_enabled_box} {$h_docs} - {$h_description} + {$h_description} " .($extension->supported===false ? "Database not supported" : ""). " "; } $h_set = $editable ? "" : ""; @@ -113,7 +118,7 @@ class ExtManagerTheme extends Themelet } */ - public function display_doc(Page $page, ExtensionInfo $info) + public function display_doc(Page $page, ExtensionManagerInfo $info) { $author = ""; if (count($info->authors) > 0) { diff --git a/ext/tips/info.php b/ext/tips/info.php new file mode 100644 index 00000000..0379c8ba --- /dev/null +++ b/ext/tips/info.php @@ -0,0 +1,22 @@ + + * License: GPLv2 + * Description: Show a random line of text in the subheader space + * Documentation: + * Formatting is done with HTML + */ + + +class TipsInfo extends ExtensionInfo +{ + public $key = "tips"; + public $name = "Random Tip"; + public $authors = ["Sein Kraft"=>"mail@seinkraft.info"]; + public $license = "GPLv2"; + public $description = "Show a random line of text in the subheader space"; + public $documentation = "Formatting is done with HTML"; + public $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::SQLITE]; +} \ No newline at end of file diff --git a/ext/tips/main.php b/ext/tips/main.php index 60564028..b8980829 100644 --- a/ext/tips/main.php +++ b/ext/tips/main.php @@ -1,12 +1,4 @@ - * License: GPLv2 - * Description: Show a random line of text in the subheader space - * Documentation: - * Formatting is done with HTML - */ class Tips extends Extension { diff --git a/themes/danbooru2/ext_manager.theme.php b/themes/danbooru2/ext_manager.theme.php index 247406c8..270ec929 100644 --- a/themes/danbooru2/ext_manager.theme.php +++ b/themes/danbooru2/ext_manager.theme.php @@ -8,7 +8,7 @@ class CustomExtManagerTheme extends ExtManagerTheme parent::display_table($page, $extensions, $editable); } - public function display_doc(Page $page, ExtensionInfo $info) + public function display_doc(Page $page, ExtensionManagerInfo $info) { $page->disable_left(); parent::display_doc($page, $info);