diff --git a/lib/zin/core/command.class.php b/lib/zin/core/command.class.php new file mode 100644 index 0000000000..4fa1ca75f9 --- /dev/null +++ b/lib/zin/core/command.class.php @@ -0,0 +1,52 @@ + + * @package zin + * @version $Id + * @link https://www.zentao.net + */ + +namespace zin; + +require_once __DIR__ . DS . 'helper.func.php'; + +/** + * The command class. + */ +class command +{ + public static function addClass(node $node, array $args) + { + $node->props->class->add(...$args); + } + + public static function removeClass(node $node, array $args) + { + + } + + public static function remove(node $node) + { + $node->removed = true; + } + + /** + * Magic static method for setting property value. + * + * @access public + * @param string $name - Property name. + * @param array $args - Property values. + * @return setting + */ + public static function __callStatic($name, $args) + { + if(isDebug()) + { + triggerError('Command not found: ' . $name); + } + } +} diff --git a/lib/zin/core/context.class.php b/lib/zin/core/context.class.php index 5242e49f66..a0b9fe3328 100644 --- a/lib/zin/core/context.class.php +++ b/lib/zin/core/context.class.php @@ -19,6 +19,7 @@ require_once dirname(__DIR__) . DS . 'utils' . DS . 'flat.func.php'; require_once dirname(__DIR__) . DS . 'utils' . DS . 'deep.func.php'; require_once __DIR__ . DS . 'helper.func.php'; require_once __DIR__ . DS . 'render.class.php'; +require_once __DIR__ . DS . 'command.class.php'; require_once __DIR__ . DS . 'js.class.php'; class context extends \zin\utils\dataset @@ -45,6 +46,10 @@ class context extends \zin\utils\dataset public array $onRenderCallbacks = array(); + public array $queries = array(); + + public ?node $rootNode = null; + public ?render $renderer = null; public function __construct(string $name) @@ -243,17 +248,44 @@ class context extends \zin\utils\dataset return $rawContent; } + public function addQuery(query $query) + { + $this->queries[] = $query; + } + + /** + * Include hooks files. + */ + public function includeHooks(): string + { + $hookFiles = $this->getHookFiles(); + ob_start(); + foreach($hookFiles as $hookFile) + { + if(!empty($hookFile) && file_exists($hookFile)) include $hookFile; + } + $hookCode = ob_get_clean(); + if(!$hookCode) return $hookCode; + return ''; + } + + public function render(node $node, null|object|string|array $selectors = null, string $renderType = 'html', null|string|array $dataCommands = null, bool $renderInner = false): string|array|object { $renderer = new render($node, $selectors, $renderType, $dataCommands, $renderInner); $this->rendered = true; $this->renderer = $renderer; + $this->rootNode = $node; + $hookHtml = $this->includeHooks(); $rawContent = $this->getRawContent(); $zinDebug = $this->getDebugData(); - $result = $renderer->render(); - $js = $this->getJS(); - $css = $this->getCSS(); + + $node->prebuild(true); + + $js = $this->getJS(); + $css = $this->getCSS(); + $result = $renderer->render(); if(is_object($result)) // renderType = json { @@ -297,12 +329,25 @@ class context extends \zin\utils\dataset return $data->output; } - public function handleBeforeBuildNode($node) + public function handleBeforeBuildNode(node $node) { foreach($this->beforeBuildNodeCallbacks as $callback) { call_user_func($callback, $node); } + + if($this->queries) + { + foreach($this->queries as $query) + { + if(!$node->is($query->selectors) || !$query->commands) continue; + foreach($query->commands as $command) + { + list($method, $args) = $command; + call_user_func("\zin\command::{$method}", $node, $args, $this->rootNode); + } + } + } } public function handleBuildNode(stdClass &$data, node $node) diff --git a/lib/zin/core/hook.class.php b/lib/zin/core/hook.class.php deleted file mode 100644 index eef5498b23..0000000000 --- a/lib/zin/core/hook.class.php +++ /dev/null @@ -1,271 +0,0 @@ - - * @package zin - * @version $Id - * @link https://www.zentao.net - */ - -namespace zin; - -require_once __DIR__ . DS . 'wg.class.php'; -require_once __DIR__ . DS . 'selector.func.php'; - -/** - * The hook class. - */ -class hook -{ - /** The global root widget. */ - public static node $globalRoot; - - /** The root widget. */ - public node $root; - - /** The selectors object. */ - public object|null $selectors; - - /** - * The items list. - * - * @var node[] - */ - public array $items; - - /** - * Construct the select object. - * - * @param array|string|node $selector - * @param node|null $root - * @access public - */ - public function __construct(array|string|node $selector = '', node|null $root = null) - { - $this->root = empty($root) ? static::$globalRoot : $root; - $this->selectors = null; - $this->items = array(); - - if(is_string($selector)) - { - $this->selectors = parseWgSelector($selector); - $this->items = $this->root->find($this->selectors); - } - elseif(is_object($selector)) - { - $this->items = array($selector); - } - elseif(is_array($selector)) - { - $this->items = $selector; - } - } - - /** - * Get item by index. - * - * @param int $index - * @access public - * @return node|null - */ - public function get(int $index = 0): node | null - { - return isset($this->items[$index]) ? $this->items[$index] : null; - } - - /** - * Select items by selector. - * - * @param string $selector - * @access public - * @return array - */ - public function select(string $selector): array - { - $list = array(); - foreach($this->items as $item) $list = array_merge($list, $item->find($selector)); - return $list; - } - - /** - * Get items count. - * - * @access public - * @return int - */ - public function count(): int - { - return count($this->items); - } - - /** - * Find items in widget. - * - * @access public - * @return hook - */ - public function find(string $selector): hook - { - if(empty($selector)) return $this; - - return new select($this->select($selector), $this->root); - } - - /** - * Get the first item. - * - * @param string $selector - * @access public - * @return hook - */ - public function first(string $selector = ''): hook - { - if(empty($selector)) return new hook(reset($this->items), $this->root); - return $this->find($selector)->first(); - } - - /** - * Get the last item. - * - * @param string $selector - * @access public - * @return hook - */ - public function last(string $selector = ''): hook - { - if(empty($selector)) return new hook(end($this->items), $this->root); - return $this->find($selector)->last(); - } - - /** - * Check if the element is match any of the selectors. - * - * @param string|array|object $selectors - * @access public - * @return bool - */ - public function is(string|array|object $selectors): bool - { - $selectors = parseWgSelectors($selectors); - foreach($this->items as $item) - { - if($item->is($selectors)) return true; - } - return false; - } - - /** - * Mark widget been removed. - * - * @param string $selector - * @access public - * @return hook - */ - public function remove(string $selector = ''): hook - { - if(empty($selector)) - { - foreach($this->items as $item) $item->removed = true; - } - else - { - $this->find($selector)->remove(); - } - return $this; - } - - /** - * Append contents to parent. - * - * @param node|array|string ...$item - * @access public - * @return hook - */ - public function append(/* node|array|string ...$item */): hook - { - $newItems = func_get_args(); - foreach($this->items as $item) $item->add($newItems); - return $this; - } - - /** - * Set widget classNames. - * - * @param node|array|string ...$item - * @access public - * @return hook - */ - public function setClass(/* string|array ...$className */): hook - { - return $this->append(setClass(func_get_args())); - } - - /** - * Set widget style. - * - * @param string|array $name - * @param string|null $value - * @access public - */ - public function setStyle(array|string $name, ?string $value = null): hook - { - return $this->append(setStyle($name, $value)); - } - - /** - * Set widget property. - * - * @param string|array|props|null $name - * @param mixed $value - * @access public - */ - public function setProp(props|array|string $prop, mixed $value = null): hook - { - foreach($this->items as $item) $item->setProp($prop, $value); - return $this; - } - - /** - * Remove prop from widget. - * - * @param string $prop - * @access public - * @return hook - */ - public function removeProp(string $prop): hook - { - foreach($this->items as $item) $item->props->remove($prop); - return $this; - } - - /** - * Debug info. - * - * @access public - * @return array - */ - public function __debugInfo(): array - { - return array( - 'gid' => $this->root->gid, - 'type' => $this->root->fullType(), - 'count' => $this->count(), - 'selectors' => $this->selectors, - 'items' => $this->items - ); - } -} - -/** - * Create a hook object. - * - * @param array|string|object $selectors - * @param node|null $root - */ -function hook($selectors = '', $root = null): hook -{ - return new hook($selectors, $root); -} diff --git a/lib/zin/core/query.class.php b/lib/zin/core/query.class.php new file mode 100644 index 0000000000..f13e888b5f --- /dev/null +++ b/lib/zin/core/query.class.php @@ -0,0 +1,85 @@ + + * @package zin + * @version $Id + * @link https://www.zentao.net + */ + +namespace zin; + +require_once __DIR__ . DS . 'wg.class.php'; +require_once __DIR__ . DS . 'selector.func.php'; +require_once __DIR__ . DS . 'query.class.php'; + +/** + * The query class. + */ +class query +{ + /** + * The selector object list. + */ + public array $selectors; + + /** + * The command list. + */ + public array $commands = array(); + + /** + * Construct the query instance. + * + * @param object|string|array - $selectors + * @access public + */ + public function __construct(object|string|array $selectors) + { + $this->selectors = parseSelectors($selectors); + context::current()->addQuery($this); + } + + /** + * Magic method for adding commands. + * + * @access public + * @param string $name - Property name. + * @param array $args - Property values. + * @return query + */ + public function __call(string $name, array $args): query + { + $this->commands[] = array($name, $args); + return $this; + } + + /** + * Debug info. + * + * @access public + * @return array + */ + public function __debugInfo(): array + { + return array + ( + 'selectors' => $this->selectors, + 'commands' => $this->commands + ); + } +} + +/** + * Create a query object. + * + * @param object|string|array $selectors + * @return query + */ +function query(object|string|array $selectors): query +{ + return new query($selectors); +} diff --git a/lib/zin/core/render.class.php b/lib/zin/core/render.class.php index 887a4c3ca0..8631493a1a 100644 --- a/lib/zin/core/render.class.php +++ b/lib/zin/core/render.class.php @@ -68,7 +68,7 @@ class render public function render(): string|array|object { - $this->node->prebuild(true); + $this->node->prebuild(); if($this->renderType === 'list') return $this->renderList(); if($this->renderType === 'json') return $this->renderJSON(); diff --git a/lib/zin/core/render.func.php b/lib/zin/core/render.func.php index 0c283183e5..07ef103f3f 100644 --- a/lib/zin/core/render.func.php +++ b/lib/zin/core/render.func.php @@ -56,5 +56,6 @@ function render(string $wgName = '', array $options = array()) /* 渲染并输出 HTML。 Render and display html. */ $html = $context->render($wg, zget($options, 'selector', null), zget($options, 'type', 'html'), zget($options, 'data', null)); + ob_start(); echo $html; } diff --git a/lib/zin/core/zin.func.php b/lib/zin/core/zin.func.php index da6b3b43b4..97a61b4ab1 100644 --- a/lib/zin/core/zin.func.php +++ b/lib/zin/core/zin.func.php @@ -26,6 +26,7 @@ require_once __DIR__ . DS . 'h.func.php'; require_once __DIR__ . DS . 'item.class.php'; require_once __DIR__ . DS . 'to.class.php'; require_once __DIR__ . DS . 'context.func.php'; +require_once __DIR__ . DS . 'query.class.php'; require_once __DIR__ . DS . 'on.class.php'; require_once __DIR__ . DS . 'jquery.class.php'; @@ -124,18 +125,3 @@ function groupWgInList(node|array $items, string|array $types): array $groups[] = $restList; return $groups; } - -/** - * Include hooks files. - */ -function includeHooks() -{ - $hookFiles = context::current()->getHookFiles(); - ob_start(); - foreach($hookFiles as $hookFile) - { - if(!empty($hookFile) && file_exists($hookFile)) include $hookFile; - } - $hookCode = ob_get_clean(); - return html($hookCode); -} diff --git a/module/execution/ui/task.html.php b/module/execution/ui/task.html.php index 2faa6b15c4..f0bbf85db8 100644 --- a/module/execution/ui/task.html.php +++ b/module/execution/ui/task.html.php @@ -201,4 +201,4 @@ dtable set::createLink($canCreate && common::canModify('execution', $execution) ? $createLink : '') ); -render(); +$query = query('sidebar')->remove();