Zikula_Core
[ class tree: Zikula_Core ] [ index: Zikula_Core ] [ all elements ]

Source for file CategoryUtil.class.php

Documentation is available at CategoryUtil.class.php

  1. <?php
  2. /**
  3.  * Zikula Application Framework
  4.  *
  5.  * @copyright Robert Gasch
  6.  * @link http://www.zikula.org
  7.  * @version $Id: CategoryUtil.class.php 24342 2008-06-06 12:03:14Z markwest $
  8.  * @license GNU/GPL - http://www.gnu.org/copyleft/gpl.html
  9.  * @author Robert Gasch rgasch@gmail.com
  10.  * @package Zikula_Core
  11.  */
  12.  
  13. /**
  14.  * CategoryUtil
  15.  *
  16.  * @package Zikula_Core
  17.  * @subpackage CategoryUtil
  18.  */
  19. {
  20.     /**
  21.      * Return a category object by ID
  22.      *
  23.      * @param cid      The category-ID to retrieve
  24.      *
  25.      * @return The resulting folder object
  26.      */
  27.     function getCategoryByID ($cid)
  28.     {
  29.         if (!$cid{
  30.             return false;
  31.         }
  32.  
  33.         pnModDBInfoLoad ('Categories');
  34.  
  35.         static $cache array();
  36.         if (isset($cache[$cid])) {
  37.             return $cache[$cid];
  38.         }
  39.  
  40.         $permFilter array();
  41.         $permFilter[array('realm'            => 0,
  42.                               'component_left'   => 'Categories',
  43.                               'component_middle' => '',
  44.                               'component_right'  => 'Category',
  45.                               'instance_left'    => 'id',
  46.                               'instance_middle'  => 'path',
  47.                               'instance_right'   => 'ipath',
  48.                               'level'            => ACCESS_OVERVIEW);
  49.  
  50.         $cache[$cidDBUtil::selectObjectByID ('categories_category'(int)$cid'id'null$permFilter);
  51.  
  52.         $cache[$cid]['display_name'DataUtil::formatForDisplayHTML(unserialize($cache[$cid]['display_name']));
  53.         $cache[$cid]['display_desc'DataUtil::formatForDisplayHTML(unserialize($cache[$cid]['display_desc']));
  54.  
  55.         return $cache[$cid];
  56.     }
  57.  
  58.  
  59.     /**
  60.      * Return an array of categories objects according the specified where-clause and sort criteria.
  61.      *
  62.      * @param where       The where clause to use in the select (optional) (default='')
  63.      * @param sort        The order-by clause to use in the select (optional) (default='')
  64.      * @param assocKey    The field to use as the associated array key (optional) (default='')
  65.      *
  66.      * @return The resulting folder object array
  67.      */
  68.     function getCategories ($where=''$sort=''$assocKey=''$enablePermissionFilter=true)
  69.     {
  70.         pnModDBInfoLoad ('Categories');
  71.         pnModLangLoad('Categories''common');
  72.         if (!$sort{
  73.             $pntables             pnDBGetTables();
  74.             $category_column      $pntables['categories_category_column'];
  75.             $sort                 "ORDER BY $category_column[sort_value]$category_column[name]";
  76.         }
  77.  
  78.         $permFilter array();
  79.         if ($enablePermissionFilter{
  80.             $permFilter[array('realm'            => 0,
  81.                                   'component_left'   => 'Categories',
  82.                                   'component_middle' => '',
  83.                                   'component_right'  => 'Category',
  84.                                   'instance_left'    => 'id',
  85.                                   'instance_middle'  => 'path',
  86.                                   'instance_right'   => 'ipath',
  87.                                   'level'            => ACCESS_OVERVIEW);
  88.         }
  89.  
  90.         $cats DBUtil::selectObjectArray ('categories_category'$where$sort-1-1$assocKey$permFilter);
  91.  
  92.         $arraykeys array_keys ($cats);
  93.         foreach ($arraykeys as $arraykey{
  94.             if ($cats[$arraykey]['display_name']{
  95.                 $cats[$arraykey]['display_name'DataUtil::formatForDisplayHTML(unserialize ($cats[$arraykey]['display_name']));
  96.             }
  97.  
  98.             if ($cats[$arraykey]['display_desc']{
  99.                 $cats[$arraykey]['display_desc'DataUtil::formatForDisplayHTML(unserialize ($cats[$arraykey]['display_desc']));
  100.             }
  101.  
  102.             if (!$enablePermissionFilter{
  103.                 $cats[$arraykey]['accessible'SecurityUtil::checkPermission('Categories::Category'$cats[$arraykey]['id'].':'.$cats[$arraykey]['path'].':'.$cats[$arraykey]['ipath']ACCESS_OVERVIEW);
  104.             }
  105.         }
  106.  
  107.         return $cats;
  108.     }
  109.  
  110.  
  111.     /**
  112.      * Return a folder object by it's path
  113.      *
  114.      * @param apath        The path to retrieve by (simple path or array of paths)
  115.      * @param field        The (path) field we search for (either path or ipath) (optional) (default='path')
  116.      *
  117.      * @return The resulting folder object
  118.      */
  119.     function getCategoryByPath ($apath$field='path')
  120.     {
  121.         pnModDBInfoLoad ('Categories');
  122.         $pntables             pnDBGetTables();
  123.         $category_column      $pntables['categories_category_column'];
  124.         if (!is_array($apath)) {
  125.             $where "$category_column[$field]='".DataUtil::formatForStore($apath)."'";
  126.         else {
  127.             $where array();
  128.             foreach ($apath as $path{
  129.                 $where["$category_column[$field]='".DataUtil::formatForStore($path)."'";
  130.             }
  131.             $where implode(' OR '$where);
  132.         }
  133.         $cats  CategoryUtil::getCategories ($where);
  134.  
  135.         if (isset($cats[0]&& is_array($cats[0])) {
  136.             return $cats[0];
  137.         }
  138.  
  139.         return $cats;
  140.     }
  141.  
  142.  
  143.     /**
  144.      * Return an array of categories by the registry info
  145.      *
  146.      * @param registry   The registered categories to retrieve
  147.      *
  148.      * @return The resulting folder object array
  149.      */
  150.     function getCategoriesByRegistry ($registry)
  151.     {
  152.         if (!$registry || !is_array($registry))
  153.             return false;
  154.  
  155.         pnModDBInfoLoad ('Categories');
  156.         $pntables             pnDBGetTables();
  157.         $category_column      $pntables['categories_category_column'];
  158.  
  159.         $where array();
  160.         foreach ($registry as $property => $catID{
  161.             $where["$category_column[id]='".DataUtil::formatForStore($catID)."'";
  162.         }
  163.         $where implode(' OR '$where);
  164.         $cats  CategoryUtil::getCategories ($where'''id');
  165.  
  166.         $result array();
  167.         if ($cats !== false{
  168.             foreach ($registry as $property => $catID{
  169.                 if (isset($cats[$catID])) {
  170.                     $result[$property$cats[$catID];
  171.                 }
  172.             }
  173.         }
  174.  
  175.         return $result;
  176.     }
  177.  
  178.  
  179.     /**
  180.      * Return the direct subcategories of the specified category
  181.      *
  182.      * @param id            The folder id to retrieve
  183.      * @param sort          The order-by clause (optional) (default='')
  184.      * @param relative      whether or not to also generate relative paths (optional) (default=false)
  185.      * @param all           whether or not to return all (or only active) categories (optional) (default=false)
  186.      * @param assocKey      The field to use as the associated array key (optional) (default='')
  187.      * @param attributes    The associative array of attribute field names to filter by (optional) (default=null)
  188.      *
  189.      * @return The resulting folder object
  190.      */
  191.     function getCategoriesByParentID ($id$sort=''$relative=false$all=false$assocKey=''$attributes=null)
  192.     {
  193.         if (!$id{
  194.             return false;
  195.         }
  196.  
  197.         pnModDBInfoLoad ('Categories');
  198.         $pntables             pnDBGetTables();
  199.         $category_column      $pntables['categories_category_column'];
  200.  
  201.         $id = (int)$id;
  202.         $where "$category_column[parent_id]='".DataUtil::formatForStore($id)."'";
  203.  
  204.         if (!$all{
  205.             $where .= " AND $category_column[status]='A'";
  206.         }
  207.  
  208.         //if ($attributes && is_array($attributes)) {
  209.         //    foreach ($attributes as $k=>$v) { 
  210.         //        $where .= " AND $category_column[$k]='$v' ";
  211.         //    }
  212.         //}
  213.  
  214.         $cats CategoryUtil::getCategories ($where$sort$assocKey);
  215.  
  216.         if ($cats && $relative{
  217.             $category CategoryUtil::getCategoryByID ($id);
  218.             $arraykeys array_keys($cats);
  219.             foreach ($arraykeys as $key{
  220.                 CategoryUtil::buildRelativePathsForCategory ($category$cats[$key]$includeRoot);
  221.             }
  222.         }
  223.  
  224.         return $cats;
  225.     }
  226.  
  227.  
  228.     /**
  229.      * Return all parent categories starting from id
  230.      *
  231.      * @param id         The (leaf) folder id to retrieve
  232.      * @param assocKey   whether or not to return an assocKeyiative array (optional) (default='id')
  233.      *
  234.      * @return The resulting folder object array
  235.      */
  236.     function getParentCategories ($id$assocKey='id')
  237.     {
  238.         if (!$id{
  239.             return false;
  240.         }
  241.  
  242.         pnModDBInfoLoad ('Categories');
  243.         $pntables             pnDBGetTables();
  244.         $category_column      $pntables['categories_category_column'];
  245.  
  246.         $cat  CategoryUtil::getCategoryByID ($id);
  247.         $cats array();
  248.  
  249.         if (!$cat || !$cat['parent_id']{
  250.             return $cats;
  251.         }
  252.  
  253.         do {
  254.             $cat CategoryUtil::getCategoryByID ($cat['parent_id']);
  255.             if ($cat{
  256.                 $cats[$cat[$assocKey]] $cat;
  257.             }
  258.         while ($cat && $cat['parent_id']);
  259.  
  260.         return $cats;
  261.     }
  262.  
  263.  
  264.     /**
  265.      * Return an array of category objects by path without the root category
  266.      *
  267.      * @param apath        The path to retrieve categories by
  268.      * @param sort         The sort field (optional) (default='')
  269.      * @param field        The the (path) field to use (path or ipath) (optional) (default='ipath')
  270.      * @param includeLeaf  whether or not to also return leaf nodes (optional) (default=true)
  271.      * @param all          whether or not to return all (or only active) categories (optional) (default=false)
  272.      * @param exclPath     The path to exclude from the retrieved categories (optional) (default='')
  273.      * @param assocKey     The field to use to build an associative key (optional) (default='')
  274.      * @param attributes   The associative array of attribute field names to filter by (optional) (default=null)
  275.      *
  276.      * @return The resulting folder object array
  277.      */
  278.     function getCategoriesByPath ($apath$sort=''$field='ipath'$includeLeaf=true,
  279.                                   $all=false$exclPath=''$assocKey=''$attributes=null)
  280.     {
  281.         pnModDBInfoLoad ('Categories');
  282.         $pntables             pnDBGetTables();
  283.         $category_column      $pntables['categories_category_column'];
  284.  
  285.         $where "$category_column[$field] = '".DataUtil::formatForStore($apath)."' OR $category_column[$field] LIKE '".DataUtil::formatForStore($apath)."/%'";
  286.         if ($exclPath{
  287.             $where .= " AND $category_column[$field] NOT LIKE '".DataUtil::formatForStore($exclPath)."%'";
  288.         }
  289.  
  290.         if (!$includeLeaf{
  291.             $where .= " AND $category_column[is_leaf]=0";
  292.         }
  293.  
  294.         if (!$all{
  295.             $where .= " AND $category_column[status]='A'";
  296.         }
  297.  
  298.         //if ($attributes && is_array($attributes)) {
  299.         //    foreach ($attributes as $k=>$v) { 
  300.         //        $where .= " AND $category_column[$k]='$v' ";
  301.         //    }
  302.         //}
  303.  
  304.         if (!$sort{
  305.             $sort "ORDER BY $category_column[sort_value]$category_column[path]";
  306.         }
  307.  
  308.         $cats  CategoryUtil::getCategories ($where$sort$assocKey);
  309.         return $cats;
  310.     }
  311.  
  312.  
  313.     /**
  314.      * Return an array of Subcategories for the specified folder
  315.      *
  316.      * @param cid          The root-category category-id
  317.      * @param recurse      whether or not to generate a recursive subcategory result set (optional) (default=true)
  318.      * @param relative     whether or not to generate relative path indexes (optional) (default=true)
  319.      * @param includeRoot  whether or not to include the root folder in the result set (optional) (default=false)
  320.      * @param includeLeaf  whether or not to also return leaf nodes (optional) (default=true)
  321.      * @param all          whether or not to include all (or only active) folders in the result set (optional) (default=false)
  322.      * @param excludeCid   CategoryID (root folder) to exclude from the result set (optional) (default='')
  323.      * @param assocKey     The field to use as the associated array key (optional) (default='')
  324.      * @param attributes   The associative array of attribute field names to filter by (optional) (default=null)
  325.      *
  326.      * @return The resulting folder object array
  327.      */
  328.     function getSubCategories ($cid$recurse=true$relative=true$includeRoot=false,
  329.                                $includeLeaf=true$all=false$excludeCid=''$assocKey=''$attributes=null)
  330.     {
  331.         if (!$cid{
  332.             return false;
  333.         }
  334.  
  335.         $rootCat CategoryUtil::getCategoryByID ($cid);
  336.         if (!$rootCat{
  337.             return false;
  338.         }
  339.  
  340.         static $catPathCache array();
  341.         $cacheKey $cid '_' . (int)$recurse '_' . (int)$relative '_' . (int)$includeRoot '_' . (int)$includeLeaf '_' . (int)$all '_' $excludeCid '_' $assocKey;
  342.         if (isset($catPathCache[$cacheKey])) {
  343.             return $catPathCache[$cacheKey];
  344.         }
  345.  
  346.         $exclCat '';
  347.         if ($excludeCid{
  348.             $exclCat CategoryUtil::getCategoryByID ($excludeCid);
  349.         }
  350.  
  351.         $cats CategoryUtil::getSubCategoriesForCategory ($rootCat$recurse$relative$includeRoot$includeLeaf$all$exclCat$assocKey$attributes);
  352.         $catPathCache[$cacheKey$cats;
  353.         return $cats;
  354.     }
  355.  
  356.  
  357.     /**
  358.      * Return an array of Subcategories for the specified folder
  359.      *
  360.      * @param apath        The path to get categories by
  361.      * @param field        The (path) field we match by (either path or ipath) (optional) (default='ipath')
  362.      * @param recurse      whether or not to generate a recursive subcategory result set (optional) (default=true)
  363.      * @param relative     whether or not to generate relative path indexes (optional) (default=true)
  364.      * @param includeRoot  whether or not to include the root folder in the result set (optional) (default=false)
  365.      * @param includeLeaf  whether or not to also return leaf nodes (optional) (default=true)
  366.      * @param all          whether or not to include all (or only active) folders in the result set (optional) (default=false)
  367.      * @param excludeCid   CategoryID (root folder) to exclude from the result set (optional) (default='')
  368.      * @param assocKey     The field to use as the associated array key (optional) (default='')
  369.      * @param attributes   The associative array of attribute field names to filter by (optional) (default=null)
  370.      *
  371.      * @return The resulting folder object array
  372.      */
  373.     function getSubCategoriesByPath ($apath$field='ipath'$recurse=true$relative=true,
  374.                                      $includeRoot=false$includeLeaf=true$all=false$excludeCid=''$assocKey=''$attributes=null)
  375.     {
  376.         if (!$apath{
  377.             return false;
  378.         }
  379.  
  380.         $rootCat CategoryUtil::getCategoryByPath ($apath$field);
  381.         if (!$rootCat{
  382.             return false;
  383.         }
  384.  
  385.         static $catPathCache array();
  386.         $cacheKey $apath '_' $field '_' . (int)$recurse '_' . (int)$relative '_' . (int)$includeRoot '_' . (int)$includeLeaf '_' . (int)$all '_' $excludeCid '_' $assocKey;
  387.         if (isset($catPathCache[$cacheKey])) {
  388.             return $catPathCache[$cacheKey];
  389.         }
  390.  
  391.         $exclCat '';
  392.         if ($excludeCid{
  393.             $exclCat CategoryUtil::getCategoryByID ($excludeCid);
  394.         }
  395.  
  396.         $cats CategoryUtil::getSubCategoriesForCategory ($rootCat$recurse$relative,
  397.                                                            $includeRoot$includeLeaf$all$exclCat$assocKey$attributes);
  398.         $catPathCache[$cacheKey$cats;
  399.         return $cats;
  400.     }
  401.  
  402.  
  403.     /**
  404.      * Return an array of Subcategories by for the given category
  405.      *
  406.      * @param category     The root category to retrieve
  407.      * @param recurse      whether or not to recruse (if false, only direct subfolders are retrieved) (optional) (default=true)
  408.      * @param relative     whether or not to also generate relative paths (optional) (default=true)
  409.      * @param includeRoot  whether or not to include the root folder in the result set (optional) (default=false)
  410.      * @param includeLeaf  whether or not to also return leaf nodes (optional) (default=true)
  411.      * @param all          whether or not to return all (or only active) categories (optional) (default=false)
  412.      * @param excludeCat   The root category of the hierarchy to exclude from the result set (optional) (default='')
  413.      * @param assocKey     The field to use as the associated array key (optional) (default='')
  414.      * @param attributes   The associative array of attribute field names to filter by (optional) (default=null)
  415.      * @param sortField    The field to sort the resulting category array by (optional) (default=null)
  416.      *
  417.      * @return The resulting folder object array
  418.      */
  419.     function getSubCategoriesForCategory ($category$recurse=true$relative=true$includeRoot=false,
  420.                                           $includeLeaf=true$all=false$excludeCat=null$assocKey=''$attributes=null$sortField=null)
  421.     {
  422.         if (!$category{
  423.             return false;
  424.         }
  425.  
  426.         $cats array();
  427.         if ($recurse{
  428.             $ipath $category['ipath'];
  429.             $ipathExcl ($excludeCat $excludeCat['ipath''');
  430.             $cats CategoryUtil::getCategoriesByPath ($ipath'path''ipath'$includeLeaf$all$ipathExcl$assocKey$attributes);
  431.         else {
  432.             $cats CategoryUtil::getCategoriesByParentID ($category['id']''$relative$all$assocKey$attributes);
  433.             array_unshift ($cats$category);
  434.         }
  435.  
  436.         // since array_shift() resets numeric array indexes, we remove the leading element like this
  437.         if (!$includeRoot{
  438.             list($k$veach($cats);
  439.             unset($cats[$k]);
  440.         }
  441.  
  442.         if ($cats && $relative{
  443.             $arraykeys array_keys($cats);
  444.             foreach ($arraykeys as $key{
  445.                 CategoryUtil::buildRelativePathsForCategory ($category$cats[$key]$includeRoot);
  446.             }
  447.         }
  448.  
  449.         if ($sortField{
  450.             global $_catSortField;
  451.             $_catSortField $sortField;
  452.             usort ($cats'_sortCategories');
  453.         }
  454.  
  455.         return $cats;
  456.     }
  457.  
  458.  
  459.     /**
  460.      * Delete a category by it's ID
  461.      *
  462.      * @param cid        The categoryID to delete
  463.      *
  464.      * @return The DB result set
  465.      */
  466.     function deleteCategoryByID ($cid)
  467.     {
  468.         pnModDBInfoLoad ('Categories');
  469.         $pntables             pnDBGetTables();
  470.         $category_table       $pntables['categories_category'];
  471.         $category_column      $pntables['categories_category_column'];
  472.  
  473.         $cid = (int)$cid;
  474.         $sql "DELETE FROM $category_table WHERE $category_column[id] = '".DataUtil::formatForStore($cid)."'";
  475.         $res DBUtil::executeSQL ($sql);
  476.  
  477.         return $res;
  478.     }
  479.  
  480.  
  481.     /**
  482.      * Delete categories by Path
  483.      *
  484.      * @param apath        The path we wish to delete
  485.      * @param field        The (path) field we delete from (either path or ipath) (optional) (default='ipath')
  486.      *
  487.      * @return The DB result set
  488.      */
  489.     function deleteCategoriesByPath ($apath$field='ipath')
  490.     {
  491.         if (!$apath{
  492.             return false;
  493.         }
  494.  
  495.         pnModDBInfoLoad ('Categories');
  496.         $pntables             pnDBGetTables();
  497.         $category_table       $pntables['categories_category'];
  498.         $category_column      $pntables['categories_category_column'];
  499.  
  500.         $sql "DELETE FROM $category_table WHERE $category_column[$field] LIKE '".DataUtil::formatForStore($apath)."%'";
  501.         $res DBUtil::executeSQL ($sql);
  502.  
  503.         return $res;
  504.     }
  505.  
  506.  
  507.     /**
  508.      * Move categories by ID (recursive move)
  509.      *
  510.      * @param cid           The categoryID we wish to move
  511.      * @param newparent_id  The categoryID of the new parent category
  512.      *
  513.      * @return true or false
  514.      */
  515.     function moveCategoriesByID ($cid$newparent_id)
  516.     {
  517.         if (!$cid{
  518.             return false;
  519.         }
  520.  
  521.         $cat CategoryUtil::getCategoryByID ($cid);
  522.  
  523.         if (!$cat{
  524.             $false false;
  525.             return $false;
  526.         }
  527.  
  528.         return CategoryUtil::moveCategoriesByPath ($cat['ipath']$newparent_id);
  529.     }
  530.  
  531.  
  532.     /**
  533.      * Move SubCategories by Path (recurisve move)
  534.      *
  535.      * @param apath         The path to move from
  536.      * @param newparent_id  The categoryID of the new parent category
  537.      * @param field         The field to use for the path reference (optional) (default='ipath')
  538.      *
  539.      * @return true or false
  540.      */
  541.     function moveSubCategoriesByPath ($apath$newparent_id$field='ipath')
  542.     {
  543.         return CategoryUtil::moveCategoriesByPath ($apath$newparent_id$fieldfalse);
  544.     }
  545.  
  546.  
  547.     /**
  548.      * Move Categories by Path (recursive move)
  549.      *
  550.      * @param apath         The path to move from
  551.      * @param newparent_id  The categoryID of the new parent category
  552.      * @param field         The field to use for the path reference (optional) (default='ipath')
  553.      * @param includeRoot   whether or not to also move the root folder  (optional) (default=true)
  554.      *
  555.      * @return true or false
  556.      */
  557.     function moveCategoriesByPath ($apath$newparent_id$field='ipath'$includeRoot=true)
  558.     {
  559.         if (!$apath{
  560.             return false;
  561.         }
  562.  
  563.         $cats CategoryUtil::getCategoriesByPath ($apath'path'$field);
  564.         $newParent CategoryUtil::getCategoryByID ($newparent_id);
  565.  
  566.         if (!$newParent || !$cats{
  567.             $false false;
  568.             return $false;
  569.         }
  570.  
  571.         // since array_shift() resets numeric array indexes, we remove the leading element like this
  572.         if (!$includeRoot{
  573.             list($k$veach($cats);
  574.             unset($cats[$k]);
  575.         }
  576.  
  577.         $newParentIPath  $newParent['ipath''/';
  578.         $newParentPath   $newParent['path''/';
  579.  
  580.         $oldParent       CategoryUtil::getCategoryByID ($cats[0]['parent_id']);
  581.         $oldParentIPath  $oldParent['ipath''/';
  582.         $oldParentPath   $oldParent['path''/';
  583.  
  584.         pnModDBInfoLoad ('Categories');
  585.         $pntables             pnDBGetTables();
  586.         $category_table       $pntables['categories_category'];
  587.         $category_column      $pntables['categories_category_column'];
  588.  
  589.         $pathField $category_column[$field];
  590.         $fpath     $category_column['path'];
  591.         $fipath    $category_column['ipath'];
  592.  
  593.         $sql "UPDATE $category_table SET
  594.                 $fpath = REPLACE($fpath, '$oldParentPath', '$newParentPath'),
  595.                 $fipath = REPLACE($fipath, '$oldParentIPath', '$newParentIPath')
  596.                 WHERE $pathField = '".DataUtil::formatForStore($apath)."' OR $pathField LIKE '".DataUtil::formatForStore($apath)."/%'";
  597.         DBUtil::executeSQL ($sql);
  598.  
  599.         $pid $cats[0]['id'];
  600.         $sql "UPDATE $category_table SET $category_column[parent_id] = '".DataUtil::formatForStore($newparent_id).
  601.                 "' WHERE $category_column[id] = '".DataUtil::formatForStore($pid)."'";
  602.         DBUtil::executeSQL ($sql);
  603.  
  604.         return true;
  605.     }
  606.  
  607.  
  608.     /**
  609.      * Copy categories by ID (recursive copy)
  610.      *
  611.      * @param cid           The categoryID we wish to copy
  612.      * @param newparent_id  The categoryID of the new parent category
  613.      *
  614.      * @return true or false
  615.      */
  616.     function copyCategoriesByID ($cid$newparent_id)
  617.     {
  618.         $cat CategoryUtil::getCategoryByID ($cid);
  619.  
  620.         if (!$cat{
  621.             return false;
  622.         }
  623.  
  624.         return CategoryUtil::copyCategoriesByPath ($cat['ipath']$newparent_id);
  625.     }
  626.  
  627.  
  628.     /**
  629.      * Copy SubCategories by Path (recurisve copy)
  630.      *
  631.      * @param apath         The path to copy from
  632.      * @param newparent_id  The categoryID of the new parent category
  633.      * @param field         The field to use for the path reference (optional) (default='ipath')
  634.      *
  635.      * @return true or false
  636.      */
  637.     function copySubCategoriesByPath ($apath$newparent_id$field='ipath')
  638.     {
  639.         return CategoryUtil::copyCategoriesByPath ($apath$newparent_id$fieldfalse);
  640.     }
  641.  
  642.  
  643.     /**
  644.      * Copy Categories by Path (recurisve copy)
  645.      *
  646.      * @param apath         The path to copy from
  647.      * @param newparent_id  The categoryID of the new parent category
  648.      * @param field         The field to use for the path reference (optional) (default='ipath')
  649.      * @param includeRoot   whether or not to also move the root folder (optional) (default=true)
  650.      *
  651.      * @return true or false
  652.      */
  653.     function copyCategoriesByPath ($apath$newparent_id$field='ipath'$includeRoot=true)
  654.     {
  655.         if (!$apath{
  656.             return false;
  657.         }
  658.  
  659.         $cats CategoryUtil::getSubCategoriesByPath ($apath'ipath'$fieldtruetrue);
  660.         $newParent CategoryUtil::getCategoryByID ($newparent_id);
  661.  
  662.         if (!$newParent || !$cats{
  663.             return false;
  664.         }
  665.  
  666.         $oldToNewID array();
  667.         $oldToNewID[$cats[0]['parent_id']] $newParent['id'];
  668.  
  669.         // since array_shift() resets numeric array indexes, we remove the leading element like this
  670.         if (!$includeRoot{
  671.             list($k$veach($cats);
  672.             unset($cats[$k]);
  673.         }
  674.  
  675.         $ak array_keys ($cats);
  676.         foreach ($ak as $v{
  677.             $cat $cats[$v];
  678.  
  679.             $oldID $cat['id'];
  680.             $cat['id']        '';
  681.             $cat['parent_id'$oldToNewID[$cat['parent_id']];
  682.             $cat['path']      $newParent['path''/' $cat['path_relative'];
  683.  
  684.             $pnCat new pnCategory ($cat);
  685.             $pnCat->insert ();
  686.             $oldToNewID[$oldID$pnCat->_objData['id'];
  687.         }
  688.  
  689.         // rebuild iPath since now we have all new PathIDs
  690.         CategoryUtil::rebuildPaths ('ipath''id');
  691.         return true;
  692.     }
  693.  
  694.  
  695.     /**
  696.      * Check whether $cid is a direct subcategory of $root_id
  697.      *
  698.      * @param root_id    The root/parent ID
  699.      * @param cid        The categoryID we wish to check for subcategory-ness.
  700.      *
  701.      * @return true or false
  702.      */
  703.     function isDirectSubCategoryByID ($root_id$cid)
  704.     {
  705.         if (!$cid{
  706.             return false;
  707.         }
  708.  
  709.         $cat CategoryUtil::getCategoryByID ($cid);
  710.  
  711.         if (isset($cat['parent_id'])) {
  712.             return $cat['parent_id'== $root_id;
  713.         }
  714.  
  715.         return false;
  716.     }
  717.  
  718.  
  719.     /**
  720.      * Check whether $cid is a direct subcategory of $root_id
  721.      *
  722.      * @param rootCat    The root/parent category
  723.      * @param cat        The category we wish to check for subcategory-ness.
  724.      *
  725.      * @return true or false
  726.      */
  727.     function isDirectSubCategory ($rootCat$cat)
  728.     {
  729.         return $cat['parent_id'== $rootCat['id'];
  730.     }
  731.  
  732.  
  733.     /**
  734.      * Check whether $cid is a subcategory of $root_id
  735.      *
  736.      * @param root_id    The ID of the root category we wish to check from
  737.      * @param cid        The category-id we wish to check for subcategory-ness.
  738.      *
  739.      * @return true or false
  740.      */
  741.     function isSubCategoryByID ($root_id$cid)
  742.     {
  743.         if (!$root_id || !$cid{
  744.             return false;
  745.         }
  746.  
  747.         $rootCat CategoryUtil::getCategoryByID ($root_id);
  748.         $cat     CategoryUtil::getCategoryByID ($cid);
  749.  
  750.         if (!$rootCat || !$cat {
  751.             return false;
  752.         }
  753.  
  754.         return CategoryUtil::isSubCategory ($rootCat$cat);
  755.     }
  756.  
  757.  
  758.     /**
  759.      * Check whether $cat is a subcategory of $rootCat
  760.      *
  761.      * @param rootCat    The root/parent category
  762.      * @param cat        The category we wish to check for subcategory-ness.
  763.      *
  764.      * @return true or false
  765.      */
  766.     function isSubCategory ($rootCat$cat)
  767.     {
  768.         $rPath $rootCat['ipath''/';
  769.         $cPath $cat['ipath'];
  770.  
  771.         return strpos($cPath$rPath=== 0;
  772.     }
  773.  
  774.  
  775.     /**
  776.      * Check whether the category $cid has subcategories (optional checks for leafe )
  777.      *
  778.      * @param cid        The parent category
  779.      * @param countOnly  whether or not to explicitly check for leaf nodes in the subcategories
  780.      * @param all        whether or not to return all (or only active) subcategories
  781.      *
  782.      * @return true or false
  783.      */
  784.     function haveDirectSubcategories ($cid$countOnly=false$all=true)
  785.     {
  786.         if (!$cid{
  787.             return false;
  788.         }
  789.  
  790.         $cats CategoryUtil::getCategoriesByParentID ($cid''false$all);
  791.  
  792.         if ($countOnly{
  793.             return (boolean)count($cats);
  794.         }
  795.  
  796.         foreach ($cats as $cat{
  797.             if ($cat['is_leaf']{
  798.                 return true;
  799.             }
  800.         }
  801.  
  802.         return false;
  803.     }
  804.  
  805.  
  806.     /**
  807.      * Get the java-script for the tree menu
  808.      *
  809.      * @param cats             The categories array to represent in the tree
  810.      * @param doReplaceRootCat Whether or not to replace the root category with a localized string (optional) (default=true)
  811.      *
  812.      * @return generated tree JS text
  813.      */
  814.     function getCategoryTreeJS ($cats$doReplaceRootCat=true)
  815.     {
  816.         $menuString CategoryUtil::getCategoryTreeStructure ($cats);
  817.  
  818.         $treemid new TreeMenu();
  819.         $treemid->setMenuStructureString($menuString);
  820.         $treemid->parseStructureForMenu('treemenu1');
  821.         $treemid->setLibjsdir("javascript/phplayersmenu/libjs");
  822.         $treemid->setImgdir("javascript/phplayersmenu/images");
  823.         $treemid->setImgwww("javascript/phplayersmenu/images");
  824.         $treemenu1 $treemid->newTreeMenu('treemenu1');
  825.  
  826.         if ($doReplaceRootCat{
  827.             $treemenu1 str_replace('__SYSTEM__'_CATEGORIES_ROOTCAT$treemenu1);
  828.         }
  829.  
  830.         return $treemenu1;
  831.     }
  832.  
  833.  
  834.     /**
  835.      * Return an array of folders the user has at least access/view rights to.
  836.      *
  837.      * @param cats       The username we wish to get the folder list for
  838.      *
  839.      * @return The resulting folder path array
  840.      */
  841.     function getCategoryTreeStructure ($cats)
  842.     {
  843.         $menuString '';
  844.         $params array();
  845.         $params['mode''edit';
  846.  
  847.         Loader::loadClass ('StringUtil');
  848.  
  849.         // use foreach as folders can come back with folderIDs as keys
  850.         foreach ($cats as $k => $v)
  851.         {
  852.             $path   $v['path'];
  853.             $depth  StringUtil::countInstances ($path'/');
  854.  
  855.             // account for the fact that a single slash is a valid root
  856.             // path but subfolders only have a single slash as well
  857.             if (strlen($path1{
  858.                 $depth++;
  859.             }
  860.  
  861.             $ds '';
  862.             for ($j=0$j<$depth$j++{
  863.                 $ds .= '.';
  864.             }
  865.  
  866.             $parent $v['id'];
  867.  
  868.             $params['cid'$v['id'];
  869.             $url DataUtil::formatForDisplay(pnModURL ('Categories''admin''edit'$params));
  870.  
  871.             if (FormUtil::getPassedValue('type'== 'admin'{
  872.                 $url .= '#top';
  873.             }
  874.  
  875.             $name DataUtil::formatForDisplay($v['name']);
  876.             $menuLine "$ds|$name|$url||||\n";
  877.  
  878.             $menuString .= $menuLine;
  879.         }
  880.  
  881.         //print (nl2br ($menuString));
  882.         return $menuString;
  883.     }
  884.  
  885.  
  886.     /**
  887.      * Return the HTML selector code for the given category hierarchy
  888.      *
  889.      * @param cats              The category hierarchy to generate a HTML selector for
  890.      * @param field             The field value to return (optional) (default='id')
  891.      * @param selected          The selected category (optional) (default=0)
  892.      * @param name              The name of the selector field to generate (optional) (default='category[parent_id]')
  893.      * @param defaultValue      The default value to present to the user (optional) (default=0)
  894.      * @param defaultText       The default text to present to the user (optional) (default='')
  895.      * @param allValue          The value to assign to the "all" option (optional) (default=0)
  896.      * @param allText           The text to assign to the "all" option (optional) (default='')
  897.      * @param submit            whether or not to submit the form upon change (optional) (default=false)
  898.      * @param displayPath       If false, the path is simulated, if true, the full path is shown (optional) (default=false)
  899.      * @param doReplaceRootCat  Whether or not to replace the root category with a localized string (optional) (default=true)
  900.      * @param multipleSize      If > 1, a multiple selector box is built, otherwise a normal/single selector box is build (optional) (default=1)
  901.      *
  902.      * @return The HTML selector code for the given category hierarchy
  903.      */
  904.     function getSelector_Categories ($cats$field='id'$selectedValue='0'$name='category[parent_id]'$defaultValue=0$defaultText=''
  905.                                      $allValue=0$allText=''$submit=false$displayPath=false$doReplaceRootCat=true$multipleSize=1
  906.                                      $fieldIsAttribute=false)
  907.     {
  908.         $line '---------------------------------------------------------------------';
  909.  
  910.         if ($multipleSize && strpos($name,'[]')===false{
  911.             $name .= '[]';
  912.         }
  913.         if (!is_array($selectedValue)) {
  914.             $selectedValue array($selectedValue);
  915.         }
  916.  
  917.         $id strtr ($name'[]''__');
  918.         $multiple     $multipleSize ' multiple="multiple"' '';
  919.         $multipleSize $multipleSize " size=\"$multipleSize\"'';
  920.         $submit       $submit ' onchange="this.form.submit();"' '';
  921.         $lang pnUserGetLang();
  922.  
  923.         $html "<select name=\"$name\" id=\"$id\"{$multipleSize}{$multiple}{$submit}>";
  924.  
  925.         if (!empty($defaultText)) {
  926.             $sel (in_array((string)$defaultValue$selectedValue' selected="selected"' '');
  927.             $html .= "<option value=\"$defaultValue\"$sel>$defaultText</option>";
  928.         }
  929.  
  930.         if ($allText{
  931.             $sel (in_array((string)$allValue$selectedValue' selected="selected"' '');
  932.             $html .= "<option value=\"$allValue\"$sel>$allText</option>";
  933.         }
  934.  
  935.         Loader::loadClass ('StringUtil');
  936.         $count 0;
  937.         if (!isset($cats|| empty($cats)) {
  938.             $cats array();
  939.         }
  940.  
  941.         foreach ($cats as $cat)
  942.         {
  943.             if ($fieldIsAttribute{
  944.                 $sel (in_array((string)$cat['__ATTRIBUTES__'][$field]$selectedValue' selected="selected"' '');
  945.             else {
  946.                 $sel (in_array((string)$cat[$field]$selectedValue' selected="selected"' '');
  947.             }
  948.             if ($displayPath{
  949.                 if ($fieldIsAttribute{
  950.                     $v $cat['__ATTRIBUTES__'][$field];
  951.                     $html .= "<option value=\"$v\"$sel>$cat[path]</option>";
  952.                 else {
  953.                     $html .= "<option value=\"$cat[$field]\"$sel>$cat[path]</option>";
  954.                 }
  955.             else {
  956.                 $cslash StringUtil::countInstances (isset($cat['ipath_relative']$cat['ipath_relative'$cat['ipath']'/');
  957.                 $indent '';
  958.                 if ($cslash 0)
  959.                     $indent substr ($line0$cslash*2);
  960.  
  961.                 $indent '|' $indent;
  962.                 //if ($count) {
  963.                 //    $indent = '|' . $indent;
  964.                 //} else {
  965.                 //    $indent = '&nbsp;' . $indent;
  966.                 //}
  967.  
  968.                 if (isset($cat['display_name'][$lang]&& !empty($cat['display_name'][$lang])) {
  969.                     $catName $cat['display_name'][$lang];
  970.                 else {
  971.                     $catName $cat['name'];
  972.                 }
  973.  
  974.                 if ($fieldIsAttribute{
  975.                     $v $cat['__ATTRIBUTES__'][$field];
  976.                     $html .= "<option value=\"$v\"$sel>$indent DataUtil::formatForDisplayHtml($catName"</option>";
  977.                 else {
  978.                     $html .= "<option value=\"$cat[$field]\"$sel>$indent DataUtil::formatForDisplayHtml($catName"</option>";
  979.                 }
  980.             }
  981.             $count++;
  982.         }
  983.  
  984.         $html .= '</select>';
  985.  
  986.         if ($doReplaceRootCat{
  987.             $html str_replace('__SYSTEM__'_CATEGORIES_ROOTCAT$html);
  988.         }
  989.  
  990.         return $html;
  991.     }
  992.  
  993.  
  994.     /**
  995.      * Compare function for ML name field
  996.      *
  997.      * @param catA      1st category
  998.      * @param catB      2nd category
  999.      *
  1000.      * @return The resulting compare value
  1001.      */
  1002.     function cmpName($catA$catB)
  1003.     {
  1004.         $lang pnUserGetLang();
  1005.  
  1006.         if (!$catA['display_name'][$lang]{
  1007.             $catA['display_name'][$lang$catA['name'];
  1008.         }
  1009.  
  1010.         if ($catA['display_name'][$lang== $catB['display_name'][$lang]{
  1011.             return 0;
  1012.         }
  1013.  
  1014.         return strcmp($catA['display_name'][$lang]$catB['display_name'][$lang]);
  1015.     }
  1016.  
  1017.  
  1018.     /**
  1019.      * Compare function for ML description field
  1020.      *
  1021.      * @param catA      1st category
  1022.      * @param catB      2nd category
  1023.      *
  1024.      * @return The resulting compare value
  1025.      */
  1026.     function cmpDesc($catA$catB)
  1027.     {
  1028.         $lang pnUserGetLang();
  1029.  
  1030.         if ($catA['display_desc'][$lang== $catB['display_desc'][$lang]{
  1031.             return 0;
  1032.         }
  1033.  
  1034.         return strcmp($catA['display_desc'][$lang]$catB['display_desc'][$lang]);
  1035.     }
  1036.  
  1037.  
  1038.     /**
  1039.      * Utility function to sort a category array by the current locate of
  1040.      * either the ML name or description
  1041.      *
  1042.      * @param cats      The categories array
  1043.      * @param func      Which compare function to use (determines field to be used for comparison) (optional) (defaylt='cmpName')
  1044.      *
  1045.      * @return The resulting sorted category array (original array altered in place)
  1046.      */
  1047.     function sortByLocale (&$cats$func='cmpName')
  1048.     {
  1049.         usort($cats$func);
  1050.         return;
  1051.     }
  1052.  
  1053.  
  1054.     /**
  1055.      * Resequence the sort fields for the given category
  1056.      *
  1057.      * @param cats      The categories array
  1058.      * @param step      The counting step/interval (optional) (default=1)
  1059.      *
  1060.      * @return True if something was done, false if an emtpy $cats was passed in
  1061.      */
  1062.     function resequence ($cats$step=1)
  1063.     {
  1064.         if (!$cats{
  1065.             return false;
  1066.         }
  1067.  
  1068.         $c  0;
  1069.         $ak array_keys ($cats);
  1070.         foreach ($ak as $k{
  1071.             $cats[$k]['sort_value'= ++$c*$step;
  1072.         }
  1073.  
  1074.         return $cats;
  1075.     }
  1076.  
  1077.  
  1078.     /**
  1079.      * Given an array of categories (with the Property-Names being
  1080.      * the keys of the array) and it corresponding Parent categories (indexed
  1081.      * with the Property-Names too), return an (identically indexed) array
  1082.      * of category-paths based on the given field (name or id make sense)
  1083.      *
  1084.      * @param rootCatIDs    The root/parent categories ID
  1085.      * @param cats          The associative categories object array
  1086.      * @param includeRoot   If true, the root portion of the path is preserved
  1087.      *
  1088.      * @return The resulting folder path array (which is also altered in place)
  1089.      */
  1090.     function buildRelativePaths ($rootCatIDs&$cats$includeRoot=false)
  1091.     {
  1092.         if (!$rootCatIDs{
  1093.             return false;
  1094.         }
  1095.  
  1096.         foreach ($cats as $prop => $catID{
  1097.             if (!isset($rootCatIDs[$prop]|| !$rootCatIDs[$prop]{
  1098.                 continue;
  1099.             }
  1100.             $rootCat CategoryUtil::getCategoryByID ($rootCatIDs[$prop]);
  1101.             CategoryUtil::buildRelativePathsForCategory ($rootCat$cats[$prop]$includeRoot);
  1102.         }
  1103.  
  1104.         return
  1105.     }
  1106.  
  1107.  
  1108.     /**
  1109.      * Given a category with its parent category, return an (idenically indexed)
  1110.      * array of category-paths based on the given field (name or id make sense)
  1111.      *
  1112.      * @param rootCategory  The root/parent category
  1113.      * @param cat           The category to process
  1114.      * @param includeRoot   If true, the root portion of the path is preserved
  1115.      *
  1116.      * @return The resulting folder path array (which is also altered in place)
  1117.      */
  1118.     function buildRelativePathsForCategory ($rootCategory&$cat$includeRoot=false)
  1119.     {
  1120.         if (!$rootCategory{
  1121.             return false;
  1122.         }
  1123.  
  1124.         if (is_numeric($rootCategory)) {
  1125.             $rootCategory CategoryUtil::getCategoryByID($rootCategory);
  1126.         }
  1127.  
  1128.         // remove the Root Category name of the paths
  1129.         // because multilanguage names has different lengths
  1130.         $pos strpos($rootCategory['path']'/'1);
  1131.         $rootCategory['path'substr ($rootCategory['path']$pos);
  1132.  
  1133.         $pos strpos($cat['path']'/'1);
  1134.         $normalizedPath substr ($cat['path']$pos);
  1135.  
  1136.         // process the normalized paths
  1137.         $ppos strrpos($rootCategory['path']'/'1;
  1138.         $ipos strrpos($rootCategory['ipath']'/'1;
  1139.  
  1140.         $cat['path_relative']  substr ($normalizedPath$ppos);
  1141.         $cat['ipath_relative'substr ($cat['ipath']$ipos);
  1142.  
  1143.         if (!$includeRoot{
  1144.             $offSlashPath  strpos($cat['path_relative']'/');
  1145.             $offSlashIPath strpos($cat['ipath_relative']'/');
  1146.  
  1147.             if ($offSlashPath !== false{
  1148.                 $cat['path_relative']  substr ($cat['path_relative']$offSlashPath+1);
  1149.             }
  1150.             if ($offSlashIPath !== false{
  1151.                 $cat['ipath_relative']  substr ($cat['ipath_relative']$offSlashIPath+1);
  1152.             }
  1153.         }
  1154.  
  1155.         return $cat;
  1156.     }
  1157.  
  1158.  
  1159.     /**
  1160.      * Given an array of categories (with the category-IDs being
  1161.      * the keys of the array), return an (idenically indexed) array
  1162.      * of category-paths based on the given field (name or id make sense)
  1163.      *
  1164.      * @param cats      The associative categories object array
  1165.      * @param field     Which field to use the building the path (optional) (default='name')
  1166.      *
  1167.      * @return The resulting folder path array
  1168.      */
  1169.     function buildPaths ($cats$field='name')
  1170.     {
  1171.         if (!$cats{
  1172.             return false;
  1173.         }
  1174.  
  1175.         $paths array ();
  1176.  
  1177.         foreach ($cats as $k => $v{
  1178.             $path $v[$field];
  1179.             $pid  $v['parent_id'];
  1180.  
  1181.             while ($pid{
  1182.                 $pcat $cats[$pid];
  1183.                 $path "$pcat[$field]/$path";
  1184.                 $pid  $pcat['parent_id'];
  1185.             }
  1186.  
  1187.             $paths[$k"/$path";
  1188.         }
  1189.  
  1190.         return $paths;
  1191.     }
  1192.  
  1193.  
  1194.     /**
  1195.      * Rebuild the path field for all categories in the database
  1196.      * Note that the
  1197.      *
  1198.      * @param field         The field which we wish to populate (optional) (default='path')
  1199.      * @param sourceField   The field we use to build the path with (optional) (default='name')
  1200.      * @param leaf_id       The leaf-category category-id (ie: we'll rebuild the path of this category and all it's parents) (optional) (default=0)
  1201.      *
  1202.      *  Note that field and sourceField go in pairs (that is, if you want sensical results)!
  1203.      */
  1204.     function rebuildPaths ($field='path'$sourceField='name'$leaf_id=0)
  1205.     {
  1206.         pnModDBInfoLoad ('Categories');
  1207.  
  1208.         //if ($leaf_id)
  1209.         //$cats  = CategoryUtil::getParentCategories ($leaf_id, 'id');
  1210.         //else
  1211.         $cats  CategoryUtil::getCategories ('''''id');
  1212.         $paths CategoryUtil::buildPaths ($cats$sourceField);
  1213.  
  1214.         if ($cats && $paths{
  1215.             foreach ($cats as $k => $v{
  1216.                 if ($v[$field!= $paths[$k][$field]{
  1217.                     $v[$field$paths[$k];
  1218.                     // since we're not going through the object layer for this, we must manually serialize the locale fields
  1219.                     $v['display_name'serialize ($v['display_name']);
  1220.                     $v['display_desc'serialize ($v['display_desc']);
  1221.  
  1222.                     $res DBUtil::updateObject ($v'categories_category');
  1223.                 }
  1224.             }
  1225.         }
  1226.     }
  1227.  
  1228.  
  1229.     /**
  1230.      * Check for access to a certain set of categories
  1231.      *
  1232.      * For each category property in the list, check if we have access to that category in that property.
  1233.      * Check is done as "Categories:Property:$propertyName", "$cat[id]::"
  1234.      *
  1235.      * @param array $categories Array of category data (as returned from ObjectUtil::expandObjectWithCategories).
  1236.      * @param int   $permLevel Required permision level.
  1237.      *
  1238.      * @return bool True if access is allowed to at least one of the categories
  1239.      */
  1240.     function hasCategoryAccess($categories$module$permLevel=ACCESS_OVERVIEW)
  1241.     {
  1242.         // Always allow access to content with no categories associated
  1243.         if (count($categories== 0)
  1244.             return true;
  1245.  
  1246.         if (pnModGetVar('Categories''permissionsall'0))
  1247.         {
  1248.             // Access is required for all categories
  1249.             $ok true;
  1250.             foreach ($categories as $propertyName => $cat)
  1251.             {
  1252.                 $ok $ok && SecurityUtil::checkPermission"Categories:$propertyName:Category""$cat[id]:$cat[path]:$cat[ipath]"$permLevel);
  1253.             }
  1254.             return $ok;
  1255.         }
  1256.         else
  1257.         {
  1258.             // Access is required for at least one category
  1259.             foreach ($categories as $propertyName => $cat)
  1260.             {
  1261.                 if (SecurityUtil::checkPermission"Categories:$propertyName:Category""$cat[id]:$cat[path]:$cat[ipath]"$permLevel))
  1262.                     return true;
  1263.             }
  1264.             
  1265.             return false;
  1266.         }
  1267.     }
  1268. }
  1269.  
  1270. function _sortCategories ($a$b)
  1271. {
  1272.     global $_catSortField;
  1273.     return ($a[$_catSortField$b[$_catSortField]? -1;
  1274. }

Documentation generated on Fri, 18 Jul 2008 21:43:19 +0200 by phpDocumentor 1.4.1