00001 <?
00011 class BaseModule
00012 {
00016 public $baseUrl;
00017
00021 public $page;
00022
00026 public $pageTitle;
00027
00031 public $template = null;
00032
00036 public $english;
00037
00041 public $xml;
00042
00046 public $doCachePage = false;
00047
00051 public static $pageCacheLife = 900;
00052
00056 private $params = array();
00057
00061 private $error = null;
00062
00066 private $status = array();
00067
00071 private $sideboxes = array();
00072
00076 private $navigation = array();
00077
00081 private static $Feeds = array();
00082
00086 private static $FeedTitles = array();
00087
00091 public $_Name = null;
00092
00096 public $_Description = null;
00097
00101 public $_Version = null;
00102
00106 public $_Author = null;
00107
00111 public $_Website = null;
00112
00116 public function __construct()
00117 {
00118 $this->_Name = preg_replace("/([A-Z])/", " $1", get_class($this));
00119
00120 $this->objectType = get_class($this);
00121 $this->english = strtolower(get_class($this));
00122 $this->baseUrl = Config::get('site_baseurl');
00123 }
00124
00131 public function init($page = 'main', $vars = array())
00132 {
00133
00134 if (!Config::get('basejumper_installed'))
00135 {
00136 $this->addStatus('BaseJumper is in installation mode. Visit the ' .
00137 $this->getLink("main.sitesql", "site SQL") . ' page to create your
00138 site sql.<br/><br/>After that, do a
00139 <b>Config::set("basejumper_installed", true);</b> in your
00140 config.inc.php when you have finished installing your
00141 site.<br/><br/>You may also want to visit the <a
00142 href="http://www.osotite.com/documentation/installation">BaseJumper
00143 installation</a> page.');
00144 }
00145
00146
00147 $page = trim($page);
00148
00149
00150 if (!$page)
00151 $page = 'main';
00152
00153
00154 $this->page = $page;
00155
00156
00157 $xml = $this->parseModuleXml();
00158
00159
00160 $rs = $xml->xpath("//page[@name='$this->page']");
00161
00162
00163 $pageXml = $rs[0];
00164
00165
00166 if ($pageXml['template'])
00167 {
00168 $templateClass = "$pageXml[template]Template";
00169 if (class_exists($templateClass))
00170 $this->setTemplate(new $templateClass());
00171 }
00172
00173
00174 if (!count($rs))
00175 throw new PageError("The page '$this->page' does not exist in the '" . get_class($this) . "' module.\n");
00176 else if (count($rs) > 1)
00177 throw new PageError("There is more than one '$this->page' in the '" . get_class($this) . "' module.");
00178 else
00179 {
00180
00181 if ($pageXml['title'])
00182 $this->pageTitle = $pageXml['title'];
00183
00184
00185 if ($pageXml['cache'] == 'true' || $pageXml['cache'] == '1')
00186 $this->doCachePage = true;
00187
00188
00189 $this->initParams($pageXml, $vars);
00190
00191
00192 $this->initPage($this->page);
00193 }
00194 }
00195
00200 public function draw()
00201 {
00202
00203 $this->template->draw();
00204 }
00205
00211 public function setTemplate(BaseTemplate $template)
00212 {
00213 $this->template = $template;
00214 $this->template->object = $this;
00215 }
00216
00223 public function initParams($page, $vars = array())
00224 {
00225
00226 $this->params = array();
00227 if (is_object($page->param[0]))
00228 {
00229 foreach ($page->param AS $param)
00230 {
00231 $name = (string)$param['name'];
00232 $required = (int)$param['required'];
00233 $type = (string)$param['type'];
00234 $regex = (string)$param['regex'];
00235
00236
00237 if ($required)
00238 {
00239 if (isset($vars[$name]) && trim($vars[$name] != ''))
00240 $this->params[$name] = trim($vars[$name]);
00241 else
00242 throw new PageError("Expected parameter '$name' for page '$page[name]'");
00243 }
00244
00245 else if (isset($vars[$name]))
00246 $this->params[$name] = $vars[$name];
00247
00248
00249 $valid = true;
00250
00251
00252 if (isset($this->params[$name]))
00253 {
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 if ($type == 'int')
00264 {
00265 if ($this->params['name'] != (int)$this->params['name'])
00266 throw new PageError("Parameter '$name' must be an integer.");
00267 }
00268
00269 else if ($type == 'float')
00270 {
00271 if ($this->params['name'] != (float)$this->params['name'])
00272 throw new PageError("Parameter '$name' must be an float.");
00273 }
00274
00275 else if (is_object($param->option[0]))
00276 {
00277 $valid = false;
00278 foreach ($param->option AS $option)
00279 {
00280 if ($option['value'] == $this->params[$name])
00281 {
00282 $valid = true;
00283 break;
00284 }
00285 }
00286
00287
00288 if (!$valid)
00289 {
00290 $error = "The parameter '$name' can only be one of these values: ";
00291 foreach ($param->option AS $option)
00292 $values[] = "'$option[value]'";
00293
00294 $error .= implode(", ", $values);
00295
00296 throw new PageError($error);
00297 }
00298 }
00299
00300 else if ($regex)
00301 {
00302 if (!preg_match($regex, $this->params[$name]))
00303 throw new PageError("The parameter '$name' must
00304 must match the <a
00305 href=\"http://www.php.net/pcre\">regular
00306 expression</a>:</b><br/>\n
00307 <pre>$regex</pre>\n");
00308 }
00309 }
00310 }
00311 }
00312 }
00313
00319 function initPage($page)
00320 {
00321
00322
00323
00324 $func = "init" . ucfirst($page) . "Page";
00325 if (method_exists($this, $func))
00326 $this->$func();
00327
00328
00329 $func = "draw" . ucfirst($page) . "Page";
00330 if (!method_exists($this, $func))
00331 throw new PageError(get_class($this) . "::$func() does not exist. You must define it.\n");
00332 }
00333
00339 public function getTitle()
00340 {
00341 if ($this->hasError())
00342 $this->pageTitle = 'Error';
00343
00344 return $this->pageTitle;
00345 }
00346
00352 public function getContent()
00353 {
00354
00355 ob_start();
00356
00357
00358 $func = "draw" . ucfirst($this->page) . "Page";
00359 $this->$func();
00360
00361
00362 $content = trim(ob_get_contents());
00363
00364
00365 ob_end_clean();
00366
00367 return $content;
00368 }
00369
00375 public function getError()
00376 {
00377 return $this->error;
00378 }
00379
00385 public function getStatus()
00386 {
00387 return $this->status;
00388 }
00389
00397 public function getUrl($params = array(), $base = null, $full = false)
00398 {
00399 if ($base === null)
00400 $url = $this->baseUrl;
00401 else
00402 $url = $base;
00403
00404 if ($full)
00405 $url = "http://" . Config::get('site_hostname') . $url;
00406
00407
00408 if (is_string($params))
00409 {
00410
00411 $module = strtolower(get_class($this));
00412 $page = 'main';
00413 $vars = array();
00414
00415
00416 if (preg_match("/^\w*$/", $params, $match))
00417 $module = $match[0];
00418 else if (preg_match("/(\w*)\.(\w*)\??([^#]*)(#\w*)?/", $params, $match))
00419 {
00420
00421 if ($match[1])
00422 $module = $match[1];
00423
00424 if($match[2])
00425 $page = $match[2];
00426
00427 if ($match[3])
00428 {
00429 $pairs = explode("&", $match[3]);
00430 if (count($pairs))
00431 {
00432 foreach ($pairs AS $pair)
00433 {
00434 $var = explode("=", $pair);
00435 $vars[$var[0]] = $var[1];
00436 }
00437 }
00438 }
00439 if ($match[4])
00440 $anchor = $match[4];
00441 }
00442
00443
00444 $params = array(
00445 'module' => $module,
00446 'page' => $page,
00447 );
00448 $params += $vars;
00449 }
00450
00451
00452 if (!isset($params['module']))
00453 $params['module'] = strtolower(get_class($this));
00454 if (!isset($params['page']))
00455 $params['page'] = 'main';
00456
00457
00458 if (Config::get("use_mod_rewrite"))
00459 {
00460
00461 $url = str_replace("index.php", "", $url);
00462
00463
00464 $url .= $params['module'] . "/" . $params['page'];
00465 unset($params['module']);
00466 unset($params['page']);
00467
00468
00469 if (count($params))
00470 foreach ($params AS $key => $val)
00471 $url .= "/$key/" . urlencode($val);
00472 }
00473 else
00474 {
00475
00476 if (is_array($params))
00477 foreach ($params AS $key => $val)
00478 $url = Util::setUrlParam($url, $key, $val);
00479 }
00480
00481
00482 if ($anchor)
00483 $url .= $anchor;
00484
00485
00486 return $url;
00487 }
00488
00495 function getParams($array)
00496 {
00497 $url = $this->getUrl($array);
00498 $link = explode("?", $url);
00499 return $link[1];
00500 }
00501
00508 public function drawUrl($params, $text)
00509 {
00510 echo $this->getLink($params, $text);
00511 }
00512
00523 public function getLink($params, $text, $base = null, $full = false)
00524 {
00525 $url = $this->getUrl($params, $base, $full);
00526 return "<a href=\"$url\" class=\"BaseLink\">$text</a>";
00527 }
00528
00534 public function hasError()
00535 {
00536 return ($this->error !== null);
00537 }
00538
00544 public function setError($error)
00545 {
00546 $this->error = $error;
00547 $this->pageTitle = 'Error';
00548 }
00549
00555 public function hasStatus()
00556 {
00557 return (bool)count($this->status);
00558 }
00559
00565 public function addStatus($str)
00566 {
00567 $this->status[] = $str;
00568 }
00569
00573 public function initParametersPage()
00574 {
00575 $this->pageTitle = get_class($this) . " Module - Pages and Parameters";
00576 }
00577
00581 public function drawParametersPage()
00582 {
00583 global $me;
00584
00585 $xml = $this->parseModuleXml();
00586
00587 echo "\n<h2>Pages</h2>\n";
00588
00589 echo "<ul>\n";
00590 foreach ($xml->page AS $page)
00591 {
00592 echo "\t<li><b>$page[name]</b>";
00593
00594 if ($page['desc'])
00595 echo " - $page[desc]";
00596
00597 echo "\n\t\t<ul>\n";
00598 if (is_object($page->param[0]))
00599 {
00600 echo "\t\t\t<li><b>parameters:</b> (pass these in as either get or post in the url)</li>\n";
00601 echo "\t\t\t\t<ul>\n";
00602 foreach ($page->param AS $param)
00603 {
00604 echo "\t\t\t\t\t<li>";
00605
00606 echo "<i>$param[name]</i> - ";
00607
00608 if ($param['required'] == '1' || $param['requied'] == 'true')
00609 echo "(<b>required</b>) ";
00610 else
00611 echo "(optional) ";
00612
00613 if ($param['desc'])
00614 echo "$param[desc]";
00615
00616 if (is_object($param->option[0]))
00617 {
00618 echo "\n\t\t\t\t\t\t<ul>\n";
00619 echo "\t\t\t\t\t\t\t<li><b>Accepted values:</b></li>\n";
00620 foreach ($param->option AS $option)
00621 {
00622 echo "\t\t\t\t\t\t\t<li><i>$option[value]</i>";
00623
00624 if ($option['desc'])
00625 echo " - $option[desc]";
00626 else
00627 echo " - sort by the $option[value] field";
00628
00629 echo "</li>\n";
00630
00631 }
00632 echo "\t\t\t\t\t\t</ul>\n";
00633 }
00634
00635
00636 $regex = (string)$param['regex'];
00637 if ($regex)
00638 {
00639 echo "\n\t\t\t\t\t\t<ul>\n";
00640 echo "\t\t\t\t\t\t\t<li>\n";
00641 echo "<b>Must match the <a href=\"http://www.php.net/pcre\">regular expression</a>:</b><br/>\n";
00642 echo "<pre>$regex</pre>\n";
00643 echo "\t\t\t\t\t\t\t</li>\n";
00644 echo "\t\t\t\t\t\t</ul>\n";
00645 }
00646
00647 echo "\t\t\t\t\t</li>\n";
00648 }
00649 echo "\t\t\t\t</ul>\n";
00650 }
00651
00652 echo "\t\t\t<li><b>output:</b> ";
00653
00654 if ($page['type'] == 'xml')
00655 echo "XML data suitable for parsing.";
00656 else
00657 echo "HTML data suitable for display.";
00658 echo "</li>\n";
00659
00660 echo "\t\t</ul>\n";
00661
00662 echo "\t</li>\n";
00663 }
00664 echo "</ul>";
00665 }
00666
00670 public function initMainPage()
00671 {
00672 $this->pageTitle = get_class($this) . " Main";
00673 }
00674
00678 public function drawMainPage()
00679 {
00680 }
00681
00685 public function initModuleXmlPage()
00686 {
00687 $this->pageTitle = get_class($this) . " Module - XML Structure";
00688
00689 $this->setTemplate(new XMLTemplate());
00690 }
00691
00695 public function drawModuleXmlPage()
00696 {
00697 echo $this->xml;
00698 }
00699
00705 public function parseModuleXml()
00706 {
00707 if (!$this->xml)
00708 $this->xml = $this->getModuleXml();
00709
00710 return simplexml_load_string($this->xml);
00711 }
00712
00720 function params($key = null)
00721 {
00722 if ($key === null)
00723 return $this->params;
00724 else if (array_key_exists($key, $this->params))
00725 return $this->params[$key];
00726 else
00727 return false;
00728 }
00729
00736 function setParam($key, $val)
00737 {
00738 $this->params[$key] = $val;
00739 }
00740
00746 function getModuleXml()
00747 {
00748 $xml = "<module name=\"" . get_class($this) . "\" english=\"$this->english\">\n";
00749 $xml .= $this->getPagesXml();
00750 $xml .= "\n\t</module>";
00751
00752 return $xml;
00753 }
00754
00762 function getPagesXml()
00763 {
00764 global $me;
00765
00766 $xml = $this->getMainPageXml();
00767 $xml .= $this->getModulePageXml();
00768 $xml .= $this->getParametersPageXml();
00769 $xml .= $this->getCreateTablePageXml();
00770
00771 return $xml;
00772 }
00773
00779 function getMainPageXml()
00780 {
00781 return "\t<page name=\"main\" type=\"content\" desc=\"the main page for the module\"/>\n";
00782 }
00783
00789 function getModulePageXml()
00790 {
00791 return "\t<page name=\"modulexml\" type=\"xml\" desc=\"get the modules structural xml description\"/>\n";
00792 }
00793
00799 function getParametersPageXml()
00800 {
00801 return "\t<page name=\"parameters\" type=\"content\" desc=\"get the pages and parameters for an object\"/>\n";
00802 }
00803
00809 function getCreateTablePageXml()
00810 {
00811 return "\t<page name=\"createtable\" type=\"content\" desc=\"get the MySQL syntax to create the needed tables.\"><param name=\"run\"/></page>\n";
00812 }
00813
00820 public function addBox($box)
00821 {
00822 $this->sideboxes[] = $box;
00823 }
00824
00830 public function needsSideBar()
00831 {
00832 return (bool)count($this->sideboxes);
00833 }
00834
00839 public function drawSideBar()
00840 {
00841 if ($this->needsSideBar())
00842 {
00843 echo "\n<div id=\"sidebar\">\n";
00844
00845 foreach ($this->sideboxes AS $box)
00846 $box->draw();
00847
00848 Util::ieDrawClear();
00849 echo "\n</div>\n";
00850 echo "<!-- end sidebar -->\n";
00851 }
00852 }
00853
00859 public function addNav($text)
00860 {
00861 $this->navigation[] = $text;
00862 }
00863
00869 public function getNav()
00870 {
00871 return $this->navigation;
00872 }
00873
00877 public function drawNavigation()
00878 {
00879 if (count($this->navigation))
00880 {
00881 echo "\n<div class=\"pageNav\">\n";
00882 echo "\t<ul>\n";
00883 foreach ($this->navigation AS $nav)
00884 echo "\t\t<li>$nav</li>\n";
00885 echo "\t</ul>\n";
00886 Util::ieDrawClear();
00887 echo "</div>\n";
00888 }
00889 }
00890
00896 public function drawPageNavigation($links)
00897 {
00898 $this->drawPlainNavigation($links);
00899 }
00900
00908 public function drawPlainNavigation($links)
00909 {
00910 echo "\n\n<div class=\"PageNavigation\">";
00911 echo implode(" ~ ", $links);
00912 echo "</div>\n\n";
00913 }
00914
00921 public function assertLogin()
00922 {
00923 global $me;
00924
00925 if (!$me->id)
00926 {
00927 Util::redirect($me->getUrl(array(
00928 'page' => 'login',
00929 'redirect' => base64_encode($_SERVER['REQUEST_URI']),
00930 'status' => 'You must be logged in to access this part of the site.'
00931 )));
00932 }
00933
00934 return $me->id;
00935 }
00936
00942 public function needsCss($file)
00943 {
00944 global $_BJ_CSS;
00945 $_BJ_CSS[] = $file;
00946 $_BJ_CSS = array_unique($_BJ_CSS);
00947 }
00948
00952 public function drawCss()
00953 {
00954 global $_BJ_CSS;
00955
00956 if (count($_BJ_CSS))
00957 foreach ($_BJ_CSS AS $file)
00958 echo "\t<link rel=\"stylesheet\" href=\"$file\" type=\"text/css\" />\n";
00959 }
00960
00966 public function needsJs($file)
00967 {
00968 global $_BJ_JAVASCRIPT;
00969
00970
00971 if (count($_BJ_JAVASCRIPT))
00972 foreach ($_BJ_JAVASCRIPT AS $key => $val)
00973 if ($val == $file)
00974 unset($_BJ_JAVASCRIPT[$key]);
00975
00976
00977 $_BJ_JAVASCRIPT[] = $file;
00978 }
00979
00984 public function drawJs()
00985 {
00986 global $_BJ_JAVASCRIPT;
00987
00988 if (count($_BJ_JAVASCRIPT))
00989 foreach ($_BJ_JAVASCRIPT AS $file)
00990 echo "\t<script type=\"text/javascript\" src=\"$file\"></script>\n";
00991 }
00992
01000 public function addFeed($url, $title)
01001 {
01002 self::$Feeds[] = $url;
01003 self::$FeedTitles[] = $title;
01004 }
01005
01009 public function drawFeeds()
01010 {
01011 self::$Feeds = array_unique(self::$Feeds);
01012 self::$FeedTitles = array_unique(self::$FeedTitles);
01013
01014 if (count(self::$Feeds))
01015 foreach (self::$Feeds AS $key => $feed)
01016 echo "\t<link rel=\"alternate\" type=\"application/rss+xml\" title=\"" . self::$FeedTitles[$key] . "\" href=\"$feed\">\n";
01017 }
01018
01024 public function drawHead()
01025 {
01026 $this->drawCss();
01027 $this->drawJs();
01028 $this->drawFeeds();
01029 }
01030
01036 public function initCreateTablePage()
01037 {
01038 global $me;
01039
01040 $this->pageTitle = 'Create Table Syntax For ' . get_class($this);
01041
01042 if ($this->params('run'))
01043 {
01044 if (!$me->isAdmin())
01045 throw new PageError('You must be an admin to run the create table query.');
01046 else
01047 {
01048 $this->runCreateTableSql();
01049 $this->addStatus('Your tables have been created. Query(s) shown below.');
01050 }
01051 }
01052 }
01053
01057 public function drawCreateTablePage()
01058 {
01059 global $me;
01060
01061 if (!$this->params('run') && $me->isAdmin())
01062 echo "<p>" . $this->getLink(".createtable?run=1", "Run the SQL below.") . "</p>";
01063
01064 echo "<p>" . nl2br($this->getCreateTableSql()) . "</p>";
01065 }
01066
01071 public function runCreateTableSql()
01072 {
01073 dbExecute($this->getCreateTableSql());
01074
01075
01076 CacheBot::delete('BaseJumper:Tables');
01077 }
01078
01085 public function getCreateTableSql()
01086 {
01087 return '';
01088 }
01089
01090
01096 public static function getCachedPage($key = null)
01097 {
01098
01099 if ($key === null)
01100 $key = self::getPageCacheKey();
01101
01102 return CacheBot::get($key, self::$pageCacheLife);
01103 }
01104
01110 public static function setCachedPage($data, $key = null)
01111 {
01112
01113 if ($key === null)
01114 $key = self::getPageCacheKey();
01115
01116 return CacheBot::set($key, $data, self::$pageCacheLife);
01117 }
01118
01124 public static function getPageCacheKey($page = null)
01125 {
01126 if ($page === null)
01127 $page = $_SERVER["REQUEST_URI"];
01128
01129 return "BaseJumper:autocache:$page";
01130 }
01131
01137 public static function deleteCachedPage($page)
01138 {
01139 $key = self::getPageCacheKey($page);
01140
01141 CacheBot::delete($key);
01142 }
01143
01155 public static function tryPageCache($page = null)
01156 {
01157
01158 $key = self::getPageCacheKey($page);
01159
01160
01161 $page = self::getCachedPage($key);
01162 if ($page)
01163 {
01164
01165 echo $page;
01166 return false;
01167 }
01168
01169
01170 return $key;
01171 }
01172 }
01173 ?>