269 lines
7.0 KiB
PHP
269 lines
7.0 KiB
PHP
<?php
|
|
namespace Crispage\DevSuite;
|
|
|
|
defined("ROOT") or die();
|
|
|
|
require_once ROOT . "/cds/IniWriter.php";
|
|
require_once ROOT . "/cds/CDSPackager.php";
|
|
|
|
use \Crispage\ApplicationConfig;
|
|
use \Crispage\Request\Route;
|
|
use \Crispage\Signaling\Receiver;
|
|
use \Crispage\Extensions\Extension;
|
|
use \Crispage\Assets\Plugin;
|
|
|
|
class DevSuite {
|
|
public const EXT_CLASS_MAP = [
|
|
"asset" => "\\Crispage\\Framework\\Asset",
|
|
"action" => "\\Crispage\\Framework\\Action",
|
|
"component" => "\\Crispage\\Framework\\Component",
|
|
"plugin" => "\\Crispage\\Framework\\PluginClass",
|
|
"modulecomponent" => "\\Crispage\\Framework\\ModuleComponent"
|
|
];
|
|
|
|
public static function nicePrint(mixed $obj): string {
|
|
if (is_object($obj))
|
|
return "{" . $obj::class . "}";
|
|
if (is_array($obj))
|
|
return "[" . count($obj) . "]";
|
|
if (is_string($obj)) return "\"$obj\"";
|
|
return @strval($obj);
|
|
}
|
|
|
|
public \Crispage $app;
|
|
public CDSPackager $packager;
|
|
private array $logs;
|
|
private string $logprefix = "";
|
|
private bool $print_enabled = true;
|
|
|
|
public function __construct(\Crispage $app) {
|
|
$this->app = $app;
|
|
@$this->app->cds = $this;
|
|
$this->packager = new CDSPackager($this);
|
|
}
|
|
|
|
public function getLogPrefix(): ?string {
|
|
return $this->logprefix;
|
|
}
|
|
|
|
public function setLogPrefix(string $prefix) {
|
|
$this->logprefix = $prefix;
|
|
}
|
|
|
|
public function clearLogPrefix(): void {
|
|
$this->logprefix = "";
|
|
}
|
|
|
|
public function disableLogPrint(): void {
|
|
$this->print_enabled = false;
|
|
}
|
|
|
|
public function log(string $msg, ?string $tag = null): float {
|
|
$time = microtime(true);
|
|
if ($tag) $this->setLogPrefix("[$tag] ");
|
|
$fmsg = $this->logprefix . preg_replace("/\\n/", "\n\t", $msg);
|
|
$this->logs[] = [$fmsg, $time];
|
|
return $time;
|
|
}
|
|
|
|
public function logEvent(...$args): float {
|
|
$event = $this->app->dispatcher->event();
|
|
$ev = $this->app->dispatcher->getValue()->current();
|
|
if ($ev) $this->app->dispatcher->pushValue($ev);
|
|
$args = array_map([$this, "nicePrint"], $args);
|
|
return $this->log("$event(" . implode(", ", $args) . "): " . self::nicePrint($ev), "Event");
|
|
}
|
|
|
|
public function printLogs(): void {
|
|
if (!$this->print_enabled) return;
|
|
$this->app->dispatcher->suppress();
|
|
@ob_end_flush();
|
|
echo "<pre class=\"cds_log\">";
|
|
foreach ($this->logs as $log)
|
|
printf("[%.6f] %s\n", $log[1] - START_TIME, $log[0]);
|
|
echo "</pre>";
|
|
}
|
|
|
|
public function init(): void {
|
|
$this->app->dispatcher->register(new Receiver(
|
|
"crispage.devsuite.log_receiver",
|
|
"", -127, [$this, "logEvent"]
|
|
));
|
|
|
|
register_shutdown_function([$this, "printLogs"]);
|
|
|
|
$this->app->router->registerHardRoute(new Route(
|
|
"cds_console", "\\Crispage\\DevSuite\\ConsoleAction",
|
|
[]
|
|
), "backend");
|
|
|
|
$this->app->router->registerHardRoute(new Route(
|
|
"cds_classmanager", "\\Crispage\\DevSuite\\ClassManagerAction",
|
|
[]
|
|
), "backend");
|
|
|
|
$this->app->router->registerHardRoute(new Route(
|
|
"cds_packager", "\\Crispage\\DevSuite\\PackagerAction",
|
|
[]
|
|
), "backend");
|
|
|
|
$this->app->page->data["styles"]["cds"] = [
|
|
"_inner" => file_get_contents(ROOT . "/cds/static/assets/cds.css")
|
|
];
|
|
|
|
$this->log("CDS Initialized");
|
|
}
|
|
|
|
public function runScript(string $script): string {
|
|
$this->log("Running script", "Console");
|
|
|
|
$output = "";
|
|
ob_start();
|
|
|
|
try {
|
|
$start = microtime(true);
|
|
$res = eval($script);
|
|
$end = microtime(true);
|
|
}
|
|
catch (\Throwable $e) {
|
|
$err = $e;
|
|
}
|
|
|
|
$output .= ob_get_clean();
|
|
|
|
if (isset($err)) {
|
|
$this->log("ERROR: $err");
|
|
$output .= "\n== Script error ==\n$err";
|
|
}
|
|
else {
|
|
$ms = sprintf("%.3f", ($end - $start) * 1000);
|
|
$rval = print_r($res ?? "[nothing returned]", true);
|
|
|
|
$this->log("Executed in $ms ms");
|
|
$this->log("Return value: $rval");
|
|
$output .= "\n== Script executed in $ms ms ==\nReturn value:\n$rval";
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
|
|
public function getExtensions(): array {
|
|
$res = $this->app->database->select(
|
|
"extensions", ["id"]
|
|
);
|
|
|
|
$exts = [];
|
|
foreach ($res->fetchAll(\PDO::FETCH_COLUMN) as $id) {
|
|
$ext = $this->app->extensions->get($id);
|
|
if ($ext) $exts[] = $ext;
|
|
}
|
|
return $exts;
|
|
}
|
|
|
|
public function registerExtension(string $classname, string $type): ?Extension {
|
|
$info = ApplicationConfig::get("cds.default_info");
|
|
|
|
$this->log("Registering $classname as $type...", "Extension");
|
|
|
|
switch ($type) {
|
|
case "asset":
|
|
case "action":
|
|
case "component":
|
|
case "plugin": {
|
|
try {
|
|
$this->app->loadClass($classname, self::EXT_CLASS_MAP[$type]);
|
|
}
|
|
catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
|
|
$info = $classname::getExtensionInfo();
|
|
if (is_a($classname, self::EXT_CLASS_MAP["modulecomponent"], true))
|
|
$info["is_module"] = true;
|
|
|
|
break;
|
|
}
|
|
case "template": {
|
|
foreach (Config::TEMPLATE_PATH as $tp) {
|
|
$path = ROOT . "$tp/$classname/template.ini";
|
|
if (file_exists($path)) break;
|
|
}
|
|
|
|
|
|
$ini = parse_ini_file($path, true, INI_SCANNER_TYPED);
|
|
$info = array_merge($info, $ini["ExtensionInfo"] ?? []);
|
|
|
|
break;
|
|
}
|
|
case "translation": {
|
|
foreach (Config::TRANSLATION_PATH as $tp) {
|
|
$path = ROOT . "$tp/$classname/translations.ini";
|
|
if (file_exists($path)) break;
|
|
}
|
|
|
|
$ini = parse_ini_file($path, true, INI_SCANNER_TYPED);
|
|
$info = array_merge($info, $ini["ExtensionInfo"] ?? []);
|
|
|
|
break;
|
|
}
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
$id = $info["id"];
|
|
$version = $info["version"] ?? VERSION;
|
|
$package = $info["package"] ?? explode(".", $id)[0] ?? "";
|
|
$data = array_diff_key($info, ApplicationConfig::get("cds.default_info"));
|
|
|
|
$ext = new Extension($id, $version, $package, $classname, $type, $data);
|
|
|
|
$this->app->extensions->register($ext);
|
|
|
|
$this->log("Success");
|
|
return $ext;
|
|
}
|
|
|
|
public function unregisterExtensions(array $ids): int {
|
|
$count = 0;
|
|
foreach ($ids as $id) {
|
|
$this->log("Unregistering $id...", "Extension");
|
|
$ext = $this->app->extensions->get($id);
|
|
if ($ext) {
|
|
$this->app->extensions->unregister($ext);
|
|
$count++;
|
|
}
|
|
}
|
|
$this->log("Unregistered $count extensions");
|
|
return $count;
|
|
}
|
|
|
|
public function createPlugin(string $extid, int $priority = 0): ?Plugin {
|
|
$ext = $this->app->extensions->get($extid);
|
|
if (!$ext || $ext->type != "plugin") return null;
|
|
$plugin = $this->app->assets->create(
|
|
"\\Crispage\\Assets\\Plugin", [
|
|
"slug" => preg_replace("/\\./", "__", $ext->id),
|
|
"classname" => $ext->classname,
|
|
"priority" => $priority
|
|
]
|
|
);
|
|
$this->log("Created plugin $extid", "Extension");
|
|
return $plugin;
|
|
}
|
|
|
|
public function deletePlugin(string $extid): void {
|
|
$ext = $this->app->extensions->get($extid);
|
|
if (!$ext || $ext->type != "plugin") return;
|
|
$plugins = $this->app->assets->getAllFiltered(
|
|
"\\Crispage\\Assets\\Plugin",
|
|
["classname" => $ext->classname]
|
|
);
|
|
foreach ($plugins as $plugin) {
|
|
if ($plugin->slug == "devsuite") continue;
|
|
$this->app->assets->delete($plugin);
|
|
}
|
|
$this->log("Deleted plugin $extid", "Extension");
|
|
}
|
|
}
|
|
?>
|