Source for file webpage-defs.php

Documentation is available at webpage-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: webpage-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for managing web-pages. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package core */
  27. include_once("plugin-defs.php");
  28. /** Date-time functions */
  29. ("datetime-defs.php");
  30.  
  31. // ----------------------------------------------------------------------
  32. // Flag determining whether webpage is cached or not..
  33.  
  34. /** The webpage is cached */
  35. ("CACHED", true);
  36. /** The webpage is not cached */
  37. ("NOT_CACHED", false);
  38.  
  39. // ----------------------------------------------------------------------
  40. // Option to determine the buffering mode.
  41.  
  42. /** The webpage is buffered using Php buffering */
  43. ("BUFFERED", true);
  44. /** The webpage is not buffered */
  45. ("UNBUFFERED", false);
  46.  
  47. // ----------------------------------------------------------------------
  48. /**
  49. * The webstream class
  50. * A class to manage buffering, cacheing, processing and output of the
  51. * content to the user agent. This is the entity which manages the Php
  52. * buffering mechanism, starting and stopping buffering and sending the
  53. * buffer to the client's browser. It also manages any cacheing of the webpage.
  54. * This class extends the session, since the whole point of the session is
  55. * to output content back to the user agent.
  56. * @package core
  57. */
  58. class webstream extends session {
  59. /** Whether to use Php buffering */
  60.  
  61. var $buffered = true;
  62. /** The content to send to browser */
  63.  
  64. var $content = "";
  65. /** Replacements to make in template */
  66.  
  67. var $replacement;
  68. /** Page is cached or dynamic */
  69.  
  70. var $cached = NOT_CACHED;
  71. /** Seconds expiry for cached webpages */
  72.  
  73. var $cache_expiry = 0;
  74. /** Path to use to save cached version of webpage */
  75.  
  76. var $cache_path = "";
  77. /** If true, force regeneration of cached webpage */
  78.  
  79. var $cache_regen = false;
  80. // .....................................................................
  81. /**
  82. * Constructor
  83. * Create a new webstream object. When this object is created it
  84. * always starts buffering with the ob_start() call. The Phplib
  85. * system always uses the Php buffering mechanism. This allows us
  86. * to process the output content and do 'clever things' right up
  87. * to the point of sending it all to the user.
  88. * @param string $initcontent Some intial content for the page
  89. */
  90. function webstream($initcontent="", $buffered=true) {
  91. // Create the session
  92. $this->session();
  93.  
  94. // Set buffering mode..
  95. $this->buffered = $buffered;
  96.  
  97. // Open for business..
  98. $this->open_webstream();
  99.  
  100. // Kick off with any initial content..
  101. $this->add_content($initcontent);
  102. } // webstream constructor
  103. // .....................................................................
  104. /** Start webstream output channel.. */
  105.  
  106. function open_webstream() {
  107. if ($this->buffered) {
  108. if ($this->multilang && $this->mbstring_avail) {
  109. ob_start("mb_output_handler");
  110. debugbr("webstream: mb_output_handler (multilang)", DBG_DEBUG);
  111. }
  112. else {
  113. ob_start();
  114. debugbr("webstream: standard buffering", DBG_DEBUG);
  115. }
  116. }
  117. else {
  118. debugbr("webstream: no buffering", DBG_DEBUG);
  119. }
  120. } // open_webstream
  121. // .....................................................................
  122. /**
  123. * Close the webstream. Return any current webpage content. Clear the
  124. * current content. This method clears content, but leaves any replacement
  125. * definitions untouched for further processing. It is designed to be
  126. * called as part of the final webpage rendering process.
  127. * @return string The current content, as it stands.
  128. */
  129. function close_webstream() {
  130. if ($this->buffered) {
  131. $content = ob_get_contents();
  132. ob_end_clean();
  133. }
  134. else {
  135. $content = $this->content;
  136. }
  137.  
  138. // Clear content..
  139. $this->content = "";
  140.  
  141. // Return what there was..
  142. return $content;
  143. } // close_webstream
  144. // .....................................................................
  145. /** Reset the webstream. This method clears any current content, and
  146. * also clears any stored replacement definitions. This resets the
  147. * stream to the point at which it was created - a virgin webstream.
  148. */
  149. function reset_webstream() {
  150. $this->content = "";
  151. unset($this->replacement);
  152. } // reset_webstream
  153. // .....................................................................
  154. /** Add new content to the webstream.. */
  155.  
  156. function add_content($content) {
  157. if ($content != "") {
  158. if ($this->buffered) {
  159. echo $content;
  160. }
  161. else {
  162. $this->content .= $content;
  163. }
  164. }
  165. } // add_content
  166. // .....................................................................
  167. /**
  168. * Cache this webpage
  169. * Causes the current webpage to be regarded as a cached page.
  170. * This means we look for a file of the same name but with extension
  171. * 'cached' in the $CACHEDIR directory, and check the modification
  172. * time. If it isn't expired then we set the page content to that file,
  173. * and send it. Otherwise we behave as if it is a normal dynamic Php page.
  174. * @param $expirysecs integer Seconds before page cacheing expires
  175. */
  176. function cache($expirysecs=0) {
  177. global $CACHEDIR;
  178. $this->cache_path = "$this->site_docroot/$CACHEDIR/" . $this->theme . "_" . basename($this->requested) . ".cached";
  179. $this->cache_expiry = $expirysecs;
  180. $this->cached = CACHED;
  181.  
  182. // Obey any cache control directives..
  183. if (isset($this->cachecontrol)) {
  184. // Possible forced refresh..
  185. if ($this->cachecontrol == "refresh" || $this->cachecontrol == "dynamic") {
  186. $this->cache_expiry = 0;
  187. debugbr("cachecontrol: forced cache refresh", DBG_DEBUG);
  188. }
  189. // Possible forced expirytime..
  190. else {
  191. $this->cache_expiry = (int)($this->cachecontrol);
  192. debugbr("cachecontrol: cache expiry set to $this->cachecontrol", DBG_DEBUG);
  193. }
  194. }
  195. if (file_exists($this->cache_path)) {
  196. $tsnow = time();
  197. $tsfile = filemtime($this->cache_path);
  198. if ($tsnow > $tsfile + $this->cache_expiry) {
  199. // We are about to drop through and allow this cached
  200. // file to be regenerated, but we touch it here to decrease
  201. // the chance of multiple rebuilds in the meantime..
  202. $this->cache_regen = true;
  203. touch($this->cache_path);
  204. debugbr("cachecontrol: re-generating expired page '$this->cache_path'", DBG_DEBUG);
  205. }
  206. else {
  207. // This cached file has a current version out on
  208. // disk, so we just return this file to the client..
  209. $this->discard();
  210. $cachefile = new inputfile($this->cache_path);
  211. if ($cachefile->opened) {
  212. $cachefile->readall();
  213. $this->content = $cachefile->content;
  214. $cachefile->closefile();
  215. $this->send_to_browser();
  216. exit;
  217. }
  218. else {
  219. log_sys("cachecontrol: failed to read cached page '$this->cache_path'");
  220. }
  221. }
  222. }
  223. else {
  224. // Non-existant cache file. Make sure it gets built..
  225. $this->cache_regen = true;
  226. touch($this->cache_path);
  227. debugbr("cachecontrol: generating cache for '$this->cache_path'", DBG_DEBUG);
  228. }
  229. } // cache
  230. // .....................................................................
  231. /**
  232. * Length of output buffer
  233. * Returns the length of our output buffer. Be careful when this is
  234. * called, since the buffer might not be filled by make_content() yet!
  235. * @param $expirysecs integer Seconds before page cacheing expires
  236. */
  237. function length() {
  238. if ($this->buffered) {
  239. return ob_get_length();
  240. }
  241. else {
  242. return strlen($this->content);
  243. }
  244. } // length
  245. // .....................................................................
  246. /**
  247. * Replace pattern in webpage content
  248. * Replaces multiple occurrences of the given tag (pattern) in the
  249. * body content with the specified new stuff. NB: when you call this
  250. * method the replacement isn't actually done there and then. It is
  251. * simply flagged as something to be done just before all of the
  252. * content is delivered to the user browser.
  253. * @param string $tag Pattern to replace in content
  254. * @param string $newstuff Stuff to replace the tag with
  255. */
  256. function replace($tag, $newstuff) {
  257. $this->replacement[$tag] = $newstuff;
  258. return $this;
  259. } // replace
  260. // .....................................................................
  261. /**
  262. * Replace all webpage content
  263. * For replacing the total contents of the buffer so far
  264. * with a new content. Throw buffer away and start anew with
  265. * immediate effect.
  266. * @param string $newcontent Replacement webpage content
  267. */
  268. function replace_content($newcontent) {
  269. $this->close_webstream();
  270. $this->reset_webstream();
  271. $this->open_webstream($newcontent);
  272. } // replace_content
  273. // .....................................................................
  274. /**
  275. * Discard all webpage content
  276. * For discarding the content so far with immediate effect.
  277. */
  278. function discard() {
  279. $this->close_webstream();
  280. $this->reset_webstream();
  281. } // discard
  282. // .....................................................................
  283. /**
  284. * Make content
  285. * This function takes our buffered content so far, stops buffering,
  286. * makes any replacements, and puts the resulting content into
  287. * the staging ($this->content) variable. This is mainly an internal
  288. * method which is called prior to sending the output to the user's
  289. * browser.
  290. * @access private
  291. */
  292. function make_content() {
  293. global $BLOCK_DEFS;
  294. $content = $this->close_webstream();
  295. if (isset($this->replacement)) {
  296. foreach ($this->replacement as $tag => $newstuff) {
  297. $tmp = str_replace($tag, $newstuff, $content);
  298. $content = $tmp;
  299. }
  300. }
  301. // Now insert our debugging output, if any..
  302. if (isset($this->debugger) && $this->debugger->debug_hascontent()) {
  303. switch($this->browser_type) {
  304. case BROWSER_TYPE_XHTML:
  305. case BROWSER_TYPE_HTML:
  306. // Tuck debugging info in after <body> tag..
  307. $pos = strpos($content, "<body");
  308. if (!($pos === false)) {
  309. $pos = strpos($content, ">", $pos);
  310. if (!($pos === false)) {
  311. $pos++;
  312. $content1 = substr($content, 0, $pos);
  313. $content2 = substr($content, $pos);
  314. $content = $content1 . $this->debugger->render() . $content2;
  315. }
  316. }
  317. break;
  318. case BROWSER_TYPE_XHTMLMP:
  319. case BROWSER_TYPE_WML:
  320. case BROWSER_TYPE_WMLUP:
  321. // For WML debug output we replace the content with a
  322. // dedicated card containing the debugging info..
  323. $bits = explode("<wml>", $content);
  324. $head = $bits[0];
  325. $dbgcard = new WMLcard("debug", "Debug");
  326. $dbgcard->insert_para($this->debugger->render());
  327. $dbgdeck = new WMLdeck($dbgcard);
  328. $content = $head . "<wml>" . $dbgdeck->render() . "</wml>";
  329. break;
  330. } // switch
  331. }
  332. $this->content = $content;
  333. return $this;
  334. } // make_content
  335. // .....................................................................
  336. /**
  337. * Send content to user browser
  338. * Deliver the content to the browser. First check if the page is cached
  339. * and if so whether we are going to update the cache. Next we get the
  340. * current buffer and aply any compression required. Then we send the
  341. * output on its way using the simple echo() function.
  342. * NOTE: If the page is not cached then we always send headers which
  343. * will make the user browser avoid cacheing it locally. This makes
  344. * sure that our dynamic pages will always be requested by it.
  345. */
  346. function send_to_browser() {
  347. global $HTTP_ACCEPT_ENCODING;
  348. global $compression_minsize;
  349. global $compression_type;
  350.  
  351. // Check if the webpage is cached or not..
  352. if ($this->cached) {
  353. if ($this->cache_regen) {
  354. $cachefile = new outputfile($this->cache_path);
  355. if ($cachefile->opened) {
  356. $cachefile->write($this->content);
  357. $cachefile->closefile();
  358. }
  359. else {
  360. log_sys("Failed to write cache file '$this->cache_path'");
  361. }
  362. }
  363. }
  364. // Deal with compression options..
  365. switch ($compression_type) {
  366. case BUILTIN_COMPRESSION:
  367. ob_start("ob_gzhandler");
  368. echo $this->content;
  369. ob_end_flush();
  370. break;
  371. case CUSTOM_COMPRESSION:
  372. $size = strlen($this->content);
  373. if ($size >= $compression_minsize) {
  374. if (isset($HTTP_ACCEPT_ENCODING) && stristr($HTTP_ACCEPT_ENCODING, "gzip")) {
  375. $crc = crc32($this->content);
  376. $this->content = gzcompress($this->content, 9);
  377. $gzlen = strlen($this->content);
  378. $this->content = substr($this->content, 0, $gzlen - 4);
  379. $this->content .= AsFourChars($crc);
  380. $this->content .= AsFourChars($size);
  381. header("Content-Encoding: gzip");
  382. echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
  383. }
  384. }
  385. echo $this->content;
  386. break;
  387. default:
  388. echo $this->content;
  389. } // switch
  390. // Log timer results, if enabled..
  391. if (isset($this->timer)) {
  392. log_sys("axyl response logging: "
  393. . "user=" . $this->userid . " "
  394. . "page=" . $this->requested . " "
  395. . "time=" . $this->timer->formatted_millisecs() . "ms"
  396. );
  397. }
  398. } // send_to_browser
  399. // .....................................................................
  400. /**
  401. * Send content to file
  402. * Deliver the content to a given file.
  403. * Make our buffer content, and then deliver it to a file.
  404. * @see make_content()
  405. * @see output_to_file()
  406. * @param string $name The name of the file
  407. * @param string $dir The directory the file is in
  408. * @return boolean True if file was opened, else false
  409. */
  410. function send_to_file($name, $dir="") {
  411. $this->make_content();
  412. return $this->output_to_file($name, $dir);
  413. } // send_to_file
  414. // .....................................................................
  415. /**
  416. * Output content to file
  417. * Raw function to output content to file..
  418. * @param string $name The name of the file
  419. * @param string $dir The directory the file is in
  420. * @return boolean True if file was opened, else false
  421. * @access private
  422. */
  423. function output_to_file($name, $dir="") {
  424. $res = false;
  425. $f = new outputfile($name, $dir);
  426. if ($f->opened) {
  427. $f->write($this->content);
  428. $f->closefile();
  429. }
  430. return $res;
  431. } // output_to_file
  432. // .....................................................................
  433. /**
  434. * Return webpage content
  435. * Builds all of the webpage content and returns it to the caller.
  436. * @return string All of the webpage content as it would be sent to the user browser
  437. */
  438. function webpage_content() {
  439. $this->make_content();
  440. return $this->content;
  441. } // webpage_content
  442. // .....................................................................
  443. /**
  444. * Send error and die
  445. * Generic function to abort and send an error notification to the user
  446. * instead. This function is a one-way trip to oblivion.
  447. * @param string $heading The error heading or subject
  448. * @param string $msg The detailed error message
  449. */
  450. function send_error_and_die($heading, $msg="") {
  451. // Discard current buffered output..
  452. $this->discard();
  453.  
  454. // Return error message in error page..
  455. $errorpg = new error_page($heading, $msg);
  456. $this->content = $errorpg->render();
  457. $this->send_to_browser();
  458. exit;
  459. } // send_error_and_die
  460. // .....................................................................
  461. /**
  462. * Send HTTP error code and die
  463. * Generic function to abort and send an error code notification to the
  464. * user. These are lookalike errors for generic ones like 404: Page not found
  465. * etc. This function will not return.
  466. * @param integer $code The HTTP error code to generate
  467. */
  468. function send_errorcode_and_die($code) {
  469. $this->send_error_and_die( HTTPError($code) );
  470. } // send_errorcode_and_die
  471.  
  472. } // webstream class
  473. // ----------------------------------------------------------------------
  474.  
  475. /**
  476. * The webpage page class.
  477. * This is the main focus of the Axyl framework for generating webpage
  478. * content of any kind and for any device. We envisage the standard page
  479. * structure with a head, body and foot section. Depending on the device
  480. * this might not be exactly right, but it doesn't really matter, since
  481. * you have complete control over the content.
  482. * @package core
  483. */
  484. class webpage extends webstream {
  485. // Public
  486. /** Webpage head object */
  487.  
  488. var $head;
  489. /** Webpage body object */
  490.  
  491. var $body;
  492. /** Webpage foot object */
  493.  
  494. var $foot;
  495. /** The name of the template which was applied, if any */
  496.  
  497. var $template = "";
  498. /** The file the template content is to be found in */
  499.  
  500. var $templatefile = "";
  501. /**
  502. * Theme to apply to the page. This should be a single-word ID, and
  503. * there should be a sub-directory of the same name in the 'templates'
  504. * directory, with templates and stylesheet(s) in it which comprise
  505. * the theme. This is how we provide different template sets and
  506. * stylesheets for branding purposes.
  507. */
  508. var $theme = "";
  509.  
  510. // Private
  511. /** True if page has been generated
  512. @access private */
  513. var $generated = false;
  514. /** Set of plugins with content
  515. @access private */
  516. var $pluginset;
  517. // .....................................................................
  518. /**
  519. * Constructor
  520. * Create a new webpage object. When this object is created it
  521. * implicitly starts buffering with the ob_start() call by creating
  522. * a webstream.
  523. * NOTES: If you name your stylesheets after the APP_PREFIX (see your
  524. * application.php setup file), eg: 'haka.css' and 'haka_ie.css', then
  525. * the system will find them for you. The same applies if you call them
  526. * 'sitestyle.css' and 'sitestyle_ie.css'.
  527. * @param string $title Webpage title string
  528. * @param string $template Template for this webpage
  529. * @param string $theme Theme to apply. This is for branding purposes
  530. * @param string $stylesheet Name of stylesheet. Defaults to {APP_PREFIX}.css
  531. */
  532. function webpage($title="", $template="", $sitetheme="", $stylesheet="") {
  533. // Create webstream, start buffering..
  534. $this->webstream();
  535.  
  536. // Define the theme, if any. We override the static
  537. // defined theme with one which might be coming in
  538. // on a URL or via a form submission..
  539. global $theme;
  540. if (isset($theme) && $theme != "") {
  541. $this->set_theme($theme);
  542. }
  543. else {
  544. $this->set_theme($sitetheme);
  545. }
  546.  
  547. // HEAD - Set up the head page section..
  548. $this->head = new head($title);
  549.  
  550. // BODY - Set up body OR deck page section..
  551. if ($this->browser == BROWSER_PHONE) {
  552. $this->body = new deck();
  553. if ($this->browser_type == BROWSER_TYPE_WMLUP) {
  554. $s = "<meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"max-age=0\"/>";
  555. $s .= "<meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"must revalidate\"/>";
  556. $this->head->add($s);
  557. }
  558. }
  559. else {
  560. $this->body = new body();
  561. }
  562.  
  563. // FOOT - Define foot page section
  564. $this->foot = new foot();
  565.  
  566. // Set up the template..
  567. $this->set_template($template);
  568.  
  569. // Set up the stylesheet(s)..
  570. $this->set_stylesheet($stylesheet);
  571.  
  572. // Set up the DTDs..
  573. $this->assign_DTD();
  574.  
  575. // Initialise a plugin set..
  576. $this->pluginset = new pluginset();
  577.  
  578. } // webpage constructor
  579. // .....................................................................
  580. /**
  581. * Add to the body content
  582. * @param string $morestuff Content to append to the body of the webpage
  583. */
  584. function add($morestuff) {
  585. $this->body->add($morestuff);
  586. return $this;
  587. } // add
  588. // .....................................................................
  589. /**
  590. * Add named script
  591. * This adds a specific lump of script to the body under a unique name.
  592. * It allows you to collect multiple additions of script content under
  593. * a single grouping, and so cause the final rendering to group it all
  594. * together.
  595. * @param string $script Script content (omit <script> tags)
  596. * @param string $name Script content grouping identity
  597. * @param string $language The language the script is in
  598. */
  599. function add_named_script($script, $name, $language="javascript") {
  600. $this->body->add_named_script($script, $name, $language);
  601. } // add_named_script
  602. // .....................................................................
  603. /**
  604. * Add named script to the body
  605. * @param string $script Script to insert into the body of the webpage
  606. * @param string $language Language of this script (default javascript)
  607. */
  608. function add_script($script, $language="javascript") {
  609. $this->body->add_script($script, $language);
  610. } // add_script
  611. // .....................................................................
  612. /**
  613. * Add script URL to the body
  614. * @param string $src URL reference to script to insert into the body
  615. * @param string $language Language of this script (default javascript)
  616. */
  617. function add_scriptsrc($src, $language="javascript") {
  618. $this->body->add_scriptsrc($src, $language);
  619. } // add_scriptsrc
  620. // .....................................................................
  621. /**
  622. * Add content to a plugin
  623. * Plugins are regions of a webpage which you want to plug content into.
  624. * This is the method to call to add content to a named region or plugin.
  625. * The plugin ID (name) is related to a COMMENT TAG which appears in the
  626. * template of the page. If the plugin doesn't exist then one is created
  627. * otherwise the content is simply appended to that already defined.
  628. * The 'content' can be any one of the following types:
  629. * String - A literal string of content to put in the plugin
  630. * Path - Path to a file containing content (can be relative)
  631. * Function - A function definition, eg: "foo('xyx')" to return content
  632. * Object - An object. Must be a descendant of RenderableObject.
  633. * NB: This method can be called multiple times for the given plugin ID,
  634. * and content will be accumulated each time.
  635. * NB: When you nominate an object or a function to provide content, the
  636. * system assumes you want these generated "late" - ie. at the time
  637. * the webpage is being sent back to the user agent. If you want
  638. * content to be inserted early, then use literal strings.
  639. * @param string $pluginid ID of this plugin. Used to find plugin location
  640. * @param mixed $content The plugin content (literal, function, object...)
  641. */
  642. function plugin($pluginid, $content) {
  643. $this->pluginset->addto($pluginid, $content);
  644. } // plugin
  645. // .....................................................................
  646. /**
  647. * Define or redefine a plugin. This acts similarly to the above plugin()
  648. * method, except that here we replace the existing content, if any is
  649. * present, with this content.
  650. * @param string $pluginid ID of this plugin. Used to find plugin location
  651. * @param mixed $content The plugin content (literal, function, object...)
  652. */
  653. function plugin_replace($pluginid, $content) {
  654. $this->pluginset->add_plugin($pluginid, $content);
  655. } // plugin_replace
  656. // .....................................................................
  657. /**
  658. * Start/stop inline plugin content definition
  659. * This method allows plugin content to be taken from inline content
  660. * in the script page itself. At the start of the content call this
  661. * method with the name of the plugin (pluginid) you want to put the
  662. * content into. At the end of the content, call this method with
  663. * no parameter.
  664. */
  665. function plugin_inline($pluginid="") {
  666. static $the_plugin_id = "";
  667. if ($the_plugin_id == "") {
  668. if ($pluginid != "") {
  669. $the_plugin_id = $pluginid;
  670. $this->inline_start();
  671. }
  672. }
  673. else {
  674. $content = $this->inline_end();
  675. $this->plugin($the_plugin_id, $content);
  676. $the_plugin_id = "";
  677. }
  678. } // plugin_inline
  679. // .....................................................................
  680. /**
  681. * Begin inline buffering
  682. * If you want to include some 'naked' HTML in-line with your webpage
  683. * content, then call this method, then close the Php script with the
  684. * usual "?>" tag. Follow this with your HTML, then restart Php script
  685. * and grab the resulting HTML with... <?php $s = $page->inline_end();
  686. * Then $s will contain all the HTML between inline_start/inline_end.
  687. * @see inline_end()
  688. */
  689. function inline_start() {
  690. ob_start();
  691. } // inline_start
  692. // .....................................................................
  693. /**
  694. * End inline buffering
  695. * Usually used as in: <?php $s = $page->inline_end();
  696. * Then $s will contain all the HTML between inline_start/inline_end.
  697. * @see inline_start()
  698. * @return string Contents of the buffer gathered since inline_start()
  699. */
  700. function inline_end() {
  701. $content = ob_get_contents();
  702. ob_end_clean();
  703. return $content;
  704. } // inline_end
  705. // .....................................................................
  706. /**
  707. * Define the theme
  708. * Set the theme to apply to the page. This should be a single-word ID,
  709. * and there should be a sub-directory of the same name in the 'templates'
  710. * directory, with templates and stylesheet(s) in it which comprise
  711. * the theme. This is how we provide different template sets and stylesheets
  712. * for branding purposes.
  713. * @param string $theme Theme name for this webpage
  714. */
  715. function set_theme($theme) {
  716. global $IMAGESDIR, $TEMPLATESDIR;
  717. // Store new theme name..
  718. $this->theme = $theme;
  719. if ($theme != "") {
  720. // Point at theme images directory..
  721. $bits = explode("/", $IMAGESDIR);
  722. $n = count($bits) - 1;
  723. if ($n >= 0) {
  724. $imgdirname = $bits[$n];
  725. $IMAGESDIR = "$TEMPLATESDIR/$this->theme/$imgdirname";
  726. debugbr("theme '$this->theme': setting images directory to '$IMAGESDIR'", DBG_DEBUG);
  727. }
  728. }
  729. } // set_theme
  730. // .....................................................................
  731. /**
  732. * Set the filenames for the main stylesheet and (optionally) the
  733. * stylesheet for Internet Explorer compatible browsers.
  734. * @param string $ss Name of normal stylesheet (others are derived)
  735. */
  736. function set_stylesheet($ss="") {
  737. $sheets = $this->get_stylesheets($ss);
  738. $this->head->set_stylesheet(
  739. $sheets["ss"],
  740. $sheets["ss_ie"],
  741. $sheets["ss_ns"]
  742. );
  743. } // set_stylesheet
  744. // .....................................................................
  745. /**
  746. * Get the filenames for the main stylesheet and (optionally) the
  747. * stylesheet for Internet Explorer compatible browsers. Note: this
  748. * should only be a filename, not a path. If a theme has been defined
  749. * then the stylesheet will be expected to be in the subdirectory of
  750. * the same name as the theme, under the 'templates' directory. If not
  751. * then the stylesheet is expected to be in the website root dir.
  752. * Defaults are in effect as follows:
  753. * If the stylesheet is nullstring, then we look for a stylesheet in
  754. * the appropriate directory with a name of APP_PREFIX.css. If that
  755. * isn't found we try looking for 'sitestyle.css'. Same applies for
  756. * the IE stylesheet, but with "_ie" appended to the filename part.
  757. * We return the results in an associative array, with elements:
  758. * returned_array["css"] = standard stylsheet
  759. * returned_array["css_ie"] = IE stylsheet
  760. * returned_array["css_ns"] = Netscape 4.xx stylsheet
  761. * @param string $ss Name of normal stylesheet (others are derived).
  762. * @param string $theme The theme to retreive the stylesheets for.
  763. * @return array Associative array of stylesheets as located.
  764. */
  765. function get_stylesheets($ss="", $theme="?") {
  766. global $TEMPLATESDIR;
  767.  
  768. // Initialise return var..
  769. $stylesheets = array();
  770. $stylesheets["ss"] = "";
  771. $stylesheets["ss_ie"] = "";
  772. $stylesheets["ss_ns"] = "";
  773.  
  774. // Use current theme unless overriden..
  775. if ($theme == "?") {
  776. $theme = $this->theme;
  777. }
  778.  
  779. // Set the path prefixes..
  780. if ($theme != "") {
  781. $prefix = $this->site_docroot . "$TEMPLATESDIR/$theme/";
  782. $wwwprefix = "$TEMPLATESDIR/$theme/";
  783. }
  784. else {
  785. $prefix = $this->site_docroot . "/";
  786. $wwwprefix = "/";
  787. }
  788.  
  789. // See if we can find defaults if null. We first try files
  790. // with the standard 'sitestyle.css' naming scheme. If that
  791. // fails we try a stem of APP_PREFIX.
  792. if ($ss == "") {
  793. $try = "sitestyle";
  794. if (file_exists($prefix.$try.".css")) {
  795. $ss = $try.".css";
  796. }
  797. else {
  798. $try = APP_PREFIX;
  799. if (file_exists($prefix.$try.".css")) {
  800. $ss = $try.".css";
  801. }
  802. }
  803. }
  804. // Check for IE & Netscape stylesheets. The rule is that if this
  805. // exists it will be the same name as the standard stylesheet but
  806. // with "_ie" & "_ns" suffixes respectively..
  807. $ss_ie = ""; $ss_ns = "";
  808. if ($ss != "") {
  809. $ssbits = explode(".", $ss);
  810. $try = $ssbits[0] . "_ie";
  811. if (file_exists($prefix.$try.".css")) {
  812. $ss_ie = $try.".css";
  813. }
  814. $try = $ssbits[0] . "_ns";
  815. if (file_exists($prefix.$try.".css")) {
  816. $ss_ns = $try.".css";
  817. }
  818. }
  819.  
  820. // Define any stylesheets found..
  821. if ($ss != "") $stylesheets["ss"] = $wwwprefix.$ss;
  822. if ($ss_ie != "") $stylesheets["ss_ie"] = $wwwprefix.$ss_ie;
  823. if ($ss_ns != "") $stylesheets["ss_ns"] = $wwwprefix.$ss_ns;
  824.  
  825. // Return the results..
  826. return $stylesheets;
  827.  
  828. } // get_stylesheets
  829. // .....................................................................
  830. /**
  831. * Define the script to execute after page has loaded
  832. * @param string $onload Script to execute when page loads
  833. */
  834. function set_onload($onload) {
  835. $this->body->set_onload($onload);
  836. return $this;
  837. } // set_onload
  838. // .....................................................................
  839. /**
  840. * Define the webpage title
  841. * @param string $title Title to give the webpage
  842. */
  843. function set_title($title) {
  844. $this->head->set_title($title);
  845. return $this;
  846. } // set_title
  847. // .....................................................................
  848. /**
  849. * Define the style settings for the webpage. Usually the stylesheet
  850. * will be all you require, however occasionally it is necessary to
  851. * have specific styles for a page. Set these here, but make sure to
  852. * provide the FULL style complete with <style></style> tags.
  853. * @param string $style Style to insert into the webpage
  854. */
  855. function set_style($style) {
  856. $this->head->set_style($style);
  857. return $this;
  858. } // set_style
  859. // .....................................................................
  860. /**
  861. * Define the template for the webpage.
  862. * The $templatename can be the special "plain" which is a pseudo template
  863. * of vanilla content, a fll path to a file, or a name. If it is a simple
  864. * name, then the system knows where to find it and constructs a full
  865. * path to the file from it.
  866. * @param string $templatename The name of, or full path to the template file
  867. */
  868. function set_template($templatename) {
  869. global $TEMPLATESDIR;
  870. if ($templatename != "") {
  871. $this->templatefile = "";
  872. if ($templatename != "plain") {
  873. if (strtolower(substr($templatename, 5)) == ".html" ||
  874. strtolower(substr($templatename, 4)) == ".wml") {
  875. // Absolute path to template as it stands..
  876. $templatefile = $templatename;
  877. $this->template = get_file_stem(basename($templatefile));
  878. }
  879. else {
  880. // Try to find the template file - fallback to "main"..
  881. $templatenames_to_try = array($templatename);
  882. if ($templatename != "main") {
  883. $templatenames_to_try[] = "main";
  884. }
  885. foreach ($templatenames_to_try as $templatename) {
  886. $this->template = $templatename;
  887. $extn = "html";
  888. if ($this->browser == BROWSER_PHONE) {
  889. $extn = "wml";
  890. }
  891. // Build assumed path to correct template file..
  892. $templatefile = "template_" . $templatename . "." . $extn;
  893. if ($this->theme != "") {
  894. // Use a template from a theme sub-directory..
  895. $templatefile = "$TEMPLATESDIR/$this->theme/$templatefile";
  896. }
  897. else {
  898. // Use standard template..
  899. $templatefile = "$TEMPLATESDIR/$templatefile";
  900. }
  901. // Check it exists..
  902. $this->templatefile = $this->site_docroot . $templatefile;
  903. if (is_readable($this->templatefile)) {
  904. break;
  905. }
  906. } // foreach
  907. }
  908. } // not plain
  909. else {
  910. $this->template = "plain";
  911. }
  912. // Now we have the template content, use it..
  913. debugbr("template name: $this->template", DBG_DEBUG);
  914. debugbr("template file: $this->templatefile", DBG_DEBUG);
  915. $this->head->load_template($this->templatefile);
  916. $this->body->load_template($this->templatefile);
  917. }
  918. } // set_template
  919. // .....................................................................
  920. /**
  921. * Assign the DTD for the resident head page section. We have two ways
  922. * to do this: directly via passed parameter $DTD, or indirectly by
  923. * using the content (browser) type, and looking up the DTD from the
  924. * array of DTD specifiers created in the response object.
  925. * @param string $DTD Optional override DTD specifier string
  926. */
  927. function assign_DTD($DTD="") {
  928. if (isset($this->head)) {
  929. if ($DTD == "" && isset($this->DTD)) {
  930. switch ($this->browser_type) {
  931. case BROWSER_TYPE_XHTML:
  932. case BROWSER_TYPE_HTML:
  933. if (isset($this->DTD[BROWSER_TYPE_HTML])) {
  934. $DTD = $this->DTD[BROWSER_TYPE_HTML];
  935. }
  936. break;
  937. case BROWSER_TYPE_XHTMLMP:
  938. case BROWSER_TYPE_WML:
  939. case BROWSER_TYPE_WMLUP:
  940. if (isset($this->DTD[BROWSER_TYPE_WML])) {
  941. $DTD = $this->DTD[BROWSER_TYPE_WML];
  942. }
  943. break;
  944. }
  945. }
  946. $this->head->set_dtd($DTD);
  947. }
  948. } // assign_DTD
  949. // .....................................................................
  950. /**
  951. * Insert a ready-made meta tag object into the webpage head section.
  952. * @param string $id Meta tag unique ID
  953. * @param object $metatag Meta tag object to insert
  954. */
  955. function insert_metatag($id, $metatag) {
  956. $this->head->insert_metatag($id, $metatag);
  957. } // insert_metatag
  958. // .....................................................................
  959. /**
  960. * Add a meta tag to the webpage head section.
  961. * @param string $name Meta tag name
  962. * @param string $content Meta tag content
  963. * @param string $language Optional language specifier for content
  964. * @param string $scheme Optional scheme specifier for content
  965. */
  966. function set_metatag($name, $content, $language, $scheme) {
  967. $this->head->set_metatag($name, $content, $language, $scheme);
  968. } // set_metatag
  969. // .....................................................................
  970. /**
  971. * Generate the webpage content
  972. * This routine is usually called after all the set-up calls for the
  973. * head, body etc. have been made. This echoes each page section to the
  974. * buffer, in preparation for delivery to the browser.
  975. */
  976. function generate() {
  977. global $HTMLAREA;
  978. if (!$this->generated) {
  979. if ($this->pluginset->hascontent) {
  980. foreach ($this->pluginset->plugins as $id => $plugin) {
  981. if (is_object($plugin)) {
  982. $newstuff = $plugin->render();
  983. $tag = "<!--" . strtoupper($id) . "-->";
  984. $this->replace($tag, $newstuff);
  985. }
  986. }
  987. }
  988. // Set up the javascript environment for any
  989. // htmlarea widgest which have been used..
  990. if (isset($HTMLAREA) && $HTMLAREA->activated) {
  991. $HTMLAREA->render();
  992. }
  993. // Produce the content..
  994. if ($this->buffered) {
  995. // Acquire content via the Php buffer..
  996. echo $this->head->render();
  997. echo $this->body->render();
  998. echo $this->foot->render();
  999. }
  1000. else {
  1001. // Content goes directly in..
  1002. $this->content .= $this->head->render();
  1003. $this->content .= $this->body->render();
  1004. $this->content .= $this->foot->render();
  1005. }
  1006. $this->generated = true;
  1007. $this->make_content();
  1008. }
  1009. } // generate
  1010. // .....................................................................
  1011. /**
  1012. * Generate the content and then send it to the user browser.
  1013. */
  1014. function send() {
  1015. $this->generate();
  1016. $this->send_to_browser();
  1017. } // send
  1018. // .....................................................................
  1019. /**
  1020. * Generate the content into the buffer, then return the content.
  1021. * @return string The webpage content complete, as a string
  1022. */
  1023. function render() {
  1024. $this->generate();
  1025. return $this->webpage_content();
  1026. } // render
  1027.  
  1028. } // webpage class
  1029. // ----------------------------------------------------------------------
  1030.  
  1031. /**
  1032. * The head class.
  1033. * The class is a special kind of page section. It contains all of the meta
  1034. * tags, style tags, title and other such things for the webpage. Note that
  1035. * this section is not just the head content, but really comprises everything
  1036. * which is prior to the /head tag. This might include the DTD specifier
  1037. * for instance.
  1038. * @package core
  1039. */
  1040. class head extends page_section {
  1041. /** Title of the webpage */
  1042.  
  1043. var $title = "";
  1044. /** Style settings for the webpage */
  1045.  
  1046. var $style = "";
  1047. /** The Document Type Definition for this head section */
  1048.  
  1049. var $DTD = "";
  1050. /** Meta tags array */
  1051.  
  1052. var $meta;
  1053. /** Name of the stylesheet associated with the webpage */
  1054.  
  1055. var $stylesheet = "";
  1056. /** Name of the IE stylesheet */
  1057.  
  1058. var $stylesheet_ie = "";
  1059. /** Name of the Netscape stylesheet */
  1060.  
  1061. var $stylesheet_ns = "";
  1062. /** Languages used in content of the page */
  1063.  
  1064. var $languages = array();
  1065. /** Charset for content of the page */
  1066.  
  1067. var $charset = "ISO-8859-1";
  1068. // .....................................................................
  1069. /**
  1070. * Constructor
  1071. * Create a new head object.
  1072. * @param string $title Title of the webpage
  1073. * @param string $style Specific style settings for the webpage
  1074. */
  1075. function head($title="", $style="") {
  1076. $this->page_section();
  1077. $this->set_title($title);
  1078. $this->set_style($style);
  1079. } //head constructor
  1080. // .....................................................................
  1081. /**
  1082. * Define the title
  1083. * @param string $title Title of the webpage
  1084. */
  1085. function set_title($title) {
  1086. $this->title = $title;
  1087. } // set_title
  1088. // .....................................................................
  1089. /**
  1090. * Define the style
  1091. * NB: The way this is currently done, you are expected to supply
  1092. * your style WITHOUT style tags here.
  1093. * @param string $style Specific style settings for the webpage
  1094. */
  1095. function set_style($style) {
  1096. $this->style = $style;
  1097. } // set_style
  1098. // .....................................................................
  1099. /**
  1100. * Add the given content to the current style. Appends style statements
  1101. * to the style string, which is rendered when the page gets rendered.
  1102. * @param string $style Style settings to add to existing ones.
  1103. */
  1104. function add_style($style) {
  1105. $this->style .= $style;
  1106. } // add_style
  1107. // .....................................................................
  1108. /**
  1109. * Set the stylesheet to use. This should be a valid pathname to an
  1110. * existing file. The second parm is for special styles for Internet
  1111. * Explorer-compatible browsers.
  1112. * @param string $ss Path to normal stylesheet
  1113. * @param string $ss_ie Path to stylesheet for Internet Explorer
  1114. */
  1115. function set_stylesheet($ss, $ss_ie="", $ss_ns="") {
  1116. $this->stylesheet = $ss;
  1117. $this->stylesheet_ie = $ss_ie;
  1118. $this->stylesheet_ns = $ss_ns;
  1119. } // set_stylesheet
  1120. // .....................................................................
  1121. /**
  1122. * Insert a ready-made meta tag object into the metatags array.
  1123. * @param string $id Meta tag unique ID
  1124. * @param object $metatag Meta tag object to insert
  1125. */
  1126. function insert_metatag($id, $metatag) {
  1127. $this->meta[$id] = $metatag;
  1128. } // insert_metatag
  1129. // .....................................................................
  1130. /**
  1131. * Add meta tag to the section
  1132. * @param string $name Meta tag name
  1133. * @param string $content Meta tag content
  1134. * @param string $language Optional language specifier for content
  1135. * @param string $scheme Optional scheme specifier for content
  1136. */
  1137. function set_metatag($name, $content, $language="", $scheme="") {
  1138. if ($name != "" && $content != "") {
  1139. $newtag = new HTMLtag("meta");
  1140. $newtag->add_attribute("name", $name);
  1141. $newtag->add_attribute("content", $content);
  1142. if ($language != "") {
  1143. $newtag->add_attribute("lang", $language);
  1144. }
  1145. if ($scheme != "") {
  1146. $newtag->add_attribute("scheme", $scheme);
  1147. }
  1148. $this->insert_metatag($name, $newtag);
  1149. }
  1150. } //set_metatag
  1151. // .....................................................................
  1152. /**
  1153. * Set the DTD specifier string for this head section.
  1154. * @param string $DTD The Document Type Definition string for this head
  1155. */
  1156. function set_dtd($DTD) {
  1157. $this->DTD = $DTD;
  1158. } // set_dtd
  1159. // ...................................................................
  1160. /**
  1161. * Adds another language for the current head. Webpages might
  1162. * contain content in multiple languages, hence the need for a list.
  1163. * @param integer $langid The new language ID to add for the webpage
  1164. */
  1165. function add_language($langid) {
  1166. if (!in_array($langid, $this->languages)) {
  1167. $this->languages[] = $langid;
  1168. }
  1169. } // add_language
  1170. // .....................................................................
  1171. /**
  1172. * Set the charset for this head section
  1173. * @param string $charset The charset code for content of this head section
  1174. */
  1175. function set_charset($charset) {
  1176. $this->charset = $charset;
  1177. } // set_charset
  1178. // ....................................................................
  1179. /**
  1180. * Load given template content.
  1181. * We scrape everything between the appropriate tags and use it as
  1182. * the template for our content.
  1183. * @param string $templatefile The full path to the template file
  1184. */
  1185. function load_template($templatefile="") {
  1186. $template = $this->get_template($templatefile);
  1187. if ($template != "") {
  1188. $bits = explode("<head>", $template);
  1189. if (isset($bits[0]) && $bits[0] != "") {
  1190. // Always use DTD from template if found..
  1191. if (preg_match("/<!DOCTYPE (.+)>/i", $bits[0], $matches)) {
  1192. $this->set_dtd($matches[0]);
  1193. }
  1194. if (isset($bits[1]) && $bits[1] != "") {
  1195. $bits = explode("</head>", $bits[1]);
  1196. if (isset($bits[0]) && $bits[0] != "") {
  1197. $head = $bits[0];
  1198. // Strip items which Axyl generates for itself..
  1199. $patts = array(
  1200. "<title>.*?<\/title>", // Title tag
  1201. "<meta http-equiv=\"content-type.*?>", // Content type meta tag
  1202. "<link rel=(.*?)stylesheet.*?>" // All stylesheet links
  1203. );
  1204. foreach ($patts as $patt) {
  1205. $head = preg_replace("/$patt\n|$patt/i", "", $head);
  1206. }
  1207. $this->content = $head;
  1208. }
  1209. }
  1210. }
  1211. }
  1212. return $this;
  1213. } // load_template
  1214. // ....................................................................
  1215. /**
  1216. * This renders the head as HTML. After the title and the meta tags
  1217. * are rendered, the stylesheets are next. For the stylesheets we first
  1218. * render the standard links, and then overlay this with the Internet Explorer
  1219. * stylesheet if it is defined. Finally any literal styles are rendered
  1220. * so they will take precedence. The scripts are rendered after the styles,
  1221. * and the head content comes last.
  1222. * @see render()
  1223. * @return string The head section as HTML.
  1224. */
  1225. function html() {
  1226. global $RESPONSE;
  1227. // Content type meta tag - always has to be first..
  1228. $meta = new HTMLtag("meta");
  1229. $meta->add_attribute("http-equiv", "content-type");
  1230. $meta->add_attribute("content", "text/html; charset=$this->charset");
  1231. $this->meta[] = $meta;
  1232.  
  1233. // Language(s) meta tag..
  1234. $languages = array();
  1235. if (count($this->languages) > 0) {
  1236. $q = "SELECT * FROM ax_language";
  1237. $q .= " WHERE lang_id IN (" . implode(",", $this->languages) . ")";
  1238. $q .= " AND lang_id <> 0";
  1239. $q .= " ORDER BY display_order";
  1240. $langs = dbrecordset($q);
  1241. if ($langs->hasdata) {
  1242. do {
  1243. $languages[] = $langs->field("char_encoding");
  1244. } while ($langs->get_next());
  1245. // Create the meta tag..
  1246. if (count($languages) > 0) {
  1247. $meta = new HTMLtag("meta");
  1248. $meta->add_attribute("http-equiv", "content-language");
  1249. $meta->add_attribute("content", implode(",", $languages));
  1250. $this->meta[] = $meta;
  1251. }
  1252. }
  1253. }
  1254.  
  1255. // Generator meta tag..
  1256. $meta = new HTMLtag("meta");
  1257. $meta->add_attribute("name", "generator");
  1258. $meta->add_attribute("content", "Catalyst IT Axyl");
  1259. $this->meta[] = $meta;
  1260.  
  1261. // Assemble head section..
  1262. $s = "";
  1263. if ($this->DTD != "") $s .= "$this->DTD\n";
  1264. $s .= "<html";
  1265. if (count($languages) > 0) {
  1266. $s .= " lang=\"" . implode(",", $languages) . "\"";
  1267. }
  1268. $s .= ">\n";
  1269. $s .= "<head>\n";
  1270. $s .= "<title>$this->title</title>\n";
  1271.  
  1272. // Now insert all defined meta tags..
  1273. foreach ($this->meta as $metatag) {
  1274. $s .= $metatag->render();
  1275. }
  1276.  
  1277. // Literal head content..
  1278. $s .= $this->get_trimcontent();
  1279.  
  1280. // The General Stylesheet..
  1281. if (isset($this->stylesheet) && $this->stylesheet != "") {
  1282. $s .= "<link rel=\"stylesheet\" href=\"$this->stylesheet\" type=\"text/css\">\n";
  1283. }
  1284.  
  1285. // Specific IE or Netscape Stylesheet..
  1286. switch ($RESPONSE->browser) {
  1287. case BROWSER_IE:
  1288. if (isset($this->stylesheet_ie) && $this->stylesheet_ie != "") {
  1289. $s .= "<link rel=\"stylesheet\" href=\"$this->stylesheet_ie\" type=\"text/css\">\n";
  1290. }
  1291. break;
  1292. case BROWSER_NETSCAPE:
  1293. if (isset($this->stylesheet_ns) && $this->stylesheet_ns != "") {
  1294. $s .= "<link rel=\"stylesheet\" href=\"$this->stylesheet_ns\" type=\"text/css\">\n";
  1295. }
  1296. break;
  1297. } // switch
  1298.  
  1299. // Static styles..
  1300. if (isset($this->style) && $this->style != "") {
  1301. $s .= "<style type=\"text/css\">\n";
  1302. $s .= "$this->style\n";
  1303. $s .= "</style>\n";
  1304. }
  1305.  
  1306. // Scripts..
  1307. $s .= $this->script();
  1308.  
  1309. $s .= "</head>\n";
  1310. return $s;
  1311. } // html
  1312. // ....................................................................
  1313. /**
  1314. * Use render() to render this element in your page.
  1315. * This renders the field as WML.
  1316. * @see render()
  1317. * @return string The field as WML.
  1318. */
  1319. function wml() {
  1320. $s = "";
  1321. $s .= "<?xml version=\"1.0\" encoding=\"$this->charset\"?>\n";
  1322. if ($this->DTD != "") $s .= "$this->DTD\n";
  1323. $s .= "<wml>";
  1324. if ($this->content != "" || isset($this->meta)) {
  1325. $s .= "<head>";
  1326. if (isset($this->meta)) {
  1327. while (list($name, $content) = each($this->meta)) {
  1328. $s .= "<meta name=\"$name\" content=\"$content\">\n";
  1329. }
  1330. }
  1331. $s .= $this->content;
  1332. $s .= "</head>";
  1333. }
  1334. return $s;
  1335. } // wml
  1336.  
  1337. } // head class
  1338. // ----------------------------------------------------------------------
  1339.  
  1340. /**
  1341. * The body class
  1342. * The class is a special kind of page section. It contains all of the
  1343. * main page content.
  1344. * @package core
  1345. */
  1346. class body extends page_section {
  1347. /** The script to execute when the page has loaded */
  1348.  
  1349. var $onload = "";
  1350. /** Miscellaneous content for the body tag */
  1351.  
  1352. var $parms = "";
  1353. // .....................................................................
  1354. /**
  1355. * Constructor
  1356. * Create a new body object.
  1357. * @param string $templatefile Template file to load content from
  1358. * @param string $onload Script to execute when page loads
  1359. * @param string $parms Misc other content for the body tag
  1360. */
  1361. function body($templatefile="", $onload="", $parms="") {
  1362. $this->page_section();
  1363. $this->load_template($templatefile);
  1364. $this->set_onload($onload);
  1365. $this->set_parms($parms);
  1366. } // body constructor
  1367. // .....................................................................
  1368. /**
  1369. * Define the script to execute after page has loaded
  1370. * @param string $onload Script to execute when page loads
  1371. */
  1372. function set_onload($onload) {
  1373. $this->onload .= $onload;
  1374. } // set_onload
  1375. // .....................................................................
  1376. /**
  1377. * Define other miscellaneous content to be put into the body tag.
  1378. * This method can be called multiple times. Each time the content
  1379. * is added (appended) to.
  1380. * @param string $parms Misc other content for the body tag
  1381. */
  1382. function set_parms($parms) {
  1383. if ($parms != "") {
  1384. if ($this->parms != "") {
  1385. $this->parms .= " ";
  1386. }
  1387. $this->parms .= $parms;
  1388. }
  1389. } // set_parms
  1390. // .....................................................................
  1391. /**
  1392. * Load given template content.
  1393. * We scrape everything between the appropriate tags and use it as
  1394. * the template for our content.
  1395. * @param string $templatefile The full path to template file
  1396. * @access private
  1397. */
  1398. function load_template($templatefile="") {
  1399. if ($templatefile == "") {
  1400. $this->content = "<!--MAIN_CONTENT-->";
  1401. }
  1402. else {
  1403. $template = $this->get_template($templatefile);
  1404. if ($template != "" && strstr($template, "<body")) {
  1405. $bits = explode("<body", $template);
  1406. if (isset($bits[1]) && $bits[1] != "") {
  1407. $i = strpos($bits[1], ">");
  1408. if ($i > 1) {
  1409. // Scrape body tag parameters and keep these..
  1410. $parms = trim( substr($bits[1], 0, $i) );
  1411. if ($parms != "") {
  1412. $this->set_parms($parms);
  1413. }
  1414. }
  1415. // Scrape body content..
  1416. $content = substr($bits[1], $i + 1);
  1417. $bits = explode("</body>", $content);
  1418. if (isset($bits[0])) {
  1419. $this->content = $bits[0];
  1420. $this->fix_imagerefs();
  1421. }
  1422. }
  1423. }
  1424. else {
  1425. $this->content = "<!--MAIN_CONTENT-->";
  1426. }
  1427. }
  1428. } // load_template
  1429. // ....................................................................
  1430. /**
  1431. * Fixes up all the media src= references taking into account theme etc.
  1432. * Operates on the current $content variable, and fixes it directly.
  1433. * Fix up all src= references (etc) to point to the correct images
  1434. * directory, appropriate to any active theme, but ignores absolute
  1435. * http;// refs..
  1436. * @access private
  1437. */
  1438. function fix_imagerefs() {
  1439. global $IMAGESDIR;
  1440. // Fix up main body content..
  1441. $this->content = preg_replace(
  1442. "/(src=[\'\"])((?!http)(.+?))([\'\"])/ie",
  1443. "'src=\"' . '$IMAGESDIR/' . basename('\\2') . '\"'",
  1444. $this->content
  1445. );
  1446. $this->content = preg_replace(
  1447. "/(background=[\'\"])((?!http)(.+?))([\'\"])/ie",
  1448. "'background=\"' . '$IMAGESDIR/' . basename('\\2') . '\"'",
  1449. $this->content
  1450. );
  1451. $this->content = preg_replace(
  1452. "/(param name=movie value=[\'\"])((?!http)(.+?))([\'\"])/ie",
  1453. "'param name=movie value=\"' . '$IMAGESDIR/' . basename('\\2') . '\"'",
  1454. $this->content
  1455. );
  1456. // Fix up background refs in <body> tag..
  1457. $this->parms = preg_replace(
  1458. "/(background=[\'\"])((?!http)(.+?))([\'\"])/ie",
  1459. "'background=\"' . '$IMAGESDIR/' . basename('\\2') . '\"'",
  1460. $this->parms
  1461. );
  1462. } // fix_imagerefs
  1463. // ....................................................................
  1464. /**
  1465. * This renders the body as HTML.
  1466. * @return string The body section as HTML.
  1467. */
  1468. function html() {
  1469. $s = "<body";
  1470. if (!empty($this->onload)) $s .= " onload=\"" . $this->onload . "\"";
  1471. if (!empty($this->parms)) $s .= " " . $this->parms;
  1472. $s .= ">\n";
  1473. $s .= $this->script();
  1474. $s .= $this->get_trimcontent();
  1475. $s .= "\n</body>\n";
  1476.  
  1477. return $s;
  1478. } //html
  1479. // ....................................................................
  1480. /**
  1481. * This renders the body as WML.
  1482. * @return string The body section as WML.
  1483. */
  1484. function wml() {
  1485. return $this->content;
  1486. } // wml
  1487.  
  1488. } // body class
  1489. // ----------------------------------------------------------------------
  1490.  
  1491. /**
  1492. * The deck class
  1493. * The class is a special kind of body section. It contains all of the
  1494. * main page content for a WAP phone (wml).
  1495. * @package core
  1496. */
  1497. class deck extends body {
  1498. /** Template object for WML deck */
  1499.  
  1500. var $WMLtemplate;
  1501. // .....................................................................
  1502. /**
  1503. * Constructor
  1504. * Create a new deck object.
  1505. * @param string $templatefile Template file to load content from
  1506. * @param string $onload Script to execute when page loads
  1507. * @param string $parms Misc other parameters
  1508. */
  1509. function deck($templatefile="", $onload="", $parms="") {
  1510. $this->body($templatefile, $onload, $parms);
  1511. } // deck constructor
  1512. // ....................................................................
  1513. /**
  1514. * Defines the template section for the deck.
  1515. * @param object $wmltemplate The template object for the WML deck
  1516. */
  1517. function wml_template($wmltemplate) {
  1518. $this->WMLtemplate = $wmltemplate;
  1519. } // wml_template
  1520. // .....................................................................
  1521. /**
  1522. * Load the template content.
  1523. * We scrape everything between the appropriate tags and use it as the
  1524. * template for our body content.
  1525. * @param string $templatefile The full path to template file
  1526. * @access private
  1527. */
  1528. function load_template($templatefile="") {
  1529. if ($templatefile == "") {
  1530. $this->content = "<!--MAIN_CONTENT-->";
  1531. }
  1532. else {
  1533. $template = $this->get_template($templatefile);
  1534. if ($template != "" && strstr($template, "<wml>")) {
  1535. $bits = explode("<wml>", $template);
  1536. if (isset($bits[1]) && $bits[1] != "") {
  1537. $bits = explode("</wml>", $bits[1]);
  1538. if (isset($bits[0]) && $bits[0] != "") {
  1539. $this->content = $bits[0];
  1540. $this->fix_imagerefs();
  1541. }
  1542. }
  1543. }
  1544. else {
  1545. $this->content = "<!--MAIN_CONTENT-->";
  1546. }
  1547. }
  1548. } // load_template
  1549. // ....................................................................
  1550. /**
  1551. * This renders the body as HTML.
  1552. * @return string The body section as HTML.
  1553. */
  1554. function html() {
  1555. $s = "<body>";
  1556. $s .= $this->get_trimcontent();
  1557. $s .= "\n</body>\n";
  1558. return $s;
  1559. } // html
  1560. // ....................................................................
  1561. /**
  1562. * This renders the deck content.
  1563. * @return string The body section as WML.
  1564. */
  1565. function wml() {
  1566. $s = "";
  1567. if (isset($this->WMLtemplate)) {
  1568. $s .= $this->WMLtemplate->wml();
  1569. }
  1570. $s .= $this->get_trimcontent();
  1571. return $s;
  1572. } // wml
  1573.  
  1574.  
  1575.  
  1576. } // deck class
  1577. // ----------------------------------------------------------------------
  1578.  
  1579. /**
  1580. * The foot class
  1581. * The class is a special kind of page section. It contains all of the
  1582. * page content for the footer region. Actually the footer is the
  1583. * simplest of the page sections in a webpage. All it really has is
  1584. * the main content, some optional script content and that's about it.
  1585. * @package core
  1586. */
  1587. class foot extends page_section {
  1588. /**
  1589. * Constructor
  1590. * Create a new foot object.
  1591. */
  1592. function foot() {
  1593. $this->page_section();
  1594. } // foot constructor
  1595. // ....................................................................
  1596. /**
  1597. * This renders the foot as HTML.
  1598. * @return string The foot section as HTML.
  1599. */
  1600. function html() {
  1601. $s = "";
  1602. $s .= $this->content;
  1603. $s .= $this->script();
  1604. $s .= "</html>\n";
  1605. return $s;
  1606. } // html
  1607. // ....................................................................
  1608. /**
  1609. * This renders the foot as WML.
  1610. * @return string The foot section as WML.
  1611. */
  1612. function wml() {
  1613. return $this->content . "</wml>";
  1614. } // wml
  1615.  
  1616. }
  1617.  
  1618. // ----------------------------------------------------------------------
  1619. /**
  1620. * The error page class
  1621. * Allows us to render errors as either HTML or WML.
  1622. * @package core
  1623. */
  1624. class error_page extends page_section {
  1625. /** Heading or subject of the error */
  1626.  
  1627. var $heading;
  1628. /** Actual error message in detail */
  1629.  
  1630. var $msg;
  1631. // .....................................................................
  1632. /**
  1633. * Constructor
  1634. * Create a new error page object.
  1635. * @param string $heading The error heading or subject
  1636. * @param string $msg The detailed error message
  1637. */
  1638. function error_page($heading, $msg="") {
  1639. $this->heading = $heading;
  1640. $this->msg = $msg;
  1641. } // error_page
  1642. // ....................................................................
  1643. /**
  1644. * This renders the error page section as HTML. We do this simply
  1645. * as a heading at level 3 (h3), and the message content.
  1646. * @return string The error page section as HTML.
  1647. */
  1648. function html() {
  1649. return "<h3>$this->heading</h3>" . $this->msg;
  1650. } // html
  1651. // ....................................................................
  1652. /**
  1653. * This renders the error page section as WML. We do this simply
  1654. * as a single card with the appropriate title, and the content
  1655. * on the card in paragraph tags.
  1656. * @return string The error page section as WML.
  1657. */
  1658. function wml() {
  1659. $card = new WMLcard("error", "Error");
  1660. $card->insert(
  1661. "<p><b>" . $this->heading . "</b><br/>" . $this->msg . "</p>"
  1662. );
  1663. // Create the card deck and output it..
  1664. $deck = new WMLdeck($card);
  1665. return $deck->wml();
  1666. } // wml
  1667.  
  1668. }
  1669.  
  1670. // ----------------------------------------------------------------------
  1671. /**
  1672. * The templated webpage page class
  1673. * This is a special case of webpage, but is largely deprecated since
  1674. * the better way of using templates is via the kind of mechanism
  1675. * seen in the "site-webpage.php" example file which comes with
  1676. * the Phplib. This method is rather a DIY approach.
  1677. * @package core
  1678. */
  1679. class templated_webpage extends webstream {
  1680. /**
  1681. * Constructor
  1682. * Create a new templated webpage object.
  1683. * @param string $path Path to the template for the webpage
  1684. */
  1685. function templated_webpage($path="") {
  1686. $this->webstream();
  1687. if ($path != "") {
  1688. $this->set_template($path);
  1689. }
  1690. } // templated_webpage
  1691. // .....................................................................
  1692. /**
  1693. * Set the template file
  1694. * Base webpage content on a template. We echo this to the buffer.
  1695. * The expected usage is that further programming will then repeatedly
  1696. * call the 'replace' function, to make the customised webpage. After
  1697. * that calling 'send' will deliver it to the end browser.
  1698. * @param string $path Path to the template for the webpage
  1699. */
  1700. function set_template($path) {
  1701. $fp = fopen($path, "r");
  1702. if ($fp) {
  1703. $content = fread($fp, filesize($path));
  1704. fclose ($fp);
  1705. echo $content;
  1706. }
  1707. return $this;
  1708. } // set_template
  1709. // .....................................................................
  1710. /**
  1711. * Send content to user browser
  1712. */
  1713. function send() {
  1714. $this->make_content();
  1715. $this->send_to_browser();
  1716. } // send
  1717. // .....................................................................
  1718. /**
  1719. * Return content to caller
  1720. * @return string Webpage content
  1721. */
  1722. function render() {
  1723. return $this->webpage_content();
  1724. } // render
  1725.  
  1726. } // templated_webpage class
  1727. // ----------------------------------------------------------------------
  1728.  
  1729. /**
  1730. * gzip utility. Returns Value as a four-char string.
  1731. * @param integer $value Character value to return as four-char string
  1732. * @return string Four char string equivalent of the given value
  1733. * @access private
  1734. */
  1735. function AsFourChars($value) {
  1736. $s = "";
  1737. for ($i = 0; $i < 4; $i++) {
  1738. $s .= chr($value % 256);
  1739. $value = floor($value / 256);
  1740. }
  1741. return $s;
  1742. } // AsFourChars
  1743. // ----------------------------------------------------------------------
  1744.  
  1745. ?>

Documentation generated by phpDocumentor 1.3.0RC3