com.lokorin.lokorin.includes
[ class tree: com.lokorin.lokorin.includes ] [ index: com.lokorin.lokorin.includes ] [ all elements ]

Source for file common.php

Documentation is available at common.php

  1. <?php
  2. /*
  3. * Lokorin.com
  4. * Copyright 2004-2006
  5. * Licensed under the GNU LGPL. See COPYING for full terms.
  6. */
  7. /**
  8. * This page contains elements that all pages need in almost every session. It
  9. * also contains a couple of function to make error loggin easier. All pages
  10. * should require this page.
  11. * @author Andreas Launila
  12. * @version $Revision: 1.27 $
  13. * @package com.lokorin.lokorin.includes
  14. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  15. */
  16.  
  17. if(!(defined('IN_LOKORIN_PUBLIC') && (IN_LOKORIN_PUBLIC === true))) {
  18. //Invalid inclusion of the page.
  19. die('Invalid access');
  20. }
  21.  
  22. error_reporting(E_ALL);
  23. session_start();
  24. /**
  25. * A microtime marking when the common page was included, i.e. when the loading
  26. * of the page started.
  27. * @var float
  28. * @access private
  29. */
  30. define('MICROTIME_START', microtime(true));
  31.  
  32. /**#@+
  33. * Site specific folder name constants.
  34. * @access public
  35. * @var string
  36. */
  37. define('FOLDER_INCLUDES','_includes/');
  38. define('FOLDER_IMAGES','_images/');
  39. define('FOLDER_THUMBNAILS','_thumbnails/');
  40. define('FOLDER_ICONS','_icons/');
  41. define('FOLDER_CSS','_css/');
  42. define('FOLDER_JS','_js/');
  43. define('FOLDER_DOWNLOADS','_downloads/');
  44. define('FOLDER_CACHE','_cache/');
  45. define('FOLDER_ADMIN','admin/');
  46. define('FOLDER_CSS_CACHE', FOLDER_CACHE);
  47. define('FOLDER_RESOURCES', '_resources/');
  48. /**#@-*/ * Date format constants to be used with the date() function.
  49. * @access public
  50. * @var string
  51. */
  52. define('DATE_LONG','jS F Y');
  53. define('DATE_SHORT','jS M Y');
  54. define('DATE_SHORTER', 'jS M y');
  55. define('DATE_TIME', 'jS M y H:i');
  56. define('DATE_SITEMAP', 'c');
  57. if(!defined('DATE_RSS')) {
  58. define('DATE_RSS', 'r');
  59. }
  60. define('DATE_COMMENT', 'jS F Y, H:i');
  61. /**#@-*/ * A switch for if debug info should be displayed or not. True if it should be
  62. * displayed, false otherwise.
  63. * @var boolean
  64. * @access public
  65. */
  66. define('DEBUG_MODE_ON', true);
  67. /**
  68. * Whether or not the site is currently closed. If the site is currently closed
  69. * then all non-admin users will be redirected to a page informing them what is
  70. * going on. The redirect does not affect the admin login page.
  71. * @var boolean
  72. * @access public
  73. */
  74. define('SITE_CLOSED', false);
  75. /**
  76. * Path from the http host to the root.
  77. * @access public
  78. * @var string
  79. */
  80. define('ROOT_PATH', '/lokorin/');
  81. /**
  82. * The path for the requested page itself. This is the actual requested page,
  83. * not the page that is actually handeling it (i.e. it's not equal to
  84. * $_SERVER['PHP_SELF']).
  85. * @access public
  86. * @var string
  87. */
  88. define('SELF', str_replace('.php', '', str_replace('?'.$_SERVER['QUERY_STRING'],
  89. '', strip_tags($_SERVER['REQUEST_URI']))));
  90. /**
  91. * Relative path from the current script to the root.
  92. * @access public
  93. * @var string
  94. */
  95. define('ROOT', getRoot(strip_tags($_SERVER['SCRIPT_NAME'])));
  96. /**
  97. * Relative path from the requested uri to the root. This is not neccessarily
  98. * the same as the path from the current scrip to the root.
  99. * @access public
  100. * @var string
  101. */
  102. define('PAGE_ROOT', getRoot(SELF));
  103. /**
  104. * The absolute path to the root of the site.
  105. * @access public
  106. * @var string
  107. */
  108. define('DOC_ROOT', $_SERVER['DOCUMENT_ROOT'].ROOT_PATH);
  109.  
  110. //Include the database abstraction library and create an instance.
  111. doInclude('lib_db');
  112. global $db;
  113. $db = DataBase::getInstance();
  114.  
  115. //Include the error logging library.
  116. doInclude('lib_errors');
  117.  
  118. //Include the CSS library.
  119. doInclude('lib_css');
  120.  
  121. //Clear the css cache if we are debugging.
  122. if(DEBUG_MODE_ON) {
  123. clearCssCache();
  124. }
  125.  
  126. /**
  127. * Includes a library into the code.
  128. * @param string $libName The name of the library, e.g. 'common' if one wants
  129. * to include the library 'common.php'.
  130. * @param boolean $required If the inclusion is required or not. If it is
  131. * true then a failure to include it will stop the script, otherwise
  132. * it will continue with a warning. The default is true.
  133. * @param boolean $onlyOnce If subsequent requests to include the same library
  134. * name should be ignored or not. If true then libraries will only be
  135. * included one, otherwise they will be included once for every request
  136. * made. The default is true.
  137. * @access public
  138. */
  139. function doInclude($libName, $required = true, $onlyOnce = true) {
  140. if(strpos($libName, '/') !== false) {
  141. die('Invalid library name ('.$libName.').');
  142. }
  143. $libFile = DOC_ROOT.FOLDER_INCLUDES.$libName.'.php';
  144. //Make sure the library exists.
  145. if(!file_exists($libFile)) {
  146. logFatalException(new FileNotFoundException("The library (".$libName.
  147. ") does not exist."));
  148. }
  149. if($onlyOnce === true) {
  150. if($required === true) {
  151. require_once($libFile);
  152. } else {
  153. @include_once($libFile);
  154. }
  155. } else {
  156. if($required === true) {
  157. require($libFile);
  158. } else {
  159. @include($libFile);
  160. }
  161. }
  162. }
  163.  
  164. /**
  165. * Get the relative path from a specified file to the site's root directory.
  166. * This method should be concidered private to the library.
  167. * @param string $url The absolute url to the file that one wants the root for.
  168. * @return string The relative root path so that getDir($url).getRoot(result)
  169. * ~ ROOT_PATH.
  170. * @access private
  171. */
  172. function getRoot($url) {
  173. if(strpos($url, ROOT_PATH) === false) {
  174. logFatalException(new IllegalArgumentException('The page ('.$url.
  175. ') does not contain the root path.'));
  176. }
  177. $strpos = strpos($url, ROOT_PATH);
  178. $path = substr($url, 0, $strpos).substr($url, $strpos.strlen(ROOT_PATH));
  179. $root = '';
  180. for($i = substr_count($path, '/'); $i>0; $i--) {
  181. $root .= '../';
  182. }
  183. return $root;
  184. }
  185.  
  186. /**
  187. * Cleans up and does anything that should be done before finishing. This
  188. * function should be called directly after a page is served to the used.
  189. * @param integer $size The number of bytes of the generated page.
  190. * @access private
  191. */
  192. function cleanUp($size) {
  193. global $db;
  194. //Log the time that it took to serve the page.
  195. $elapsedTime = round((microtime(true) - MICROTIME_START)*pow(10, 6));
  196. $vars = array(
  197. "requested_uri" => $_SERVER['REQUEST_URI'],
  198. "started" => round(MICROTIME_START),
  199. "elapsed_microseconds" => $elapsedTime,
  200. "db_queries" => $db->getQueryCount(),
  201. "db_microseconds" => $db->getElapsedQueryTime(),
  202. "page_size" => $size
  203. );
  204. $db->queryInsert(TABLE_PERFORMANCE, $vars);
  205. }
  206.  
  207. /**
  208. * Describes something that can add contents to the <head></head> elements of
  209. * pages that are displayed.
  210. * @author Andreas Launila
  211. * @package com.lokorin.lokorin.lib
  212. */
  213. interface HeadAddable {
  214. /**
  215. * Gets the things that should be added to the page's head element.
  216. * @return string XHTML compliant code.
  217. */
  218. public function getHeadAddition();
  219. }
  220.  
  221. /**
  222. * A simple implementation of HeadAddable. It's an immutable instance that
  223. * just takes a string of the things that should be included in the head tag.
  224. * @author Andreas Launila
  225. * @package com.lokorin.lokorin.lib
  226. */
  227. class HeadData implements HeadAddable{
  228. /**
  229. * The data that should be added to the head tag.
  230. */
  231. private $text;
  232. /**
  233. * Constructor for HeadData.
  234. * @param string The code that should be added to the head tag.
  235. */
  236. public function __construct($text) {
  237. $this->text = $text;
  238. }
  239. /**
  240. * @see com.lokorin.lokorin.lib.HeadAddable.getHeadAddition()
  241. */
  242. public function getHeadAddition() {
  243. return $this->text;
  244. }
  245. }
  246.  
  247. /**
  248. * Describes a page that can be displayed. It's the end result of the whole
  249. * script.
  250. * @author Andreas Launila
  251. * @package com.lokorin.lokorin.lib
  252. */
  253. class Page implements HeadAddable {
  254. /**
  255. * The one and only instance of the class.
  256. * @var Page
  257. */
  258. private static $instance;
  259. /**
  260. * All instances of HeadAddable that should be added to the head contents.
  261. * @var array
  262. */
  263. private $headAdditions;
  264. /**
  265. * The title of the page.
  266. * @var string
  267. */
  268. private $title;
  269. /**
  270. * True if links in the page be followed by robots, false otherwise.
  271. * @var boolean
  272. */
  273. private $doFollow;
  274. /**
  275. * True if the page should be indexed by robots, false otherwise.
  276. * @var boolean
  277. */
  278. private $doIndex;
  279. /**
  280. * The project that the page belongs to.
  281. * @var Project
  282. */
  283. private $project;
  284. /**
  285. * Gets the one and only instance of the class.
  286. * @return CssTemplateConverter The one and only instance.
  287. */
  288. public static function getInstance() {
  289. if(!isset(Page::$instance)) {
  290. Page::$instance = new Page();
  291. }
  292. return Page::$instance;
  293. }
  294. /**
  295. * Constructor for Page.
  296. */
  297. private function __construct() {
  298. $this->headAdditions = array();
  299. $this->doFollow = true;
  300. $this->doIndex = true;
  301. //Start an output buffer for that page's contents.
  302. ob_start();
  303. }
  304. /**
  305. * Displays the page.
  306. */
  307. public function display() {
  308. if(!isset($this->title)) {
  309. die("No title specified.");
  310. }
  311. $this->displayContents(ob_get_clean());
  312. }
  313. /**
  314. * Flushes the page, totally unprocessed, to the output stream.
  315. */
  316. public function flush() {
  317. cleanUp(strlen(ob_get_flush()));
  318. }
  319. /**
  320. * Displays the page with the specified contents.
  321. * @param string $contents The contents that the page should contain.
  322. */
  323. private function displayContents($contents) {
  324. //Ensure that the common css files are included.
  325. CssHandler::getInstance()->includeCss('page');
  326. CssHandler::getInstance()->includeCss('menu');
  327.  
  328. ob_start();
  329.  
  330. //Add the header and footer.
  331. doInclude('header');
  332. echo $contents;
  333. doInclude('footer');
  334. cleanUp(strlen(ob_get_flush()));
  335. }
  336.  
  337. /**
  338. * Adds something that is head addable (implements HeadAddable) to the head
  339. * tag of the page.
  340. * @param HeadAddable The data that should be added.
  341. */
  342. public function addToHead(HeadAddable $headAddable) {
  343. $this->headAdditions[] = $headAddable;
  344. }
  345. /**
  346. * Sets the title of the page to a new title.
  347. * @param string $newTitle The new title that should be sued for the page.
  348. */
  349. public function setTitle($newTitle) {
  350. $this->title = $newTitle;
  351. }
  352. /**
  353. * Gets all additional head data that is specified by the page.
  354. * @return string XHTML compliant code that can be placed inside a head
  355. * tag.
  356. * @see com.lokorin.lokorin.lib.HeadAddable.getHeadAddition()
  357. */
  358. public function getHeadAddition() {
  359. $code = array();
  360. foreach($this->headAdditions as $addition) {
  361. $code[] = $addition->getHeadAddition();
  362. }
  363. return implode("\n", $code);
  364. }
  365. /**
  366. * Sets whether or not the current page should be indexed by robots. This
  367. * is by default set to true.
  368. * @param boolean $shouldIndex True if pages should be indexed by robots,
  369. * false otherwise.
  370. */
  371. public function setShouldIndex($shouldIndex) {
  372. $this->doIndex = $shouldIndex;
  373. }
  374. /**
  375. * Sets whether or not links in the current page should be followed. This
  376. * is by default set to true.
  377. * @param boolean $shouldFollow True if links in the page should be
  378. * followed by robots, false otherwise.
  379. */
  380. public function setShouldFollow($shouldFollow) {
  381. $this->doFollow = $shouldFollow;
  382. }
  383. /**
  384. * Gets where or not the page should be indexed by robots.
  385. * @return boolean True if the page should be indexed by robots, false
  386. * otherwise.
  387. */
  388. public function doIndex() {
  389. return $this->doIndex;
  390. }
  391. /**
  392. * Gets whether or not links in the page should be followed by robots.
  393. * @return boolean True if the page should be indexed by robots, false
  394. * otherwise.
  395. */
  396. public function doFollow() {
  397. return $this->doFollow;
  398. }
  399. /**
  400. * Gets the description of the current page.
  401. * @return string A short description of the page.
  402. */
  403. public function getDescription() {
  404. if($this->project == null) {
  405. //Use a generic description.
  406. return "A collection of open-source programming ".
  407. "projects started by Andreas \"Lokorin\" Launila. ".
  408. "The languages used are primarily Java, PHP and Delphi.";
  409. } else {
  410. //Use the project's description.
  411. return $this->project->getPageDescription();
  412. }
  413. }
  414. /**
  415. * Gets the text that should be used in the main page header.
  416. * @return string A few words.
  417. */
  418. public function getMainHeader() {
  419. $prefix = '';
  420. if($this->project != null) {
  421. $prefix = $this->project->getName().': ';
  422. }
  423. return $prefix.$this->title;
  424. }
  425. /**
  426. * Gets the title of the page.
  427. * @return string A textual page title.
  428. */
  429. public function getTitle() {
  430. if($this->project == null) {
  431. $prefix = 'Lokorin\'s Projects: ';
  432. } else {
  433. $prefix = $this->project->getName().': ';
  434. }
  435. return $prefix.$this->title;
  436. }
  437. /**
  438. * Whether or not the page has a submenu that should be displayed.
  439. * @return boolean True if the page has a submenu, false otherwise.
  440. */
  441. public function hasSubmenu() {
  442. return $this->project != null && $this->project->hasMenu();
  443. }
  444. /**
  445. * Gets the submenu that should be disiplayed. The function should only
  446. * be called if hasSubmenu returns true.
  447. * @return string XHTML compliant code containing an unordered list of
  448. * links.
  449. */
  450. public function getSubmenu() {
  451. if($this->project != null) {
  452. return $this->project->getMenu();
  453. } else {
  454. logException(new IllegalStateException("No default submenu ".
  455. "exists."));
  456. }
  457. }
  458. /**
  459. * Sets the project that the page is contained in.
  460. * @param $newProject The new project that should be set. The value may be
  461. * null in which case the defailt project is used.
  462. */
  463. public function setProject(Project $newProject) {
  464. $this->project = $newProject;
  465. if($newProject->hasMenu()) {
  466. CssHandler::getInstance()->includeCss('submenu');
  467. }
  468. }
  469. }
  470.  
  471. /**
  472. * Describes a table entry in a table where each entry has an unique
  473. * identifier with a key named 'id'.
  474. * @author Andreas Launila
  475. * @package com.lokorin.lokorin.lib
  476. */
  477. abstract class TableEntry {
  478. /**
  479. * The unique identifier for the entry.
  480. */
  481. private $id;
  482. /**
  483. * Constructor for TableEntry.
  484. * @param string $table The name of the table in which the row should be
  485. * searched for.
  486. * @param mixed $id The unique identifier for the table row that
  487. * describes the entry.
  488. * @param array $fields An array that contains all fields that should be
  489. * retrieved from the table. If the array is empty then all columns
  490. * are retrieved. The parameter is optional, if not specified then all
  491. * columns are retrieved.
  492. * @param string $idFieldName The name of table field that contains the
  493. * unique identifier. Defaults to 'id'.
  494. * @throws IllegalArgumentException If there is no entry with such and
  495. * identifier.
  496. */
  497. public function __construct($table, $id, $fields = array(), $idFieldName = 'id') {
  498. global $db;
  499. //Add the id field if it's not already included.
  500. if(count($fields) != 0 && !in_array($idFieldName, $fields)) {
  501. $fields[] = $idFieldName;
  502. }
  503. //Run the query.
  504. if(count($fields) != 0) {
  505. //A normal select query should be performed.
  506. $rows = $db->querySelect($table, $fields,
  507. "WHERE ".$idFieldName."=".$db->escape($id)." LIMIT 1");
  508. } else {
  509. //All fields should be selected.
  510. $rows = $db->querySelectAll($table,
  511. "WHERE ".$idFieldName."=".$db->escape($id)." LIMIT 1");
  512. }
  513. //Check if we got any result.
  514. if(count($rows) == 0) {
  515. throw new IllegalArgumentException("The id (".$id.") did not match " .
  516. "any row in the table (".$table.").");
  517. }
  518. $row = $rows[0];
  519. $this->id = $row[$idFieldName];
  520. $this->readRow($row);
  521. }
  522. /**
  523. * Processes the contents of a retrieved row that describes the entry.
  524. * @param array $row The contents of a row. Each elements has the field
  525. * name as key and the corresponding field value as value.
  526. */
  527. protected abstract function readRow($row);
  528. /**
  529. * Gets the unique identifier for the table entry.
  530. * @return integer A unique identifier.
  531. */
  532. public function getId() {
  533. return $this->id;
  534. }
  535. }
  536.  
  537. //Initialise the page.
  538. Page::getInstance();
  539. ?>

Documentation generated on Sun, 16 Apr 2006 21:02:57 +0200 by phpDocumentor 1.3.0RC4