b2evolution

Multilingual multiuser multiblog engine

b2evolution Technical Documentation (Version 1.9) [ class tree: admin ] [ index: admin ] [ all elements ]

Source for file _adminUI_general.class.php

Documentation is available at _adminUI_general.class.php

  1. <?php
  2. /**
  3.  * This file implements the Admin UI class.
  4.  * Admin skins should derive from this class and override {@link get_template()}
  5.  * for example.
  6.  *
  7.  * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}.
  8.  * See also {@link http://sourceforge.net/projects/evocms/}.
  9.  *
  10.  * @copyright (c)2003-2006 by Francois PLANQUE - {@link http://fplanque.net/}.
  11.  *  Parts of this file are copyright (c)2005 by Daniel HAHLER - {@link http://thequod.de/contact}.
  12.  *
  13.  * @license http://b2evolution.net/about/license.html GNU General Public License (GPL)
  14.  *
  15.  *  {@internal Open Source relicensing agreement:
  16.  *  Daniel HAHLER grants Francois PLANQUE the right to license
  17.  *  Daniel HAHLER's contributions to this file and the b2evolution project
  18.  *  under any OSI approved OSS license (http://www.opensource.org/licenses/).
  19.  *  }}}
  20.  *
  21.  * @package admin
  22.  *
  23.  *  {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  24.  * @author blueyed: Daniel HAHLER
  25.  * @author fplanque: Francois PLANQUE.
  26.  *
  27.  * @todo Refactor to allow easier contributions! (blueyed)
  28.  *
  29.  * @version $Id: _adminUI_general.class.php,v 1.25.2.6 2006/11/27 19:11:12 fplanque Exp $
  30.  */
  31. if!defined('EVO_MAIN_INIT') ) die'Please, do not access this page directly.' );
  32.  
  33.  
  34. /**
  35.  * The general Admin UI class. It provides functions to handle the UI part of the
  36.  * Backoffice.
  37.  *
  38.  * Admin skins should derive from this class and override {@link get_template()}
  39.  * for example.
  40.  *
  41.  * @package admin
  42.  * @todo CODE DOCUMENTATION!!!
  43.  */
  44. {
  45.  
  46.     /**
  47.      * List of the headlines to output.
  48.      * @var array 
  49.      */
  50.     var $headlines = array();
  51.  
  52.     /**
  53.      * Visual path seperator (used in html title, ..)
  54.      *
  55.      * @var string 
  56.      */
  57.     var $pathSeperator;
  58.  
  59.     /**
  60.      * The Logo for the admin.
  61.      *
  62.      * Defaults to {@link $app_admin_logo} if not set.
  63.      *
  64.      * @var string 
  65.      */
  66.     var $admin_logo;
  67.  
  68.     /*-------------------------------------------------------------------*/
  69.     /*- The members below should not get overridden in a derived class. -*/
  70.  
  71.     /**
  72.      * The menus.
  73.      *
  74.      * Use {@link add_menu_entries()} to add them here.
  75.      *
  76.      * @access protected
  77.      * @var array 
  78.      */
  79.     var $_menus = array();
  80.  
  81.     /**
  82.      * The path of the current selected menu entry.
  83.      * Array of strings.
  84.      * The top level entry is at position 0. Selected submenu entries follow.
  85.      *
  86.      * Use {@link get_path()} or {@link get_path_range()} to access it.
  87.      * Use {@link set_path()}{@link append_path_level()} or {@link set_path_level()} to set it.
  88.      *
  89.      * @access protected
  90.      * @var array 
  91.      */
  92.     var $path = array();
  93.  
  94.     /**
  95.      * The properties of the path entries.
  96.      * Numbered Array of arrays.
  97.      * The top level entry is at position 0. Selected submenu entries follow.
  98.      *
  99.      * Use {@link get_prop_for_path()} or {@link get_properties_for_path()} to access it
  100.      * Use {@link set_path()}{@link append_path_level()} or {@link set_path_level()} to set it.
  101.      *
  102.      * @access protected
  103.      * @var array 
  104.      */
  105.     var $pathProps = array();
  106.  
  107.     /**
  108.      * The explicit title for the page.
  109.      * @var string 
  110.      */
  111.     var $title;
  112.  
  113.     /**
  114.      * The explicit title for the titlearea (<h1>).
  115.      * @var string 
  116.      */
  117.     var $title_titlearea;
  118.     var $title_titlearea_appendix = '';
  119.  
  120.  
  121.     /**
  122.      * Constructor.
  123.      */
  124.     function AdminUI_general()
  125.     {
  126.         global $mode// TODO: make it a real property
  127.         global $htsrv_url$baseurl;
  128.  
  129.         $this->mode $mode;
  130.  
  131.         ifis_null($this->admin_logo) )
  132.         {
  133.             global $app_admin_logo;
  134.             $this->admin_logo = $app_admin_logo;
  135.         }
  136.  
  137.         ifis_null($this->pathSeperator) )
  138.         {
  139.             global $admin_path_seprator;
  140.             $this->pathSeperator = $admin_path_seprator;
  141.         }
  142.  
  143.         $this->init_templates();
  144.     }
  145.  
  146.  
  147.     /**
  148.      * This function should init the templates - like adding Javascript through the {@link add_headline()} method.
  149.      */
  150.     function init_templates()
  151.     {
  152.     }
  153.  
  154.  
  155.     /**
  156.      * Add menu entries to the list of entries for a given path.
  157.      *
  158.      * @param NULL|string|arrayThe path to add the entries to. See {@link get_node_by_path()}.
  159.      * @param array Menu entries to add (key (string) => entry (array)).
  160.      *    An entry can have the following keys:
  161.      *      'text': Text/Caption for this entry.
  162.      *      'href': The link for this entry.
  163.      *      'style': CSS style for this entry.
  164.      *      'onclick': onclick property for this entry.
  165.      *      'name': name attribute of the link/entry.
  166.      *      'perm_name': permission name to check.
  167.      *      'perm_level': permission level that must be granted.
  168.      *      'perm_eval': This gets evaluated and must return true for the entry to be accessible.
  169.      *      'text_noperm': Text to display if no permission granted.
  170.      *      'entries': array of sub-entries
  171.      */
  172.     function add_menu_entries$path$entries )
  173.     {
  174.         // Get a reference to the node in the menu list.
  175.         $node $this->get_node_by_path$pathtrue );
  176.  
  177.         /*
  178.         if( !is_array($node) )
  179.         {
  180.             debug_die( 'add_menu_entries() with non-existing path!' );
  181.         }
  182.         */
  183.  
  184.         foreach$entries as $l_key => $l_menu_props )
  185.         {
  186.             $node['entries'][$l_key$l_menu_props;
  187.         }
  188.     }
  189.  
  190.  
  191.     /**
  192.      * Add menu entries to the beginning of the list for given path.
  193.      *
  194.      * @param NULL|string|arrayThe path to add the entries to.
  195.      * @param array Menu entries to add (key (string) => entry (array)).
  196.      * @uses add_menu_entries()
  197.      */
  198.     function unshift_menu_entries$path$entries )
  199.     {
  200.         // Get a reference to the node in the menu list.
  201.         $node $this->get_node_by_path$pathtrue );
  202.  
  203.         $node['entries'array_reverse$node['entries');
  204.  
  205.         $this->add_menu_entries$path$entries );
  206.  
  207.         $node['entries'array_reverse$node['entries');
  208.     }
  209.  
  210.  
  211.     /**
  212.      * Get the <title> of the page.
  213.      *
  214.      * This is either {@link $title} or will be constructed from title/text properties
  215.      * of the path entries.
  216.      *
  217.      * @param boolean If true, the fallback will be in reversed order
  218.      * @return string 
  219.      */
  220.     function get_title$reversedDefault false )
  221.     {
  222.         ifisset($this->title) )
  223.         // Explicit title has been set:
  224.             return $this->title;
  225.         }
  226.         else
  227.         // Fallback: implode title/text properties of the path
  228.             $titles $this->get_properties_for_path$this->patharray'title''text' ) );
  229.             if$reversedDefault )
  230.             // We have asked for reverse order of the path elements:
  231.                 $titles array_reverse($titles);
  232.             }
  233.             return implode$this->pathSeperator$titles );
  234.         }
  235.     }
  236.  
  237.  
  238.     /**
  239.      * Get the title for the titlearea (<h1>).
  240.      *
  241.      * This is the current path in the site structure
  242.      *
  243.      * @return string 
  244.      */
  245.     function get_title_for_titlearea()
  246.     {
  247.         ifisset$this->title_titlearea ) )
  248.         // Construct path:
  249.             $titles array();
  250.             foreach$this->path as $i => $lPath )
  251.             {
  252.                 iffalse !== ($title_text $this->get_prop_for_path$iarray'title''text' ) )) )
  253.                 {
  254.                     $titles['<a href="'.$this->get_prop_for_path$iarray'href' ) ).'">'.$title_text.'</a>';
  255.                 }
  256.             }
  257.  
  258.             $this->title_titlearea = implode$this->pathSeperator$titles );
  259.         }
  260.  
  261.         return $this->title_titlearea.$this->title_titlearea_appendix;
  262.     }
  263.  
  264.  
  265.     /**
  266.      * Append a string at the end of the existing titlearea.
  267.      *
  268.      * We actually keep the appended stuff separate from the main title, because the main title
  269.      * might in some occasions not be known immediately.
  270.      *
  271.      * @param string What to append to the titlearea
  272.      */
  273.     function append_to_titlearea$string )
  274.     {
  275.         $this->title_titlearea_appendix .= $this->pathSeperator.$string;
  276.     }
  277.  
  278.  
  279.     /**
  280.      * Get the title for HTML <title> tag.
  281.      *
  282.      * If no explicit title has been specified, auto construct one from path.
  283.      *
  284.      * @return string 
  285.      */
  286.     function get_html_title()
  287.     {
  288.         global $app_shortname;
  289.  
  290.         $r $app_shortname.$this->pathSeperator;
  291.  
  292.         if$htmltitle $this->get_prop_for_node$this->patharray'htmltitle' ) ) )
  293.         // Explicit htmltitle set:
  294.             $r .= $htmltitle;
  295.         }
  296.         else
  297.         {    // No explicit title set, construct Title from path
  298.             $r .= #preg_replace( '/:$/', '',
  299.                         $this->get_title()
  300.                         #)
  301.                         ;
  302.         }
  303.  
  304.         return $r;
  305.     }
  306.  
  307.  
  308.     /**
  309.      * Get a list of properties for a given path for a set of property names to check.
  310.      * The result is a list of properties for each node down the path.
  311.      *
  312.      * The property names must be given in $prop_by_ref, ordered by preference.
  313.      *
  314.      * @param string|arrayThe path. See {@link get_node_by_path()}.
  315.      * @param array Alternative names of the property to receive (ordered by priority).
  316.      * @return array List of the properties.
  317.      */
  318.     function get_properties_for_path$path$prop_by_pref )
  319.     {
  320.         if!is_array($path) )
  321.         {
  322.             $path array$path );
  323.         }
  324.         $r array();
  325.  
  326.         $prevPath array();
  327.         foreach$path as $i => $lPath )
  328.         {
  329.             iffalse !== ($prop $this->get_prop_for_path$i$prop_by_pref )) )
  330.             {
  331.                 $r[$prop;
  332.             }
  333.  
  334.             $prevPath[$lPath;
  335.         }
  336.  
  337.         return $r;
  338.     }
  339.  
  340.  
  341.     /**
  342.      * Get a property of a node, given by path.
  343.      *
  344.      * @param string|arrayThe path. See {@link get_node_by_path()}.
  345.      * @param array Alternative names of the property to receive (ordered by priority).
  346.      * @return mixed|falseFalse if property is not set for the node, otherwise its value.
  347.      */
  348.     function get_prop_for_node$path$prop_by_pref )
  349.     {
  350.         $node $this->get_node_by_path$path );
  351.  
  352.         foreach$prop_by_pref as $lProp )
  353.         {
  354.             ifisset($node[$lProp]) )
  355.             {
  356.                 return $node[$lProp];
  357.             }
  358.         }
  359.  
  360.         return false;
  361.     }
  362.  
  363.  
  364.     /**
  365.      * Get a property for a specific path entry.
  366.      *
  367.      * @param int The numeric index of the path entry to query (0 is first).
  368.      * @param array A list of properties to check, ordered by priority.
  369.      * @return mixed|falseThe first found property or false if it does not exist
  370.      */
  371.     function get_prop_for_path$depth$prop_by_pref )
  372.     {
  373.         if$pathWithProps $this->get_path$depthtrue ) )
  374.         {
  375.             foreach$prop_by_pref as $lProp )
  376.             {
  377.                 ifisset($pathWithProps['props'][$lProp]) )
  378.                 {
  379.                     // echo "<br>path depth $depth property $lProp = ".$pathWithProps['props'][$lProp];
  380.                     return $pathWithProps['props'][$lProp];
  381.                 }
  382.             }
  383.         }
  384.  
  385.         return false;
  386.     }
  387.  
  388.  
  389.     /**
  390.      * Get a menu, any level.
  391.      *
  392.      * @param NULL|string|arrayThe path. See {@link get_node_by_path()}.
  393.      * @param string The template name, see {@link get_template()}.
  394.      */
  395.     function get_html_menu$path NULL$template 'main' )
  396.     {
  397.         /* debug:
  398.         $r = ' dispMenu-BEGIN ';
  399.         $r .= $this->get_html_menu_entries( $path, $template );
  400.         $r .= ' dispMenu-END ';
  401.         return $r;
  402.         */
  403.         return $this->get_html_menu_entries$path$template );
  404.     }
  405.  
  406.  
  407.     /**
  408.      * Display doctype + <head>...</head> section
  409.      */
  410.     function disp_html_head()
  411.     {
  412.         global $view_path;
  413.  
  414.         require $view_path.'_menutop.php';
  415.     }
  416.  
  417.  
  418.     /**
  419.      * Dsiplay the top of the HTML <body>...
  420.      *
  421.      * Typically includes title, menu, messages, etc.
  422.      */
  423.     function disp_body_top()
  424.     {
  425.         echo "<body>\n";
  426.  
  427.         echo $this->get_body_top();
  428.     }
  429.  
  430.     /**
  431.      * Display body bottom, debug info and close </html>
  432.      */
  433.     function disp_global_footer()
  434.     {
  435.         global $view_path;
  436.  
  437.         require $view_path.'_footer.php';
  438.     }
  439.  
  440.  
  441.     /**
  442.      * Display the start of a payload block
  443.      *
  444.      * Note: it is possible to display several payload blocks on a single page.
  445.      *       The first block uses the "sub" template, the others "block".
  446.      *
  447.      * @see disp_payload_end()
  448.      * @todo check if the plugin event is appropriate. Maybe it should rather go as 'AdminAfterBodyTop' or sth like this.
  449.      */
  450.     function disp_payload_begin()
  451.     {
  452.         global $Plugins;
  453.  
  454.         ifempty($this->displayed_sub_begin) )
  455.         {
  456.             $Plugins->trigger_event'AdminBeginPayload' );
  457.  
  458.             // Display submenu (this also opens a div class="panelblock" or class="panelblocktabs")
  459.  
  460.             //echo ' disp_submenu-BEGIN ';
  461.             $path array$this->get_path(0) );
  462.             echo $this->get_html_menu$path'sub' );
  463.             //echo ' disp_submenu-END ';
  464.  
  465.             $this->displayed_sub_begin 1;
  466.         }
  467.         else
  468.         {
  469.             $template $this->get_template'block' );
  470.  
  471.             echo $template['begin'];
  472.         }
  473.  
  474.     }
  475.  
  476.  
  477.     /**
  478.      * Display the end of a payload block
  479.      *
  480.      * Note: it is possible to display several payload blocks on a single page.
  481.      *       The first block uses the "sub" template, the others "block".
  482.      * @see disp_payload_begin()
  483.      */
  484.     function disp_payload_end()
  485.     {
  486.         ifempty($this->displayed_sub_end) )
  487.         {
  488.             $name 'sub';
  489.             $this->displayed_sub_end 1;
  490.         }
  491.         else
  492.         {
  493.             $name 'block';
  494.         }
  495.  
  496.         $template $this->get_template$name );
  497.  
  498.         echo $template['end'];
  499.     }
  500.  
  501.  
  502.     /**
  503.      * Display a view (from the inc/VIEWS/ hierarchy )
  504.      *
  505.      * Note: doing the require inside of a function has the side effect of forcing the view
  506.      * to declare any global object it wants to use. This can be a little tedious but on the
  507.      * other hand it has the advantage of clearly showing what objects are used and makes it
  508.      * easier to audit the views in order to determine if they include more business logic
  509.      * than they ought to.
  510.      *
  511.      * @param string 
  512.      * @param array params to be used in the view (optional)
  513.      */
  514.     function disp_view$view_name$view_params array() )
  515.     {
  516.         global $view_path;
  517.  
  518.         // THESE ARE THE GLOBALS WE WANT TO MAKE AVAILABLE TO ALL VIEWS:
  519.         global $action;
  520.         global $ctrl;
  521.  
  522.         global $DB;    // Note: not sure it's agood idea to let the views hit on the db...
  523.  
  524.         global $model_path;        // TEMP (for object inclusion)
  525.         global $misc_inc_path;
  526.  
  527.         global $current_User;
  528.         global $Request;
  529.  
  530.  
  531.         require $view_path.$view_name;
  532.     }
  533.  
  534.  
  535.     /**
  536.      * Returns the list of available Collections (aka Blogs) to work on.
  537.      *
  538.      * @todo Use BlogCache(?)
  539.      * @todo Use a template (i wanna make an UL/LI/A list structure in newer skins)
  540.      *
  541.      * @param string name of required permission needed to display the blog in the list
  542.      * @param string level of required permission needed to display the blog in the list
  543.      * @param string Url format string for elements, with %d for blog number.
  544.      * @param string Title for "all" button
  545.      * @param string URL for "all" button
  546.      * @param string onclick attribute format string, with %d for blog number.
  547.      * @param string name attribute for each button (%d for blog number)
  548.      * @return string HTML
  549.      */
  550.     function get_html_collection_list$permname 'blog_ismember'$permlevel 1$url_format '?blog=%d',
  551.                             $all_title NULL$all_url ''$onclick NULL$name NULL )
  552.     {
  553.         global $current_User$blog;
  554.  
  555.         $template $this->get_template'CollectionList' );
  556.  
  557.         $r $template['before'];
  558.  
  559.         if!is_null($all_title) )
  560.         {    // We want to add an "all" button
  561.             $r .= $template$blog == 'beforeEachSel' 'beforeEach' ];
  562.             $r .= '<a href="'.$all_url
  563.                         .'" class="'.$blog == 'CurrentBlog' 'OtherBlog' ).'">'
  564.                         .$all_title.'</a> ';
  565.             $r .= $template$blog == 'afterEachSel' 'afterEach' ];
  566.         }
  567.  
  568.         for$curr_blog_ID blog_list_start();
  569.                     $curr_blog_ID != false;
  570.                     $curr_blog_ID blog_list_next() )
  571.         {
  572.             if$current_User->check_perm$permname$permlevelfalse$curr_blog_ID ) )
  573.             // Current user doesn't have required permission on this blog...
  574.                 continue;
  575.             }
  576.  
  577.             $r .= $template$curr_blog_ID == $blog 'beforeEachSel' 'beforeEach' ];
  578.  
  579.             $r .= '<a href="'.sprintf$url_format$curr_blog_ID )
  580.                         .'" class="'.$curr_blog_ID == $blog 'CurrentBlog' 'OtherBlog' ).'"';
  581.  
  582.             if!is_null($onclick) )
  583.             {    // We want to include an onclick attribute:
  584.                 $r .= ' onclick="'.sprintf$onclick$curr_blog_ID ).'"';
  585.             }
  586.  
  587.             if!is_null($name) )
  588.             {    // We want to include a name attribute:
  589.                 $r .= ' name="'.sprintf$name$curr_blog_ID ).'"';
  590.             }
  591.  
  592.             $r .= '>'.blog_list_iteminfo'shortname'false ).'</a> ';
  593.  
  594.             $r .= $template$curr_blog_ID == $blog 'afterEachSel' 'afterEach' ];
  595.         }
  596.  
  597.         $r .= $template['after'];
  598.  
  599.         return $r;
  600.     }
  601.  
  602.  
  603.     /**
  604.      * Get the HTML for the menu entries of a specific path.
  605.      *
  606.      * @param NULL|string|arrayThe path. See {@link get_node_by_path()}.
  607.      * @param string Template name, see {@link get_template()}.
  608.      * @param int Depth (recursion)
  609.      * @return string The HTML for the menu.
  610.      */
  611.     function get_html_menu_entries$path$template$depth )
  612.     {
  613.         global $current_User;
  614.  
  615.         $r '';
  616.  
  617.         $templateForLevel $this->get_template$template$depth );
  618.  
  619.         if!$menuEntries $this->get_menu_entries($path) ) )
  620.         {    // No menu entries at this level
  621.             ifisset($templateForLevel['empty']) )
  622.             {
  623.                 $r .= $templateForLevel['empty'];
  624.             }
  625.         }
  626.         else
  627.         {    // There are entries to display:
  628.             $r .= $templateForLevel['before'];
  629.  
  630.             $selected $this->get_selected($path);
  631.  
  632.             foreach$menuEntries as $loop_key => $loop_details )
  633.             {
  634.                 $perm true// By default
  635.  
  636.                 if($perm $this->check_perm$loop_details )) && isset($loop_details['text_noperm']) )
  637.                 // If permission requested but not granted, and we have no alt text, display no tab:
  638.                     continue;
  639.                 }
  640.  
  641.                 $anchor '<a href="';
  642.  
  643.                 ifisset$loop_details['href') )
  644.                 {
  645.                     $anchor .= $loop_details['href'];
  646.                 }
  647.                 elseif!empty($loop_details['href_eval']) )
  648.                 // Useful for passing dynamic context vars (fp>> I AM using it)
  649.                     $anchor .= eval$loop_details['href_eval');
  650.                 }
  651.                 else
  652.                 {
  653.                     $anchor .= regenerate_url'tab''tab='.$loop_key );
  654.                 }
  655.                 $anchor .= '"';
  656.                 ifisset($loop_details['style']) )
  657.                 {
  658.                     $anchor .= ' style="'.$loop_details['style'].'"';
  659.                 }
  660.                 ifisset($loop_details['onclick']) )
  661.                 {
  662.                     $anchor .= ' onclick="'.$loop_details['onclick'].'"';
  663.                 }
  664.                 ifisset($loop_details['name']) )
  665.                 {
  666.                     $anchor .= ' name="'.$loop_details['name'].'"';
  667.                 }
  668.  
  669.                 $anchor .= '>'.format_to_output$perm $loop_details['text'$loop_details['text_noperm']'htmlbody' )
  670.                               ."</a>";
  671.  
  672.                 if$loop_key == $selected )
  673.                 // Highlight selected entry
  674.                     if!empty$templateForLevel['_props']['recurseSelected')
  675.                             && $recursePath array_merge$path$loop_key ) )
  676.                             && ($this->get_menu_entries($recursePath) ) )
  677.                     {
  678.                         $r .= isset($templateForLevel['beforeEachSelWithSub'])
  679.                             ? $templateForLevel['beforeEachSelWithSub']
  680.                             : $templateForLevel['beforeEachSel'];
  681.                         $r .= $anchor;
  682.  
  683.                         // Recurse:
  684.                         $r .= $this->get_html_menu_entries$recursePath$template$depth+);
  685.  
  686.                         $r .= isset($templateForLevel['afterEachSelWithSub'])
  687.                             ? $templateForLevel['afterEachSelWithSub']
  688.                             : $templateForLevel['afterEachSel'];
  689.                     }
  690.                     else
  691.                     {
  692.                         $r .= $templateForLevel['beforeEachSel'];
  693.                         $r .= $anchor;
  694.                         $r .= $templateForLevel['afterEachSel'];
  695.                     }
  696.                 }
  697.                 else
  698.                 {
  699.                     $r .= $templateForLevel['beforeEach'];
  700.                     $r .= $anchor;
  701.                     $r .= $templateForLevel['afterEach'];
  702.                 }
  703.             }
  704.             $r .= $templateForLevel['after'];
  705.         }
  706.  
  707.         return $r;
  708.     }
  709.  
  710.  
  711.     /**
  712.      * Get menu entries for a given path.
  713.      *
  714.      * @param NULL|string|arrayThe path. See {@link get_node_by_path()}.
  715.      * @return array The menu entries (may be empty).
  716.      */
  717.     function get_menu_entries$path )
  718.     {
  719.         $node $this->get_node_by_path$path );
  720.  
  721.         return isset$node['entries'$node['entries'array();
  722.     }
  723.  
  724.  
  725.     /**
  726.      * Get the key of a selected entry for a path.
  727.      *
  728.      * @param NULL|string|arrayThe path. See {@link get_node_by_path()}.
  729.      * @return string|false
  730.      */
  731.     function get_selected$path )
  732.     {
  733.         $node $this->get_node_by_path($path);
  734.  
  735.         ifisset($node['selected']) )
  736.         {
  737.             return $node['selected'];
  738.         }
  739.  
  740.         return false;
  741.     }
  742.  
  743.  
  744.     /**
  745.      * Get the reference of a node from the menu entries using a path.
  746.      *
  747.      * @param array|string|NULLThe path. NULL means root, string means child of root,
  748.      *                           array means path below root.
  749.      *                           (eg <code>array('options', 'general')</code>).
  750.      * @param boolean Should the node be created if it does not exist already?
  751.      * @return array|falseThe node as array or false, if the path does not exist (and we do not $createIfNotExisting).
  752.      */
  753.     function get_node_by_path$path$createIfNotExisting false )
  754.     {
  755.         ifis_null($path) )
  756.         // root element
  757.             $path array();
  758.         }
  759.         elseifis_array($path) )
  760.         {
  761.             $path array($path);
  762.         }
  763.  
  764.         $node $this->_menus;
  765.         foreach$path as $lStep )
  766.         {
  767.             ifisset($node['entries'][$lStep]) )
  768.             {
  769.                 if$createIfNotExisting )
  770.                 {
  771.                     $node['entries'][$lSteparray();
  772.                 }
  773.                 else
  774.                 {
  775.                     $r false;
  776.                     return $r;
  777.                 }
  778.             }
  779.             $node $node['entries'][$lStep];
  780.         }
  781.  
  782.         return $node;
  783.     }
  784.  
  785.  
  786.     /**
  787.      * Get a template by name and depth.
  788.      *
  789.      * Templates can handle multiple depth levels
  790.      *
  791.      * This is a method (and not a member array) to allow dynamic generation.
  792.      * fp>>I'm not so sure about this... feels a little bloated... gotta think about it..
  793.      *
  794.      * @param string Name of the template ('main', 'sub')
  795.      * @param integer Nesting level (start at 0)
  796.      * @return array Associative array which defines layout and optionally properties.
  797.      */
  798.     function get_template$name$depth )
  799.     {
  800.         switch$name )
  801.         {
  802.             case 'main':
  803.                 switch$depth )
  804.                 {
  805.                     case 0:
  806.                         // main level
  807.                         global $app_shortname$app_version;
  808.  
  809.                         return array(
  810.                             'before' => '<div id="mainmenu"><ul>',
  811.                             'after' => "</ul>\n<p class=\"center\">$app_shortname v <strong>$app_version</strong></p>\n</div>",
  812.                             'beforeEach' => '<li>',
  813.                             'afterEach' => '</li>',
  814.                             'beforeEachSel' => '<li class="current">',
  815.                             'afterEachSel' => '</li>',
  816.                             'beforeEachSelWithSub' => '<li class="parent">',
  817.                             'afterEachSelWithSub' => '</li>',
  818.                             '_props' => array(
  819.                                 /**
  820.                                  * @todo Move to new skin (recurse for subentries if an entry is selected)
  821.                                 'recurseSelected' => true,
  822.                                 */
  823.                             ),
  824.                         );
  825.  
  826.                     default:
  827.                         // any sublevel
  828.                         return array(
  829.                             'before' => '<ul class="submenu">',
  830.                             'after' => '</ul>',
  831.                             'beforeEach' => '<li>',
  832.                             'afterEach' => '</li>',
  833.                             'beforeEachSel' => '<li class="current">',
  834.                             'afterEachSel' => '</li>',
  835.                         );
  836.                 }
  837.  
  838.                 break;
  839.  
  840.  
  841.             case 'sub':
  842.                 // submenu, we support just one sub-level (by default)
  843.                 return array(
  844.                         'before' => '<div class="pt">'
  845.                             ."\n".'<ul class="hack">'
  846.                             ."\n<li><!-- Yes, this empty UL is needed! It's a DOUBLE hack for correct CSS display --></li>"
  847.                             // TODO: this hack MAY NOT be needed when not using pixels instead of decimal ems or exs in the CSS
  848.                             ."\n</ul>"
  849.                             ."\n".'<div class="panelblocktabs">'
  850.                             ."\n".'<ul class="tabs">',
  851.                         'after' => "</ul>\n</div>\n</div>"
  852.                             ."\n".'<div class="tabbedpanelblock">',
  853.                         'empty' => '<div class="panelblock">',
  854.                         'beforeEach' => '<li>',
  855.                         'afterEach'  => '</li>',
  856.                         'beforeEachSel' => '<li class="current">',
  857.                         'afterEachSel' => '</li>',
  858.                         'end' => '</div>'// used to end payload block that opened submenu
  859.                     );
  860.  
  861.  
  862.             case 'block':
  863.                 // a payload block, anywhere "below" submenu. Gets used by disp_payload_begin()/disp_payload_end()
  864.                 return array(
  865.                         'begin' => '<div class="panelblock">',
  866.                         'end' => "\n</div>",
  867.                     );
  868.  
  869.  
  870.             case 'CollectionList':
  871.                 // Template for a list of Collections (Blogs)
  872.                 return array(
  873.                         'before' => '',
  874.                         'after' => '',
  875.                         'beforeEach' => '',
  876.                         'afterEach' => '',
  877.                         'beforeEachSel' => '',
  878.                         'afterEachSel' => '',
  879.                     );
  880.                 // fp>> I'll use the following as soon as I have time to play with the CSS:
  881.                 return array(
  882.                         'before' => '<ul class="submenu">',
  883.                         'after' => '</ul>',
  884.                         'beforeEach' => '<li>',
  885.                         'afterEach' => '</li>',
  886.                         'beforeEachSel' => '<li class="current">',
  887.                         'afterEachSel' => '</li>',
  888.                     );
  889.  
  890.  
  891.             case 'Results':
  892.                 // Results list:
  893.                 return array(
  894.                     'before' => '<div class="results">',
  895.                     'header_start' => '<div class="results_nav">',
  896.                         'header_text' => '<strong>'.T_('Pages').'</strong>: $prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$',
  897.                         'header_text_single' => '',
  898.                     'header_end' => '</div>',
  899.                     'list_start' => '<table class="grouped" cellspacing="0">'."\n\n",
  900.                         'head_start' => "<thead><tr>\n",
  901.                             'head_title' => '<th colspan="$nb_cols$"><span style="float:right">$global_icons$</span>$title$</th></tr>'
  902.                                             ."\n\n<tr>\n",
  903.                             'filters_start' => '<tr class="filters"><td colspan="$nb_cols$">',
  904.                             'filters_end' => '</td></tr>',
  905.                             'line_start_head' => '<tr>',  // TODO: fusionner avec colhead_start_first; mettre à jour admin_UI_general; utiliser colspan="$headspan$"
  906.                             'colhead_start' => '<th $class_attrib$>',
  907.                             'colhead_start_first' => '<th class="firstcol $class$">',
  908.                             'colhead_start_last' => '<th class="lastcol $class$">',
  909.                             'colhead_end' => "</th>\n",
  910.                             'sort_asc_off' => '<img src="../admin/img/grey_arrow_up.gif" alt="A" title="'.T_('Ascending order')
  911.                                                 .'" height="12" width="11" />',
  912.                             'sort_asc_on' => '<img src="../admin/img/black_arrow_up.gif" alt="A" title="'.T_('Ascending order')
  913.                                                 .'" height="12" width="11" />',
  914.                             'sort_desc_off' => '<img src="../admin/img/grey_arrow_down.gif" alt="D" title="'.T_('Descending order')
  915.                                                 .'" height="12" width="11" />',
  916.                             'sort_desc_on' => '<img src="../admin/img/black_arrow_down.gif" alt="D" title="'.T_('Descending order')
  917.                                                 .'" height="12" width="11" />',
  918.                             'basic_sort_off' => '',
  919.                             'basic_sort_asc' => get_icon'ascending' ),
  920.                             'basic_sort_desc' => get_icon'descending' ),
  921.                         'head_end' => "</tr></thead>\n\n",
  922.                         'tfoot_start' => "<tfoot>\n",
  923.                         'tfoot_end' => "</tfoot>\n\n",
  924.                         'body_start' => "<tbody>\n",
  925.                             'line_start' => "<tr>\n",
  926.                             'line_start_odd' => '<tr class="odd">'."\n",
  927.                             'line_start_last' => '<tr class="lastline">'."\n",
  928.                             'line_start_odd_last' => '<tr class="odd lastline">'."\n",
  929.                                 'col_start' => '<td $class_attrib$>',
  930.                                 'col_start_first' => '<td class="firstcol $class$">',
  931.                                 'col_start_last' => '<td class="lastcol $class$">',
  932.                                 'col_end' => "</td>\n",
  933.                             'line_end' => "</tr>\n\n",
  934.                             'grp_line_start' => '<tr class="group">'."\n",
  935.                             'grp_line_start_odd' => '<tr class="odd">'."\n",
  936.                             'grp_line_start_last' => '<tr class="lastline">'."\n",
  937.                             'grp_line_start_odd_last' => '<tr class="odd lastline">'."\n",
  938.                                         'grp_col_start' => '<td $class_attrib$ $colspan_attrib$>',
  939.                                         'grp_col_start_first' => '<td class="firstcol $class$" $colspan_attrib$>',
  940.                                         'grp_col_start_last' => '<td class="lastcol $class$" $colspan_attrib$>',
  941.                                 'grp_col_end' => "</td>\n",
  942.                             'grp_line_end' => "</tr>\n\n",
  943.                         'body_end' => "</tbody>\n\n",
  944.                         'total_line_start' => '<tr class="total">'."\n",
  945.                             'total_col_start' => '<td $class_attrib$>',
  946.                             'total_col_start_first' => '<td class="firstcol $class$">',
  947.                             'total_col_start_last' => '<td class="lastcol $class$">',
  948.                             'total_col_end' => "</td>\n",
  949.                         'total_line_end' => "</tr>\n\n",
  950.                     'list_end' => "</table>\n\n",
  951.                     'footer_start' => '<div class="results_nav">',
  952.                     'footer_text' => '<strong>'.T_('Pages').'</strong>: $prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$'
  953.                                       /* T_('Page $scroll_list$ out of $total_pages$   $prev$ | $next$<br />'. */
  954.                                       /* '<strong>$total_pages$ Pages</strong> : $prev$ $list$ $next$' */
  955.                                       /* .' <br />$first$  $list_prev$  $list$  $list_next$  $last$ :: $prev$ | $next$') */,
  956.                     'footer_text_single' => T_('1 page'),
  957.                     'footer_text_no_limit' => ''// Text if theres no LIMIT and therefor only one page anyway
  958.                         'prev_text' => T_('Previous'),
  959.                         'next_text' => T_('Next'),
  960.                         'list_prev_text' => T_('...'),
  961.                         'list_next_text' => T_('...'),
  962.                         'list_span' => 11,
  963.                         'scroll_list_range' => 5,
  964.                     'footer_end' => "</div>\n\n",
  965.                     'no_results_start' => '<table class="grouped clear" cellspacing="0">'."\n\n"
  966.                                                 .'<th><span style="float:right">$global_icons$</span>'
  967.                                                 .'$title$</th></tr>'."\n",
  968.                     'no_results_end'   => '<tr class="lastline"><td class="firstcol lastcol">'.T_('No results.').'</td></tr>'
  969.                                                 .'</table>'."\n\n",
  970.                 'after' => '</div>',
  971.                 'sort_type' => 'basic'
  972.                 );
  973.  
  974.             case 'Form':
  975.                 // Default Form settings:
  976.                 return array(
  977.                     'layout' => 'fieldset',
  978.                 );
  979.  
  980.             // TODO: add default settings for 'table', 'fieldset', etc...
  981.  
  982.             default:
  983.                 debug_die'Unknown $name for AdminUI::get_template(): '.var_export($nametrue/* PHP 4.2 ! */ );
  984.         }
  985.     }
  986.  
  987.  
  988.     /**
  989.      * Add a headline for HTML <head>.
  990.      *
  991.      * @param string The line that should be added to <head>.
  992.      */
  993.     function add_headline$headline )
  994.     {
  995.         $this->headlines[$headline;
  996.     }
  997.  
  998.  
  999.     /**
  1000.      * Get the headlines for HTML <head> (CSS files especially).
  1001.      *
  1002.      * To define headlines for a derived skin, add entries to
  1003.      * {@link $headlines} and "return parent::get_headlines();".
  1004.      *
  1005.      * @return string The concatenated headlines to output in HTML <head>.
  1006.      */
  1007.     function get_headlines()
  1008.     {
  1009.         $r implode"\n\t"$this->headlines )."\n\t";
  1010.  
  1011.         return $r;
  1012.     }
  1013.  
  1014.  
  1015.     /**
  1016.      *
  1017.      * @todo Move generation of blog list to this class!
  1018.      *
  1019.      * @return string 
  1020.      */
  1021.     function get_bloglist_buttons$before ''$after '' )
  1022.     {
  1023.         global $blogListButtons;
  1024.  
  1025.         if!empty($blogListButtons) )
  1026.         {
  1027.             return $before.$blogListButtons.$after;
  1028.         }
  1029.     }
  1030.  
  1031.  
  1032.     /**
  1033.      * Get a path key by numeric key. Starts with 0.
  1034.      *
  1035.      * @param integer The numeric index of the path (0 is first).
  1036.      * @param boolean Also return properties?
  1037.      * @return string|array|false(depends on $withProps)
  1038.      */
  1039.     function get_path$which$withProps false )
  1040.     {
  1041.         if$which === 'last' )
  1042.         {
  1043.             $which count($this->path)-1;
  1044.         }
  1045.         if!isset($this->path[$which]) )
  1046.         {
  1047.             return false;
  1048.         }
  1049.  
  1050.         if$withProps )
  1051.         {
  1052.             return array(
  1053.                 'path' => $this->path[$which],
  1054.                 'props' => isset$this->pathProps[$which$this->pathProps[$whicharray(),
  1055.             );
  1056.         }
  1057.  
  1058.         return $this->path[$which];
  1059.     }
  1060.  
  1061.  
  1062.     /**
  1063.      * Get tghe list of path keys in a given range.
  1064.      *
  1065.      * @param integer start index
  1066.      * @param integer|NULLend index (NULL means same as start index)
  1067.      * @return array List of path keys.
  1068.      */
  1069.     function get_path_range$start$end NULL )
  1070.     {
  1071.         ifis_null($end) )
  1072.         {
  1073.             $end $start;
  1074.         }
  1075.  
  1076.         $r array();
  1077.         for$i $start$i <= $end$i++ )
  1078.         {
  1079.             $r[= isset($this->path[$i]$this->path[$iNULL;
  1080.         }
  1081.  
  1082.         return $r;
  1083.     }
  1084.  
  1085.  
  1086.     /**
  1087.      * Set a specific path level (specific depth).
  1088.      *
  1089.      * First level is 0, then the first subpath/submenu is level 1, etc.
  1090.      *
  1091.      * E.g., if plugins.php gets called, there could be a call to
  1092.      * $AdminUI->set_path_level( 0, 'plugins' ), which selects this entry from the menu.
  1093.      * If a specific tab is called inside of plugins.php, there could be a call to
  1094.      * $AdminUI->set_path_level( 1, $tab )
  1095.      *
  1096.      * Though, it is recommended to call the wrapper functions:
  1097.      *  - {@link append_path_level()}
  1098.      *  - {@link set_path()}
  1099.      *
  1100.      * This also marks the parent node as selected and checks for permissions.
  1101.      *
  1102.      * @param integer Path level to set (starts at 0)
  1103.      * @param array Either the key of the path or an array(keyname, propsArray).
  1104.      * @param array Properties for this path entry.
  1105.      * @param boolean Exit script when the user has no permissions to this path and
  1106.      *                 text_noperm is not set for the path?
  1107.      * @return boolean True if perm granted, false if not (and we're not exiting).
  1108.      */
  1109.     function set_path_level$level$pathKey$pathProps array()$die_if_no_perm true )
  1110.     {
  1111.         // Get the parent node (the level above this one):
  1112.         if$level == )
  1113.         // first level in menu-path: parent node is NULL
  1114.             $parentNode $this->get_node_by_pathNULL );
  1115.         }
  1116.         else
  1117.         // parent node is the trunk from root to previous level
  1118.             $parentNode $this->get_node_by_path$this->get_path_range0$level-) );
  1119.         }
  1120.         if$parentNode )
  1121.         // parent node does not exist:
  1122.             return false;
  1123.         }
  1124.  
  1125.         // Store the selected entry name in the parent node:
  1126.         $parentNode['selected'$pathKey;
  1127.  
  1128.         $this->path[$level$pathKey;
  1129.         $this->pathProps[$level$pathProps;
  1130.         // FP> WHY ON EARTH would we want to do that? $this->pathProps[$level] = array_merge( $parentNode, $pathProps );
  1131.  
  1132.         // pre_dump( 'set_path_level: ', $level, $pathKey, $this->pathProps[$level] );
  1133.  
  1134.         $perm $this->check_perm$pathProps );
  1135.         if$perm && empty($pathProps['text_noperm']&& $die_if_no_perm )
  1136.         {
  1137.             debug_dieT_('Permission denied!').' (set_path_level: '.$level.'/'.$pathKey.')' );
  1138.         }
  1139.  
  1140.         return $perm;
  1141.     }
  1142.  
  1143.  
  1144.     /**
  1145.      * Append a selected menu entry to the current path of selected entries.
  1146.      *
  1147.      * @param string|arrayEither the key of the path or an array(keyname, propsArray).
  1148.      */
  1149.     function append_path_level$path$pathProps array() )
  1150.     {
  1151.         $search_path $this->path;
  1152.         $search_path[$path;
  1153.         // auto-detect path props from menu entries
  1154.         if$node $this->get_node_by_path$search_path ) )
  1155.         {
  1156.             $pathProps array_merge$node$pathProps );
  1157.         }
  1158.  
  1159.         // Set the path level right after the last existing one:
  1160.         return $this->set_path_levelcount($this->path)$path$pathProps );
  1161.     }
  1162.  
  1163.  
  1164.     /**
  1165.      * Set the full selected path.
  1166.      *
  1167.      * For example, this selects the tab/submenu 'plugins' in the main menu 'options':
  1168.      * <code>
  1169.      * set_path( 'options', 'plugins' );
  1170.      * </code>
  1171.      *
  1172.      * Use {@link append_path_level()} to append a single path element.
  1173.      *
  1174.      * This is an easy stub for {@link set_path_level()}.
  1175.      *
  1176.      * @param string|array,...VARIABLE NUMBER OF ARGUMENTS. Each is either the key of a path entry or an array(keyname, propsArray).
  1177.      */
  1178.     function set_path(        )
  1179.     {
  1180.         $args func_get_args();
  1181.  
  1182.         $i 0;
  1183.         $prevPath array();  // Remember the path we have walked through
  1184.  
  1185.         // Loop though all path levels to set:
  1186.         foreach$args as $arg )
  1187.         {
  1188.             ifis_array($arg) )
  1189.             // Path name and properties given
  1190.                 list$pathName$pathProps $arg;
  1191.             }
  1192.             else
  1193.             // Just the path name
  1194.                 $pathName $arg;
  1195.                 $pathProps array();
  1196.             }
  1197.  
  1198.             if$node $this->get_node_by_patharray_merge$prevPatharray($pathName) ) ) )
  1199.             // the node exists in the menu entries: merge the properties
  1200.                 $pathProps array_merge$node$pathProps );
  1201.             }
  1202.  
  1203.             if$this->set_path_level$i++$pathName$pathProps ) )
  1204.             {
  1205.                 return false;
  1206.             }
  1207.  
  1208.             $prevPath[$pathName;
  1209.         }
  1210.  
  1211.         return true;
  1212.     }
  1213.  
  1214.  
  1215.     /**
  1216.      * Get the top of the HTML <body>.
  1217.      *
  1218.      * @return string 
  1219.      */
  1220.     function get_body_top()
  1221.     {
  1222.         return '';
  1223.     }
  1224.  
  1225.  
  1226.     /**
  1227.      * Get the end of the HTML <body>. Close open divs, etc...
  1228.      *
  1229.      * @return string 
  1230.      */
  1231.     function get_body_bottom()
  1232.     {
  1233.         return '';
  1234.     }
  1235.  
  1236.  
  1237.     /**
  1238.      * GLOBAL HEADER - APP TITLE, LOGOUT, ETC.
  1239.      *
  1240.      * @return string 
  1241.      */
  1242.     function get_page_head()
  1243.     {
  1244.         global $app_shortname$app_version$current_User$htsrv_url_sensitive$admin_url$baseurl$rsc_url;
  1245.  
  1246.         $r '
  1247.         <div id="header">
  1248.             '.$this->admin_logo.'
  1249.  
  1250.             <div id="headinfo">
  1251.                 <span id="headfunctions">'
  1252.                     // Note: if we log in with another user, we may not have the perms to come back to the same place any more, thus: redirect to admin home.
  1253.                     .'<a href="'.$htsrv_url_sensitive.'login.php?action=logout&amp;redirect_to='.rawurlencode(url_rel_to_same_host($admin_url$htsrv_url_sensitive)).'">'.T_('Logout').'</a>
  1254.                     <img src="'.$rsc_url.'icons/close.gif" width="14" height="14" border="0" class="top" alt="" title="'
  1255.                     .T_('Logout').'" /></a>
  1256.                 </span>
  1257.  
  1258.                 '.$app_shortname.' v <strong>'.$app_version.'</strong>
  1259.                 &middot; '.$this->get_head_info().'
  1260.             </div>
  1261.  
  1262.             <h1>'.$this->get_title_for_titlearea().'</h1>
  1263.         </div>
  1264.         ';
  1265.  
  1266.         return $r;
  1267.     }
  1268.  
  1269.  
  1270.     /**
  1271.      * Get default head info (local time, GMT, Login).
  1272.      *
  1273.      * @return string 
  1274.      */
  1275.     function get_head_info()
  1276.     {
  1277.         global $pagenow$obhandler_debug$localtimenow$servertimenow$current_User;
  1278.  
  1279.         $r '';
  1280.  
  1281.         if!$obhandler_debug )
  1282.         // don't display changing time when we want to test obhandler
  1283.             $r .= "\n".T_('Time:').' <strong>'.date_i18nlocale_timefmt()$localtimenow ).'</strong>'
  1284.                 .' &middot; <acronym title="'.T_('Greenwich Mean Time').'">'
  1285.                 ./* TRANS: short for Greenwich Mean Time */ T_('GMT:').'</acronym> <strong>'.gmdatelocale_timefmt()$servertimenow).'</strong>'
  1286.                 .' &middot; '.T_('Logged in as:').' <strong><a href="'.$pagenow.'?ctrl=users&amp;user_ID='.$current_User->ID.'">'.$current_User->dget('login').'</a></strong>'
  1287.                 ."\n";
  1288.         }
  1289.  
  1290.         return $r;
  1291.     }
  1292.  
  1293.  
  1294.     /**
  1295.      * Checks if {@link $current_User the current User} has needed perms on a menu entry.
  1296.      *
  1297.      * @param array Path properties: An array, where 'perm_name' and/or 'perm_eval' might be set.
  1298.      *               'perm_level' (used with 'perm_name') defaults to 'any' if not given.
  1299.      * @return boolean 
  1300.      */
  1301.     function check_perm$perminfo )
  1302.     {
  1303.         global $current_User;
  1304.  
  1305.         ifisset($perminfo['perm_name']) )
  1306.         // 'perm_name' given, check it together with 'perm_level' (which defaults to 'any')
  1307.             $perm_level = isset$perminfo['perm_level'$perminfo['perm_level''any';
  1308.             if$current_User->check_perm$perminfo['perm_name']$perm_level ) )
  1309.             {    // permission denied!
  1310.                 return false;
  1311.             }
  1312.         }
  1313.  
  1314.         ifisset($perminfo['perm_eval']) )
  1315.         // also check for 'perm_eval'
  1316.             ifeval($perminfo['perm_eval']) )
  1317.             {    // permission denied!
  1318.                 return false;
  1319.             }
  1320.         }
  1321.  
  1322.         return true;
  1323.     }
  1324.  
  1325. }
  1326.  
  1327. /*
  1328.  * $Log: _adminUI_general.class.php,v $
  1329.  * Revision 1.25.2.6  2006/11/27 19:11:12  fplanque
  1330.  * i18n
  1331.  *
  1332.  * Revision 1.25.2.5  2006/11/04 19:55:15  fplanque
  1333.  * Reinjected old Log blocks. Removing them from CVS was a bad idea -- especially since Daniel has decided branch 1.9 was his HEAD...
  1334.  *
  1335.  * Revision 1.25  2006/07/12 20:17:13  fplanque
  1336.  * minor
  1337.  *
  1338.  * Revision 1.24  2006/07/08 22:33:43  blueyed
  1339.  * Integrated "simple edit form".
  1340.  *
  1341.  * Revision 1.23  2006/07/08 17:04:19  fplanque
  1342.  * minor
  1343.  *
  1344.  * Revision 1.21  2006/06/25 23:34:15  blueyed
  1345.  * wording pt2
  1346.  *
  1347.  * Revision 1.20  2006/06/25 23:23:38  blueyed
  1348.  * wording
  1349.  *
  1350.  * Revision 1.19  2006/06/22 22:30:05  blueyed
  1351.  * htsrv url for password related scripts (login, register and profile update)
  1352.  *
  1353.  * Revision 1.18  2006/06/22 19:23:01  blueyed
  1354.  * Text for fotter, if no LIMIT
  1355.  *
  1356.  * Revision 1.17  2006/06/22 18:37:48  fplanque
  1357.  * fixes
  1358.  *
  1359.  * Revision 1.16  2006/06/14 17:03:59  fplanque
  1360.  * A little better logout from admin... useful for bozos.
  1361.  *
  1362.  * Revision 1.15  2006/06/13 21:49:16  blueyed
  1363.  * Merged from 1.8 branch
  1364.  *
  1365.  * Revision 1.13.2.3  2006/06/12 20:00:57  fplanque
  1366.  * one too many massive syncs...
  1367.  *
  1368.  * Revision 1.13  2006/05/12 21:53:38  blueyed
  1369.  * Fixes, cleanup, translation for plugins
  1370.  *
  1371.  * Revision 1.12  2006/05/02 18:15:20  fplanque
  1372.  * invalid xhtml fix
  1373.  *
  1374.  * Revision 1.11  2006/04/27 18:28:33  fplanque
  1375.  * moved Blog specific stuff out of evocore
  1376.  *
  1377.  * Revision 1.10  2006/04/24 20:43:43  blueyed
  1378.  * Exit to selected blog, if any
  1379.  *
  1380.  * Revision 1.9  2006/04/19 17:17:19  blueyed
  1381.  * Fix
  1382.  *
  1383.  * Revision 1.8  2006/04/19 12:54:41  fplanque
  1384.  * not using exit links any more because it won't translate
  1385.  *
  1386.  * Revision 1.7  2006/04/14 19:25:32  fplanque
  1387.  * evocore merge with work app
  1388.  *
  1389.  * Revision 1.6  2006/04/12 15:16:54  fplanque
  1390.  * partial cleanup
  1391.  *
  1392.  * Revision 1.5  2006/04/11 21:56:27  blueyed
  1393.  * cleanup
  1394.  *
  1395.  * Revision 1.4  2006/04/04 21:54:23  blueyed
  1396.  * cleanup/whitespace
  1397.  *
  1398.  * Revision 1.2  2006/03/12 23:09:30  fplanque
  1399.  * doc cleanup
  1400.  *
  1401.  * Revision 1.1  2006/02/23 21:12:51  fplanque
  1402.  * File reorganization to MVC (Model View Controller) architecture.
  1403.  * See index.hml files in folders.
  1404.  * (Sorry for all the remaining bugs induced by the reorg... :/)
  1405.  *
  1406.  * Revision 1.52  2006/02/03 21:58:04  fplanque
  1407.  * Too many merges, too little time. I can hardly keep up. I'll try to check/debug/fine tune next week...
  1408.  *
  1409.  * Revision 1.51  2006/02/01 20:06:15  blueyed
  1410.  * die_if_no_perm re-enabled
  1411.  *
  1412.  * Revision 1.50  2006/01/30 19:49:17  fplanque
  1413.  * Fixed the 3 broken check_perm() features! 1) text_no_perm 2) perm_eval 3) average user trying to edit his profile
  1414.  *
  1415.  * Revision 1.49  2006/01/30 16:09:33  blueyed
  1416.  * doc
  1417.  *
  1418.  * Revision 1.47  2006/01/26 23:08:35  blueyed
  1419.  * Plugins enhanced.
  1420.  *
  1421.  * Revision 1.46  2006/01/26 20:27:45  blueyed
  1422.  * minor
  1423.  *
  1424.  * Revision 1.45  2006/01/25 18:24:21  fplanque
  1425.  * hooked bozo validator in several different places
  1426.  *
  1427.  * Revision 1.44  2006/01/23 23:29:49  blueyed
  1428.  * Added permission checks when setting a path
  1429.  *
  1430.  * Revision 1.43  2006/01/10 19:03:16  blueyed
  1431.  * Use $app_shortname in get_page_head()
  1432.  *
  1433.  * Revision 1.42  2005/12/12 19:21:20  fplanque
  1434.  * big merge; lots of small mods; hope I didn't make to many mistakes :]
  1435.  *
  1436.  * Revision 1.41  2005/12/08 22:54:02  blueyed
  1437.  * Doc, Normalization
  1438.  *
  1439.  * Revision 1.40  2005/11/25 03:57:57  blueyed
  1440.  * doc, normalization
  1441.  *
  1442.  * Revision 1.39  2005/11/17 17:39:55  blueyed
  1443.  * Removed trailing whitespace in T_() for acronym title
  1444.  *
  1445.  * Revision 1.38  2005/11/03 18:23:43  fplanque
  1446.  * minor
  1447.  *
  1448.  * Revision 1.37  2005/10/30 23:42:46  blueyed
  1449.  * Refactored get_head_links() into existing get_headlines(); doc
  1450.  *
  1451.  * Revision 1.36  2005/10/28 20:08:46  blueyed
  1452.  * Normalized AdminUI
  1453.  *
  1454.  * Revision 1.35  2005/10/26 23:08:28  blueyed
  1455.  * doc; todo
  1456.  *
  1457.  * Revision 1.34  2005/10/12 18:24:37  fplanque
  1458.  * bugfixes
  1459.  *
  1460.  * Revision 1.33  2005/09/06 17:13:53  fplanque
  1461.  * stop processing early if referer spam has been detected
  1462.  *
  1463.  * Revision 1.32  2005/08/31 19:06:41  fplanque
  1464.  * minor
  1465.  *
  1466.  * Revision 1.30  2005/07/18 14:21:37  fplanque
  1467.  * Use a default Form layout which can be skin dependant
  1468.  *
  1469.  * Revision 1.29  2005/07/15 16:41:50  fplanque
  1470.  * fixed typo
  1471.  *
  1472.  * Revision 1.28  2005/07/14 21:03:31  blueyed
  1473.  * Fixed notice with array_merge() again.
  1474.  *
  1475.  * Revision 1.27  2005/07/10 00:09:06  blueyed
  1476.  * renamed getNode() to get_node_by_path(), fixed array_merge() notice for PHP5
  1477.  *
  1478.  * Revision 1.26  2005/06/23 18:43:06  blueyed
  1479.  * Fixed constructor's name.
  1480.  *
  1481.  * Revision 1.25  2005/06/22 17:21:39  blueyed
  1482.  * css fix for khtml
  1483.  *
  1484.  * Revision 1.24  2005/06/03 20:14:37  fplanque
  1485.  * started input validation framework
  1486.  *
  1487.  * Revision 1.22  2005/05/02 19:06:44  fplanque
  1488.  * started paging of user list..
  1489.  *
  1490.  * Revision 1.21  2005/04/28 20:44:17  fplanque
  1491.  * normalizing, doc
  1492.  *
  1493.  * Revision 1.20  2005/04/21 18:01:28  fplanque
  1494.  * CSS styles refactoring
  1495.  *
  1496.  * Revision 1.19  2005/04/15 18:02:57  fplanque
  1497.  * finished implementation of properties/meta data editor
  1498.  * started implementation of files to items linking
  1499.  *
  1500.  * Revision 1.18  2005/03/21 17:37:47  fplanque
  1501.  * results/table layout refactoring
  1502.  *
  1503.  * Revision 1.17  2005/03/18 00:24:04  blueyed
  1504.  * doc
  1505.  *
  1506.  * Revision 1.16  2005/03/17 14:06:37  fplanque
  1507.  * put back page titles in logical order
  1508.  *
  1509.  * Revision 1.15  2005/03/16 19:58:13  fplanque
  1510.  * small AdminUI cleanup tasks
  1511.  *
  1512.  * Revision 1.14  2005/03/16 16:05:09  fplanque
  1513.  * $app_footer_text
  1514.  *
  1515.  * Revision 1.13  2005/03/13 19:46:53  blueyed
  1516.  * application config layer
  1517.  *
  1518.  * Revision 1.12  2005/03/11 12:40:15  fplanque
  1519.  * multiple browsing views, part ONE
  1520.  *
  1521.  */
  1522. ?>

Documentation generated on Tue, 18 Dec 2007 19:10:08 +0100 by phpDocumentor 1.4.0