diff Page.inc.php @ 134:b6b4a58c7625

Using .inc.php rather than just .inc for include files.
author Tom Fredrik Blenning <bfg@bfgconsult.no>
date Sun, 22 Jan 2023 19:22:00 +0100
parents Page.inc@df158368051e
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Page.inc.php	Sun Jan 22 19:22:00 2023 +0100
@@ -0,0 +1,231 @@
+<?php
+include_once 'ScriptIncludeCache.inc.php';
+
+/// @cond
+$baseDir = dirname(__FILE__);
+$cache = ScriptIncludeCache::instance(__FILE__);
+$cache->includeOnce('OnlineBufferValidator.inc.php', $baseDir);
+$cache->includeOnce('Options.inc.php', $baseDir);
+/// @endcond
+
+/**
+ * Container for headers and content, used for compounding these
+ */
+class PageContent
+{
+  /// The headers for the page
+  public $headers = array();
+  /// The content of the page
+  public $content;
+
+  /**
+   * Constructs a PageContent object containing only content
+   *
+   * @param $content The content of this page
+   */
+  function __construct($content = "")
+  {
+    $this->content = $content;
+  }
+
+  /**
+   * Sets a header
+   *
+   * @param $headername Name of the header
+   * @param $value Value for the header
+   */
+  function setHeader($headername, $value)
+  {
+    $this->headers[$headername] = $value;
+  }
+
+  /**
+   * Returns a string representation of this object, containing only
+   * the content
+   *
+   * @return the content of the page
+   */
+  function __toString()
+  {
+    return $this->content;
+  }
+}
+
+/**
+ * Master class for generating a page
+ */
+abstract class Page
+{
+  private $cache;
+  private $variants = array();
+
+  function addVariant($value)
+  {
+    array_push($this->variants, $value);
+  }
+
+  function getVariants()
+  {
+    return $this->variants;
+  }
+
+  /**
+   * Constructs a page
+   *
+   * @param $cache optionally sets a cache
+   */
+  function __construct($cache = null)
+  {
+    $this->setCache($cache);
+  }
+
+  /**
+   * Set the cache
+   *
+   * @param $cache The cache object
+   */
+  protected function setCache($cache)
+  {
+    $this->cache = $cache;
+  }
+
+  /**
+   * Get the cache
+   *
+   * @return The cache object
+   */
+  protected function getCache()
+  {
+    return $this->cache;
+  }
+
+  /**
+   * Decide wether or not this page may be compressed.
+   *
+   * Normally this is a check for http headers, but some pages
+   * eg. pictures may not want to be compressed, and may override this
+   * function.
+   *
+   * @return bool if this page may be compressed
+   */
+  function mayCompress()
+  {
+    if (COMPRESSION_DISABLED)
+      return false;
+    //We want to add the variant even if we don't serve with compression.
+    $this->addVariant('Accept-Encoding');
+    if (!array_key_exists('HTTP_ACCEPT_ENCODING', $_SERVER))
+      return false;
+    return (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'));
+  }
+
+  /**
+   * Decide wether or not this page may be validated.
+   *
+   * Normally this is a check for the option novalidate, but this may
+   * be overridden
+   *
+   * @return bool if this page may be validated
+   */
+  function mayValidate()
+  {
+    if (!VALIDATE)
+      return false;
+    if (array_key_exists('novalidate', $_GET))
+      return !$_GET['novalidate'];
+    if (!array_key_exists('HTTP_USER_AGENT', $_SERVER))
+      return false;
+    //UserAgent should be W3C_Validator/1.3
+    return !startswith($_SERVER['HTTP_USER_AGENT'], 'W3C');
+  }
+
+
+  /**
+   * Turns on compression for this page
+   *
+   * @note This may not be reversed
+   */
+  function startCompression()
+  {
+    ob_start("ob_gzhandler");
+  }
+
+  /**
+   * Generates the actual content of the page
+   *
+   * @return the content buffer
+   */
+  abstract function generateContent();
+
+  /**
+   * Finishes all necessary processing to determine the cacheset of this page.
+   *
+   * @return bool if this page may be cached
+   */
+  abstract function cacheCheck();
+
+  /**
+   * Generates an appropriate response to the request.
+   *
+   * Eg. 304 NOT CHANGED, error message or the actual content
+   */
+  function genPage()
+  {
+    $cacheable = $this->cacheCheck();
+    if ($cacheable == Cacheable::YES) {
+      if (!CheckHttpModified($this->cache))
+	return false;
+    }
+    $res = $this->generateContent();
+    if ($cacheable == Cacheable::UNDETERMINED) {
+      $cacheable = $this->cacheCheck();
+      if ($cacheable == Cacheable::YES) {
+	if (!CheckHttpModified($this->cache))
+	  return false;
+      }
+    }
+
+    if ($this->mayValidate()) {
+      /*
+      $request = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+      $validator = new OnlineUriValidator($request);
+      */
+      $validator = new OnlineBufferValidator($res);
+      if (!$validator->check())
+	throw new LogicException('The page could be generated, but contained errors');
+    }
+    if ($this->mayCompress()) {
+      $this->startCompression();
+    }
+    $t = gettype($res);
+    if ($t === "string") {
+      $res = new PageContent($res);
+    }
+    elseif (get_class($res) !== "PageContent") {
+      throw new InvalidArgumentException("generateContent returned an unexpected type");
+    }
+    if ($variants = $this->getVariants()) {
+      $res->setHeader('Vary', join(",", $variants));
+    }
+    return $res;
+  }
+
+  /**
+   * Displays the result from genPage.
+   *
+   * Printing headers and content.
+   */
+  function display()
+  {
+    $res = $this->genPage();
+    if ($res) {
+      foreach ($res->headers as $header => $value) {
+	header("${header}: ${value}");
+      }
+      print $res;
+    }
+  }
+
+
+}
+?>