* zin: improve zin lib.
This commit is contained in:
@@ -155,6 +155,6 @@ formPanel
|
||||
)
|
||||
);
|
||||
|
||||
useData('title', $title);
|
||||
setPageData('title', $title);
|
||||
|
||||
render();
|
||||
|
||||
@@ -1002,28 +1002,26 @@ class baseControl
|
||||
chdir(dirname($viewFile));
|
||||
|
||||
/**
|
||||
* Set zin context data
|
||||
* Init zin context data.
|
||||
* 设置 zin 渲染上下文数据。
|
||||
*/
|
||||
\zin\zin::$globalRenderList = array();
|
||||
\zin\zin::$enabledGlobalRender = true;
|
||||
\zin\zin::$rendered = false;
|
||||
\zin\zin::$rawContentCalled = false;
|
||||
$context = \zin\context();
|
||||
$context->data = (array)$this->view;
|
||||
$context->data['zinDebug'] = array();
|
||||
|
||||
\zin\zin::$data = (array)$this->view;
|
||||
\zin\zin::$data['zinDebug'] = array();
|
||||
if($this->config->debug && $this->config->debug >= 2 && $this->config->installed)
|
||||
{
|
||||
\zin\zin::$data['zinDebug']['trace'] = $this->app->loadClass('trace')->getTrace();
|
||||
$context->data['zinDebug']['trace'] = $this->app->loadClass('trace')->getTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用extract和ob方法渲染$viewFile里面的代码。
|
||||
* Use extract and ob functions to eval the codes in $viewFile.
|
||||
*/
|
||||
extract(\zin\zin::$data);
|
||||
extract($context->data);
|
||||
|
||||
/* 将 hooks 文件添加到当前 context 中。 */
|
||||
if(!empty($hookFiles)) \zin\context::current()->addHookFiles($hookFiles);
|
||||
if(!empty($hookFiles)) $context->addHookFiles($hookFiles);
|
||||
|
||||
/* 加载 common.field.php 和 method.field.php。 */
|
||||
$commonFieldFile = dirname($viewFile) . DS . 'common.field.php';
|
||||
@@ -1034,7 +1032,7 @@ class baseControl
|
||||
ob_start();
|
||||
include $viewFile;
|
||||
|
||||
if(!\zin\zin::$rendered) \zin\render();
|
||||
if(!$context->rendered) \zin\render();
|
||||
$content = ob_get_clean();
|
||||
|
||||
ob_start();
|
||||
|
||||
+120
-21
@@ -16,13 +16,110 @@ use function zin\utils\flat;
|
||||
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'dataset.class.php';
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'flat.func.php';
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'deep.func.php';
|
||||
|
||||
class context extends \zin\utils\dataset
|
||||
{
|
||||
public string $name;
|
||||
|
||||
public array $globalRenderList = array();
|
||||
|
||||
public int $globalRenderLevel = 0;
|
||||
|
||||
public array $data = array();
|
||||
|
||||
public bool $rendered = false;
|
||||
|
||||
public bool $rawContentCalled = false;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
return array_merge(array
|
||||
(
|
||||
'name' => $this->name,
|
||||
'globalRenderListLen' => count($this->globalRenderList),
|
||||
'globalRenderList' => $this->globalRenderList,
|
||||
'globalRenderLevel' => $this->globalRenderLevel,
|
||||
'rendered' => $this->rendered,
|
||||
'rawContentCalled' => $this->rawContentCalled,
|
||||
), $this->storedData);
|
||||
}
|
||||
|
||||
public function getData(string $namePath, mixed $defaultValue = null): mixed
|
||||
{
|
||||
return \zin\utils\deepGet($this->data, $namePath, $defaultValue);
|
||||
}
|
||||
|
||||
public function setData(string $namePath, mixed $value)
|
||||
{
|
||||
\zin\utils\deepSet($this->data, $namePath, $value);
|
||||
}
|
||||
|
||||
public function enableGlobalRender()
|
||||
{
|
||||
$this->globalRenderLevel--;
|
||||
}
|
||||
|
||||
public function disableGlobalRender()
|
||||
{
|
||||
$this->globalRenderLevel++;
|
||||
}
|
||||
|
||||
public function enabledGlobalRender()
|
||||
{
|
||||
return $this->globalRenderLevel < 1;
|
||||
}
|
||||
|
||||
public function renderInGlobal(node|iDirective $item): bool
|
||||
{
|
||||
if($this->globalRenderLevel > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($item instanceof node)
|
||||
{
|
||||
if($item->parent || $item->shortType() === 'wg') return false;
|
||||
|
||||
if(!isset($this->globalRenderList[$item->gid])) $this->globalRenderList[$item->gid] = $item;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(in_array($item, $this->globalRenderList)) return false;
|
||||
|
||||
$this->globalRenderList[] = $item;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getGlobalRenderList(bool $clear = true): array
|
||||
{
|
||||
$globalItems = array();
|
||||
|
||||
foreach($this->globalRenderList as $item)
|
||||
{
|
||||
if(is_object($item) && ((isset($item->parent) && $item->parent) || (isset($item->notRenderInGlobal) && $item->notRenderInGlobal)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$globalItems[] = $item;
|
||||
}
|
||||
|
||||
/* Clear globalRenderList. */
|
||||
if($clear) $this->globalRenderList = array();
|
||||
|
||||
return $globalItems;
|
||||
}
|
||||
|
||||
public function addHookFiles(string|array ...$files)
|
||||
{
|
||||
$files = flat($files);
|
||||
return $this->mergeToList('hookFiles', $files);
|
||||
return $this->mergeToList('hookFiles', array_filter(array_values($files)));
|
||||
}
|
||||
|
||||
public function getHookFiles(): array
|
||||
@@ -30,12 +127,12 @@ class context extends \zin\utils\dataset
|
||||
return $this->getList('hookFiles');
|
||||
}
|
||||
|
||||
public function addImport(string ...$files)
|
||||
public function addImports(string ...$files)
|
||||
{
|
||||
return $this->mergeToList('import', $files);
|
||||
}
|
||||
|
||||
public function getImportList(): array
|
||||
public function getImports(): array
|
||||
{
|
||||
return $this->getList('import');
|
||||
}
|
||||
@@ -57,7 +154,7 @@ class context extends \zin\utils\dataset
|
||||
|
||||
public function addJSVar(string $name, mixed $value)
|
||||
{
|
||||
return $this->addToList('jsVar', h::createJsVarCode($name, $value));
|
||||
// return $this->addToList('jsVar', h::createJsVarCode($name, $value));
|
||||
}
|
||||
|
||||
public function addWgWithEvents($wg)
|
||||
@@ -107,7 +204,7 @@ class context extends \zin\utils\dataset
|
||||
return $js;
|
||||
}
|
||||
|
||||
public static $map = array();
|
||||
public static array $stack = array();
|
||||
|
||||
public static function js(/* string ...$code */)
|
||||
{
|
||||
@@ -121,7 +218,6 @@ class context extends \zin\utils\dataset
|
||||
call_user_func_array(array($context, 'addJSCall'), func_get_args());
|
||||
}
|
||||
|
||||
|
||||
public static function jsVar($name, $value)
|
||||
{
|
||||
$context = static::current();
|
||||
@@ -137,7 +233,7 @@ class context extends \zin\utils\dataset
|
||||
public static function import(/* string ...$files */)
|
||||
{
|
||||
$context = static::current();
|
||||
call_user_func_array(array($context, 'addImport'), func_get_args());
|
||||
call_user_func_array(array($context, 'addImports'), func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,35 +244,38 @@ class context extends \zin\utils\dataset
|
||||
*/
|
||||
public static function current(): context
|
||||
{
|
||||
if(empty(static::$map)) static::$map['current'] = new context();
|
||||
return static::$map['current'];
|
||||
if(empty(static::$stack))
|
||||
{
|
||||
$context = new context('default');
|
||||
static::$stack['default'] = $context;
|
||||
return $context;
|
||||
}
|
||||
return end(static::$stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create widget context.
|
||||
* Create context.
|
||||
*
|
||||
* @access public
|
||||
* @param string $gid The widget gid.
|
||||
* @param string $name Context name.
|
||||
* @return context
|
||||
*/
|
||||
public static function create(string $gid): context
|
||||
public static function create(string $name): context
|
||||
{
|
||||
if(isset(static::$map[$gid])) return static::$map[$gid];
|
||||
$context = new context();
|
||||
static::$map[$gid] = $context;
|
||||
if(isset(static::$stack[$name])) return static::$stack[$name];
|
||||
$context = new context($name);
|
||||
static::$stack[$name] = $context;
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy widget context.
|
||||
* Pop last context.
|
||||
*
|
||||
* @access public
|
||||
* @param string $gid The widget gid.
|
||||
* @return void
|
||||
* @return ?context
|
||||
*/
|
||||
public static function destroy(string $gid = null): void
|
||||
public static function pop(): ?context
|
||||
{
|
||||
if($gid === null) unset(static::$map['current']);
|
||||
elseif(isset(static::$map[$gid])) unset(static::$map[$gid]);
|
||||
return array_pop(static::$stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,32 @@ namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'context.class.php';
|
||||
|
||||
function context(?string $name = null): context
|
||||
{
|
||||
if($name) return context::create($name);
|
||||
return context::current();
|
||||
}
|
||||
|
||||
function popContext()
|
||||
{
|
||||
return context::pop();
|
||||
}
|
||||
|
||||
function enableGlobalRender()
|
||||
{
|
||||
context::current()->enableGlobalRender();
|
||||
}
|
||||
|
||||
function disableGlobalRender()
|
||||
{
|
||||
context::current()->disableGlobalRender();
|
||||
}
|
||||
|
||||
function renderInGlobal(node|iDirective $item): bool
|
||||
{
|
||||
return context::current()->renderInGlobal($item);
|
||||
}
|
||||
|
||||
function pageJS()
|
||||
{
|
||||
call_user_func_array('\zin\context::js', func_get_args());
|
||||
@@ -38,3 +64,38 @@ function import()
|
||||
{
|
||||
call_user_func_array('\zin\context::import', func_get_args());
|
||||
}
|
||||
|
||||
function setPageData($name, $value)
|
||||
{
|
||||
$context = context::current();
|
||||
if(is_array($value) && empty($name))
|
||||
{
|
||||
foreach ($value as $key => $val) $context->setData($key, $val);
|
||||
return;
|
||||
}
|
||||
$context->setData($name, $value);
|
||||
}
|
||||
|
||||
function getPageData($name)
|
||||
{
|
||||
$context = context::current();
|
||||
if(is_array($name))
|
||||
{
|
||||
$values = array();
|
||||
foreach($name as $propName)
|
||||
{
|
||||
$values[] = $context->getData($propName);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $context->getData($name);
|
||||
}
|
||||
|
||||
function data()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
if(count($args) >= 2) return setPageData($args[0], $args[1]);
|
||||
return getPageData($args[0]);
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The data function file of zin of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2023 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @version $Id
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
function setPageData($name, $value)
|
||||
{
|
||||
if(is_array($value) && empty($name))
|
||||
{
|
||||
foreach ($value as $key => $val) zin::setData($key, $val);
|
||||
return;
|
||||
}
|
||||
zin::setData($name, $value);
|
||||
}
|
||||
|
||||
function getPageData($name)
|
||||
{
|
||||
if(is_array($name))
|
||||
{
|
||||
$values = array();
|
||||
foreach($name as $propName)
|
||||
{
|
||||
$values[] = zin::getData($propName);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
return zin::getData($name);
|
||||
}
|
||||
|
||||
function data()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
if(count($args) >= 2) return setPageData($args[0], $args[1]);
|
||||
return getPageData($args[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set page data
|
||||
* @deprecated Use data($name, $value) insteadOf useData($name, $value)
|
||||
*/
|
||||
function useData($name, $value)
|
||||
{
|
||||
return setPageData($name, $value);
|
||||
}
|
||||
@@ -13,8 +13,16 @@ declare(strict_types=1);
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'zin.class.php';
|
||||
require_once __DIR__ . DS . 'context.func.php';
|
||||
|
||||
class directive
|
||||
use zin\node;
|
||||
|
||||
interface iDirective
|
||||
{
|
||||
public function apply(node $node, string $blockName): void;
|
||||
}
|
||||
|
||||
class directive implements iDirective
|
||||
{
|
||||
public string $type;
|
||||
|
||||
@@ -37,7 +45,10 @@ class directive
|
||||
$this->data = $data;
|
||||
$this->options = $options;
|
||||
|
||||
zin::renderInGlobal($this);
|
||||
if(!$options || !isset($options['notRenderInGlobal']) || !$options['notRenderInGlobal'])
|
||||
{
|
||||
renderInGlobal($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function __debugInfo(): array
|
||||
@@ -49,50 +60,52 @@ class directive
|
||||
);
|
||||
}
|
||||
|
||||
public function applyToWg(wg &$wg, string $blockName): void
|
||||
public function apply(node $node, string $blockName): void
|
||||
{
|
||||
$this->parent = $wg;
|
||||
$this->parent = $node;
|
||||
|
||||
$data = $this->data;
|
||||
$type = $this->type;
|
||||
|
||||
if($type === 'prop')
|
||||
{
|
||||
$wg->setProp($data);
|
||||
$node->setProp($data);
|
||||
return;
|
||||
}
|
||||
if($type === 'class' || $type === 'style')
|
||||
{
|
||||
$wg->setProp($type, $data);
|
||||
$node->setProp($type, $data);
|
||||
return;
|
||||
}
|
||||
if($type === 'cssVar')
|
||||
{
|
||||
$wg->setProp('--', $data);
|
||||
$node->setProp('--', $data);
|
||||
return;
|
||||
}
|
||||
if($type === 'html')
|
||||
{
|
||||
$wg->addToBlock($blockName, $this);
|
||||
$html = new stdClass();
|
||||
$html->html = implode("\n", $data);
|
||||
$node->addToBlock($blockName, $html);
|
||||
return;
|
||||
}
|
||||
if($type === 'text')
|
||||
{
|
||||
$wg->addToBlock($blockName, htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, null, false));
|
||||
$node->addToBlock($blockName, $data);
|
||||
return;
|
||||
}
|
||||
if($type === 'block')
|
||||
{
|
||||
foreach($data as $blockName => $blockChildren)
|
||||
{
|
||||
$wg->add($blockChildren, $blockName);
|
||||
$node->add($blockChildren, $blockName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function is(mixed $item, ?string $type = null): bool
|
||||
public static function is(mixed $item): bool
|
||||
{
|
||||
return $item instanceof directive && ($type === null || $item->type === $type);
|
||||
return ($item instanceof directive) || $item instanceof iDirective || (is_object($item) && method_exists($item, 'apply'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,5 +116,5 @@ function directive($type, $data, $options = null): directive
|
||||
|
||||
function isDirective(mixed $item, ?string $type = null): bool
|
||||
{
|
||||
return directive::is($item, $type);
|
||||
return directive::is($item);
|
||||
}
|
||||
|
||||
@@ -130,8 +130,7 @@ class dom
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
public function build(): mixed {
|
||||
if($this->wg->removed) return array();
|
||||
|
||||
if($this->buildList !== null && $this->buildListInner === $this->renderInner) return $this->buildList;
|
||||
|
||||
+98
-174
@@ -12,153 +12,141 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'flat.func.php';
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'json.func.php';
|
||||
require_once __DIR__ . DS . 'wg.class.php';
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'node.class.php';
|
||||
require_once __DIR__ . DS . 'text.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
|
||||
class h extends wg
|
||||
class h extends node
|
||||
{
|
||||
protected static array $defineProps = array(
|
||||
'tagName: string',
|
||||
'selfClose?: bool'
|
||||
public static array $defineProps = array
|
||||
(
|
||||
'tagName' => 'string',
|
||||
'selfClose' => '?bool'
|
||||
);
|
||||
|
||||
public function tagName(): string
|
||||
{
|
||||
$tagName = $this->prop('tagName');
|
||||
return $tagName === null ? '' : $tagName;
|
||||
}
|
||||
|
||||
public function type(): string
|
||||
{
|
||||
return 'h::' . $this->tagName();
|
||||
}
|
||||
|
||||
public function shortType(): string
|
||||
{
|
||||
return $this->tagName();
|
||||
}
|
||||
|
||||
public function isSelfClose(): bool
|
||||
{
|
||||
$selfClose = $this->prop('selfClose');
|
||||
if($selfClose !== null) return boolval($selfClose);
|
||||
|
||||
return in_array($this->tagName(), static::$selfCloseTags);
|
||||
}
|
||||
|
||||
protected function onSetProp(array|string $prop, mixed $value)
|
||||
{
|
||||
if($prop === 'className') $prop = 'class';
|
||||
return parent::onSetProp($prop, $value);
|
||||
}
|
||||
|
||||
public function getTagName(): string
|
||||
public function build(): mixed
|
||||
{
|
||||
return $this->props->get('tagName');
|
||||
}
|
||||
|
||||
public function isDomElement(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isSelfClose()
|
||||
{
|
||||
$selfClose = $this->props->get('selfClose');
|
||||
if($selfClose !== null) return $selfClose;
|
||||
|
||||
return in_array($this->getTagName(), static::$selfCloseTags);
|
||||
}
|
||||
|
||||
public function build(): array
|
||||
{
|
||||
if($this->isSelfClose()) return array($this->buildSelfCloseTag());
|
||||
if($this->isSelfClose()) return $this->buildSelfCloseTag();
|
||||
|
||||
return array($this->buildTagBegin(), parent::build(), $this->buildTagEnd());
|
||||
}
|
||||
|
||||
public function toJSON(): array
|
||||
{
|
||||
$data = parent::toJSON();
|
||||
$data['type'] = 'h:' . $this->getTagName();
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function type(): string
|
||||
{
|
||||
return $this->getTagName();
|
||||
}
|
||||
|
||||
public function shortType(): string
|
||||
{
|
||||
return $this->getTagName();
|
||||
}
|
||||
|
||||
protected function getPropsStr(): string
|
||||
{
|
||||
$propStr = $this->props->toStr(array_keys(static::definedPropsList()));
|
||||
if($this->props->hasEvent() && empty($this->id()) && $this->getTagName() !== 'html') $propStr = "$propStr id='$this->gid'";
|
||||
if($this->props->hasEvent() && empty($this->id()) && $this->tagName() !== 'html') $propStr = "$propStr id='$this->gid'";
|
||||
return empty($propStr) ? '' : " $propStr";
|
||||
}
|
||||
|
||||
protected function buildSelfCloseTag(): string
|
||||
{
|
||||
$tagName = $this->getTagName();
|
||||
$tagName = $this->tagName();
|
||||
$propStr = $this->getPropsStr();
|
||||
return "<$tagName$propStr />";
|
||||
}
|
||||
|
||||
protected function buildTagBegin(): string
|
||||
{
|
||||
$tagName = $this->getTagName();
|
||||
$tagName = $this->tagName();
|
||||
$propStr = $this->getPropsStr();
|
||||
return "<$tagName$propStr>";
|
||||
}
|
||||
|
||||
protected function buildTagEnd(): string
|
||||
{
|
||||
$tagName = $this->getTagName();
|
||||
$tagName = $this->tagName();
|
||||
return "</$tagName>";
|
||||
}
|
||||
|
||||
public static function create(): h
|
||||
public static function create(string $tagName, mixed ...$args): h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$tagName = array_shift($args);
|
||||
return new h(is_string($tagName) ? set('tagName', $tagName) : $tagName, $args);
|
||||
$h = new h(...$args);
|
||||
$h->setProp('tagName', $tagName);
|
||||
return $h;
|
||||
}
|
||||
|
||||
public static function __callStatic(string $tagName, array $args): h
|
||||
{
|
||||
return new h(set('tagName', $tagName), $args);
|
||||
return static::create($tagName, ...$args);
|
||||
}
|
||||
|
||||
public static function a(): h
|
||||
{
|
||||
$a = static::create('a', func_get_args());
|
||||
if($a->prop('target') === '_blank' && !$a->hasProp('rel')) $a->prop('rel', 'noopener noreferrer');
|
||||
if($a->prop('target') === '_blank' && !$a->hasProp('rel'))
|
||||
{
|
||||
$a->setProp('rel', 'noopener noreferrer');
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
|
||||
public static function button()
|
||||
public static function button(mixed ...$args): h
|
||||
{
|
||||
return static::create('button', set('type', 'button'), func_get_args());
|
||||
$button = static::create('button', ...$args);
|
||||
$button->setDefaultProps('type', 'button');
|
||||
return $button;
|
||||
}
|
||||
|
||||
public static function input()
|
||||
public static function input(mixed ...$args): h
|
||||
{
|
||||
return static::create('input', set('type', 'text'), func_get_args());
|
||||
$input = static::create('input', ...$args);
|
||||
$input->setDefaultProps('type', 'text');
|
||||
return $input;
|
||||
}
|
||||
|
||||
public static function formHidden(/* $name, $value, ...$args */)
|
||||
public static function formHidden(string $name, string $value, mixed ...$args): h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$name = array_shift($args);
|
||||
$value = array_shift($args);
|
||||
return static::create('input', set('type', 'hidden'), set::name($name), set::value($value), $args);
|
||||
$input = static::create('input', ...$args);
|
||||
$input->setDefaultProps(array('type' => 'hidden', 'name' => $name, 'value' => $value));
|
||||
return $input;
|
||||
}
|
||||
|
||||
public static function checkbox()
|
||||
public static function checkbox(mixed ...$args): h
|
||||
{
|
||||
return static::create('input', set('type', 'checkbox'), func_get_args());
|
||||
$input = static::create('input', ...$args);
|
||||
$input->setDefaultProps('type', 'checkbox');
|
||||
return $input;
|
||||
}
|
||||
|
||||
public static function radio()
|
||||
public static function radio(mixed ...$args): h
|
||||
{
|
||||
return static::create('input', set('type', 'radio'), func_get_args());
|
||||
$input = static::create('input', ...$args);
|
||||
$input->setDefaultProps('type', 'radio');
|
||||
return $input;
|
||||
}
|
||||
|
||||
public static function date()
|
||||
public static function textarea(mixed ...$args)
|
||||
{
|
||||
return static::create('input', set('type', 'date'), func_get_args());
|
||||
}
|
||||
|
||||
public static function file()
|
||||
{
|
||||
return static::create('input', set('type', 'file'), func_get_args());
|
||||
}
|
||||
|
||||
public static function textarea(/* ...$args */)
|
||||
{
|
||||
$args = func_get_args();
|
||||
list($code, $args) = h::splitRawCode($args);
|
||||
return static::create('textarea', $code, $args);
|
||||
}
|
||||
@@ -168,33 +156,29 @@ class h extends wg
|
||||
*
|
||||
* @access public
|
||||
* @param string $comment
|
||||
* @return directive
|
||||
* @return node
|
||||
*/
|
||||
public static function comment(string $comment): directive
|
||||
public static function comment(string $comment): text
|
||||
{
|
||||
return html("<!-- $comment -->");
|
||||
}
|
||||
|
||||
public static function importJs(/* $src, ...$args */)
|
||||
public static function importJs(string $src, mixed ...$args): h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$src = array_shift($args);
|
||||
return static::create('script', set('src', $src), $args);
|
||||
$script = static::create('script', ...$args);
|
||||
$script->setDefaultProps('src', 'src');
|
||||
return $script;
|
||||
}
|
||||
|
||||
public static function importCss(/* $src, ...$args */)
|
||||
public static function importCss(string $href, mixed ...$args): h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$src = array_shift($args);
|
||||
return static::create('link', set('rel', 'stylesheet'), set('href', $src), $args);
|
||||
$link = static::create('link', ...$args);
|
||||
$link->setDefaultProps(array('rel' => 'stylesheet', 'href' => $href));
|
||||
return $link;
|
||||
}
|
||||
|
||||
public static function import(/* $file, $type = null, ...$args */)
|
||||
public static function import(string|array $file, ?string $type = null, mixed ...$args): ?h
|
||||
{
|
||||
$args = array_merge(func_get_args(), array(null, null));
|
||||
$file = array_shift($args);
|
||||
$type = array_shift($args);
|
||||
|
||||
if(is_array($file))
|
||||
{
|
||||
$children = array();
|
||||
@@ -210,37 +194,35 @@ class h extends wg
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function css(/* ...$args */)
|
||||
public static function css(mixed ...$args): ?h
|
||||
{
|
||||
list($code, $args) = h::splitRawCode(func_get_args());
|
||||
list($code, $args) = h::splitRawCode($args);
|
||||
if(empty($code)) return null;
|
||||
return static::create('style', html(implode("\n", $code)), $args);
|
||||
return static::create('style', html(...$code), $args);
|
||||
}
|
||||
|
||||
public static function globalJS(/* ...$args */)
|
||||
public static function globalJS(mixed ...$args): ?h
|
||||
{
|
||||
list($code, $args) = h::splitRawCode(func_get_args());
|
||||
list($code, $args) = h::splitRawCode($args);
|
||||
if(empty($code)) return null;
|
||||
return static::create('script', html(implode("\n", $code)), $args);
|
||||
return static::create('script', html(...$code), $args);
|
||||
}
|
||||
|
||||
public static function js(/* ...$args */)
|
||||
public static function js(mixed ...$args): ?h
|
||||
{
|
||||
|
||||
list($code, $args) = h::splitRawCode(func_get_args());
|
||||
list($code, $args) = h::splitRawCode($args);
|
||||
if(empty($code)) return null;
|
||||
return static::create('script', html(h::createJsScopeCode($code)), $args);
|
||||
$code = ';(function(){' . implode("\n", $code) . '}());';
|
||||
return static::create('script', html($code, $args));
|
||||
}
|
||||
|
||||
public static function jsVar(/* $name, $value, ...$args */)
|
||||
public static function jsVar(string $name, mixed $value, mixed ...$args): ?h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$name = array_shift($args);
|
||||
$value = array_shift($args);
|
||||
return static::js(static::createJsVarCode($name, $value), $args);
|
||||
|
||||
return static::js(js()->var($name, $value), $args);
|
||||
}
|
||||
|
||||
public static function jsCall(/* $funcName, ...$args */)
|
||||
public static function jsCall(string $funcName, mixed ...$args): h
|
||||
{
|
||||
$args = func_get_args();
|
||||
$funcName = array_shift($args);
|
||||
@@ -250,69 +232,11 @@ class h extends wg
|
||||
foreach($args as $arg)
|
||||
{
|
||||
if(isDirective($arg)) $directives[] = $arg;
|
||||
else $funcArgs[] = $arg;
|
||||
}
|
||||
$code = static::createJsCallCode($funcName, $funcArgs);
|
||||
return static::js($code, $directives);
|
||||
}
|
||||
|
||||
public static function createJsCallCode($func, $args)
|
||||
{
|
||||
foreach($args as $index => $arg)
|
||||
{
|
||||
$args[$index] = h::encodeJsonWithRawJs($arg, JSON_UNESCAPED_UNICODE);
|
||||
else $funcArgs[] = $arg;
|
||||
}
|
||||
|
||||
if($func[0] === '~')
|
||||
{
|
||||
$func = substr($func, 1);
|
||||
return "$(() => $func(" . implode(',', $args) . "));";
|
||||
}
|
||||
return $func . '(' . implode(',', $args) . ');';
|
||||
}
|
||||
|
||||
public static function createJsVarCode($name, $value)
|
||||
{
|
||||
$vars = is_string($name) ? array($name => $value) : $name;
|
||||
$jsCode = '';
|
||||
foreach($vars as $var => $val)
|
||||
{
|
||||
if(empty($var)) continue;
|
||||
|
||||
$val = h::encodeJsonWithRawJs($val);
|
||||
|
||||
if(str_starts_with($var, 'window.')) $jsCode .= "$var=" . $val . ';';
|
||||
elseif(str_starts_with($var, '+')) $jsCode .= 'let ' . substr($var, 1) . '=' . $val . ';';
|
||||
else $jsCode .= "const $var=" . $val . ';';
|
||||
}
|
||||
return $jsCode;
|
||||
}
|
||||
|
||||
public static function createJsScopeCode(string|array $codes): string
|
||||
{
|
||||
if(is_array($codes)) $codes = implode("\n", $codes);
|
||||
return ";(function(){\n$codes\n}());";
|
||||
}
|
||||
|
||||
public static function jsRaw(): string
|
||||
{
|
||||
$js = implode('RAWJS_LINE', func_get_args());
|
||||
$js = str_replace(array("\n", '"'), array('RAWJS_LINE', 'RAWJS_QUOTE'), $js);
|
||||
return "RAWJS<$js>RAWJS";
|
||||
}
|
||||
|
||||
public static function decodeJSRaw(string $str): string
|
||||
{
|
||||
if(!str_contains($str, 'RAWJS')) return $str;
|
||||
return str_replace(array('RAWJS_LINE', 'RAWJS_QUOTE', '"RAWJS<', '>RAWJS"'), array("\n", '"', '', ''), $str);
|
||||
}
|
||||
|
||||
public static function encodeJsonWithRawJs($data)
|
||||
{
|
||||
$json = \zin\utils\jsonEncode($data, JSON_UNESCAPED_UNICODE);
|
||||
if(empty($json) && (is_array($data) || is_object($data))) return '[]';
|
||||
|
||||
return static::decodeJSRaw($json);
|
||||
$js = js()->call($funcName, ...$funcArgs);
|
||||
return static::js($js->toJS(), $directives);
|
||||
}
|
||||
|
||||
protected static function splitRawCode($children)
|
||||
@@ -323,9 +247,9 @@ class h extends wg
|
||||
foreach($children as $child)
|
||||
{
|
||||
if(is_string($child)) $code[] = $child;
|
||||
else $args[] = $child;
|
||||
else $args[] = $child;
|
||||
}
|
||||
return [$code, $args];
|
||||
return array($code, $args);
|
||||
}
|
||||
|
||||
public static $selfCloseTags = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr');
|
||||
|
||||
+23
-31
@@ -13,35 +13,27 @@ declare(strict_types=1);
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'h.class.php';
|
||||
require_once __DIR__ . DS . 'item.class.php';
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'set.class.php';
|
||||
require_once __DIR__ . DS . 'to.class.php';
|
||||
require_once __DIR__ . DS . 'data.func.php';
|
||||
require_once __DIR__ . DS . 'on.class.php';
|
||||
|
||||
function h(): h {return call_user_func_array('\zin\h::create', func_get_args());}
|
||||
|
||||
function div(): h {return call_user_func_array('\zin\h::div', func_get_args());}
|
||||
function span(): h {return call_user_func_array('\zin\h::span', func_get_args());}
|
||||
function code(): h {return call_user_func_array('\zin\h::code', func_get_args());}
|
||||
function canvas(): h {return call_user_func_array('\zin\h::canvas', func_get_args());}
|
||||
function br(): h {return call_user_func_array('\zin\h::br', func_get_args());}
|
||||
function a(): h {return call_user_func_array('\zin\h::a', func_get_args());}
|
||||
function p(): h {return call_user_func_array('\zin\h::p', func_get_args());}
|
||||
function img(): h {return call_user_func_array('\zin\h::img', func_get_args());}
|
||||
function button(): h {return call_user_func_array('\zin\h::button', func_get_args());}
|
||||
function h1(): h {return call_user_func_array('\zin\h::h1', func_get_args());}
|
||||
function h2(): h {return call_user_func_array('\zin\h::h2', func_get_args());}
|
||||
function h3(): h {return call_user_func_array('\zin\h::h3', func_get_args());}
|
||||
function h4(): h {return call_user_func_array('\zin\h::h4', func_get_args());}
|
||||
function h5(): h {return call_user_func_array('\zin\h::h5', func_get_args());}
|
||||
function h6(): h {return call_user_func_array('\zin\h::h6', func_get_args());}
|
||||
function ul(): h {return call_user_func_array('\zin\h::ul', func_get_args());}
|
||||
function li(): h {return call_user_func_array('\zin\h::li', func_get_args());}
|
||||
function template(): h {return call_user_func_array('\zin\h::template', func_get_args());}
|
||||
function formHidden(): h {return call_user_func_array('\zin\h::formHidden', func_get_args());}
|
||||
function fieldset(): h {return call_user_func_array('\zin\h::fieldset', func_get_args());}
|
||||
function legend(): h {return call_user_func_array('\zin\h::legend', func_get_args());}
|
||||
|
||||
function jsRaw(): string {return call_user_func_array('\zin\h::jsRaw', func_get_args());}
|
||||
function h(mixed ...$args): h {return h::create(...$args);}
|
||||
function div(mixed ...$args): h {return h::div(...$args);}
|
||||
function span(mixed ...$args): h {return h::span(...$args);}
|
||||
function code(mixed ...$args): h {return h::code(...$args);}
|
||||
function canvas(mixed ...$args): h {return h::canvas(...$args);}
|
||||
function br(mixed ...$args): h {return h::br(...$args);}
|
||||
function a(mixed ...$args): h {return h::a(...$args);}
|
||||
function p(mixed ...$args): h {return h::p(...$args);}
|
||||
function img(mixed ...$args): h {return h::img(...$args);}
|
||||
function button(mixed ...$args): h {return h::button(...$args);}
|
||||
function h1(mixed ...$args): h {return h::h1(...$args);}
|
||||
function h2(mixed ...$args): h {return h::h2(...$args);}
|
||||
function h3(mixed ...$args): h {return h::h3(...$args);}
|
||||
function h4(mixed ...$args): h {return h::h4(...$args);}
|
||||
function h5(mixed ...$args): h {return h::h5(...$args);}
|
||||
function h6(mixed ...$args): h {return h::h6(...$args);}
|
||||
function ul(mixed ...$args): h {return h::ul(...$args);}
|
||||
function li(mixed ...$args): h {return h::li(...$args);}
|
||||
function template(mixed ...$args): h {return h::template(...$args);}
|
||||
function formHidden(mixed ...$args): h {return h::formHidden(...$args);}
|
||||
function fieldset(mixed ...$args): h {return h::fieldset(...$args);}
|
||||
function legend(mixed ...$args): h {return h::legend(...$args);}
|
||||
function rawContent(): text {return h::comment('{{RAW_CONTENT}}');}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The helpers of zin lib of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2024 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @version $Id
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
/**
|
||||
* Check if the debug mode is on.
|
||||
*
|
||||
* @param int $level - The min debug level.
|
||||
* @return bool
|
||||
*/
|
||||
function isDebug(int $level = 1): bool
|
||||
{
|
||||
global $config;
|
||||
$debug = isset($config->debug) ? $config->debug : 0;
|
||||
if(is_bool($debug)) $debug = $debug ? 1 : 0;
|
||||
|
||||
return $debug >= $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an error.
|
||||
*
|
||||
* @param string $message - The error message.
|
||||
* @param int $level - The error level.
|
||||
* @param string $scope - The error scope.
|
||||
* @return void
|
||||
*/
|
||||
function triggerError(string $message, int $level = E_USER_ERROR, string $scope = 'ZIN')
|
||||
{
|
||||
trigger_error("[$scope] $message", $level);
|
||||
}
|
||||
@@ -13,7 +13,7 @@ declare(strict_types=1);
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.class.php';
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'zin.func.php';
|
||||
|
||||
class item extends wg
|
||||
{
|
||||
|
||||
+58
-19
@@ -12,11 +12,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'node.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
require_once __DIR__ . DS . 'zin.func.php';
|
||||
|
||||
use zin\jsContext;
|
||||
use zin\jsCallback;
|
||||
use zin\jQuery;
|
||||
use zin\node;
|
||||
|
||||
/**
|
||||
* Class for generating js code.
|
||||
@@ -24,8 +27,10 @@ use zin\jQuery;
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
class js extends directive implements \JsonSerializable
|
||||
class js implements \JsonSerializable, iDirective
|
||||
{
|
||||
public bool $notRenderInGlobal = true;
|
||||
|
||||
/**
|
||||
* The js code lines.
|
||||
* JS 代码行。
|
||||
@@ -43,7 +48,6 @@ class js extends directive implements \JsonSerializable
|
||||
*/
|
||||
public function __construct(null|string|js|array ...$codes)
|
||||
{
|
||||
parent::__construct('js');
|
||||
$this->appendLines(...$codes);
|
||||
}
|
||||
|
||||
@@ -104,9 +108,10 @@ class js extends directive implements \JsonSerializable
|
||||
$argCodes = array();
|
||||
foreach($args as $arg)
|
||||
{
|
||||
$argCodes[] = ($arg instanceof js) ? $arg->toJS() : static::json($arg);
|
||||
$argCodes[] = ($arg instanceof js) ? $arg->toJS() : static::value($arg);
|
||||
}
|
||||
return $this->appendLine($func, '(', implode(',', $argCodes), ')');
|
||||
|
||||
return $this->appendLine($func . '(' . implode(',', $argCodes) . ')');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +138,7 @@ class js extends directive implements \JsonSerializable
|
||||
*/
|
||||
public function let(string $name, mixed $value): self
|
||||
{
|
||||
return $this->appendLine('let', $name, '=', static::json($value));
|
||||
return $this->appendLine('let', $name, '=', static::value($value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,7 +152,7 @@ class js extends directive implements \JsonSerializable
|
||||
*/
|
||||
public function const(string $name, mixed $value): self
|
||||
{
|
||||
return $this->appendLine('const', $name, '=', static::json($value));
|
||||
return $this->appendLine('const', $name, '=', static::value($value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +167,21 @@ class js extends directive implements \JsonSerializable
|
||||
public function globalVar(string $name, mixed $value): self
|
||||
{
|
||||
if(!str_starts_with($name, 'window.')) $name = 'window.' . $name;
|
||||
return $this->appendLine($name, '=', static::json($value));
|
||||
return $this->appendLine($name, '=', static::value($value));
|
||||
}
|
||||
|
||||
public function var(string|array $nameOrVars, mixed $value = null): self
|
||||
{
|
||||
if(is_array($nameOrVars))
|
||||
{
|
||||
foreach($nameOrVars as $name => $val) $this->var($name, $val);
|
||||
return $this;
|
||||
}
|
||||
|
||||
$name = $nameOrVars;
|
||||
if(str_starts_with($name, '+')) return $this->let(substr($name, 1), $value);
|
||||
if(str_starts_with($name, 'window.')) return $this->globalVar($name, $value);
|
||||
return $this->const($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +314,6 @@ class js extends directive implements \JsonSerializable
|
||||
}
|
||||
if($line instanceof js)
|
||||
{
|
||||
$line->parent = $this;
|
||||
$line = $line->toJS();
|
||||
}
|
||||
$this->appendLine($line);
|
||||
@@ -348,16 +366,16 @@ class js extends directive implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply JS code to zin widget.
|
||||
* Apply JS code to zin node.
|
||||
* 将 JS 代码应用到指定的 zin 部件中。
|
||||
*
|
||||
* @access public
|
||||
* @param wg $wg zin widget object.
|
||||
* @param string $blockName zin widget block name.
|
||||
* @param node $node zin node object.
|
||||
* @param string $blockName zin node block name.
|
||||
*/
|
||||
public function applyToWg(wg &$wg, string $blockName): void
|
||||
public function apply(node $node, string $blockName): void
|
||||
{
|
||||
$wg->addToBlock($blockName, h::js($this->toJS()));
|
||||
$node->addToBlock($blockName, h::js($this->toJS()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,7 +389,20 @@ class js extends directive implements \JsonSerializable
|
||||
{
|
||||
$js = trim($this->toJS());
|
||||
if(str_ends_with(';', $js)) $js = substr($js, 0, -1);
|
||||
return h::jsRaw($js);
|
||||
return js::raw($js);
|
||||
}
|
||||
|
||||
public static function raw(string ...$codes)
|
||||
{
|
||||
$js = implode('<RAWJS_LINE>', $codes);
|
||||
$js = str_replace(array("\n", '"'), array('<RAWJS_LINE>', '<RAWJS_QUOTE>'), $js);
|
||||
return "RAWJS<$js>RAWJS";
|
||||
}
|
||||
|
||||
public static function decodeRaw(string $str): string
|
||||
{
|
||||
if(!str_contains($str, 'RAWJS')) return $str;
|
||||
return str_replace(array('<RAWJS_LINE>', '<RAWJS_QUOTE>', '"RAWJS<', '>RAWJS"'), array("\n", '"', '', ''), $str);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,16 +420,19 @@ class js extends directive implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode php value to JSON.
|
||||
* 将 PHP 值编码为 JSON。
|
||||
* Encode php value to JS code.
|
||||
* 将 PHP 值编码为 JS 代码。
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $data PHP value.
|
||||
* @return string
|
||||
*/
|
||||
public static function json($data): string
|
||||
public static function value(mixed $data): string
|
||||
{
|
||||
return h::encodeJsonWithRawJs($data);
|
||||
$js = \zin\utils\jsonEncode($data, JSON_UNESCAPED_UNICODE);
|
||||
if(empty($js) && (is_array($data) || is_object($data))) return '[]';
|
||||
|
||||
return static::decodeRaw($js);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -488,3 +522,8 @@ function js(null|string|js|array ...$codes): js
|
||||
{
|
||||
return new js(...$codes);
|
||||
}
|
||||
|
||||
function jsRaw(string ...$codes): string
|
||||
{
|
||||
return js::raw(...$codes);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'zin.func.php';
|
||||
require_once __DIR__ . DS . 'jshelper.class.php';
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,643 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The base node class file of zin of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2023 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @version $Id
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'helper.func.php';
|
||||
require_once __DIR__ . DS . 'props.class.php';
|
||||
|
||||
/**
|
||||
* The base node class.
|
||||
*/
|
||||
class node implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Define properties
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
protected static array $defineProps = array();
|
||||
|
||||
/**
|
||||
* Default properties
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
protected static array $defaultProps = array();
|
||||
|
||||
protected static array $defineBlocks = array();
|
||||
|
||||
public string $gid;
|
||||
|
||||
public ?node $parent = null;
|
||||
|
||||
public props $props;
|
||||
|
||||
public array $blocks = array();
|
||||
|
||||
public bool $removed = false;
|
||||
|
||||
public ?array $buildList = null;
|
||||
|
||||
public function __construct(mixed ...$args)
|
||||
{
|
||||
$this->gid = 'zin_' . uniqid();
|
||||
$this->props = new props();
|
||||
|
||||
disableGlobalRender();
|
||||
|
||||
$this->setDefaultProps(static::getDefaultProps());
|
||||
$this->add($args);
|
||||
$this->created();
|
||||
|
||||
enableGlobalRender();
|
||||
renderInGlobal($this);
|
||||
}
|
||||
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
return (array)$this->toJSON();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
public function type(): string
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
public function shortType(): string
|
||||
{
|
||||
$type = $this->type();
|
||||
if(str_contains($type, '\\'))
|
||||
{
|
||||
$type = substr($type, strrpos($type, '\\') + 1);
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function id(): ?string
|
||||
{
|
||||
return $this->props->get('id');
|
||||
}
|
||||
|
||||
public function displayID(): string
|
||||
{
|
||||
$displayID = $this->type() . '~' . $this->gid;
|
||||
|
||||
$id = $this->id();
|
||||
if(!empty($id)) $displayID .= "#$id";
|
||||
|
||||
return $displayID;
|
||||
}
|
||||
|
||||
public function prop(array|string $name, mixed $defaultValue = null): mixed
|
||||
{
|
||||
if(is_array($name))
|
||||
{
|
||||
$values = array();
|
||||
foreach($name as $index => $propName)
|
||||
{
|
||||
$values[] = $this->onGetProp($propName, is_array($defaultValue) ? (isset($defaultValue[$propName]) ? $defaultValue[$propName] : $defaultValue[$index]) : $defaultValue);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $this->onGetProp($name, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set property, an array can be passed to set multiple properties
|
||||
*
|
||||
* @access public
|
||||
* @param props|array|string $prop - Property name or properties list
|
||||
* @param mixed $value - Property value
|
||||
*/
|
||||
public function setProp(props|array|string $prop, mixed $value = null)
|
||||
{
|
||||
if($prop instanceof props) $prop = $prop->toJSON();
|
||||
|
||||
if(is_array($prop))
|
||||
{
|
||||
foreach($prop as $name => $value) $this->setProp($name, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(!is_string($prop) || empty($prop)) return $this;
|
||||
|
||||
if($prop[0] === '#')
|
||||
{
|
||||
$this->add($value, substr($prop, 1));
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->onSetProp($prop, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasProp(): bool
|
||||
{
|
||||
$names = func_get_args();
|
||||
if(empty($names)) return false;
|
||||
foreach($names as $name)
|
||||
{
|
||||
if(!$this->props->has($name)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setDefaultProps(string|array $props, mixed $value = null)
|
||||
{
|
||||
if(is_string($props)) $props = array($props => $value);
|
||||
if(!is_array($props) || empty($props)) return;
|
||||
|
||||
foreach($props as $name => $value)
|
||||
{
|
||||
if($this->props->isset($name)) continue;
|
||||
$this->setProp($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRestProps(): array
|
||||
{
|
||||
return $this->props->skip(array_keys(static::definedPropsList()));
|
||||
}
|
||||
|
||||
public function getDefinedProps(): array
|
||||
{
|
||||
return $this->props->pick(array_keys(static::definedPropsList()));
|
||||
}
|
||||
|
||||
public function add($item, string $blockName = 'children')
|
||||
{
|
||||
if($item === null || is_bool($item)) return;
|
||||
|
||||
if(is_array($item))
|
||||
{
|
||||
foreach($item as $child) $this->add($child, $blockName);
|
||||
return;
|
||||
}
|
||||
|
||||
if(isDirective($item)) $this->directive($item, $blockName);
|
||||
else $this->addToBlock($blockName, $item);
|
||||
}
|
||||
|
||||
public function addToBlock(string $name, mixed $child)
|
||||
{
|
||||
if($child === null || is_bool($child)) return;
|
||||
|
||||
if(is_array($child))
|
||||
{
|
||||
foreach($child as $blockChild)
|
||||
{
|
||||
$this->addToBlock($name, $blockChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if($child instanceof node) $child->parent = $this;
|
||||
|
||||
if($name === 'children' && $child instanceof node)
|
||||
{
|
||||
$blockName = static::getNameFromBlockMap($child->type());
|
||||
if($blockName !== null) $name = $blockName;
|
||||
}
|
||||
|
||||
$result = $name === 'children' ? $this->onAddChild($child) : $this->onAddBlock($child, $name);
|
||||
if($result === false) return;
|
||||
if($result !== null && $result !== true) $child = $result;
|
||||
|
||||
if(isset($this->blocks[$name])) $this->blocks[$name][] = $child;
|
||||
else $this->blocks[$name] = array($child);
|
||||
}
|
||||
|
||||
public function directive(iDirective $directive, string $blockName = 'children')
|
||||
{
|
||||
$directive->parent = $this;
|
||||
$directive->apply($this, $blockName);
|
||||
}
|
||||
|
||||
public function addChild(mixed $child)
|
||||
{
|
||||
return $this->addToBlock('children', $child);
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
if($this->removed) return '';
|
||||
|
||||
return renderToHtml(...$this->prebuild());
|
||||
}
|
||||
|
||||
public function prebuild(): array
|
||||
{
|
||||
if($this->removed) return array();
|
||||
|
||||
if($this->buildList === null)
|
||||
{
|
||||
$list = $this->build();
|
||||
$list = is_array($list) ? $list : array($list);
|
||||
$list = array_merge($this->buildBefore(), $list, $this->buildAfter());
|
||||
|
||||
$this->buildList = $list;
|
||||
}
|
||||
|
||||
return $this->buildList;
|
||||
}
|
||||
|
||||
public function children(): array
|
||||
{
|
||||
return $this->block('children');
|
||||
}
|
||||
|
||||
public function block(string $name): array
|
||||
{
|
||||
$list = array();
|
||||
if(isset($this->blocks[$name]))
|
||||
{
|
||||
$items = $this->blocks[$name];
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(is_array($item)) $list = array_merge($list, $item);
|
||||
else $list[] = $item;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function hasBlock(string $name): bool
|
||||
{
|
||||
return isset($this->blocks[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to JSON object.
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function toJSON(): object
|
||||
{
|
||||
$json = new stdClass();
|
||||
$json->gid = $this->gid;
|
||||
$json->type = $this->shortType();
|
||||
$json->props = $this->props->toJSON();
|
||||
|
||||
$json->blocks = array();
|
||||
foreach($this->blocks as $key => $block)
|
||||
{
|
||||
if($key === 'children')
|
||||
{
|
||||
$json->$key = $block;
|
||||
unset($json->blocks[$key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$json->blocks[$key] = $block;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$json->blocks) unset($json->blocks);
|
||||
|
||||
$id = $this->id();
|
||||
if($id !== null) $json->id = $id;
|
||||
|
||||
$parent = $this->parent;
|
||||
if($parent !== null) $json->parent = $parent->displayID();
|
||||
|
||||
if($this->removed) $json->removed = true;
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialized to JSON string.
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function jsonSerialize(): string
|
||||
{
|
||||
return json_encode($this->toJSON());
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger error in debug mode.
|
||||
*
|
||||
* @access public
|
||||
* @param string $message
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public function triggerError(string $message, int $level = E_USER_ERROR)
|
||||
{
|
||||
triggerError("{$this->displayID()}: $message", $level);
|
||||
}
|
||||
|
||||
protected function build()
|
||||
{
|
||||
return $this->children();
|
||||
}
|
||||
|
||||
protected function buildBefore(): array
|
||||
{
|
||||
return $this->block('before');
|
||||
}
|
||||
|
||||
protected function buildAfter(): array
|
||||
{
|
||||
return $this->block('after');
|
||||
}
|
||||
|
||||
protected function created()
|
||||
{
|
||||
}
|
||||
|
||||
protected function onAddChild(mixed $child)
|
||||
{
|
||||
return $child;
|
||||
}
|
||||
|
||||
protected function onAddBlock(mixed $child, string $name)
|
||||
{
|
||||
return $child;
|
||||
}
|
||||
|
||||
protected function onSetProp(array|string $prop, mixed $value)
|
||||
{
|
||||
if($prop === 'id' && $value === '$GID') $value = $this->gid;
|
||||
$this->props->set($prop, $value);
|
||||
}
|
||||
|
||||
protected function onGetProp(string $prop, mixed $defaultValue): mixed
|
||||
{
|
||||
return $this->props->get($prop, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check errors in debug mode.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function checkErrors()
|
||||
{
|
||||
if(!isDebug()) return;
|
||||
|
||||
$definedProps = static::definedPropsList();
|
||||
foreach($definedProps as $name => $definition)
|
||||
{
|
||||
if($this->hasProp($name)) continue;
|
||||
if(isset($definition['default']) && $definition['default'] !== null) continue;
|
||||
if(isset($definition['optional']) && $definition['optional']) continue;
|
||||
|
||||
$this->triggerError("The value of property \"$name: {$definition['type']}\" is required.");
|
||||
}
|
||||
|
||||
$wgErrors = $this->onCheckErrors();
|
||||
if(empty($wgErrors)) return;
|
||||
|
||||
foreach($wgErrors as $error)
|
||||
{
|
||||
if(is_array($error)) $this->triggerError(...$error);
|
||||
else $this->triggerError($error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The lifecycle method for checking errors in debug mode.
|
||||
*
|
||||
* @access protected
|
||||
* @return array|null
|
||||
*/
|
||||
protected function onCheckErrors(): ?array
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static array $definedPropsMap = array();
|
||||
|
||||
protected static array $blockMap = array();
|
||||
|
||||
public static function getBlockMap(): array
|
||||
{
|
||||
$type = get_called_class();
|
||||
if(!isset(node::$blockMap[$type]))
|
||||
{
|
||||
$blockMap = array();
|
||||
if(is_array(static::$defineBlocks))
|
||||
{
|
||||
foreach(static::$defineBlocks as $blockName => $setting)
|
||||
{
|
||||
if(!isset($setting['map'])) continue;
|
||||
$map = $setting['map'];
|
||||
if(is_string($map)) $map = explode(',', $map);
|
||||
foreach($map as $name) $blockMap[$name] = $blockName;
|
||||
}
|
||||
}
|
||||
node::$blockMap[$type] = $blockMap;
|
||||
}
|
||||
return node::$blockMap[$type];
|
||||
}
|
||||
|
||||
public static function getNameFromBlockMap(string $type): ?string
|
||||
{
|
||||
$blockMap = static::getBlockMap();
|
||||
if(str_starts_with($type, 'zin\\')) $type = substr($type, 4);
|
||||
return isset($blockMap[$type]) ? $blockMap[$type] : null;
|
||||
}
|
||||
|
||||
public static function definedPropsList(?string $type = null): array
|
||||
{
|
||||
if($type === null) $type = get_called_class();
|
||||
|
||||
if(!isset(node::$definedPropsMap[$type]) && $type === get_called_class())
|
||||
{
|
||||
node::$definedPropsMap[$type] = static::parsePropsDefinition(static::$defineProps);
|
||||
}
|
||||
return node::$definedPropsMap[$type];
|
||||
}
|
||||
|
||||
public static function getDefaultProps(?string $type = null): array
|
||||
{
|
||||
$defaultProps = array();
|
||||
foreach(static::definedPropsList($type) as $name => $definition)
|
||||
{
|
||||
if(!isset($definition['default'])) continue;
|
||||
$defaultProps[$name] = $definition['default'];
|
||||
}
|
||||
return $defaultProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse props definition
|
||||
* @param $definition
|
||||
* @example
|
||||
*
|
||||
* $definition = array('name', 'desc:string', 'title?:string|array', 'icon?:string="star"');
|
||||
* $definition = array('name' => 'mixed', 'desc' => '?string', 'title' => array('type' => 'string|array', 'optional' => true), 'icon' => array('type' => 'string', 'default' => 'star', 'optional' => true))))
|
||||
*/
|
||||
protected static function parsePropsDefinition(array $definition): array
|
||||
{
|
||||
$parentClass = get_parent_class(get_called_class());
|
||||
$parentProps = array();
|
||||
$defaultProps = static::$defaultProps;
|
||||
|
||||
if($parentClass)
|
||||
{
|
||||
$parentProps = call_user_func("$parentClass::definedPropsList", $parentClass);
|
||||
if($defaultProps === $parentClass::$defaultProps)
|
||||
{
|
||||
$defaultProps = array();
|
||||
}
|
||||
}
|
||||
|
||||
return parsePropsMap($definition, $parentProps, $defaultProps);
|
||||
}
|
||||
}
|
||||
|
||||
function renderToHtml(mixed ...$items): string
|
||||
{
|
||||
$html = '';
|
||||
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(is_array($item))
|
||||
{
|
||||
$html .= renderToHtml(...$item);
|
||||
continue;
|
||||
}
|
||||
if($item instanceof node || (is_object($item) && method_exists($item, 'render')))
|
||||
{
|
||||
$html .= $item->render();
|
||||
continue;
|
||||
}
|
||||
if(is_object($item) && isset($item->html))
|
||||
{
|
||||
$html .= $item->html;
|
||||
continue;
|
||||
}
|
||||
if(!is_string($item)) $item = strval($item);
|
||||
$html .= htmlspecialchars(strval($item), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, null, false);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the props definition.
|
||||
*
|
||||
* @param array $definition - The props definition.
|
||||
* @param array $parentProps - The parent props.
|
||||
* @param array $defaultValues - The default values.
|
||||
* @return array
|
||||
*/
|
||||
function parsePropsMap(array $definition, array $parentProps = array(), array $defaultValues = array())
|
||||
{
|
||||
$props = $parentProps;
|
||||
|
||||
foreach($definition as $name => $value)
|
||||
{
|
||||
$prop = parseProp($value, is_string($name) ? $name : null);
|
||||
$name = $prop['name'];
|
||||
|
||||
if($prop['default'] === null)
|
||||
{
|
||||
if(isset($defaultValues[$prop['name']])) $prop['default'] = $defaultValues[$prop['name']];
|
||||
else if(isset($parentProps[$prop['name']])) $prop['default'] = $parentProps[$prop['name']]['default'];
|
||||
}
|
||||
|
||||
$props[$name] = $prop;
|
||||
}
|
||||
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the prop definition.
|
||||
*
|
||||
* @param string|array $definition - The prop definition.
|
||||
* @param string|null $name - The prop name.
|
||||
* @param mixed $default - The default value.
|
||||
* @return array
|
||||
*/
|
||||
function parseProp(string|array $definition, ?string $name = null, mixed $default = null)
|
||||
{
|
||||
$optional = false;
|
||||
$type = 'mixed';
|
||||
|
||||
if(is_string($definition)) $definition = trim($definition);
|
||||
|
||||
/* Parse definition like `'name?: type1|type2="default"'` . */
|
||||
if(!$name && is_string($definition))
|
||||
{
|
||||
if(str_contains($definition, ':'))
|
||||
{
|
||||
list($name, $definition) = explode(':', $definition, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
$name = $definition;
|
||||
$definition = '';
|
||||
}
|
||||
$name = trim($name);
|
||||
if(str_ends_with($name, '?'))
|
||||
{
|
||||
$name = substr($name, 0, strlen($name) - 1);
|
||||
$optional = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse definition like `'name' => '?type1|type2="default"'` . */
|
||||
if(is_array($definition))
|
||||
{
|
||||
if(isset($definition['type'])) $type = $definition['type'];
|
||||
if(isset($definition['default'])) $default = $definition['default'];
|
||||
if(isset($definition['optional'])) $optional = $definition['optional'];
|
||||
}
|
||||
else if(is_string($definition))
|
||||
{
|
||||
if(str_contains($definition, '='))
|
||||
{
|
||||
list($type, $default) = explode('=', $definition, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = $definition;
|
||||
}
|
||||
if(is_string($default)) $default = json_decode(trim($default));
|
||||
}
|
||||
|
||||
$type = trim($type);
|
||||
if(str_starts_with($type, '?'))
|
||||
{
|
||||
$type = substr($type, 1);
|
||||
$optional = true;
|
||||
}
|
||||
|
||||
$typeList = explode('|', $type);
|
||||
if(in_array('null', $typeList) || in_array('mixed', $typeList))
|
||||
{
|
||||
$optional = true;
|
||||
}
|
||||
elseif($optional)
|
||||
{
|
||||
array_unshift($typeList, 'null');
|
||||
}
|
||||
|
||||
return array('name' => $name, 'type' => implode('|', $typeList), 'default' => $default, 'optional' => $default !== null || $optional);
|
||||
}
|
||||
@@ -12,10 +12,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'zin.func.php';
|
||||
require_once __DIR__ . DS . 'jscallback.class.php';
|
||||
|
||||
use zin\wg;
|
||||
use zin\node;
|
||||
|
||||
/**
|
||||
* Events binding class.
|
||||
@@ -170,16 +170,16 @@ class on extends jsCallback
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply to widget.
|
||||
* Apply to node.
|
||||
* 应用到部件。
|
||||
*
|
||||
* @access public
|
||||
* @param wg $wg The widget instance.
|
||||
* @param node $node The node instance.
|
||||
* @param string $blockName The block name.
|
||||
* @return void
|
||||
* @override
|
||||
*/
|
||||
public function applyToWg(wg &$wg, string $blockName): void
|
||||
public function apply(node $node, string $blockName): void
|
||||
{
|
||||
if($this->compatible)
|
||||
{
|
||||
@@ -187,12 +187,12 @@ class on extends jsCallback
|
||||
$options['selector'] = $this->selector;
|
||||
$options['handler'] = parent::buildBody('');
|
||||
|
||||
$wg->setProp("@{$this->event}", (object)$options);
|
||||
$node->setProp("@{$this->event}", (object)$options);
|
||||
return;
|
||||
}
|
||||
|
||||
$zuiInitCode = $wg->prop('zui-init', '');
|
||||
$wg->setProp('zui-init', $zuiInitCode . "\n" . $this->toJS());
|
||||
$zuiInitCode = $node->prop('zui-init', '');
|
||||
$node->setProp('zui-init', $zuiInitCode . "\n" . $this->toJS());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,8 +70,6 @@ class props extends \zin\utils\dataset
|
||||
elseif(str_starts_with($prop, '~')) $this->style->set(substr($prop, 1), $value);
|
||||
elseif($prop === '--') $this->style->cssVar($value);
|
||||
elseif(str_starts_with($prop, '--')) $this->style->cssVar(substr($prop, 2), $value);
|
||||
elseif($prop === '!') $this->hx($value);
|
||||
elseif(str_starts_with($prop, '!')) $this->hx(substr($prop, 1), $value);
|
||||
elseif(str_starts_with($prop, ':')) $this->set('data-' . substr($prop, 1), $value);
|
||||
elseif($prop === '@') $this->bindEvent($value);
|
||||
elseif(str_starts_with($prop, '@')) $this->bindEvent(substr($prop, 1), $value);
|
||||
@@ -149,17 +147,6 @@ class props extends \zin\utils\dataset
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hx(array|string $name, ?string $value = null)
|
||||
{
|
||||
if(is_array($name))
|
||||
{
|
||||
foreach($name as $key => $val) $this->set("hx-$key", $val);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set("hx-$name", $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert props to html string
|
||||
*
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The rawContent class file of zin lib.
|
||||
*
|
||||
* @copyright Copyright 2023 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @version $Id
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.class.php';
|
||||
|
||||
class rawContent extends wg
|
||||
{
|
||||
protected function build(): directive
|
||||
{
|
||||
return h::comment('{{RAW_CONTENT}}');
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,8 @@ require_once __DIR__ . DS . 'hook.class.php';
|
||||
function render(string $wgName = '', array $options = array())
|
||||
{
|
||||
/* 获取全局渲染部件实例和指令。 Get global render widgets and directives. */
|
||||
$globalItems = zin::getGlobalRenderList();
|
||||
$context = context();
|
||||
$globalItems = $context->getGlobalRenderList();
|
||||
|
||||
/* 决定部件名称,如果是 Ajax 请求则进行特殊处理。 Decide widget name, if is ajax request, then do special process. */
|
||||
if(empty($wgName))
|
||||
@@ -51,17 +52,17 @@ function render(string $wgName = '', array $options = array())
|
||||
/* 创建部件实例。 Create widget instance. */
|
||||
$wg = createWg($wgName, $globalItems);
|
||||
|
||||
/* 如果不是渲染一个完整页面,则使用 fragment 进行渲染。 If not render in full page, then render all items in a fragment. */
|
||||
if(!$isFullPage && $wgName !== 'fragment') $wg = fragment($wg);
|
||||
|
||||
/* 设置全局根部件。 Set global root widget. */
|
||||
hook::$globalRoot = $wg;
|
||||
|
||||
/* 添加 hooks 内容。Add hooks contents. */
|
||||
$wg->add(includeHooks());
|
||||
|
||||
/* 如果不是渲染一个完整页面,则使用 fragment 进行渲染。 If not render in full page, then render all items in a fragment. */
|
||||
if(!$isFullPage && $wgName !== 'fragment') $wg = fragment($wg);
|
||||
|
||||
/* 渲染并输出 HTML。 Render and display html. */
|
||||
$wg->display($options);
|
||||
// $wg->display($options);
|
||||
|
||||
zin::$rendered = true;
|
||||
$context->rendered = true;
|
||||
}
|
||||
|
||||
+123
-5
@@ -12,12 +12,34 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'setting.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
require_once __DIR__ . DS . 'context.func.php';
|
||||
|
||||
class set
|
||||
class set extends setting implements iDirective
|
||||
{
|
||||
public static function __callStatic($prop, $args)
|
||||
/**
|
||||
* Create an instance, the initialed data can be passed.
|
||||
*
|
||||
* @access public
|
||||
* @param array|object|string $data Properties list array.
|
||||
* @param mixed $value Property value.
|
||||
*/
|
||||
public function __construct(array|string $data = null, mixed $value = null)
|
||||
{
|
||||
parent::__construct($data, $value);
|
||||
|
||||
renderInGlobal($this);
|
||||
}
|
||||
|
||||
public function apply(node $node, string $blockName): void
|
||||
{
|
||||
$node->setProp($this->toArray());
|
||||
}
|
||||
|
||||
public static function __callStatic($prop, $args): set
|
||||
{
|
||||
$set = new set();
|
||||
if($prop === 'class' || strtolower($prop) === 'classname')
|
||||
{
|
||||
global $config;
|
||||
@@ -25,13 +47,13 @@ class set
|
||||
{
|
||||
trigger_error("[ZIN] Use set::className() instead of set::class() to compatible with php 5.4.", E_USER_WARNING);
|
||||
}
|
||||
return directive('prop', array('class' => $args));
|
||||
return $set->setClass('class', $args);
|
||||
}
|
||||
|
||||
/* Compatible with zui prop className. */
|
||||
if($prop === '_className')
|
||||
{
|
||||
return directive('prop', array('className' => $args));
|
||||
return $set->setClass('className', $args);
|
||||
}
|
||||
|
||||
/* Support to set url with createLink params. */
|
||||
@@ -44,6 +66,102 @@ class set
|
||||
$value = count($args) > 1 ? $args : array_shift($args);
|
||||
}
|
||||
|
||||
return directive('prop', array($prop => $value));
|
||||
return $set->set($prop, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget properties.
|
||||
*
|
||||
* @param string|array|props|null $name
|
||||
* @param mixed $value
|
||||
* @return set
|
||||
*/
|
||||
function set(string|array|props|null $name = null, mixed $value = null): set
|
||||
{
|
||||
$set = new set();
|
||||
if($name === null) return $set;
|
||||
|
||||
$props = null;
|
||||
if($name instanceof props) $props = $name->toArray();
|
||||
else if(is_array($name)) $props = $name;
|
||||
else if(is_object($name)) $props = (array)$name;
|
||||
else if(is_string($name)) $props = array($name => $value);
|
||||
$set->set($props);
|
||||
return $set;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set widget CSS class attribute.
|
||||
*
|
||||
* @param mixed ...$class
|
||||
* @return set
|
||||
*/
|
||||
function setClass(mixed ...$class): set
|
||||
{
|
||||
return set()->setClass('class', ...$class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget style attribute.
|
||||
*
|
||||
* @return set
|
||||
*/
|
||||
function setStyle(array|string $name, ?string $value = null): set
|
||||
{
|
||||
return set()->addToMap('style', is_array($name) ? $name : array($name => $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget CSS variable.
|
||||
*
|
||||
* @return set
|
||||
*/
|
||||
function setCssVar(array|string $name, ?string $value = null): set
|
||||
{
|
||||
return set()->addToMap('--', is_array($name) ? $name : array($name => $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget ID attribute.
|
||||
*
|
||||
* @return ?set
|
||||
*/
|
||||
function setID(?string $id = null): set
|
||||
{
|
||||
return set('id', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget element tag name.
|
||||
*
|
||||
* @return set
|
||||
*/
|
||||
function setTag(string $id): set
|
||||
{
|
||||
return set('tagName', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget data-* attribute.
|
||||
*
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
* @return set
|
||||
*/
|
||||
function setData(null|string|array $name, mixed $value = null): set
|
||||
{
|
||||
if($name === null) return set();
|
||||
$map = is_array($name) ? $name : array($name => $value);
|
||||
$attrs = array();
|
||||
foreach($map as $key => $value)
|
||||
{
|
||||
if(is_numeric($key)) $key = (string)$key;
|
||||
$name = 'data-' . strtolower(preg_replace('/(?<!^)[A-Z]/', '-$0', $key));
|
||||
if(is_bool($value)) $attrs[$name] = $value ? 'true' : 'false';
|
||||
else if(is_array($value)) $attrs[$name] = json_encode($value);
|
||||
else $attrs[$name] = $value;
|
||||
}
|
||||
return set($attrs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The text element class file of zin of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2023 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @version $Id
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'node.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
|
||||
class text extends node
|
||||
{
|
||||
public static array $defineProps = array
|
||||
(
|
||||
'html' => '?bool',
|
||||
);
|
||||
|
||||
public function type(): string
|
||||
{
|
||||
return 'node::' . $this->shortType();
|
||||
}
|
||||
|
||||
public function shortType(): string
|
||||
{
|
||||
return $this->prop('html') ? 'html' : 'text';
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
if($this->prop('html')) return implode('', $this->children());
|
||||
return parent::render();
|
||||
}
|
||||
}
|
||||
|
||||
function text(string ...$texts): text
|
||||
{
|
||||
return new text(...$texts);
|
||||
}
|
||||
|
||||
function html(string ...$codes): text
|
||||
{
|
||||
$text = new text(...$codes);
|
||||
$text->setProp('html', true);
|
||||
return $text;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'wg.func.php';
|
||||
require_once __DIR__ . DS . 'zin.func.php';
|
||||
|
||||
class to
|
||||
{
|
||||
|
||||
+49
-772
@@ -12,645 +12,55 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
require_once __DIR__ . DS . 'props.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
require_once __DIR__ . DS . 'setting.class.php';
|
||||
require_once __DIR__ . DS . 'zin.class.php';
|
||||
require_once __DIR__ . DS . 'context.class.php';
|
||||
require_once __DIR__ . DS . 'selector.func.php';
|
||||
require_once __DIR__ . DS . 'dom.class.php';
|
||||
require_once __DIR__ . DS . 'node.class.php';
|
||||
|
||||
class wg
|
||||
class wg extends node
|
||||
{
|
||||
/**
|
||||
* Define props for the element
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static array $defineProps = array();
|
||||
// public function buildEvents(): ?string
|
||||
// {
|
||||
// $events = $this->props->events();
|
||||
// if(empty($events)) return null;
|
||||
|
||||
protected static array $defaultProps = array();
|
||||
// $id = $this->id();
|
||||
// $code = array($this->shortType() === 'html' ? 'const ele = document;' : 'const ele = document.getElementById("' . (empty($id) ? $this->gid : $id) . '");if(!ele)return;const $ele = $(ele); const events = new Set(($ele.attr("data-zin-events") || "").split(" ").filter(Boolean));');
|
||||
// foreach($events as $event => $bindingList)
|
||||
// {
|
||||
// $code[] = "\$ele.on('$event.on.zin', function(e){";
|
||||
// foreach($bindingList as $binding)
|
||||
// {
|
||||
// if(is_string($binding)) $binding = (object)array('handler' => $binding);
|
||||
// $selector = isset($binding->selector) ? $binding->selector : null;
|
||||
// $handler = isset($binding->handler) ? trim($binding->handler) : '';
|
||||
// $stop = isset($binding->stop) ? $binding->stop : null;
|
||||
// $prevent = isset($binding->prevent) ? $binding->prevent : null;
|
||||
// $self = isset($binding->self) ? $binding->self : null;
|
||||
|
||||
protected static array $defineBlocks = array();
|
||||
// $code[] = '(function(){';
|
||||
// if($selector) $code[] = "const target = e.target.closest('$selector');if(!target) return;";
|
||||
// else $code[] = "const target = ele;";
|
||||
// if($self) $code[] = "if(ele !== e.target) return;";
|
||||
// if($stop) $code[] = "e.stopPropagation();";
|
||||
// if($prevent) $code[] = "e.preventDefault();";
|
||||
|
||||
protected static array $wgToBlockMap = array();
|
||||
// if(preg_match('/^[$A-Z_][0-9A-Z_$\[\]."\']*$/i', $handler)) $code[] = "($handler).call(target,e);";
|
||||
// else $code[] = $handler;
|
||||
|
||||
protected static array $definedPropsMap = array();
|
||||
// $code[] = '})();';
|
||||
// }
|
||||
// $code[] = "});events.add('$event');";
|
||||
// }
|
||||
// $code[] = '$ele.attr("data-zin-events", Array.from(events).join(" "));';
|
||||
// return h::createJsScopeCode($code);
|
||||
// }
|
||||
|
||||
protected static array $pageResources = array();
|
||||
|
||||
/**
|
||||
* The props of the element
|
||||
*
|
||||
* @access public
|
||||
* @var props
|
||||
*/
|
||||
public props $props;
|
||||
|
||||
public array $blocks = array();
|
||||
|
||||
public ?wg $parent = null;
|
||||
|
||||
public string $gid;
|
||||
|
||||
public bool $displayed = false;
|
||||
|
||||
public bool $removed = false;
|
||||
|
||||
protected array $renderOptions = array();
|
||||
|
||||
public function __construct(/* string|element|object|array|null ...$args */)
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
$this->props = new props();
|
||||
|
||||
$this->gid = 'zin_' . uniqid();
|
||||
$this->setDefaultProps(static::getDefaultProps());
|
||||
$this->add(func_get_args());
|
||||
$this->created();
|
||||
|
||||
zin::renderInGlobal($this);
|
||||
static::checkPageResources();
|
||||
|
||||
$this->checkErrors();
|
||||
return null; // No css
|
||||
}
|
||||
|
||||
public function __debugInfo(): array
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return $this->toJSON();
|
||||
}
|
||||
|
||||
public function isDomElement(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the element is match any of the selectors
|
||||
* @param string|array|object $selectors
|
||||
*/
|
||||
public function isMatch(string|array|object $selectors): bool
|
||||
{
|
||||
$list = parseWgSelectors($selectors);
|
||||
foreach($list as $selector)
|
||||
{
|
||||
if(isset($selector->command)) continue;
|
||||
if(!empty($selector->id) && $this->id() !== $selector->id) continue;
|
||||
if(!empty($selector->tag) && $this->shortType() !== $selector->tag) continue;
|
||||
if(!empty($selector->class) && !$this->props->class->has($selector->class)) continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build dom object
|
||||
* @return dom
|
||||
*/
|
||||
public function buildDom(): dom
|
||||
{
|
||||
$before = $this->buildBefore();
|
||||
$children = $this->build();
|
||||
$after = $this->buildAfter();
|
||||
$options = $this->renderOptions;
|
||||
$selectors = (!empty($options) && isset($options['selector'])) ? $options['selector'] : null;
|
||||
|
||||
return new dom
|
||||
(
|
||||
$this,
|
||||
[$before, $children, $after],
|
||||
$selectors,
|
||||
(!empty($options) && isset($options['type'])) ? $options['type'] : 'html', // TODO: () may not work in lower php
|
||||
(!empty($options) && isset($options['data'])) ? $options['data'] : null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark widget been removed.
|
||||
*
|
||||
* @param string $selector
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function remove(string $selector = '')
|
||||
{
|
||||
if(!empty($selector))
|
||||
{
|
||||
$list = $this->find($selector);
|
||||
foreach($list as $item) $item->remove();
|
||||
return;
|
||||
}
|
||||
$this->removed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find widgets by selector.
|
||||
*
|
||||
* @param string|array|object $selector
|
||||
* @param string $blockName
|
||||
* @param bool $nested
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
public function find(string|array|object $selector, string $blockName = '', bool $nested = true): array
|
||||
{
|
||||
$selectors = parseWgSelectors($selector);
|
||||
$result = array();
|
||||
$blocks = empty($blockName) ? $this->blocks : array($blockName => isset($this->blocks[$blockName]) ? $this->blocks[$blockName] : array());
|
||||
foreach($blocks as $items)
|
||||
{
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(!($item instanceof wg)) continue;
|
||||
|
||||
if($item->isMatch($selectors)) $result[] = $item;
|
||||
elseif($nested) $result = array_merge($result, $item->find($selectors, '', $nested));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find children widgets by selector.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
public function findChildren(string $selector): array
|
||||
{
|
||||
return $this->find($selector, 'children', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first widget by selector.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return wg|null
|
||||
* @access public
|
||||
*/
|
||||
public function first(string $selector = ''): wg | null
|
||||
{
|
||||
return reset($this->find($selector));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find last widget by selector.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return wg|null
|
||||
* @access public
|
||||
*/
|
||||
public function last(string $selector = ''): wg | null
|
||||
{
|
||||
return end($this->find($selector));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render widget to html
|
||||
* @return string
|
||||
*/
|
||||
public function render(): string
|
||||
{
|
||||
if($this->removed) return '';
|
||||
|
||||
$dom = $this->buildDom();
|
||||
$result = $dom->render();
|
||||
|
||||
return is_string($result) ? $result : json_encode($result);
|
||||
}
|
||||
|
||||
public function display(array $options = array()): wg
|
||||
{
|
||||
zin::disableGlobalRender();
|
||||
$this->renderOptions = $options;
|
||||
|
||||
$dom = $this->buildDom();
|
||||
$result = $dom->render();
|
||||
$context = context::current();
|
||||
$css = $context->getCSS();
|
||||
$js = $context->getJS();
|
||||
|
||||
global $app, $config;
|
||||
$zinDebug = null;
|
||||
if($config->debug && (!isAjaxRequest() || isAjaxRequest('zin')))
|
||||
{
|
||||
$zinDebug = data('zinDebug');
|
||||
if(is_array($zinDebug))
|
||||
{
|
||||
$zinDebug['basePath'] = $app->getBasePath();
|
||||
if(isset($app->zinErrors)) $zinDebug['errors'] = $app->zinErrors;
|
||||
}
|
||||
}
|
||||
|
||||
$rawContent = ob_get_contents();
|
||||
if(!is_string($rawContent)) $rawContent = '';
|
||||
ob_end_clean();
|
||||
|
||||
if(is_object($result))
|
||||
{
|
||||
if($zinDebug && isset($result['zinDebug'])) $result['zinDebug'] = $zinDebug;
|
||||
$result = json_encode($result);
|
||||
}
|
||||
elseif(is_array($result))
|
||||
{
|
||||
foreach($result as $index => $item)
|
||||
{
|
||||
if($item['name'] === 'zinDebug' && $zinDebug)
|
||||
{
|
||||
$result[$index]['data'] = $zinDebug;
|
||||
continue;
|
||||
}
|
||||
if(!isset($item['type']) || $item['type'] !== 'html') continue;
|
||||
|
||||
$data = $item['data'];
|
||||
$data = str_replace('/*{{ZIN_PAGE_CSS}}*/', $css, $data);
|
||||
$data = str_replace('/*{{ZIN_PAGE_JS}}*/', $js, $data);
|
||||
$data = str_replace('<!-- {{RAW_CONTENT}} -->', $rawContent, $data);
|
||||
$result[$index]['data'] = $data;
|
||||
}
|
||||
$result = json_encode($result, JSON_PARTIAL_OUTPUT_ON_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
if($zinDebug) $js .= h::createJsVarCode('window.zinDebug', $zinDebug);
|
||||
$result = str_replace('/*{{ZIN_PAGE_CSS}}*/', $css, $result);
|
||||
$result = str_replace('/*{{ZIN_PAGE_JS}}*/', $js, $result);
|
||||
$result = str_replace('<!-- {{RAW_CONTENT}} -->', $rawContent, $result);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
echo $result;
|
||||
|
||||
$this->displayed = true;
|
||||
context::destroy();
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function created() {}
|
||||
|
||||
protected function buildBefore(): array
|
||||
{
|
||||
return $this->block('before');
|
||||
}
|
||||
|
||||
protected function buildAfter(): array
|
||||
{
|
||||
return $this->block('after');
|
||||
}
|
||||
|
||||
protected function build()
|
||||
{
|
||||
if($this->removed) return array();
|
||||
|
||||
return $this->children();
|
||||
}
|
||||
|
||||
public function buildEvents(): ?string
|
||||
{
|
||||
$events = $this->props->events();
|
||||
if(empty($events)) return null;
|
||||
|
||||
$id = $this->id();
|
||||
$code = array($this->shortType() === 'html' ? 'const ele = document;' : 'const ele = document.getElementById("' . (empty($id) ? $this->gid : $id) . '");if(!ele)return;const $ele = $(ele); const events = new Set(($ele.attr("data-zin-events") || "").split(" ").filter(Boolean));');
|
||||
foreach($events as $event => $bindingList)
|
||||
{
|
||||
$code[] = "\$ele.on('$event.on.zin', function(e){";
|
||||
foreach($bindingList as $binding)
|
||||
{
|
||||
if(is_string($binding)) $binding = (object)array('handler' => $binding);
|
||||
$selector = isset($binding->selector) ? $binding->selector : null;
|
||||
$handler = isset($binding->handler) ? trim($binding->handler) : '';
|
||||
$stop = isset($binding->stop) ? $binding->stop : null;
|
||||
$prevent = isset($binding->prevent) ? $binding->prevent : null;
|
||||
$self = isset($binding->self) ? $binding->self : null;
|
||||
|
||||
$code[] = '(function(){';
|
||||
if($selector) $code[] = "const target = e.target.closest('$selector');if(!target) return;";
|
||||
else $code[] = "const target = ele;";
|
||||
if($self) $code[] = "if(ele !== e.target) return;";
|
||||
if($stop) $code[] = "e.stopPropagation();";
|
||||
if($prevent) $code[] = "e.preventDefault();";
|
||||
|
||||
if(preg_match('/^[$A-Z_][0-9A-Z_$\[\]."\']*$/i', $handler)) $code[] = "($handler).call(target,e);";
|
||||
else $code[] = $handler;
|
||||
|
||||
$code[] = '})();';
|
||||
}
|
||||
$code[] = "});events.add('$event');";
|
||||
}
|
||||
$code[] = '$ele.attr("data-zin-events", Array.from(events).join(" "));';
|
||||
return h::createJsScopeCode($code);
|
||||
}
|
||||
|
||||
|
||||
protected function onAddBlock(array|string|wg|directive $child, string $name)
|
||||
{
|
||||
return $child;
|
||||
}
|
||||
|
||||
protected function onAddChild(array|string|wg|directive $child)
|
||||
{
|
||||
return $child;
|
||||
}
|
||||
|
||||
protected function onSetProp(array|string $prop, mixed $value)
|
||||
{
|
||||
if($prop === 'id' && $value === '$GID') $value = $this->gid;
|
||||
if($prop[0] === '@')
|
||||
{
|
||||
$this->setDefaultProps(array('id' => $this->gid));
|
||||
context::current()->addWgWithEvents($this);
|
||||
}
|
||||
$this->props->set($prop, $value);
|
||||
}
|
||||
|
||||
protected function onGetProp(string $prop, mixed $defaultValue): mixed
|
||||
{
|
||||
return $this->props->get($prop, $defaultValue);
|
||||
}
|
||||
|
||||
public function add($item, string $blockName = 'children')
|
||||
{
|
||||
if($item === null || is_bool($item)) return $this;
|
||||
|
||||
if(is_array($item))
|
||||
{
|
||||
foreach($item as $child) $this->add($child, $blockName);
|
||||
return $this;
|
||||
}
|
||||
|
||||
zin::disableGlobalRender();
|
||||
|
||||
if($item instanceof setting) $item = $item->toDirective();
|
||||
|
||||
if($item instanceof wg) $this->addToBlock($blockName, $item);
|
||||
elseif(is_string($item)) $this->addToBlock($blockName, htmlspecialchars($item, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, null, false));
|
||||
elseif(isDirective($item)) $this->directive($item, $blockName);
|
||||
else $this->addToBlock($blockName, htmlspecialchars(strval($item), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, null, false));
|
||||
|
||||
zin::enableGlobalRender();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addToBlock(array|string $name, array|string|null|wg|directive $child = null)
|
||||
{
|
||||
if(is_array($name))
|
||||
{
|
||||
foreach($name as $blockName => $blockChildren)
|
||||
{
|
||||
$this->addToBlock($blockName, $blockChildren);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(is_array($child))
|
||||
{
|
||||
foreach($child as $blockChild)
|
||||
{
|
||||
$this->addToBlock($name, $blockChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if($child instanceof wg && empty($child->parent)) $child->parent = &$this;
|
||||
|
||||
if($name === 'children' && $child instanceof wg)
|
||||
{
|
||||
$blockName = static::getBlockNameForWg($child);
|
||||
if($blockName !== null) $name = $blockName;
|
||||
}
|
||||
|
||||
$result = $name === 'children' ? $this->onAddChild($child) : $this->onAddBlock($child, $name);
|
||||
|
||||
if($result === false) return;
|
||||
if($result !== null && $result !== true) $child = $result;
|
||||
|
||||
if(isset($this->blocks[$name])) $this->blocks[$name][] = $child;
|
||||
else $this->blocks[$name] = array($child);
|
||||
}
|
||||
|
||||
public function children(): array
|
||||
{
|
||||
return $this->block('children');
|
||||
}
|
||||
|
||||
public function block(string $name): array
|
||||
{
|
||||
$list = array();
|
||||
if(isset($this->blocks[$name]))
|
||||
{
|
||||
$items = $this->blocks[$name];
|
||||
foreach($items as $item)
|
||||
{
|
||||
$isWg = $item instanceof wg && $item->shortType() === 'wg';
|
||||
$item = $isWg ? $item->children() : $item;
|
||||
if(is_array($item)) $list = array_merge($list, $item);
|
||||
else $list[] = $item;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function hasBlock(string $name): bool
|
||||
{
|
||||
return isset($this->blocks[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply directive
|
||||
*/
|
||||
public function directive(directive &$directive, string $blockName)
|
||||
{
|
||||
$directive->parent = &$this;
|
||||
$directive->applyToWg($this, $blockName);
|
||||
}
|
||||
|
||||
public function prop(array|string $name, mixed $defaultValue = null): mixed
|
||||
{
|
||||
if(is_array($name))
|
||||
{
|
||||
$values = array();
|
||||
foreach($name as $index => $propName)
|
||||
{
|
||||
$values[] = $this->onGetProp($propName, is_array($defaultValue) ? (isset($defaultValue[$propName]) ? $defaultValue[$propName] : $defaultValue[$index]) : $defaultValue);
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $this->onGetProp($name, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set property, an array can be passed to set multiple properties
|
||||
*
|
||||
* @access public
|
||||
* @param props|array|string $prop - Property name or properties list
|
||||
* @param mixed $value - Property value
|
||||
*/
|
||||
public function setProp(props|array|string $prop, mixed $value = null)
|
||||
{
|
||||
if($prop instanceof props) $prop = $prop->toJSON();
|
||||
|
||||
if(is_array($prop))
|
||||
{
|
||||
foreach($prop as $name => $value) $this->setProp($name, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(!is_string($prop) || empty($prop)) return $this;
|
||||
|
||||
if($prop[0] === '#')
|
||||
{
|
||||
$this->add($value, substr($prop, 1));
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->onSetProp($prop, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasProp(): bool
|
||||
{
|
||||
$names = func_get_args();
|
||||
if(empty($names)) return false;
|
||||
foreach($names as $name)
|
||||
{
|
||||
if(!$this->props->has($name)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setDefaultProps(array $props)
|
||||
{
|
||||
if(!is_array($props) || empty($props)) return;
|
||||
|
||||
foreach($props as $name => $value)
|
||||
{
|
||||
if($this->props->has($name)) continue;
|
||||
$this->setProp($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRestProps(): array
|
||||
{
|
||||
return $this->props->skip(array_keys(static::definedPropsList()));
|
||||
}
|
||||
|
||||
public function getDefinedProps(): array
|
||||
{
|
||||
return $this->props->pick(array_keys(static::definedPropsList()));
|
||||
}
|
||||
|
||||
public function type(): string
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
public function shortType(): string
|
||||
{
|
||||
$type = $this->type();
|
||||
$pos = strrpos($type, '\\');
|
||||
return $pos === false ? $type : substr($type, $pos + 1);
|
||||
}
|
||||
|
||||
public function id(): ?string
|
||||
{
|
||||
return $this->prop('id');
|
||||
}
|
||||
|
||||
public function toJSON(): array
|
||||
{
|
||||
$data = array();
|
||||
$data['gid'] = $this->gid;
|
||||
$data['id'] = $this->id();
|
||||
$data['removed'] = $this->removed;
|
||||
$data['props'] = $this->props->toJSON();
|
||||
|
||||
$data['type'] = $this->type();
|
||||
if(str_starts_with($data['type'], 'zin\\')) $data['type'] = substr($data['type'], 4);
|
||||
|
||||
$data['blocks'] = array();
|
||||
foreach($this->blocks as $key => $value)
|
||||
{
|
||||
foreach($value as $index => $child)
|
||||
{
|
||||
if($child instanceof wg || (is_object($child) && method_exists($child, 'toJSON')))
|
||||
{
|
||||
$value[$index] = $child->toJSON();
|
||||
}
|
||||
elseif(isDirective($child, 'html'))
|
||||
{
|
||||
$value[$index] = $child->data;
|
||||
}
|
||||
}
|
||||
if($key === 'children')
|
||||
{
|
||||
unset($data['blocks'][$key]);
|
||||
$data['children'] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['blocks'][$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($data['blocks'])) unset($data['blocks']);
|
||||
|
||||
if(!empty($this->parent)) $data['parent'] = $this->parent->gid;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check errors in debug mode.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function checkErrors()
|
||||
{
|
||||
global $config;
|
||||
if(!isset($config->debug) || !$config->debug) return;
|
||||
|
||||
$definedProps = static::definedPropsList();
|
||||
foreach($definedProps as $name => $definition)
|
||||
{
|
||||
if($this->hasProp($name)) continue;
|
||||
if(isset($definition['default']) && $definition['default'] !== null) continue;
|
||||
if(isset($definition['optional']) && $definition['optional']) continue;
|
||||
|
||||
trigger_error("[ZIN] The property \"$name: {$definition['type']}\" of widget \"{$this->type()}#$this->gid\" is required.", E_USER_ERROR);
|
||||
}
|
||||
|
||||
$wgErrors = $this->onCheckErrors();
|
||||
if(empty($wgErrors)) return;
|
||||
|
||||
foreach($wgErrors as $error)
|
||||
{
|
||||
if(is_array($error)) trigger_error("[ZIN] $error[0]", count($error) > 1 ? $error[1] : E_USER_WARNING);
|
||||
else trigger_error("[ZIN] $error", E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The lifecycle method for checking errors in debug mode.
|
||||
*
|
||||
* @access protected
|
||||
* @return array|null
|
||||
*/
|
||||
protected function onCheckErrors(): array|null
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
{
|
||||
return false; // No css
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
{
|
||||
return false; // No js
|
||||
return null; // No js
|
||||
}
|
||||
|
||||
protected static function checkPageResources()
|
||||
@@ -667,148 +77,15 @@ class wg
|
||||
if(!empty($pageJS)) context::js($pageJS);
|
||||
}
|
||||
|
||||
public static function wgBlockMap(): array
|
||||
{
|
||||
$wgName = get_called_class();
|
||||
if(!isset(wg::$wgToBlockMap[$wgName]))
|
||||
{
|
||||
$wgBlockMap = array();
|
||||
if(!empty(static::$defineBlocks))
|
||||
{
|
||||
foreach(static::$defineBlocks as $blockName => $setting)
|
||||
{
|
||||
if(!isset($setting['map'])) continue;
|
||||
$map = $setting['map'];
|
||||
if(is_string($map)) $map = explode(',', $map);
|
||||
foreach($map as $name) $wgBlockMap[$name] = $blockName;
|
||||
}
|
||||
}
|
||||
wg::$wgToBlockMap[$wgName] = $wgBlockMap;
|
||||
}
|
||||
return wg::$wgToBlockMap[$wgName];
|
||||
}
|
||||
|
||||
public static function getBlockNameForWg(wg|string $wg): ?string
|
||||
{
|
||||
$wgType = ($wg instanceof wg) ? $wg->type() : $wg;
|
||||
$wgBlockMap = static::wgBlockMap();
|
||||
if(str_starts_with($wgType, 'zin\\')) $wgType = substr($wgType, 4);
|
||||
return isset($wgBlockMap[$wgType]) ? $wgBlockMap[$wgType] : null;
|
||||
}
|
||||
|
||||
protected static function definedPropsList(?string $wgName = null): array
|
||||
{
|
||||
if($wgName === null) $wgName = get_called_class();
|
||||
|
||||
if(!isset(wg::$definedPropsMap[$wgName]) && $wgName === get_called_class())
|
||||
{
|
||||
wg::$definedPropsMap[$wgName] = static::parsePropsDefinition(static::$defineProps);
|
||||
}
|
||||
return wg::$definedPropsMap[$wgName];
|
||||
}
|
||||
|
||||
protected static function getDefaultProps(?string $wgName = null): array
|
||||
{
|
||||
$defaultProps = array();
|
||||
foreach(static::definedPropsList($wgName) as $name => $definition)
|
||||
{
|
||||
if(!isset($definition['default'])) continue;
|
||||
$defaultProps[$name] = $definition['default'];
|
||||
}
|
||||
return $defaultProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse props definition
|
||||
* @param $definition
|
||||
* @example
|
||||
*
|
||||
* $definition = array('name', 'desc:string', 'title?:string|element', 'icon?:string="star"');
|
||||
* $definition = array('name' => 'mixed', 'desc' => 'string', 'title' => array('type' => 'string|element', 'optional' => true), 'icon' => array('type' => 'string', 'default' => 'star', 'optional' => true))))
|
||||
*/
|
||||
private static function parsePropsDefinition(array $definition): array
|
||||
{
|
||||
$parentClass = get_parent_class(get_called_class());
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
$props = $parentClass ? call_user_func("$parentClass::definedPropsList") : array();
|
||||
|
||||
if($parentClass !== false && $definition === $parentClass::$defineProps)
|
||||
{
|
||||
if(!empty(static::$defaultProps) && static::$defaultProps !== $parentClass::$defaultProps)
|
||||
{
|
||||
foreach($props as $name => $value)
|
||||
{
|
||||
if(isset(static::$defaultProps[$name]))
|
||||
{
|
||||
$value['default'] = static::$defaultProps[$name];
|
||||
$props[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
|
||||
foreach($definition as $name => $value)
|
||||
{
|
||||
$optional = false;
|
||||
$type = 'mixed';
|
||||
$default = (isset($props[$name]) && isset($props[$name]['default'])) ? $props[$name]['default'] : null;
|
||||
|
||||
if(is_int($name) && is_string($value))
|
||||
{
|
||||
$value = trim($value);
|
||||
if(!str_contains($value, ':'))
|
||||
{
|
||||
$name = $value;
|
||||
$value = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
list($name, $value) = explode(':', $value, 2);
|
||||
}
|
||||
$name = trim($name);
|
||||
if($name[strlen($name) - 1] === '?')
|
||||
{
|
||||
$name = substr($name, 0, strlen($name) - 1);
|
||||
$optional = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_array($value))
|
||||
{
|
||||
$type = isset($value['type']) ? $value['type'] : $type;
|
||||
$default = isset($value['default']) ? $value['default'] : $default;
|
||||
$optional = isset($value['optional'])? $value['optional']: $optional;
|
||||
}
|
||||
else if(is_string($value))
|
||||
{
|
||||
if(!str_contains($value, '='))
|
||||
{
|
||||
$type = $value;
|
||||
$default = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
list($type, $default) = explode('=', $value, 2);
|
||||
}
|
||||
$type = trim($type);
|
||||
|
||||
if(is_string($default)) $default = json_decode(trim($default));
|
||||
}
|
||||
|
||||
$props[$name] = array('type' => empty($type) ? 'mixed' : $type, 'default' => $default, 'optional' => $default !== null || $optional);
|
||||
}
|
||||
|
||||
if(static::$defaultProps && (!$parentClass || static::$defaultProps !== $parentClass::$defaultProps))
|
||||
{
|
||||
foreach(static::$defaultProps as $name => $value)
|
||||
{
|
||||
if(!isset($props[$name])) continue;
|
||||
$props[$name]['default'] = $value;
|
||||
}
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
protected static array $pageResources = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an new widget.
|
||||
*
|
||||
* @return wg
|
||||
*/
|
||||
function wg(mixed ...$args): wg
|
||||
{
|
||||
return new wg(...$args);
|
||||
}
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The widget function file of zin module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author sunhao<sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'flat.func.php';
|
||||
require_once __DIR__ . DS . 'loader.func.php';
|
||||
require_once __DIR__ . DS . 'props.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
require_once __DIR__ . DS . 'setting.class.php';
|
||||
require_once __DIR__ . DS . 'rawcontent.class.php';
|
||||
require_once __DIR__ . DS . 'wg.class.php';
|
||||
require_once __DIR__ . DS . 'context.func.php';
|
||||
require_once __DIR__ . DS . 'on.class.php';
|
||||
require_once __DIR__ . DS . 'jquery.class.php';
|
||||
|
||||
/**
|
||||
* Create an new widget.
|
||||
*
|
||||
* @return wg
|
||||
*/
|
||||
function wg(): wg
|
||||
{
|
||||
return new wg(func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget properties.
|
||||
*
|
||||
* @param string|array|props|null $name
|
||||
* @param mixed $value
|
||||
* @return directive|null
|
||||
*/
|
||||
function set(string|array|props|null $name, mixed $value = null): ?directive
|
||||
{
|
||||
if($name === null) return null;
|
||||
|
||||
$props = null;
|
||||
if($name instanceof props) $props = $name;
|
||||
else if(is_array($name)) $props = $name;
|
||||
else if(is_object($name)) $props = (array)$name;
|
||||
else if(is_string($name)) $props = array($name => $value);
|
||||
return $props ? directive('prop', $props) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget CSS class attribute.
|
||||
*
|
||||
* @param array|string|null ...$classList
|
||||
* @return directive
|
||||
*/
|
||||
function setClass(/* array|string|null ...$classList */): directive
|
||||
{
|
||||
return directive('class', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget style attribute.
|
||||
*
|
||||
* @return directive
|
||||
*/
|
||||
function setStyle(array|string $name, ?string $value = null): directive
|
||||
{
|
||||
return directive('style', is_array($name) ? $name : array($name => $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget CSS variable.
|
||||
*
|
||||
* @return directive
|
||||
*/
|
||||
function setCssVar(array|string $name, ?string $value = null): directive
|
||||
{
|
||||
return directive('cssVar', is_array($name) ? $name : array($name => $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget ID attribute.
|
||||
*
|
||||
* @return ?directive
|
||||
*/
|
||||
function setID(?string $id = null): directive
|
||||
{
|
||||
return set('id', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget element tag name.
|
||||
*
|
||||
* @return directive
|
||||
*/
|
||||
function setTag(string $id): directive
|
||||
{
|
||||
return set('tagName', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set widget data-* attribute.
|
||||
*
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
* @return directive
|
||||
*/
|
||||
function setData(null|string|array $name, mixed $value = null): ?directive
|
||||
{
|
||||
if($name === null) return null;
|
||||
$map = is_array($name) ? $name : array($name => $value);
|
||||
$attrs = array();
|
||||
foreach($map as $key => $value)
|
||||
{
|
||||
if(is_numeric($key)) $key = (string)$key;
|
||||
$name = 'data-' . strtolower(preg_replace('/(?<!^)[A-Z]/', '-$0', $key));
|
||||
if(is_bool($value)) $attrs[$name] = $value ? 'true' : 'false';
|
||||
else if(is_array($value)) $attrs[$name] = json_encode($value);
|
||||
else $attrs[$name] = $value;
|
||||
}
|
||||
return set($attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create html content.
|
||||
*
|
||||
* @param string ...$lines
|
||||
* @return directive
|
||||
*/
|
||||
function html(/* string ...$lines */): directive
|
||||
{
|
||||
return directive('html', implode("\n", \zin\utils\flat(func_get_args())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create text content.
|
||||
*
|
||||
* @param string ...$lines
|
||||
* @return directive
|
||||
*/
|
||||
function text(/* string ...$lines */): directive
|
||||
{
|
||||
return directive('text', implode("\n", \zin\utils\flat(func_get_args())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create block content.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed ...$wgs
|
||||
* @return directive
|
||||
*/
|
||||
function to(/* string $name, mixed ...$wgs */): directive
|
||||
{
|
||||
$args = func_get_args();
|
||||
$name = array_shift($args);
|
||||
$wg = new wg(count($args) > 1 ? $args : $args[0]);
|
||||
return directive('block', array($name => $wg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content for block "before".
|
||||
*
|
||||
* @param string $wgs
|
||||
* @return directive
|
||||
*/
|
||||
function before(/* mixed ...$wgs */): directive
|
||||
{
|
||||
return to('before', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content for block "after".
|
||||
*
|
||||
* @param string $wgs
|
||||
* @return directive
|
||||
*/
|
||||
function after(): directive
|
||||
{
|
||||
return to('after', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create widget contents inherited from the given widget.
|
||||
*
|
||||
* @param wg|array $item
|
||||
* @return array
|
||||
*/
|
||||
function inherit(wg|array $item): array
|
||||
{
|
||||
if(!($item instanceof wg)) $item = new wg($item);
|
||||
return array(set($item->props), directive('block', $item->blocks), $item->children());
|
||||
}
|
||||
|
||||
/**
|
||||
* Divorce widget from parent.
|
||||
*
|
||||
* @param wg|array $item
|
||||
* @return array
|
||||
*/
|
||||
function divorce(wg|array $item): wg|array
|
||||
{
|
||||
if($item instanceof wg)
|
||||
{
|
||||
$item->parent = null;
|
||||
}
|
||||
else if(is_array($item))
|
||||
{
|
||||
foreach($item as $i) divorce($i);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given widget list has the given widget type.
|
||||
*
|
||||
* @param wg|array $items
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
function hasWgInList(wg|array $items, string $type): bool
|
||||
{
|
||||
if(!is_array($items)) $items = array($items);
|
||||
foreach($items as $item)
|
||||
{
|
||||
if($item instanceof wg && $item->type() == $type) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group widgets by type.
|
||||
*
|
||||
* @param wg|array $items
|
||||
* @param string $types
|
||||
* @return array
|
||||
*/
|
||||
function groupWgInList(wg|array $items, string|array $types): array
|
||||
{
|
||||
if(is_string($types)) $types = explode(',', $types);
|
||||
$typesMap = array();
|
||||
$restList = array();
|
||||
|
||||
foreach($types as $type) $typesMap[$type] = array();
|
||||
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(!($item instanceof wg)) continue;
|
||||
|
||||
$type = $item->shortType();
|
||||
if(isset($typesMap[$type])) $typesMap[$type][] = $item;
|
||||
else $restList[] = $item;
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
foreach($types as $index => $type) $groups[] = $typesMap[$type];
|
||||
$groups[] = $restList;
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create raw content placeholder.
|
||||
*
|
||||
* @return rawContent
|
||||
*/
|
||||
function rawContent(): rawContent
|
||||
{
|
||||
zin::$rawContentCalled = true;
|
||||
|
||||
return new rawContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The widget function file of zin module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author sunhao<sunhao@easycorp.ltd>
|
||||
* @package zin
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
require_once dirname(__DIR__) . DS . 'utils' . DS . 'flat.func.php';
|
||||
require_once __DIR__ . DS . 'loader.func.php';
|
||||
require_once __DIR__ . DS . 'node.class.php';
|
||||
require_once __DIR__ . DS . 'text.class.php';
|
||||
require_once __DIR__ . DS . 'props.class.php';
|
||||
require_once __DIR__ . DS . 'directive.class.php';
|
||||
require_once __DIR__ . DS . 'setting.class.php';
|
||||
require_once __DIR__ . DS . 'set.class.php';
|
||||
require_once __DIR__ . DS . 'wg.class.php';
|
||||
require_once __DIR__ . DS . 'h.class.php';
|
||||
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 . 'on.class.php';
|
||||
require_once __DIR__ . DS . 'jquery.class.php';
|
||||
|
||||
/**
|
||||
* Create block content.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed ...$args
|
||||
* @return directive
|
||||
*/
|
||||
function to(string $blockName, mixed ...$args): directive
|
||||
{
|
||||
$node = new node(...$args);
|
||||
return directive('block', array($blockName => $node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content for block "before".
|
||||
*
|
||||
* @param string $args
|
||||
* @return directive
|
||||
*/
|
||||
function before(mixed ...$args): directive
|
||||
{
|
||||
return to('before', ...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create content for block "after".
|
||||
*
|
||||
* @param string $args
|
||||
* @return directive
|
||||
*/
|
||||
function after(mixed ...$args): directive
|
||||
{
|
||||
return to('after', ...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create widget contents inherited from the given widget.
|
||||
*
|
||||
* @param node|array $item
|
||||
* @return array
|
||||
*/
|
||||
function inherit(node|array $item): array
|
||||
{
|
||||
if(!($item instanceof node)) $item = new node($item);
|
||||
return array(set($item->props), directive('block', $item->blocks), $item->children());
|
||||
}
|
||||
|
||||
/**
|
||||
* Divorce widget from parent.
|
||||
*
|
||||
* @param node|array $item
|
||||
* @return array
|
||||
*/
|
||||
function divorce(node|array $item): node|array
|
||||
{
|
||||
if($item instanceof node)
|
||||
{
|
||||
$item->parent = null;
|
||||
}
|
||||
else if(is_array($item))
|
||||
{
|
||||
foreach($item as $i) divorce($i);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group widgets by type.
|
||||
*
|
||||
* @param wg|array $items
|
||||
* @param string $types
|
||||
* @return array
|
||||
*/
|
||||
function groupWgInList(wg|array $items, string|array $types): array
|
||||
{
|
||||
if(is_string($types)) $types = explode(',', $types);
|
||||
$typesMap = array();
|
||||
$restList = array();
|
||||
|
||||
foreach($types as $type) $typesMap[$type] = array();
|
||||
|
||||
foreach($items as $item)
|
||||
{
|
||||
if(!($item instanceof wg)) continue;
|
||||
|
||||
$type = $item->shortType();
|
||||
if(isset($typesMap[$type])) $typesMap[$type][] = $item;
|
||||
else $restList[] = $item;
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
foreach($types as $index => $type) $groups[] = $typesMap[$type];
|
||||
$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);
|
||||
}
|
||||
+143
-1888
File diff suppressed because it is too large
Load Diff
@@ -18,12 +18,12 @@ class aclBox extends wg
|
||||
'userValue?: string=""', // 用户组默认选中值。
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($aclItems, $aclValue, $whitelistLabel, $groupLabel, $userLabel, $groupName, $userName, $groupItems, $groupValue, $userValue) = $this->prop(array('aclItems', 'aclValue', 'whitelistLabel', 'groupLabel', 'userLabel', 'groupName', 'userName', 'groupItems', 'groupValue', 'userValue'));
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ class actionItem extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($name, $type, $outerTag, $outerProps, $outerClass) = $this->prop(array('name', 'type', 'outerTag', 'outerProps', 'outerClass'));
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class avatar extends wg
|
||||
return $child;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
/* Attach classes. */
|
||||
$this->finalClass[] = $this->prop('className');
|
||||
|
||||
@@ -8,12 +8,12 @@ class batchActions extends wg
|
||||
'actionClass?: string=""',
|
||||
);
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return formGroup
|
||||
(
|
||||
|
||||
@@ -90,7 +90,7 @@ class btn extends wg
|
||||
return $classList;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$props = $this->getProps();
|
||||
$children = $this->getChildren();
|
||||
|
||||
@@ -28,7 +28,7 @@ class btnGroup extends wg
|
||||
return $className;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$items = $this->prop('items');
|
||||
$className = $this->getclassName();
|
||||
|
||||
@@ -13,7 +13,7 @@ class cell extends wg
|
||||
'align?: string' // align-self 属性,例如 'auto'、'flex-start'、'flex-end'、'center'、'baseline'、'stretch'。
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$basis = null;
|
||||
$class = array('cell');
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace zin;
|
||||
|
||||
class center extends wg
|
||||
{
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -55,7 +55,7 @@ class checkbox extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
if($this->prop('primary')) return $this->buildPrimary();
|
||||
list($text, $type, $typeClass) = $this->prop(array('text', 'type', 'typeClass'));
|
||||
|
||||
@@ -14,12 +14,12 @@ class checkboxGroup extends wg
|
||||
'disabled' => false
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class checkboxGroup extends wg
|
||||
return checkbox(set($title), setClass('checkbox-title'));
|
||||
}
|
||||
|
||||
private function buildCheckboxList(): wg
|
||||
private function buildCheckboxList(): node
|
||||
{
|
||||
$items = $this->prop('items');
|
||||
$title = array_merge(self::$checkboxProps, $this->prop('title'));
|
||||
@@ -52,7 +52,7 @@ class checkboxGroup extends wg
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function build(): wg
|
||||
public function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -6,7 +6,7 @@ require_once dirname(__DIR__) . DS . 'checkbox' . DS . 'v1.php';
|
||||
|
||||
class checkBtn extends checkbox
|
||||
{
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return <<<CSS
|
||||
.check-btn > input + label {color: var(--color-gray-500)}
|
||||
|
||||
@@ -13,7 +13,7 @@ class checkBtnGroup extends checkList
|
||||
'type' => 'radio'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return <<<CSS
|
||||
.check-btn-group {gap: 1px; border: 1px solid var(--form-control-border); padding: 0; border-radius: var(--radius)}
|
||||
@@ -30,7 +30,7 @@ class checkBtnGroup extends checkList
|
||||
return new checkBtn(set($props));
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$div = parent::build();
|
||||
$div->add(setClass('check-btn-group'));
|
||||
|
||||
@@ -6,7 +6,7 @@ require_once dirname(__DIR__) . DS . 'checkbtngroup' . DS . 'v1.php';
|
||||
|
||||
class checkColorGroup extends checkBtnGroup
|
||||
{
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return <<<CSS
|
||||
.check-btn-group {gap: 1px; padding: 0; border-radius: var(--radius); margin-top: 4px;}
|
||||
@@ -25,7 +25,7 @@ class checkColorGroup extends checkBtnGroup
|
||||
return parent::buildItem($props);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return parent::build();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class checkList extends wg
|
||||
return new checkbox(set($props));
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($items, $inline, $disabled, $className) = $this->prop(array('items', 'inline', 'disabled', 'className'));
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class col extends wg
|
||||
'align?:string'
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$classList = 'col';
|
||||
list($justify, $align) = $this->prop(array('justify', 'align'));
|
||||
|
||||
@@ -11,7 +11,7 @@ class collapseBtn extends wg
|
||||
'parent: string' // 目标元素与按钮共同的父级元素选择器,使用 closest 辅助目标元素的确定。
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$target = $this->prop('target');
|
||||
$parent = $this->prop('parent');
|
||||
|
||||
@@ -44,7 +44,7 @@ class colorInput extends inputControl
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($id, $name, $value, $inputClass, $colorName, $colorValue, $syncColor) = $this->prop(array('id', 'name', 'value', 'inputClass', 'colorName', 'colorValue', 'syncColor'));
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ class colorPicker extends wg
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($props, $restProps) = $this->props->split(array_keys(static::definedPropsList()));
|
||||
if(isset($props['id']))
|
||||
|
||||
@@ -13,7 +13,7 @@ class commentDialog extends wg
|
||||
'load?: bool|string'
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $lang;
|
||||
$id = $this->prop('id');
|
||||
|
||||
@@ -12,7 +12,7 @@ class commentForm extends wg
|
||||
'method?:string="POST"'
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $lang;
|
||||
$url = $this->prop('url');
|
||||
|
||||
@@ -20,7 +20,7 @@ class contactList extends wg
|
||||
'placeholder?: string', // picker 占位符。
|
||||
);
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class contactList extends wg
|
||||
}
|
||||
}
|
||||
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
global $app, $lang;
|
||||
$app->loadLang('user');
|
||||
|
||||
@@ -218,7 +218,7 @@ class control extends wg
|
||||
return new dropdown($this->prop('text'), set($this->props->skip('control,text,name,widget')));
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$builder = $this->prop('builder');
|
||||
if(is_callable($builder)) return $builder($this->props->skip('builder'), $this->children());
|
||||
|
||||
@@ -55,7 +55,7 @@ class dashboard extends wg
|
||||
/**
|
||||
* Build widget.
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return zui::dashboard
|
||||
(
|
||||
|
||||
@@ -65,7 +65,7 @@ class datePicker extends wg
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($props, $restProps) = $this->props->split(array_keys(static::definedPropsList()));
|
||||
if(isset($props['id']))
|
||||
|
||||
@@ -112,7 +112,7 @@ class dateRangePicker extends wg
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$begin = new datePicker(set($this->buildBeginProps()));
|
||||
$end = new datePicker(set($this->buildEndProps()));
|
||||
|
||||
@@ -54,7 +54,7 @@ class datetimePicker extends wg
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($props, $restProps) = $this->props->split(array_keys(static::definedPropsList()));
|
||||
if(isset($props['id']))
|
||||
|
||||
@@ -15,17 +15,17 @@ class detailBody extends wg
|
||||
'floating' => array('map' => 'floatToolbar')
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$main = $this->block('main');
|
||||
$side = $this->block('side');
|
||||
|
||||
@@ -28,7 +28,7 @@ class detailHeader extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$prefix = $this->block('prefix');
|
||||
$title = $this->block('title');
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace zin;
|
||||
|
||||
class detailSide extends wg
|
||||
{
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return <<<CSS
|
||||
.detail-side {width: 370px;}
|
||||
@@ -15,7 +15,7 @@ class detailSide extends wg
|
||||
CSS;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace zin;
|
||||
|
||||
class divider extends wg
|
||||
{
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -25,12 +25,12 @@ class docMenu extends wg
|
||||
'hover?: bool=true'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class dropmenu extends wg
|
||||
* @access public
|
||||
* @return string|false
|
||||
*/
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class dtable extends wg
|
||||
|
||||
static $dtableID = 0;
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
@@ -266,7 +266,7 @@ class dtable extends wg
|
||||
return $setting;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $lang, $app;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class dynamic extends wg
|
||||
'className?: string'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class dynamic extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$users = $this->prop('users', (array)data('users'));
|
||||
$dynamics = $this->prop('dynamics', (array)data('dynamics'));
|
||||
|
||||
@@ -33,12 +33,12 @@ class editor extends wg
|
||||
.tippy-content zen-editor-menu-item .label {all: unset;}
|
||||
CSS;
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
$content = file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
$content .= '$.getLib(\'zen-editor/zen-editor.esm.js\', {type: "module"}, () => {document.body.dataset.loadedEditor = true;});';
|
||||
@@ -75,7 +75,7 @@ class editor extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $lang;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class entityLabel extends wg
|
||||
'suffix' => array()
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
@@ -86,7 +86,7 @@ class entityLabel extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$reverse = $this->prop('reverse');
|
||||
$prefix = $this->block('prefix');
|
||||
|
||||
@@ -143,7 +143,7 @@ class featureBar extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -16,12 +16,12 @@ class fileList extends wg
|
||||
'padding?:bool=true'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class fileList extends wg
|
||||
return $fileListView;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $lang;
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class fileSelector extends wg
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return zui::fileSelector(inherit($this));
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ class filter extends wg
|
||||
return $this->buildInput();
|
||||
}
|
||||
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
$type = $this->prop('type');
|
||||
$class = $this->prop('class', 'w-1/4');
|
||||
|
||||
@@ -9,16 +9,16 @@ class floatPreNextBtn extends wg
|
||||
'nextLink?:string'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
global $app;
|
||||
$preLink = $this->prop('preLink');
|
||||
|
||||
@@ -74,7 +74,7 @@ class floatToolbar extends wg
|
||||
return array_merge($btns, $block);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$prefixBtns = $this->buildBtns($this->prop('prefix'));
|
||||
$mainBtns = $this->buildBtns($this->prop('main'));
|
||||
|
||||
@@ -107,7 +107,7 @@ class formBase extends wg
|
||||
return $after;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return h::form
|
||||
(
|
||||
|
||||
@@ -136,7 +136,7 @@ class formGroup extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
list($name, $labelWidth, $required, $width, $id, $hidden, $foldable, $pinned, $children, $wrapBefore, $wrapAfter, $data) = $this->prop(array('name', 'labelWidth', 'required', 'width', 'id', 'hidden', 'foldable', 'pinned', 'children', 'wrapBefore', 'wrapAfter', 'data'));
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class formItemDropdown extends wg
|
||||
'target?: string'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class formItemDropdown extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -18,7 +18,7 @@ class formLabel extends wg
|
||||
'checkbox?: bool|array'
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($text, $required, $for, $hint, $hintClass, $hintProps, $hintIcon, $actions, $actionsClass, $actionsProps, $checkbox) = $this->prop(array('text', 'required', 'for', 'hint', 'hintClass', 'hintProps', 'hintIcon', 'actions', 'actionsClass', 'actionsProps', 'checkbox'));
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class formPanel extends panel
|
||||
'customFields?: array=[]' // @deprecated 自定义表单项。
|
||||
);
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class formRow extends wg
|
||||
return new formGroup(inherit($item));
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($width, $items, $hidden) = $this->prop(['width', 'items', 'hidden']);
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ class formRowGroup extends formRow
|
||||
'suffix' => array()
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return formRow
|
||||
(
|
||||
|
||||
@@ -19,12 +19,12 @@ class formSettingBtn extends wg
|
||||
'urlParams' => ''
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class formSettingBtn extends wg
|
||||
return $items;
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$customFields = $this->prop('customFields', array());
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class fragment extends wg
|
||||
{
|
||||
$css = array(data('pageCSS'), '/*{{ZIN_PAGE_CSS}}*/');
|
||||
$js = array('/*{{ZIN_PAGE_JS}}*/', data('pageJS'));
|
||||
$rawContent = $this->prop('rawContent', !zin::$rawContentCalled);
|
||||
$rawContent = $this->prop('rawContent', !context()->rawContentCalled);
|
||||
|
||||
return array
|
||||
(
|
||||
|
||||
@@ -9,7 +9,7 @@ class gantt extends wg
|
||||
return file_get_contents(dirname(__DIR__, 4) . '/www/js/dhtmlxgantt/min.css');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $app;
|
||||
$jsFile = $app->getWebRoot() . 'js/dhtmlxgantt/min.js';
|
||||
|
||||
@@ -4,12 +4,12 @@ namespace zin;
|
||||
|
||||
class globalSearch extends wg
|
||||
{
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $config, $lang;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class header extends wg
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return h::header
|
||||
(
|
||||
|
||||
@@ -95,7 +95,7 @@ class heading extends wg
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace zin;
|
||||
|
||||
class hr extends wg
|
||||
{
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return h::hr(setClass('my-5'));
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class icon extends wg
|
||||
}
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($name, $size) = $this->prop(array('name', 'size'));
|
||||
return h::i
|
||||
|
||||
@@ -17,7 +17,7 @@ class imageSelector extends fileSelector
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return zui::imageSelector(inherit($this));
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class input extends wg
|
||||
'class' => 'form-control'
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$props = $this->props->skip('required');
|
||||
$required = $this->prop('required');
|
||||
|
||||
@@ -19,7 +19,7 @@ class inputControl extends wg
|
||||
'suffix' => array()
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($prefix, $suffix, $prefixWidth, $suffixWidth, $class) = $this->prop(array('prefix', 'suffix', 'prefixWidth', 'suffixWidth', 'class'));
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class inputGroup extends wg
|
||||
return new input(set::type($control), set($item->props->skip('control')));
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($items, $seg) = $this->prop(['items', 'seg']);
|
||||
$children = $this->children();
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace zin;
|
||||
*/
|
||||
class inputGroupAddon extends wg
|
||||
{
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return h::span(setClass('input-group-addon'), set($this->props), $this->children());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ class label extends wg
|
||||
'text?:string'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class label extends wg
|
||||
}
|
||||
}
|
||||
|
||||
public function build(): wg
|
||||
public function build()
|
||||
{
|
||||
return span
|
||||
(
|
||||
|
||||
@@ -134,7 +134,7 @@ class main extends wg
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -40,7 +40,7 @@ class mainNavbar extends nav
|
||||
* @access public
|
||||
* @return string|false
|
||||
*/
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class mainNavbar extends nav
|
||||
* @access protected
|
||||
* @return wg
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $app, $config;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class menu extends wg
|
||||
/**
|
||||
* @return builder
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$items = $this->prop('items');
|
||||
return h::menu
|
||||
|
||||
@@ -15,7 +15,7 @@ class modal extends modalDialog
|
||||
'modalProps' => array()
|
||||
);
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($id, $modalProps) = $this->prop(array('id', 'modalProps'));
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class modalDialog extends wg
|
||||
|
||||
protected function buildBody()
|
||||
{
|
||||
$rawContent = $this->prop('rawContent', !zin::$rawContentCalled);
|
||||
$rawContent = $this->prop('rawContent', !context()->rawContentCalled);
|
||||
return div
|
||||
(
|
||||
setClass('modal-body scrollbar-hover', $this->prop('bodyClass')),
|
||||
@@ -125,7 +125,7 @@ class modalDialog extends wg
|
||||
return "$objectType:$objectID";
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return div
|
||||
(
|
||||
|
||||
@@ -34,7 +34,7 @@ class modalHeader extends wg
|
||||
$this->setDefaultProps(array('title' => $title, 'entityText' => $entityText, 'entityID' => $entityID));
|
||||
}
|
||||
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
list($title, $entityText, $entityID, $inModal) = $this->prop(array('title', 'entityText', 'entityID', 'inModal'));
|
||||
if(empty($inModal)) $inModal = false;
|
||||
|
||||
@@ -9,12 +9,12 @@ class modalNextStep extends wg
|
||||
'items: array'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
$tip = $this->prop('tip');
|
||||
$items = $this->prop('items');
|
||||
|
||||
@@ -24,7 +24,7 @@ class moduleMenu extends wg
|
||||
'onCheck?: function'
|
||||
);
|
||||
|
||||
public static function getPageCSS(): string|false
|
||||
public static function getPageCSS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ class modulePicker extends wg
|
||||
'manageLink?: string' // 维护模块链接
|
||||
);
|
||||
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
protected function build(): wg|array
|
||||
protected function build()
|
||||
{
|
||||
global $app, $lang;
|
||||
$app->loadLang('tree');
|
||||
|
||||
@@ -20,12 +20,12 @@ class monaco extends wg
|
||||
'onMouseDown' => '',
|
||||
'onMouseMouse' => ''
|
||||
);
|
||||
public static function getPageJS(): string|false
|
||||
public static function getPageJS(): ?string
|
||||
{
|
||||
return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
global $app;
|
||||
$vsPath = $app->getWebRoot() . 'js/monaco-editor/min/vs';
|
||||
|
||||
@@ -23,7 +23,7 @@ class nav extends wg
|
||||
);
|
||||
}
|
||||
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
list($items, $type, $stacked, $justified) = $this->prop(array('items', 'type', 'stacked', 'justified'));
|
||||
return h::menu
|
||||
|
||||
@@ -291,7 +291,7 @@ class navbar extends wg
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
protected function build(): wg
|
||||
protected function build()
|
||||
{
|
||||
return h::nav
|
||||
(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user