Files
DomFramework/outputhtml.php

200 lines
6.7 KiB
PHP

<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
require_once ("domframework/output.php");
/** Display in HTML the data provided, with the layout support
*/
class outputhtml extends output
{
/** Data is printed by viewClass->viewmethod, in the middle of $layout
* title is put in the title of the HTML page
* $replacement modify the result (it can do title too :
* array ("{title}"=>"title to display")
* @param mixed $data Data to display on the page
* @param string|null $title Title to put on head of page
* @param string|null $viewClass Class in views to use to display
* @param string|null $viewMethod Method in the class in views
* @param string|null $layout Layout file in views
* @param array|null $replacement Replace the {key}=>value
* @param array|null $variable PHP variables send to the view and to layout
* (can be processed by foreach, if...)
* @param string|null $module The module name to use if needed
* @return Exit from PHP at the end of HTML display
*/
public function out ($data, $title = FALSE,
$viewClass = FALSE, $viewMethod = FALSE,
$layout = FALSE, $replacement = array(),
$variable = array (), $module = "")
{
@header("Cache-Control: no-store, no-cache, must-revalidate");
@header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
@header('Last-Modified: '.gmdate ('D, d M Y H:i:s').' GMT');
@header('Cache-Control: post-check=0, pre-check=0', false);
@header('Pragma: no-cache');
@header ("Content-Type: text/html");
$resView = $data;
if ($viewClass !== FALSE && $viewMethod !== FALSE)
{
if (! class_exists ($viewClass))
{
if ($module !== "" &&
file_exists ("modules/$module/views/$viewClass.php"))
require_once ("modules/$module/views/$viewClass.php");
elseif (file_exists ("views/$viewClass.php"))
require_once ("views/$viewClass.php");
// If the file doesn't exists, an autoloader maybe exists. If it is not
// the case, the class will not be found
}
$obj = new $viewClass;
$resView = $obj->$viewMethod ($data, $variable);
if (is_array ($resView))
{
if (isset ($resView["title"]))
$title = $resView["title"];
if (! isset ($resView["content"]))
throw new \Exception (sprintf ( dgettext ("domframework",
"No data provided from view %s::%s"), $viewClass, $viewMethod),
500);
}
}
if ($layout !== FALSE)
{
if (! file_exists ($layout) && file_exists ("views/$layout.html"))
$layout = "views/$layout.html";
$layoutPage = $this->layoutVariables ($layout, $variable);
}
else
{
// No layout : display a very basic HTML page
$layoutPage = <<< EOT
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>{title}</title>
</head>
<body>
{flash}
{content}
</body>
</html>
EOT;
}
// Get all the substitute zones
preg_match_all ("~({[\w_-]+})~", $layoutPage, $matches);
$zones = $matches[1];
// All the entries coming from views in array are substitute in layout
// {content}, {title}
if (is_array ($resView))
{
foreach ($resView as $key => $val)
{
$layoutPage = str_replace ("{".$key."}", $val, $layoutPage);
}
}
else
$layoutPage = str_replace ("{content}", $resView, $layoutPage);
// Do the title replacement in the replacement structure
if (! isset ($replacement["{flash}"]))
$replacement["{flash}"] = "";
foreach ($replacement as $key=>$val)
$layoutPage = str_replace ($key, $val, $layoutPage);
// Remove the not used {XXX}
foreach ($zones as $zone)
$layoutPage = str_replace ($zone, "", $layoutPage);
//echo $layoutPage;exit;
// Manage the timestamp/md5sum for the external files managed by this
// server.
if (! class_exists ("DOMDocument"))
die ("PHP Support for XML not enabled or not installed : ".
"apt-get install php-xml\n");
$dom = new \DOMDocument ();
libxml_use_internal_errors (true);
$dom->loadHTML ($layoutPage);
$errors = libxml_get_errors ();
foreach ($errors as $key => $err)
{
// Tag YYY invalid : code 801
// Like in <nav> <section>
if ($err->code === 801)
unset ($errors[$key]);
}
libxml_clear_errors();
/* if (! empty ($errors))
{
echo "ERROR: Invalid HTML provided\n";
echo "<pre>"; print_r ($errors);
foreach (explode ("\n", $layoutPage) as $key => $val)
{
echo sprintf ("%5d", $key+1)." ".htmlentities ($val)."\n";
}
echo "</pre>";
exit;
}*/
foreach (array ("script" => "src", "link" => "href", "img" => "src")
as $key=>$val)
{
$files = $dom->getElementsByTagName ($key);
foreach ($files as $id=>$file)
{
if ($file->hasAttribute ($val) === false)
continue;
$src = $file->getAttribute ($val);
if ($src === "")
continue;
if (substr ($src, 0, 7) === "http://" ||
substr ($src, 0, 8) === "https://" ||
substr ($src, 0, 2) === "//")
continue;
// If there is already a ? with some variables, don't add the timestamp
if (strpos ($src, "?"))
continue;
if (! array_key_exists ("{baseurl}", $replacement))
continue;
$srcFile = substr ($src, strlen ($replacement["{baseurl}"]));
if (file_exists ($srcFile))
$srcHash = filemtime ($srcFile);
else
$srcHash = time();
$file->setAttribute ($val, "$src?$srcHash");
}
}
// Bug with html_entity_decode if double quotes in form text
// Bug with html_entity_decode in connaissances if <IfModule mpm_itk_module>
//echo html_entity_decode ($dom->saveHTML());
echo $dom->saveHTML();
if (!defined ("PHPUNIT"))
exit;
}
/** Get the layout and provide it the variables. The variables will be push in
* global to the layout (they can be used like $XX)
* @param string $layout the layout file to load
* @param array $variables The variables array to push to the layout
* @return string the Layout with variables interpreted */
private function layoutVariables ($layout, $variables)
{
// The layout can be a external layout file or the HTML page itself.
// FIXME : Allow to manage variables in a layout provided in the variable,
// without eval use
if (! file_exists ($layout))
return "$layout doesn't exists";
extract ($variables);
ob_start();
require ($layout);
return ob_get_clean ();
}
}