365 lines
9.6 KiB
PHP
365 lines
9.6 KiB
PHP
<?php
|
|
namespace nur\v\html5;
|
|
|
|
use nur\A;
|
|
use nur\b\ValueException;
|
|
use nur\co;
|
|
use nur\config;
|
|
use nur\func;
|
|
use nur\msg;
|
|
use nur\str;
|
|
use nur\v\base\AbstractPageContainer;
|
|
use nur\v\base\MenuManager;
|
|
use nur\v\fo;
|
|
use nur\v\ly;
|
|
use nur\v\model\IComponent;
|
|
use nur\v\model\IPage;
|
|
use nur\v\model\IPlugin;
|
|
use nur\v\navbar;
|
|
use nur\v\prefix;
|
|
use nur\v\v;
|
|
|
|
class Html5VanillaPageContainer extends AbstractPageContainer {
|
|
protected function initToolkit(): void {
|
|
msg::set_messenger_class(Html5Messenger::class);
|
|
fo::set_manager_class(Html5FormManager::class);
|
|
ly::set_manager_class(Html5LayoutManager::class);
|
|
navbar::set_manager_class(Html5NavbarManager::class);
|
|
navbar::set_menu_manager_class(MenuManager::class);
|
|
}
|
|
|
|
protected function overrideSetup(IPage $page): void {
|
|
$plugins =& $this->config["plugins"];
|
|
foreach ($this->components as $c) {
|
|
if ($c instanceof IComponent) {
|
|
self::ensure_preparec($c, true);
|
|
self::ensure_setupc($c, true);
|
|
}
|
|
if ($c instanceof IPlugin) $plugins[] = $c;
|
|
}
|
|
# Si la page courante est un plugin, l'ajouter aussi
|
|
if ($page instanceof IPlugin) $plugins[] = $page;
|
|
foreach ($plugins as &$plugin) {
|
|
if (is_string($plugin)) $plugin = new $plugin();
|
|
elseif (is_array($plugin)) $plugin = func::cons(...$plugin);
|
|
}; unset($plugin);
|
|
}
|
|
|
|
protected function overridePrint(IPage $page): void {
|
|
if ($page->haveContent()) {
|
|
$this->doResolveConfig();
|
|
$this->haveOutput = true;
|
|
$this->printStartHtml();
|
|
$this->printStartHead();
|
|
$this->printCssLinks();
|
|
$this->printCss();
|
|
$this->printJsLinks();
|
|
$this->printJs();
|
|
$this->printScript();
|
|
$this->printHeadTitle();
|
|
$this->printEndHead();
|
|
$this->printStartBody();
|
|
$this->printContent();
|
|
$this->printEndBody();
|
|
$this->printEndHtml();
|
|
}
|
|
}
|
|
|
|
const JQUERY_MIN_JS = "nur-base/jquery/jquery.min.js";
|
|
const JQUERY_JS = "nur-base/jquery/jquery.js";
|
|
|
|
protected $haveCss = [];
|
|
protected function setHaveCss(string $name, bool $haveCss=true): void {
|
|
$this->haveCss[$name] = $haveCss;
|
|
}
|
|
protected function haveCss(string $name): bool {
|
|
return boolval(A::get($this->haveCss, $name));
|
|
}
|
|
protected $haveJs = [];
|
|
protected function setHaveJs(string $name, bool $haveJs=true): void {
|
|
$this->haveJs[$name] = $haveJs;
|
|
}
|
|
protected function haveJs(string $name): bool {
|
|
return boolval(A::get($this->haveJs, $name));
|
|
}
|
|
|
|
/** @var string[] */
|
|
protected $cssUrls;
|
|
/** @var string[] */
|
|
protected $jsUrls;
|
|
/** @var bool */
|
|
protected $needsJquery;
|
|
|
|
function doResolveConfig(): void {
|
|
$cssUrls = $this->getCssUrls();
|
|
$jsUrls = $this->getJsUrls();
|
|
$this->needsJquery = config::is_fact(config::FACT_NEEDS_JQUERY);
|
|
$plugins = $this->getPlugins();
|
|
foreach ($plugins as $plugin) {
|
|
if ($plugin instanceof IPlugin) {
|
|
$this->needsJquery |= $plugin->haveJquery();
|
|
|
|
$urls = A::with($plugin->getCss());
|
|
if ($plugin->isDynamicCss()) {
|
|
A::merge($cssUrls, $urls);
|
|
} else {
|
|
$index = 0;
|
|
foreach ($urls as $key => $url) {
|
|
if (!$url) continue;
|
|
if ($key === $index) {
|
|
if (in_array($url, $cssUrls)) continue;
|
|
$cssUrls[] = $url;
|
|
} else {
|
|
if ($this->haveCss($key)) continue;
|
|
if (in_array($url, $cssUrls)) continue;
|
|
$cssUrls[$key] = $url;
|
|
$this->setHaveCss($key);
|
|
}
|
|
$index++;
|
|
}
|
|
}
|
|
$urls = A::with($plugin->getJs());
|
|
if ($plugin->isDynamicJs()) {
|
|
A::merge($jsUrls, $urls);
|
|
} else {
|
|
$index = 0;
|
|
foreach ($urls as $key => $url) {
|
|
if (!$url) continue;
|
|
if (array_key_exists($key, $jsUrls)) continue;
|
|
if ($key === $index) {
|
|
if (in_array($url, $jsUrls)) continue;
|
|
$jsUrls[] = $url;
|
|
} else {
|
|
if ($this->haveJs($key)) continue;
|
|
if (in_array($url, $jsUrls)) continue;
|
|
$jsUrls[$key] = $url;
|
|
$this->setHaveJs($key);
|
|
}
|
|
$index++;
|
|
}
|
|
}
|
|
} else {
|
|
throw ValueException::unexpected_type(IPlugin::class, $plugin);
|
|
}
|
|
}
|
|
if ($this->needsJquery && !$this->haveJs("jquery")) {
|
|
# toujours mettre jquery en premier
|
|
$prevJsUrls = $jsUrls;
|
|
$jsUrls = ["jquery" => self::JQUERY_MIN_JS];
|
|
A::merge($jsUrls, $prevJsUrls);
|
|
}
|
|
$this->cssUrls = $cssUrls;
|
|
$this->jsUrls = $jsUrls;
|
|
}
|
|
|
|
function printStartHtml(): void {
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="fr" xmlns="http://www.w3.org/1999/xhtml">
|
|
<?php
|
|
}
|
|
|
|
function printStartHead(): void {
|
|
$prefix = $this->getSelfRelativePrefix();
|
|
?>
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<link href="<?=$prefix?>nur-base/base.css" rel="stylesheet"/>
|
|
<?php
|
|
}
|
|
|
|
function printCssLinks(): void {
|
|
$prefix = $this->getSelfRelativePrefix();
|
|
foreach ($this->cssUrls as $url) {
|
|
$url = prefix::add($url, $prefix);
|
|
?>
|
|
<link href="<?=$url?>" rel="stylesheet"/>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
function printCss(): void {
|
|
foreach ($this->getPlugins() as $plugin) {
|
|
$plugin->printCss();
|
|
}
|
|
}
|
|
|
|
function printJsLinks(): void {
|
|
$prefix = $this->getSelfRelativePrefix();
|
|
foreach ($this->jsUrls as $url) {
|
|
$url = prefix::add($url, $prefix);
|
|
?>
|
|
<script src="<?=$url?>" type="text/javascript"></script>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
function printJs(): void {
|
|
foreach ($this->getPlugins() as $plugin) {
|
|
$plugin->printJs();
|
|
}
|
|
}
|
|
|
|
protected function beforeCapture(): void {
|
|
ob_start(null, 0, PHP_OUTPUT_HANDLER_STDFLAGS ^ PHP_OUTPUT_HANDLER_FLUSHABLE);
|
|
}
|
|
|
|
private static function strip_lines(array &$lines): void {
|
|
while (count($lines) > 0 && !$lines[0]) {
|
|
# enlever les lignes vides au début
|
|
array_shift($lines);
|
|
}
|
|
while (($count = count($lines)) > 0 && !$lines[$count - 1]) {
|
|
# enlever les lignes vides à la fin
|
|
array_pop($lines);
|
|
}
|
|
}
|
|
|
|
const RE_START_SCRIPT = '/^\s*<script\s+type="(?:text\/)?javascript">\s*(.*)/';
|
|
const RE_END_SCRIPT = '/(.*?)\s*<\/script>\s*$/';
|
|
|
|
private static function unwrap_script(array &$lines): void {
|
|
$count = count($lines);
|
|
if ($count >= 2) {
|
|
$first = $lines[0];
|
|
$last = $lines[$count - 1];
|
|
if (preg_match(self::RE_START_SCRIPT, $first)
|
|
&& preg_match(self::RE_END_SCRIPT, $last)) {
|
|
$last = preg_replace(self::RE_END_SCRIPT, '$1', $last);
|
|
if ($last) $lines[$count - 1] = $last;
|
|
else $lines = array_slice($lines, 0, $count - 1);
|
|
$first = preg_replace(self::RE_START_SCRIPT, '$1', $first);
|
|
if ($first) $lines[0] = $first;
|
|
else $lines = array_slice($lines, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected $scripts = [];
|
|
protected function captureScript(): void {
|
|
$lines = trim(ob_get_clean());
|
|
if ($lines) {
|
|
$lines = str::split_nl($lines);
|
|
self::strip_lines($lines);
|
|
self::unwrap_script($lines);
|
|
$this->scripts[] = implode("\n", $lines);
|
|
}
|
|
}
|
|
|
|
const RE_START_JQUERY = '/^\s*jQuery(?:.noConflict\(\))?\(function\(\$\) {\s*(.*)/';
|
|
const RE_END_JQUERY = '/(.*?)\s*}\);\s*$/';
|
|
|
|
private static function unwrap_jquery(array &$lines): void {
|
|
$count = count($lines);
|
|
if ($count >= 2) {
|
|
$first = $lines[0];
|
|
$last = $lines[$count - 1];
|
|
if (preg_match(self::RE_START_JQUERY, $first)
|
|
&& preg_match(self::RE_END_JQUERY, $last)) {
|
|
$last = preg_replace(self::RE_END_JQUERY, '$1', $last);
|
|
if ($last) $lines[$count - 1] = $last;
|
|
else $lines = array_slice($lines, 0, $count - 1);
|
|
$first = preg_replace(self::RE_START_JQUERY, '$1', $first);
|
|
if ($first) $lines[0] = $first;
|
|
else $lines = array_slice($lines, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected $jqueries = [];
|
|
protected function captureJquery(): void {
|
|
$lines = trim(ob_get_clean());
|
|
if ($lines) {
|
|
$lines = str::split_nl($lines);
|
|
self::strip_lines($lines);
|
|
self::unwrap_script($lines);
|
|
self::unwrap_jquery($lines);
|
|
$this->jqueries[] = implode("\n", $lines);
|
|
}
|
|
}
|
|
|
|
protected function resolvePluginsScripts(): void {
|
|
foreach ($this->getPlugins() as $plugin) {
|
|
if ($plugin->haveScript()) {
|
|
$this->beforeCapture();
|
|
$plugin->printScript();
|
|
$this->captureScript();
|
|
}
|
|
if ($plugin->haveJquery()) {
|
|
$this->beforeCapture();
|
|
$plugin->printJquery();
|
|
$this->captureJquery();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function printMergedScripts(): void {
|
|
$scripts = $this->scripts;
|
|
$jqueries = $this->jqueries;
|
|
if ($scripts || $jqueries) {
|
|
?>
|
|
<script type="text/javascript">
|
|
<?php
|
|
foreach ($scripts as $script) {
|
|
echo "$script\n";
|
|
}
|
|
}
|
|
if ($jqueries) {
|
|
?>
|
|
jQuery.noConflict()(function($) {
|
|
<?php
|
|
foreach ($jqueries as $jquery) {
|
|
echo "$jquery\n";
|
|
}
|
|
?>
|
|
});
|
|
<?php
|
|
}
|
|
if ($scripts || $jqueries) {
|
|
?>
|
|
</script>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
function printScript(): void {
|
|
$this->resolvePluginsScripts();
|
|
$this->printMergedScripts();
|
|
}
|
|
|
|
function printHeadTitle(): void {
|
|
co::_print(v::tag("title", $this->getTitle()));
|
|
}
|
|
|
|
function printEndHead(): void {
|
|
?>
|
|
</head>
|
|
<?php
|
|
}
|
|
|
|
function printStartBody(): void {
|
|
?>
|
|
<body>
|
|
<?php
|
|
}
|
|
|
|
function printContent(): void {
|
|
co::_write([$this->page]);
|
|
ly::end();
|
|
}
|
|
|
|
function printEndBody(): void {
|
|
?>
|
|
</body>
|
|
<?php
|
|
}
|
|
|
|
function printEndHtml(): void {
|
|
?>
|
|
</html>
|
|
<?php
|
|
}
|
|
}
|