1f94a8540c663f80c4c17f21f6947497a5c650c7
2 // PHP Layers Menu 3.1.1 (C) 2001-2003 Marco Pratesi (marco at telug dot it)
5 * This file contains the code of the LayersMenuCommon class.
6 * @package PHPLayersMenu
11 * This is the "common" class of the PHP Layers Menu library.
13 * @package PHPLayersMenu
15 class LayersMenuCommon
{
18 * The name of the package
24 * The version of the package
30 * The copyright of the package
36 * The author of the package
43 * URL to be prepended to the menu hrefs
47 var $prependedUrl = "";
49 * Do you want that code execution halts on error?
53 var $haltOnError = "yes";
56 * The base directory where the package is installed
62 * The "libjs" directory of the package
68 * The directory where images related to the menu can be found
74 * The http path corresponding to imgdir
80 * The directory where templates can be found
86 * The string containing the menu structure
93 * It counts nodes for all menus
99 * A multi-dimensional array where we store informations for each menu entry
105 * The maximum hierarchical level of menu items
111 * An array that counts the number of first level items for each menu
117 * An array containing the number identifying the first item of each menu
123 * An array containing the number identifying the last item of each menu
130 * Data Source Name: the connection string for PEAR DB
134 var $dsn = "pgsql://dbuser:dbpass@dbhost/dbname";
136 * DB connections are either persistent or not persistent
140 var $persistent = false
;
142 * Name of the table storing data describing the menu
146 var $tableName = "phplayersmenu";
148 * Name of the i18n table corresponding to $tableName
152 var $tableName_i18n = "phplayersmenu_i18n";
154 * Names of fields of the table storing data describing the menu
156 * default field names correspond to the same field names foreseen
157 * by the menu structure format
162 var $tableFields = array(
164 "parent_id" => "parent_id",
169 "target" => "target",
170 "orderfield" => "orderfield",
171 "expanded" => "expanded"
174 * Names of fields of the i18n table corresponding to $tableName
178 var $tableFields_i18n = array(
179 "language" => "language",
185 * A temporary array to store data retrieved from the DB and to perform the depth-first search
189 var $_tmpArray = array();
192 * The constructor method; it initializates the menu system
195 function LayersMenuCommon() {
197 $this->_packageName
= "PHP Layers Menu";
198 $this->version
= "3.1.1";
199 $this->copyright
= "(C) 2001-2003";
200 $this->author
= "Marco Pratesi (marco at telug dot it)";
202 $this->prependedUrl
= "";
204 $this->dirroot
= "./";
205 $this->libjsdir
= "./libjs/";
206 $this->imgdir
= "./images/";
207 $this->imgwww
= "images/";
208 $this->tpldir
= "./templates/";
209 $this->menuStructure
= "";
210 $this->separator
= "|";
212 $this->_nodesCount
= 0;
213 $this->tree
= array();
214 $this->_maxLevel
= array();
215 $this->_firstLevelCnt
= array();
216 $this->_firstItem
= array();
217 $this->_lastItem
= array();
221 * The method to set the prepended URL
225 function setPrependedUrl($prependedUrl) {
226 // We do not perform any check
227 $this->prependedUrl
= $prependedUrl;
232 * The method to set the dirroot directory
236 function setDirrootCommon($dirroot) {
237 if (!is_dir($dirroot)) {
238 $this->error("setDirroot: $dirroot is not a directory.");
241 if (substr($dirroot, -1) != "/") {
244 $oldlength = strlen($this->dirroot
);
245 $foobar = strpos($this->libjsdir
, $this->dirroot
);
246 if (!($foobar === false ||
$foobar != 0)) {
247 $this->libjsdir
= $dirroot . substr($this->libjsdir
, $oldlength);
249 $foobar = strpos($this->imgdir
, $this->dirroot
);
250 if (!($foobar === false ||
$foobar != 0)) {
251 $this->imgdir
= $dirroot . substr($this->imgdir
, $oldlength);
253 $foobar = strpos($this->tpldir
, $this->dirroot
);
254 if (!($foobar === false ||
$foobar != 0)) {
255 $this->tpldir
= $dirroot . substr($this->tpldir
, $oldlength);
257 $this->dirroot
= $dirroot;
262 * The method to set the libjsdir directory
266 function setLibjsdir($libjsdir) {
267 if ($libjsdir != "" && substr($libjsdir, -1) != "/") {
270 if ($libjsdir == "" ||
substr($libjsdir, 0, 1) != "/") {
271 $foobar = strpos($libjsdir, $this->dirroot
);
272 if ($foobar === false ||
$foobar != 0) {
273 $libjsdir = $this->dirroot
. $libjsdir;
276 if (!is_dir($libjsdir)) {
277 $this->error("setLibjsdir: $libjsdir is not a directory.");
280 $this->libjsdir
= $libjsdir;
285 * The method to set the imgdir directory
289 function setImgdir($imgdir) {
290 if ($imgdir != "" && substr($imgdir, -1) != "/") {
293 if ($imgdir == "" ||
substr($imgdir, 0, 1) != "/") {
294 $foobar = strpos($imgdir, $this->dirroot
);
295 if ($foobar === false ||
$foobar != 0) {
296 $imgdir = $this->dirroot
. $imgdir;
299 if (!is_dir($imgdir)) {
300 $this->error("setImgdir: $imgdir is not a directory.");
303 $this->imgdir
= $imgdir;
308 * The method to set imgwww
312 function setImgwww($imgwww) {
313 if ($imgwww != "" && substr($imgwww, -1) != "/") {
316 $this->imgwww
= $imgwww;
320 * The method to set the tpldir directory
324 function setTpldirCommon($tpldir) {
325 if ($tpldir != "" && substr($tpldir, -1) != "/") {
328 if ($tpldir == "" ||
substr($tpldir, 0, 1) != "/") {
329 $foobar = strpos($tpldir, $this->dirroot
);
330 if ($foobar === false ||
$foobar != 0) {
331 $tpldir = $this->dirroot
. $tpldir;
334 if (!is_dir($tpldir)) {
335 $this->error("setTpldir: $tpldir is not a directory.");
338 $this->tpldir
= $tpldir;
343 * The method to read the menu structure from a file
345 * @param string $tree_file the menu structure file
348 function setMenuStructureFile($tree_file) {
349 if (!($fd = fopen($tree_file, "r"))) {
350 $this->error("setMenuStructureFile: unable to open file $tree_file.");
353 $this->menuStructure
= "";
354 while ($buffer = fgets($fd, 4096)) {
355 $buffer = ereg_replace(chr(13), "", $buffer); // Microsoft Stupidity Suppression
356 $this->menuStructure
.= $buffer;
359 if ($this->menuStructure
== "") {
360 $this->error("setMenuStructureFile: $tree_file is empty.");
367 * The method to set the menu structure passing it through a string
369 * @param string $tree_string the menu structure string
372 function setMenuStructureString($tree_string) {
373 $this->menuStructure
= ereg_replace(chr(13), "", $tree_string); // Microsoft Stupidity Suppression
374 if ($this->menuStructure
== "") {
375 $this->error("setMenuStructureString: empty string.");
382 * The method to set the value of separator
386 function setSeparator($separator) {
387 $this->separator
= $separator;
391 * The method to set parameters for the DB connection
393 * @param string $dns Data Source Name: the connection string for PEAR DB
394 * @param bool $persistent DB connections are either persistent or not persistent
397 function setDBConnParms($dsn, $persistent=false
) {
398 if (!is_string($dsn)) {
399 $this->error("initdb: \$dsn is not an string.");
402 if (!is_bool($persistent)) {
403 $this->error("initdb: \$persistent is not a boolean.");
407 $this->persistent
= $persistent;
412 * The method to set the name of the table storing data describing the menu
417 function setTableName($tableName) {
418 if (!is_string($tableName)) {
419 $this->error("setTableName: \$tableName is not a string.");
422 $this->tableName
= $tableName;
427 * The method to set the name of the i18n table corresponding to $tableName
432 function setTableName_i18n($tableName_i18n) {
433 if (!is_string($tableName_i18n)) {
434 $this->error("setTableName_i18n: \$tableName_i18n is not a string.");
437 $this->tableName_i18n
= $tableName_i18n;
442 * The method to set names of fields of the table storing data describing the menu
447 function setTableFields($tableFields) {
448 if (!is_array($tableFields)) {
449 $this->error("setTableFields: \$tableFields is not an array.");
452 if (count($tableFields) == 0) {
453 $this->error("setTableFields: \$tableFields is a zero-length array.");
456 reset ($tableFields);
457 while (list($key, $value) = each($tableFields)) {
458 $this->tableFields
[$key] = ($value == "") ?
"''" : $value;
464 * The method to set names of fields of the i18n table corresponding to $tableName
469 function setTableFields_i18n($tableFields_i18n) {
470 if (!is_array($tableFields_i18n)) {
471 $this->error("setTableFields_i18n: \$tableFields_i18n is not an array.");
474 if (count($tableFields_i18n) == 0) {
475 $this->error("setTableFields_i18n: \$tableFields_i18n is a zero-length array.");
478 reset ($tableFields_i18n);
479 while (list($key, $value) = each($tableFields_i18n)) {
480 $this->tableFields_i18n
[$key] = ($value == "") ?
"''" : $value;
486 * The method to parse the current menu structure and correspondingly update related variables
488 * @param string $menu_name the name to be attributed to the menu
489 * whose structure has to be parsed
492 function parseStructureForMenu(
493 $menu_name = "" // non consistent default...
495 $this->_maxLevel
[$menu_name] = 0;
496 $this->_firstLevelCnt
[$menu_name] = 0;
497 $this->_firstItem
[$menu_name] = $this->_nodesCount +
1;
498 $cnt = $this->_firstItem
[$menu_name];
499 $menuStructure = $this->menuStructure
;
501 /* *********************************************** */
502 /* Partially based on a piece of code taken from */
503 /* TreeMenu 1.1 - Bjorge Dijkstra (bjorge@gmx.net) */
504 /* *********************************************** */
506 while ($menuStructure != "") {
507 $before_cr = strcspn($menuStructure, "\n");
508 $buffer = substr($menuStructure, 0, $before_cr);
509 $menuStructure = substr($menuStructure, $before_cr+
1);
510 if (substr($buffer, 0, 1) != "#") { // non commented item line...
511 $tmp = rtrim($buffer);
512 $node = explode($this->separator
, $tmp);
513 for ($i=count($node); $i<=6; $i++
) {
516 $this->tree
[$cnt]["level"] = strlen($node[0]);
517 $this->tree
[$cnt]["text"] = $node[1];
518 $this->tree
[$cnt]["href"] = $node[2];
519 $this->tree
[$cnt]["title"] = $node[3];
520 $this->tree
[$cnt]["icon"] = $node[4];
521 $this->tree
[$cnt]["target"] = $node[5];
522 $this->tree
[$cnt]["expanded"] = $node[6];
527 /* *********************************************** */
529 $this->_lastItem
[$menu_name] = count($this->tree
);
530 $this->_nodesCount
= $this->_lastItem
[$menu_name];
531 $this->tree
[$this->_lastItem
[$menu_name]+
1]["level"] = 0;
532 $this->_postParse($menu_name);
536 * The method to parse the current menu table and correspondingly update related variables
538 * @param string $menu_name the name to be attributed to the menu
539 * whose structure has to be parsed
540 * @param string $language i18n language; either omit it or pass
541 * an empty string ("") if you do not want to use any i18n table
544 function scanTableForMenu(
545 $menu_name = "", // non consistent default...
548 $this->_maxLevel
[$menu_name] = 0;
549 $this->_firstLevelCnt
[$menu_name] = 0;
550 unset($this->tree
[$this->_nodesCount+
1]);
551 $this->_firstItem
[$menu_name] = $this->_nodesCount +
1;
552 /* BEGIN BENCHMARK CODE
553 $time_start = $this->_getmicrotime();
554 /* END BENCHMARK CODE */
555 $db = DB
::connect($this->dsn
, $this->persistent
);
556 if (DB
::isError($db)) {
557 $this->error("scanTableForMenu: " . $db->getMessage());
559 $dbresult = $db->query("
561 $this->tableFields
["id"] . " AS id, " .
562 $this->tableFields
["parent_id"] . " AS parent_id, " .
563 $this->tableFields
["text"] . " AS text, " .
564 $this->tableFields
["href"] . " AS href, " .
565 $this->tableFields
["title"] . " AS title, " .
566 $this->tableFields
["icon"] . " AS icon, " .
567 $this->tableFields
["target"] . " AS target, " .
568 $this->tableFields
["expanded"] . " AS expanded
569 FROM " . $this->tableName
. "
570 WHERE " . $this->tableFields
["id"] . " <> 1
571 ORDER BY " . $this->tableFields
["orderfield"] . ", " . $this->tableFields
["text"] . " ASC
573 $this->_tmpArray
= array();
574 while ($dbresult->fetchInto($row, DB_FETCHMODE_ASSOC
)) {
575 $this->_tmpArray
[$row["id"]]["parent_id"] = $row["parent_id"];
576 $this->_tmpArray
[$row["id"]]["text"] = $row["text"];
577 $this->_tmpArray
[$row["id"]]["href"] = $row["href"];
578 $this->_tmpArray
[$row["id"]]["title"] = $row["title"];
579 $this->_tmpArray
[$row["id"]]["icon"] = $row["icon"];
580 $this->_tmpArray
[$row["id"]]["target"] = $row["target"];
581 $this->_tmpArray
[$row["id"]]["expanded"] = $row["expanded"];
583 if ($language != "") {
584 $dbresult = $db->query("
586 $this->tableFields_i18n
["id"] . " AS id, " .
587 $this->tableFields_i18n
["text"] . " AS text, " .
588 $this->tableFields_i18n
["title"] . " AS title
589 FROM " . $this->tableName_i18n
. "
590 WHERE " . $this->tableFields_i18n
["id"] . " <> 1
591 AND " . $this->tableFields_i18n
["language"] . " = '$language'
593 while ($dbresult->fetchInto($row, DB_FETCHMODE_ASSOC
)) {
594 $this->_tmpArray
[$row["id"]]["text"] = $row["text"];
595 $this->_tmpArray
[$row["id"]]["title"] = $row["title"];
600 $this->_depthFirstSearch($this->_tmpArray
, $menu_name, 1, 1);
601 /* BEGIN BENCHMARK CODE
602 $time_end = $this->_getmicrotime();
603 $time = $time_end - $time_start;
604 print "TIME ELAPSED = " . $time . "\n<br>";
605 /* END BENCHMARK CODE */
606 $this->_lastItem
[$menu_name] = count($this->tree
);
607 $this->_nodesCount
= $this->_lastItem
[$menu_name];
608 $this->tree
[$this->_lastItem
[$menu_name]+
1]["level"] = 0;
609 $this->_postParse($menu_name);
612 function _getmicrotime() {
613 list($usec, $sec) = explode(" ", microtime());
614 return ((float) $usec +
(float) $sec);
618 * Recursive method to perform the depth-first search of the tree data taken from the current menu table
620 * @param array $tmpArray the temporary array that stores data to perform
621 * the depth-first search
622 * @param string $menu_name the name to be attributed to the menu
623 * whose structure has to be parsed
624 * @param integer $parent_id id of the item whose children have
626 * @param integer $level the hierarchical level of children to be searched for
629 function _depthFirstSearch($tmpArray, $menu_name, $parent_id=1, $level) {
631 while (list($id, $foobar) = each($tmpArray)) {
632 if ($foobar["parent_id"] == $parent_id) {
633 unset($tmpArray[$id]);
634 unset($this->_tmpArray
[$id]);
635 $cnt = count($this->tree
) +
1;
636 $this->tree
[$cnt]["level"] = $level;
637 $this->tree
[$cnt]["text"] = $foobar["text"];
638 $this->tree
[$cnt]["href"] = $foobar["href"];
639 $this->tree
[$cnt]["title"] = $foobar["title"];
640 $this->tree
[$cnt]["icon"] = $foobar["icon"];
641 $this->tree
[$cnt]["target"] = $foobar["target"];
642 $this->tree
[$cnt]["expanded"] = $foobar["expanded"];
644 if ($id != $parent_id) {
645 $this->_depthFirstSearch($this->_tmpArray
, $menu_name, $id, $level+
1);
652 * A method providing parsing needed after both file/string parsing and DB table parsing
654 * @param string $menu_name the name of the menu for which the parsing
655 * has to be performed
659 $menu_name = "" // non consistent default...
661 for ($cnt=$this->_firstItem
[$menu_name]; $cnt<=$this->_lastItem
[$menu_name]; $cnt++
) { // this counter scans all nodes of the new menu
662 $this->tree
[$cnt]["child_of_root_node"] = ($this->tree
[$cnt]["level"] == 1);
663 $this->tree
[$cnt]["parsed_text"] = stripslashes($this->tree
[$cnt]["text"]);
664 $this->tree
[$cnt]["parsed_href"] = (ereg_replace(" ", "", $this->tree
[$cnt]["href"]) == "") ?
"#" : $this->prependedUrl
. $this->tree
[$cnt]["href"];
665 $this->tree
[$cnt]["parsed_title"] = ($this->tree
[$cnt]["title"] == "") ?
"" : " title=\"" . addslashes($this->tree
[$cnt]["title"]) . "\"";
666 $fooimg = $this->imgdir
. $this->tree
[$cnt]["icon"];
667 if ($this->tree
[$cnt]["icon"] == "" ||
!(file_exists($fooimg))) {
668 $this->tree
[$cnt]["parsed_icon"] = "";
670 $this->tree
[$cnt]["parsed_icon"] = $this->tree
[$cnt]["icon"];
671 $foobar = getimagesize($fooimg);
672 $this->tree
[$cnt]["iconwidth"] = $foobar[0];
673 $this->tree
[$cnt]["iconheight"] = $foobar[1];
675 $this->tree
[$cnt]["parsed_target"] = ($this->tree
[$cnt]["target"] == "") ?
"" : " target=\"" . $this->tree
[$cnt]["target"] . "\"";
676 // $this->tree[$cnt]["expanded"] = ($this->tree[$cnt]["expanded"] == "") ? 0 : $this->tree[$cnt]["expanded"];
677 $this->_maxLevel
[$menu_name] = max($this->_maxLevel
[$menu_name], $this->tree
[$cnt]["level"]);
678 if ($this->tree
[$cnt]["level"] == 1) {
679 $this->_firstLevelCnt
[$menu_name]++
;
685 * Method to handle errors
687 * @param string $errormsg the error message
690 function error($errormsg) {
691 print "<b>LayersMenu Error:</b> " . $errormsg . "<br />\n";
692 if ($this->haltOnError
== "yes") {
693 die("<b>Halted.</b><br />\n");