forked from Cavemanon/cavepaintings
Merge pull request #680 from sanmadjack/ext_info
Proposed extension info change to allow getting info for unloaded ext…
This commit is contained in:
@@ -22,11 +22,11 @@ $tracer_enabled = constant('TRACE_FILE')!==null;
|
||||
|
||||
// load base files
|
||||
$_tracer->begin("Bootstrap");
|
||||
$_tracer->begin("Opening files");
|
||||
$_tracer->begin("Opening core files");
|
||||
$_shm_files = array_merge(
|
||||
zglob("core/*.php"),
|
||||
zglob("core/{".ENABLED_MODS."}/*.php"),
|
||||
zglob("ext/{".ENABLED_EXTS."}/main.php")
|
||||
zglob("ext/*/info.php")
|
||||
);
|
||||
foreach ($_shm_files as $_shm_filename) {
|
||||
if (basename($_shm_filename)[0] != "_") {
|
||||
@@ -37,6 +37,22 @@ unset($_shm_files);
|
||||
unset($_shm_filename);
|
||||
$_tracer->end();
|
||||
|
||||
$_tracer->begin("Loading extension info");
|
||||
ExtensionInfo::load_all_extension_info();
|
||||
Extension::determine_enabled_extensions();
|
||||
$_tracer->end();
|
||||
|
||||
$_tracer->begin("Opening enabled extension files");
|
||||
$_shm_files = zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/main.php");
|
||||
foreach ($_shm_files as $_shm_filename) {
|
||||
if (basename($_shm_filename)[0] != "_") {
|
||||
require_once $_shm_filename;
|
||||
}
|
||||
}
|
||||
unset($_shm_files);
|
||||
unset($_shm_filename);
|
||||
$_tracer->end();
|
||||
|
||||
// connect to the database
|
||||
$_tracer->begin("Connecting to DB");
|
||||
$database = new Database();
|
||||
@@ -52,8 +68,7 @@ unset($themelet);
|
||||
$page = class_exists("CustomPage") ? new CustomPage() : new Page();
|
||||
$_tracer->end();
|
||||
|
||||
// hook up event handlers
|
||||
$_tracer->begin("Loading extensions");
|
||||
$_tracer->begin("Loading extensions/event listeners");
|
||||
_load_event_listeners();
|
||||
$_tracer->end();
|
||||
|
||||
|
@@ -83,24 +83,24 @@
|
||||
*/
|
||||
abstract class Extension
|
||||
{
|
||||
/** @var array which DBs this ext supports (blank for 'all') */
|
||||
protected $db_support = [];
|
||||
public $key;
|
||||
|
||||
/** @var Themelet this theme's Themelet object */
|
||||
public $theme;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->theme = $this->get_theme_object(get_called_class());
|
||||
}
|
||||
public $info;
|
||||
|
||||
public function is_live(): bool
|
||||
private static $enabled_extensions = [];
|
||||
|
||||
public function __construct($class = null)
|
||||
{
|
||||
global $database;
|
||||
return (
|
||||
empty($this->db_support) ||
|
||||
in_array($database->get_driver_name(), $this->db_support)
|
||||
);
|
||||
$class = $class ?? get_called_class();
|
||||
$this->theme = $this->get_theme_object($class);
|
||||
$this->info = ExtensionInfo::get_for_extension_class($class);
|
||||
if($this->info===null) {
|
||||
throw new Exception("Info class not found for extension $class");
|
||||
}
|
||||
$this->key = $this->info->key;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,6 +128,193 @@ abstract class Extension
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
public static function determine_enabled_extensions()
|
||||
{
|
||||
self::$enabled_extensions = [];
|
||||
foreach(array_merge(ExtensionInfo::get_core_extensions(),
|
||||
explode(",", EXTRA_EXTS)) as $key) {
|
||||
$ext = ExtensionInfo::get_by_key($key);
|
||||
if($ext===null) {
|
||||
continue;
|
||||
}
|
||||
self::$enabled_extensions[] = $ext->key;
|
||||
if(!empty($ext->dependencies)) {
|
||||
foreach ($ext->dependencies as $dep) {
|
||||
self::$enabled_extensions[] = $dep;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function is_enabled(string $key): ?bool
|
||||
{
|
||||
return in_array($key, self::$enabled_extensions);
|
||||
}
|
||||
|
||||
public static function get_enabled_extensions(): array
|
||||
{
|
||||
return self::$enabled_extensions;
|
||||
}
|
||||
public static function get_enabled_extensions_as_string(): string
|
||||
{
|
||||
return implode(",",self::$enabled_extensions);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ExtensionInfo
|
||||
{
|
||||
// Every credit you get costs us RAM. It stops now.
|
||||
public const SHISH_NAME = "Shish";
|
||||
public const SHISH_EMAIL = "webmaster@shishnet.org";
|
||||
public const SHIMMIE_URL = "http://code.shishnet.org/shimmie2/";
|
||||
public const SHISH_AUTHOR = [self::SHISH_NAME=>self::SHISH_EMAIL];
|
||||
|
||||
public const LICENSE_GPLV2 = "GPLv2";
|
||||
public const LICENSE_MIT = "MIT";
|
||||
public const LICENSE_WTFPL = "WTFPL";
|
||||
|
||||
public const VISIBLE_ADMIN = "admin";
|
||||
public const VISIBLE_HIDDEN = "hidden";
|
||||
private const VALID_VISIBILITY = [self::VISIBLE_ADMIN, self::VISIBLE_HIDDEN];
|
||||
|
||||
public $key;
|
||||
|
||||
public $core = false;
|
||||
|
||||
public $beta = false;
|
||||
|
||||
public $name;
|
||||
public $authors = [];
|
||||
public $link;
|
||||
public $license;
|
||||
public $version;
|
||||
public $dependencies = [];
|
||||
public $visibility;
|
||||
public $description;
|
||||
public $documentation;
|
||||
|
||||
/** @var array which DBs this ext supports (blank for 'all') */
|
||||
public $db_support = [];
|
||||
|
||||
private $supported = null;
|
||||
private $support_info = null;
|
||||
|
||||
public function is_supported(): bool
|
||||
{
|
||||
if($this->supported===null) {
|
||||
$this->check_support();
|
||||
}
|
||||
return $this->supported;
|
||||
}
|
||||
|
||||
public function get_support_info(): string
|
||||
{
|
||||
if($this->supported===null) {
|
||||
$this->check_support();
|
||||
}
|
||||
return $this->support_info;
|
||||
}
|
||||
|
||||
private static $all_info_by_key = [];
|
||||
private static $all_info_by_class = [];
|
||||
private static $core_extensions = [];
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
if(empty($this->key)) {
|
||||
throw new Exception("key field is required");
|
||||
}
|
||||
if(empty($this->name)) {
|
||||
throw new Exception("name field is required for extension $this->key");
|
||||
}
|
||||
if(!empty($this->visibility)&&!in_array($this->visibility, self::VALID_VISIBILITY)) {
|
||||
throw new Exception("Invalid visibility for extension $this->key");
|
||||
}
|
||||
if(!is_array($this->db_support)) {
|
||||
throw new Exception("db_support has to be an array for extension $this->key");
|
||||
}
|
||||
if(!is_array($this->authors)) {
|
||||
throw new Exception("authors has to be an array for extension $this->key");
|
||||
}
|
||||
if(!is_array($this->dependencies)) {
|
||||
throw new Exception("dependencies has to be an array for extension $this->key");
|
||||
}
|
||||
}
|
||||
|
||||
public function is_enabled(): bool
|
||||
{
|
||||
return Extension::is_enabled($this->key);
|
||||
}
|
||||
|
||||
private function check_support()
|
||||
{
|
||||
global $database;
|
||||
$this->support_info = "";
|
||||
if(!empty($this->db_support)&&!in_array($database->get_driver_name(), $this->db_support)) {
|
||||
$this->support_info .= "Database not supported. ";
|
||||
}
|
||||
// Additional checks here as needed
|
||||
|
||||
$this->supported = empty($this->support_info);
|
||||
}
|
||||
|
||||
public static function get_all(): array
|
||||
{
|
||||
return array_values(self::$all_info_by_key);
|
||||
}
|
||||
|
||||
public static function get_all_keys(): array
|
||||
{
|
||||
return array_keys(self::$all_info_by_key);
|
||||
}
|
||||
|
||||
public static function get_core_extensions(): array
|
||||
{
|
||||
return self::$core_extensions;
|
||||
}
|
||||
|
||||
public static function get_by_key(string $key): ?ExtensionInfo
|
||||
{
|
||||
if(array_key_exists($key, self::$all_info_by_key)) {
|
||||
return self::$all_info_by_key[$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function get_for_extension_class(string $base): ?ExtensionInfo
|
||||
{
|
||||
$normal = $base.'Info';
|
||||
|
||||
if (array_key_exists($normal, self::$all_info_by_class)) {
|
||||
return self::$all_info_by_class[$normal];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function load_all_extension_info()
|
||||
{
|
||||
|
||||
foreach (get_declared_classes() as $class) {
|
||||
$rclass = new ReflectionClass($class);
|
||||
if ($rclass->isAbstract()) {
|
||||
// don't do anything
|
||||
} elseif (is_subclass_of($class, "ExtensionInfo")) {
|
||||
$extension_info = new $class();
|
||||
if(array_key_exists($extension_info->key, self::$all_info_by_key)) {
|
||||
throw new Exception("Extension Info $class with key $extension_info->key has already been loaded");
|
||||
}
|
||||
|
||||
self::$all_info_by_key[$extension_info->key] = $extension_info;
|
||||
self::$all_info_by_class[$class] = $extension_info;
|
||||
if($extension_info->core===true) {
|
||||
self::$core_extensions[] = $extension_info->key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -468,7 +468,7 @@ class Page
|
||||
/*** Generate CSS cache files ***/
|
||||
$css_latest = $config_latest;
|
||||
$css_files = array_merge(
|
||||
zglob("ext/{" . ENABLED_EXTS . "}/style.css"),
|
||||
zglob("ext/{" . Extension::get_enabled_extensions_as_string() . "}/style.css"),
|
||||
zglob("themes/$theme_name/style.css")
|
||||
);
|
||||
foreach ($css_files as $css) {
|
||||
@@ -499,7 +499,7 @@ class Page
|
||||
"vendor/bower-asset/js-cookie/src/js.cookie.js",
|
||||
"ext/handle_static/modernizr-3.3.1.custom.js",
|
||||
],
|
||||
zglob("ext/{" . ENABLED_EXTS . "}/script.js"),
|
||||
zglob("ext/{" . Extension::get_enabled_extensions_as_string() . "}/script.js"),
|
||||
zglob("themes/$theme_name/script.js")
|
||||
);
|
||||
foreach ($js_files as $js) {
|
||||
|
@@ -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 (;$i<count($tokens);$i++) {
|
||||
if ($tokens[$i][0] === T_CLASS) {
|
||||
for ($j=$i+1;$j<count($tokens);$j++) {
|
||||
if ($tokens[$j] === '{') {
|
||||
$class = $tokens[$i+2][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $class;
|
||||
}
|
@@ -44,7 +44,7 @@ function _set_event_listeners(): void
|
||||
$extension = new $class();
|
||||
|
||||
// skip extensions which don't support our current database
|
||||
if (!$extension->is_live()) {
|
||||
if (!$extension->info->is_supported()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -88,16 +88,6 @@ function _dump_event_listeners(array $event_listeners, string $path): void
|
||||
file_put_contents($path, $p);
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
|
||||
/** @private */
|
||||
global $_shm_event_count;
|
||||
@@ -109,7 +99,7 @@ $_shm_event_count = 0;
|
||||
function send_event(Event $event): void
|
||||
{
|
||||
global $tracer_enabled;
|
||||
|
||||
|
||||
global $_shm_event_listeners, $_shm_event_count, $_tracer;
|
||||
if (!isset($_shm_event_listeners[get_class($event)])) {
|
||||
return;
|
||||
|
@@ -40,7 +40,6 @@ _d("SEARCH_ACCEL", false); // boolean use search accelerator
|
||||
_d("WH_SPLITS", 1); // int how many levels of subfolders to put in the warehouse
|
||||
_d("VERSION", '2.7-beta'); // string shimmie version
|
||||
_d("TIMEZONE", null); // string timezone
|
||||
_d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,setup,upgrade,handle_404,handle_static,comment,tag_list,index,tag_edit,alias_editor,media,help_pages,system"); // extensions to always enable
|
||||
_d("EXTRA_EXTS", ""); // string optional extra extensions
|
||||
_d("BASE_URL", null); // string force a specific base URL (default is auto-detect)
|
||||
_d("MIN_PHP_VERSION", '7.1');// string minimum supported PHP version
|
||||
@@ -53,4 +52,3 @@ _d("ENABLED_MODS", "imageboard");
|
||||
* directly, only the things they're built from
|
||||
*/
|
||||
_d("SCORE_VERSION", 'develop/'.VERSION); // string SCore version
|
||||
_d("ENABLED_EXTS", CORE_EXTS.",".EXTRA_EXTS);
|
||||
|
@@ -454,8 +454,8 @@ function _get_themelet_files(string $_theme): array
|
||||
$base_themelets[] = 'themes/'.$_theme.'/layout.class.php';
|
||||
$base_themelets[] = 'themes/'.$_theme.'/themelet.class.php';
|
||||
|
||||
$ext_themelets = zglob("ext/{".ENABLED_EXTS."}/theme.php");
|
||||
$custom_themelets = zglob('themes/'.$_theme.'/{'.ENABLED_EXTS.'}.theme.php');
|
||||
$ext_themelets = zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/theme.php");
|
||||
$custom_themelets = zglob('themes/'.$_theme.'/{'.Extension::get_enabled_extensions_as_string().'}.theme.php');
|
||||
|
||||
return array_merge($base_themelets, $ext_themelets, $custom_themelets);
|
||||
}
|
||||
|
Reference in New Issue
Block a user