Ignore:
Timestamp:
05/21/08 16:56:17 (16 years ago)
Author:
rafaelraymundo
Message:

Vide Trac - #197, #166, #198, #199

  1. Correção de problema na leitura do arquivo configuração.
  2. Permissão do click2dial também no contactcenter.
  3. Visualização de matricula, e nro celular no resultado da pesquisa(se estiverem populados)
  4. Adicionada a leitura a Catálogos Externos
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/contactcenter/inc/class.bo_ldap_manager.inc.php

    r23 r284  
    1212  \***************************************************************************/ 
    1313 
    14          
     14 
    1515        /* 
    1616                This class is responsible for the LDAP control/generic functions and for 
    1717                configuration gathering 
    1818        */ 
    19  
    20         class bo_ldap_manager  
     19        include_once('class.Thread.inc.php'); 
     20 
     21        class bo_ldap_manager 
    2122        { 
    22                  
     23 
    2324                var $srcs; 
    2425 
    25                  
    2626                function bo_ldap_manager () 
    2727                { 
     28 
    2829                        if (!($this->srcs = $GLOBALS['phpgw']->session->appsession('bo_ldap_manager.srcs','contactcenter'))) 
    2930                        { 
    3031                                $c = CreateObject('phpgwapi.config','contactcenter'); 
    3132                                $data = $c->read_repository(); 
    32                                  
     33 
    3334                                if (!$data or $data['cc_global_source0'] !== 'ldap') 
    3435                                { 
     
    3637                                        return; 
    3738                                } 
    38                                  
     39 
    3940                                $this->srcs = array( 
    4041                                        1 => array( 
     
    4748                                                'branch' => strtolower('ou') 
    4849                                        ) 
     50 
    4951                                ); 
    5052                        } 
     
    5456                { 
    5557                } 
    56          
     58 
    5759                /* 
    58                  
     60 
    5961                        @function get_all_ldap_sources 
    6062                        @abstract Returns an array containing all LDAP sources informations 
    6163                        @author Raphael Derosso Pereira 
    62                  
     64 
    6365                        @return array All LDAP information 
    6466                                $return = array( 
     
    6769                                                'dn'   => (string), 
    6870                                                'acc'  => (string), 
    69                                                 'pw'   => (string)    
     71                                                'pw'   => (string) 
    7072                                        ), 
    7173                                        ... 
    7274                                ) 
    73                                  
     75 
    7476                        TODO: Return multiple sources... 
    7577                */ 
     
    7880                        return $this->srcs; 
    7981                } 
    80                  
     82 
     83                /* 
     84                * @function get_external_ldap_sources 
     85                * @author Mário César Kolling <mario.kolling@serpro.gov.br> 
     86                * @abstract returns an array with the external sources 
     87                * @return (array) the external sources 
     88                */ 
     89 
     90                function get_external_ldap_sources() 
     91                { 
     92                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' ); 
     93                        //include('external_catalogs.inc.php' ); 
     94                        return $external_srcs; 
     95                } 
     96 
     97                /* 
     98                 * @function get_ldap_fields_association 
     99                 * @abstract get the fields associantion for ldap source 
     100                 * @return an array with attribute mappings 
     101                 */ 
    81102                function get_ldap_fields_association ( $id_source ) 
    82103                { 
    83                          
     104 
    84105                        $op_iop = array( 
    85106                                'contact.id_contact'               => array('dn'), 
     
    90111                                'contact.family_names'             => array('sn'), 
    91112                                'contact.names_ordered'            => array('cn'),//,'displayName'), 
     113 
    92114                                'contact.suffixes.suffix'          => false, 
    93115                                'contact.birthdate'                => false, 
     
    95117                                'contact.pgp_key'                  => false, 
    96118                                'contact.notes'                    => false, 
    97                                 'contact.mail_forwarding_address' => array('mailForwardingAddress'), 
    98                                 'contact.account_type' => array('phpgwAccountType'), 
     119                                'contact.mail_forwarding_address'  => array('mailForwardingAddress'), 
     120                                'contact.account_type'             => array('phpgwAccountType'), 
     121                                'contact.account_status'           => array('phpgwAccountStatus'), 
     122                                'contact.account_visible'          => array('phpgwAccountVisible'), 
     123                                'contact.object_class'             => array('objectClass'), 
    99124                                'contact.business_info.title'      => array('title'), 
    100                                 'contact.business_info.department' => array('ou'), 
     125                                'contact.business_info.department' => array('ou'), // Setor do empregado... 
     126                                'contact.business_info.empNumber'  => array('employeeNumber'), // Matricula do empregado 
    101127                                'contact.company.company_name'     => array('o'), 
    102128                                'contact.company.company_notes'    => array('businessCategory'), 
    103                                  
     129 
    104130                                'contact.contact_related.names_ordered' => 'contact.contact_related.typeof_relation.contact_relation_name', 
    105131                                'contact.contact_related.typeof_relation.contact_relation_name' =>  array( 
     
    107133                                        'secretary' => array('secretary') 
    108134                                ), 
    109                                  
     135 
    110136                                'contact.address.address1'         => 'contact.address.typeof_address.contact_address_type_name', 
    111137                                'contact.address.typeof_address.contact_address_type_name' => array( 
    112138                                        'home' => array('street', 'st', 'postalAddress', 'homePostalAddress'), 
    113139                                ), 
    114                                  
     140 
    115141                                'contact.address.postal_code'      => 'contact.address.typeof_address.contact_address_type_name', 
    116142                                'contact.address.typeof_address.contact_address_type_name' => array( 
    117143                                        'home' => array('PostalCode'), 
    118144                                ), 
    119                                  
     145 
    120146                                'contact.address.city.city_name'   => 'contact.address.typeof_address.contact_address_type_name', 
    121147                                'contact.address.typeof_address.contact_address_type_name' => array( 
    122148                                        'home' => array('l'), 
    123149                                ), 
    124                                  
     150 
    125151                                'contact.address.city.state.state_name'       => 'contact.address.typeof_address.contact_address_type_name', 
    126152                                'contact.address.typeof_address.contact_address_type_name' => array( 
    127153                                        'home' => false, 
    128154                                ), 
    129                                  
     155 
    130156                                'contact.address.city.country.id_country'     => 'contact.address.typeof_address.contact_address_type_name', 
    131157                                'contact.address.typeof_address.contact_address_type_name' => array( 
    132158                                        'home' => array('c') 
    133159                                ), 
    134                                  
     160 
    135161                                'contact.connection.connection_value'         => 'contact.connection.typeof_connection.contact_connection_type_name', 
    136162                                'contact.connection.typeof_connection.contact_connection_type_name' => array ( 
     
    143169                                ), 
    144170                        ); 
    145                          
     171 
    146172                        return $op_iop; 
     173 
     174                } 
     175 
     176                /* 
     177                 * @function get_external_ldap_fields_association 
     178                 * @author Mário César Kolling <mario.kolling@serpro.gov.br> 
     179                 * @abstract get the fields association for an external ldap_source 
     180                 * @return an array with attribute mappings 
     181                 */ 
     182                function get_external_ldap_fields_association ( $id_source ) 
     183                { 
     184                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' ); 
     185                        //include('external_catalogs.inc.php' ); 
     186                        return $external_mappings[$id_source]; 
     187                } 
     188 
     189                /* 
     190                 * @function test_connection 
     191                 * @author Mário César Kolling <mario.kolling@serpro.gov.br> 
     192                 * @abstract Test if we can bind to a ldap server in a reasonable time 
     193                 * @param (string) $host ldap server's hostname 
     194                 * @param (string) $account ldap bind dn 
     195                 * @param (string) $password a bind dn's password 
     196                 * @return (array) an array with the answer from the subprocess, null otherwise 
     197                 */ 
     198                function test_connection($host, $account, $password, $timeout = 5) 
     199                { 
     200                        //opens a subprocess for nonblocking bind 
     201                        $tsearch = Thread::Create('class.ldap_assync.inc.php', array('host'     => $host, 
     202                                                                                                                                'account'       => $account, 
     203                                                                                                                                'password'      => $password 
     204                                                                                                                                ) 
     205                        ); 
     206 
     207                        // It's problably more efficient to let method readResponse control the timeout through 
     208                        // stream_select native timeout. 
     209                        $response = NULL; 
     210                        for ($i = 0; $i < $timeout; $i++) 
     211                        { 
     212                                if ($tsearch->isActive()) 
     213                                { 
     214                                        sleep(1); 
     215                                        if (($response = $tsearch->readResponse()) !== NULL) 
     216                                        { 
     217                                                $tsearch->close(); 
     218                                                return $response; 
     219                                        } 
     220 
     221                                } 
     222                                else 
     223                                { 
     224                                        $response = $tsearch->readResponse(); 
     225                                        break; 
     226                                } 
     227                        } 
     228 
     229                        $tsearch->close(); 
     230                        return null; 
    147231                } 
    148232 
    149233                /*! 
    150                  
     234 
    151235                        @function get_ldap_tree 
    152236                        @abstract Returns the LDAP tree corresponding to the specified level 
    153237                        @author Raphael Derosso Pereira 
    154                          
     238 
    155239                        @param (integer) $id_source The ID of the LDAP source 
    156                          
     240 
    157241                        @param (string)  $context The context to be used as root branch 
    158                                  
     242 
    159243                        @param (boolean) $recursive Make it a recursive construction. 
    160244                                CAUTION! This is EXTREMELY SLOW on large LDAP databases, 
    161245                                specially when they're not indexed 
    162                 */               
    163                 function get_ldap_tree($id_source, $context = false, $recursive = false)  
     246                */ 
     247                function get_ldap_tree($id_source, $context = false, $recursive = false) 
    164248                { 
    165249                        if (!$this->srcs[$id_source]) 
     
    167251                                return null; 
    168252                        } 
    169                          
     253 
    170254                        $ldap = $GLOBALS['phpgw']->common->ldapConnect($this->srcs[$id_source]['host'], $this->srcs[$id_source]['acc'],$this->srcs[$id_source]['pw'], false); 
    171255                        if (!$ldap) 
     
    173257                                return false; 
    174258                        } 
    175                          
     259 
    176260                        if ($recursive) 
    177261                        { 
     
    181265                                return $tree; 
    182266                        } 
    183                          
    184                         return $this->get_ldap_tree_level($id_source, $ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch']); 
    185                 } 
    186  
     267 
     268                        return $this->get_ldap_tree_level($id_source, $ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch'], 0); 
     269                } 
     270 
     271                /*! 
     272 
     273                        @function get_external_ldap_tree 
     274                        @abstract Returns the LDAP external tree corresponding to the specified level 
     275                        @author Mário César Kolling <mario.kolling@serpro.gov.br> 
     276                        @param (integer) $id_source The ID of the external LDAP source 
     277                        @param (string)  $context The context to be used as root branch 
     278                        @param (boolean) $recursive Make it a recursive construction. 
     279                                CAUTION! This is EXTREMELY SLOW on large LDAP databases, 
     280                                specially when they're not indexed 
     281                */ 
     282                function get_external_ldap_tree($id_source, $context = false, $recursive = false) 
     283                { 
     284 
     285 
     286                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' ); 
     287                        //include('external_catalogs.inc.php' ); 
     288 
     289                        if (!$external_srcs[$id_source]) 
     290                        { 
     291                                return null; 
     292                        } 
     293 
     294                        // calls test_connection first. If succeeded continue, return error message otherwise. 
     295                        if (!($response = $this->test_connection($external_srcs[$id_source]['host'], $external_srcs[$id_source]['acc'], $external_srcs[$id_source]['pw'], 10))) 
     296                        { 
     297                                return array( 
     298                                        'msg'           =>      lang("Catalog %1 temporarily unavailable. Please try again later!", $external_srcs[$id_source]['name']), 
     299                                        'timeout'       =>      'true' 
     300                                ); 
     301                        } 
     302 
     303                        $ldap = $GLOBALS['phpgw']->common->ldapConnect($external_srcs[$id_source]['host'], $external_srcs[$id_source]['acc'],$external_srcs[$id_source]['pw'], false); 
     304                        if (!$ldap) 
     305                        { 
     306                                return false; 
     307                        } 
     308 
     309                        // Option recursive commented out 
     310                        /* 
     311                        if ($recursive) 
     312                        { 
     313                                $tree = $this->get_ldap_tree_recursive($ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch']); 
     314                                $tree['recursive'] = true; 
     315 
     316                                return $tree; 
     317                        } 
     318                        */ 
     319 
     320                        return $this->get_ldap_tree_level($id_source, $ldap, $context, $external_srcs[$id_source]['obj'],$external_srcs[$id_source]['branch'], 1); 
     321                } 
    187322 
    188323                /*! 
     
    201336                                return null; 
    202337                        } 
    203                          
     338 
    204339                        $count = ldap_count_entries($resource,$result_res); 
    205340                        if ( $count == 0 ) 
     
    218353                                } 
    219354                        } 
    220                          
     355 
    221356                        $entries = ldap_get_entries($resource, $result_res); 
    222                          
     357 
    223358                        for ($i = 0; $i < $entries['count']; $i++) 
    224359                        { 
    225360                                $subtree = $this->get_ldap_tree_recursive($resource, $entries[$i]['dn'], $objectClass); 
    226                                  
     361 
    227362                                $dn_parts=ldap_explode_dn($entries[$i]['dn'],1); 
    228                                  
    229                                 if ($subtree !== null and is_array($subtree))  
     363 
     364 
     365 
     366                                if ($subtree !== null and is_array($subtree)) 
    230367                                { 
    231368                                        $tree[$i]['name'] = $dn_parts[0]; 
     
    244381                                                'sub_branch' => false 
    245382                                        ); 
    246                                 }  
     383                                } 
    247384                        } 
    248385 
     
    256393                        } 
    257394                } 
    258                  
     395 
    259396                function get_ldap_referrals($ds, $dn, $filter) { 
    260                          
     397 
    261398                        ldap_set_option($ds, LDAP_OPT_REFERRALS, 0); 
    262399                        ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3); 
    263                          
     400 
    264401                        if ($ds) { 
    265402                            ldap_bind($ds); 
    266                                 $sr=ldap_list($ds,$dn, $filter);                     
     403                                $sr=ldap_list($ds,$dn, $filter); 
    267404                                $ref = ldap_first_reference($ds, $sr); 
    268405                                $array_referral = array(); 
    269406                                $idx = 0; 
    270                                  
     407 
    271408                                 while ($ref) { 
    272409                                        $array_referral[$idx++] = ldap_get_dn($ds, $ref); 
     
    275412                                return $array_referral; 
    276413                        } 
    277                         else  
     414                        else 
    278415                                return false; 
    279416                } 
    280417 
    281418                function get_ldap_sub_branches_referrals($ds, $dn, $filter) { 
    282                          
     419 
    283420                        $referral = $this -> get_ldap_referrals($ds, $dn, $filter); 
    284421                        $sub_branches = array(); 
    285                          
     422 
    286423                        for($i = 0; $i <count($referral); $i++) { 
    287424                                $dn = str_replace("??base","",preg_replace('!^(ldap://[^/]+)/(.*$)!', '\\2', $referral[$i])); 
    288                                 $dn = explode(",",$dn);                          
     425                                $dn = explode(",",$dn); 
    289426                                $dn = strtoupper(str_replace("ou=", "",$dn[0])); 
    290427                                $dn = str_replace("DC=", "",$dn); 
    291                                                                                                                                                                                  
     428 
    292429                                $sub_branch = array( 
    293430                                                                                        'name' => $dn, 
    294431                                                                'type' => 'unknown', 
    295432                                                                'value' => $referral[$i], 
    296                                                                 'sub_branch' => false            
    297                                                                                 );                                                                                                                       
    298                                 $sub_branches[$i] = $sub_branch;                         
     433                                                                'sub_branch' => false 
     434                                                                                ); 
     435                                $sub_branches[$i] = $sub_branch; 
    299436                        } 
    300437                        return $sub_branches; 
    301438                } 
    302                  
    303  
    304                 function get_ldap_tree_level($id_source, $resource, $context, $objectClass, $branch_dn) 
     439 
     440                function translate_accentuation($text) 
     441                { 
     442                        /* 
     443                         * Esta operação resolve o problema causado pela conversão de caracteres acentuados realizada 
     444                         * pela função ldap_explode_dn(). 
     445                         */ 
     446 
     447                        return utf8_decode(preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $text)); 
     448                } 
     449 
     450                function get_ldap_tree_level($id_source, $resource, $context, $objectClass, $branch_dn, $external = 0) 
    305451                { 
    306452                        if(strstr($context, "ldap://")){ 
    307                                 $refer_context = str_replace("??base","",preg_replace('!^(ldap://[^/]+)/(.*$)!', '\\2', $context));                                                                                              
    308                                 $host   = preg_replace('!^(ldap://[^/]+)/.*$!', '\\1', $context);                                                                                                                                
     453                                $refer_context = str_replace("??base","",preg_replace('!^(ldap://[^/]+)/(.*$)!', '\\2', $context)); 
     454                                $host   = preg_replace('!^(ldap://[^/]+)/.*$!', '\\1', $context); 
    309455                                $resource = ldap_connect($host); 
    310                                 ldap_bind($resource);    
    311                         } 
    312                         $dn_parts = ldap_explode_dn(($refer_context ? $refer_context : $context),1);                     
     456                                ldap_bind($resource); 
     457                        } 
     458 
     459                        /* 
     460                         * TODO: Search timeouts 
     461                         */ 
     462 
     463                        $dn_parts = ldap_explode_dn(($refer_context ? $refer_context : $context),1); 
    313464                        //$filter = '(!(objectClass='.$objectClass.'))'; 
    314465                        // Don't show OU's whith phpgwAccountVisible equal to '-1' 
    315                         $filter = '(&(!(objectClass='.$objectClass.')) (!(phpgwAccountVisible=-1)))'; 
    316                         $result_res = @ldap_list($resource,  ($refer_context ? $refer_context : $context), $filter); 
     466 
     467                        if ($external) 
     468                        { 
     469                                // external source: get all organizationalUnits 
     470                                $filter = '(objectClass=organizationalUnit)'; 
     471                        } 
     472                        else 
     473                        { 
     474                                // get any objectClass except the objectClass used for the source 
     475                                // and whose attribute phpgwAccountVisible value is different from -1 
     476                                $filter = '(&(!(objectClass='.$objectClass.')) (!(phpgwAccountVisible=-1)))'; 
     477                        } 
     478                        $result_res = @ldap_list($resource,  ($refer_context ? $refer_context : $context), $filter, array(), 0, 0); 
    317479                        @ldap_sort($resource, $result_res, 'ou'); 
    318480 
     481                        // Timeouts commented out 
     482                        /* 
    319483                        if ($result_res === false) 
    320484                        { 
     485                                if (ldap_errno($resource) === 3) 
     486                                { 
     487                                        return array('error_msg' => ldap_error($resource)); 
     488                                } 
    321489                                return null; 
    322490                        } 
     491                        */ 
    323492 
    324493                        $count = ldap_count_entries($resource,$result_res); 
     
    326495                        if ( $count == 0 ) 
    327496                        { 
    328                                 $filter = 'objectClass='.$objectClass; 
    329                                 $result_res2 = @ldap_list($resource, ($refer_context ? $refer_context : $context), $filter); 
     497                                $filter = '(objectClass='.$objectClass.')'; 
     498                                // Get only one attribute of the source's objectClass 
     499                                $result_res2 = @ldap_list($resource, ($refer_context ? $refer_context : $context), $filter, Array('cn'), 0, 1); 
    330500                                $entries_count = ldap_count_entries($resource, $result_res2); 
    331501 
     
    333503                                { 
    334504                                        return array( 
    335                                                 'name'       => $dn_parts[0], 
     505                                                'name'       => $this->translate_accentuation($dn_parts[0]), 
    336506                                                'type'       => 'catalog', 
    337507                                                'class'      => 'bo_global_ldap_catalog', 
    338                                                 'class_args' => array($id_source, $context), 
     508                                                // Pass the variable $external as a parameter to the constructor 
     509                                                'class_args' => array($id_source, $context, $external), 
    339510                                                'icon'       => 'globalcatalog-mini.png', 
    340511                                                'value'      => $context, 
     
    345516                                { 
    346517                                        return array( 
    347                                                 'name' => $dn_parts[0], 
     518                                                'name' => $this->translate_accentuation($dn_parts[0]), 
    348519                                                'type' => 'empty' 
    349520                                        ); 
     
    361532                                $dn_parts_full = ldap_explode_dn($dn,0); 
    362533                                list($group) = explode('=',$dn_parts_full[0]); 
    363                                  
    364                                 if ($group == $branch_dn or $branch_dn === 'all') 
     534 
     535                                //Faz a comparação do branch como case insensitive 
     536                                if (strtolower($group) == strtolower($branch_dn) or $branch_dn === 'all') 
    365537                                { 
    366538                                        $tree['sub_branch'][$i] = array( 
    367                                                 'name'  => $dn_parts_1[0], 
     539                                                'name'  => $this->translate_accentuation($dn_parts_1[0]), 
    368540                                                'type'  => 'unknown', 
    369541                                                'value' =>  ($refer_context ? $host."/" : "").$dn, 
    370                                                 'sub_branch' => false                                    
     542                                                'sub_branch' => false 
    371543                                        ); 
    372544                                        $sub_branch_found = true; 
     
    374546                                $i++; 
    375547                        } 
    376                          
     548 
    377549                        if(! $refer_context) { 
    378550                                $array_referral = $this -> get_ldap_sub_branches_referrals($resource, $context,'(objectClass=organizationalUnit)'); 
     
    383555 
    384556                        $filter = 'objectClass='.$objectClass; 
    385                         $result_res2 = @ldap_list($resource, ($refer_context ? $refer_context : $context), $filter); 
     557                        $result_res2 = @ldap_list($resource, ($refer_context ? $refer_context : $context), $filter, Array('cn'), 0, 1); 
    386558                        $entries_count = ldap_count_entries($resource, $result_res2); 
    387559 
    388560                        if ($result_res2 !== false && $entries_count > 0 && $sub_branch_found) 
    389561                        { 
    390                                 $tree['name']       = $dn_parts[0]; 
     562                                $tree['name']       = $this->translate_accentuation($dn_parts[0]); 
    391563                                $tree['type']       = 'mixed_catalog_group'; 
    392564                                $tree['class']      = 'bo_global_ldap_catalog'; 
    393                                 $tree['class_args'] = array($id_source,$context); 
     565                                // Pass the variable $external as a parameter to the constructor 
     566                                $tree['class_args'] = array($id_source,$context,$external); 
    394567                                $tree['icon']       = 'globalcatalog-mini.png'; 
    395568                                $tree['value']      = $context; 
     
    398571                        { 
    399572                                return array( 
    400                                         'name'       => $dn_parts[0], 
     573                                        'name'       => $this->translate_accentuation($dn_parts[0]), 
    401574                                        'type'       => 'catalog', 
    402575                                        'class'      => 'bo_global_ldap_catalog', 
    403                                         'class_args' => array($id_source, $context), 
     576                                        // Pass the variable $external as a parameter to the constructor 
     577                                        'class_args' => array($id_source, $context,$external), 
    404578                                        'icon'       => 'globalcatalog-mini.png', 
    405579                                        'value'      => $context, 
     
    409583                        else 
    410584                        { 
    411                                 $tree['name']       = $dn_parts[0]; 
     585                                $tree['name']       = $this->translate_accentuation($dn_parts[0]); 
    412586                                $tree['type']       = 'catalog_group'; 
    413587                                $tree['class']      = 'bo_catalog_group_catalog'; 
    414                                 $tree['class_args'] = array('$this', '$this->get_branch_by_level($this->catalog_level[0])'); 
     588                                // Pass the variable $external as a parameter to the constructor 
     589                                $tree['class_args'] = array('$this', '$this->get_branch_by_level($this->catalog_level[0])', $external); 
    415590                                $tree['value']      = $context; 
    416591                                $tree['ldap']       = array('id_source' => $id_source, 'context' => $context); 
    417592                        } 
    418                          
    419593                        usort($tree['sub_branch'], array($this, "compareTreeNodes")); 
    420594                        return $tree; 
     
    422596 
    423597                function compareTreeNodes($a, $b)       { 
    424                                                  
     598 
    425599                        return strnatcasecmp($a['name'], $b['name']); 
    426                 }        
     600                } 
    427601 
    428602        } 
Note: See TracChangeset for help on using the changeset viewer.