[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 require_once 'Horde/Form.php'; 4 5 /** 6 * The Config:: package provides a framework for managing the 7 * configuration of Horde applications, writing conf.php files from 8 * conf.xml source files, generating user interfaces, etc. 9 * 10 * The Horde_Config_Node DOM classes and subclasses 11 * (Horde_Config_Document, Horde_Config_Element) are simply massaged 12 * from code written by to emulate PHP4's DOMXML extension with PHP5's 13 * DOM support. Only changes are naming and syntactic sugar/Horde 14 * coding standards; all credit goes to Alexandre and the code is used 15 * with his permission. His original code can be found at: 16 * 17 * http://alexandre.alapetite.net/doc-alex/domxml-php4-php5/ 18 * 19 * $Horde: framework/Horde/Horde/Config.php,v 1.80.2.26 2006/06/01 23:44:32 jan Exp $ 20 * 21 * Copyright 2002-2006 Chuck Hagenbuch <chuck@horde.org> 22 * 23 * See the enclosed file COPYING for license information (LGPL). If you 24 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 25 * 26 * @author Chuck Hagenbuch <chuck@horde.org> 27 * @since Horde 3.0 28 * @package Horde_Framework 29 */ 30 class Horde_Config { 31 32 /** 33 * The name of the configured application. 34 * 35 * @var string 36 */ 37 var $_app; 38 39 /** 40 * The XML tree of the configuration file traversed to an 41 * associative array. 42 * 43 * @var array 44 */ 45 var $_xmlConfigTree = null; 46 47 /** 48 * The content of the generated configuration file. 49 * 50 * @var string 51 */ 52 var $_phpConfig; 53 54 /** 55 * The content of the old configuration file. 56 * 57 * @var string 58 */ 59 var $_oldConfig; 60 61 /** 62 * The manual configuration in front of the generated configuration. 63 * 64 * @var string 65 */ 66 var $_preConfig; 67 68 /** 69 * The manual configuration after the generated configuration. 70 * 71 * @var string 72 */ 73 var $_postConfig; 74 75 /** 76 * The current $conf array of the configured application. 77 * 78 * @var array 79 */ 80 var $_currentConfig = array(); 81 82 /** 83 * The CVS version tag of the conf.xml file which will be copied into the 84 * conf.php file. 85 * 86 * @var string 87 */ 88 var $_versionTag = ''; 89 90 /** 91 * The line marking the begin of the generated configuration. 92 * 93 * @var string 94 */ 95 var $_configBegin = "/* CONFIG START. DO NOT CHANGE ANYTHING IN OR AFTER THIS LINE. */\n"; 96 97 /** 98 * The line marking the end of the generated configuration. 99 * 100 * @var string 101 */ 102 var $_configEnd = "/* CONFIG END. DO NOT CHANGE ANYTHING IN OR BEFORE THIS LINE. */\n"; 103 104 /** 105 * Constructor. 106 * 107 * @param string $app The name of the application to be configured. 108 */ 109 function Horde_Config($app) 110 { 111 $this->_app = $app; 112 } 113 114 /** 115 * Reads the application's conf.xml file and builds an associative array 116 * from its XML tree. 117 * 118 * @param array $custom_conf Any settings that shall be included in the 119 * generated configuration. 120 * 121 * @return array An associative array representing the configuration tree. 122 */ 123 function readXMLConfig($custom_conf = null) 124 { 125 if (is_null($this->_xmlConfigTree) || $custom_conf) { 126 require_once 'Horde/Text.php'; 127 128 global $registry; 129 $path = $registry->get('fileroot', $this->_app) . '/config'; 130 131 if ($custom_conf) { 132 $this->_currentConfig = $custom_conf; 133 } else { 134 /* Fetch the current conf.php contents. */ 135 @eval($this->getPHPConfig()); 136 if (isset($conf)) { 137 $this->_currentConfig = $conf; 138 } 139 } 140 141 /* Load the DOM object. */ 142 $doc = Horde_Config_Document::factory($path . '/conf.xml'); 143 144 /* Check if there is a CVS version tag and store it. */ 145 $node = $doc->first_child(); 146 while (!empty($node)) { 147 if ($node->type == XML_COMMENT_NODE) { 148 if (preg_match('/\$.*?conf\.xml,v .*? .*\$/', $node->node_value(), $match)) { 149 $this->_versionTag = $match[0] . "\n"; 150 break; 151 } 152 } 153 $node = $node->next_sibling(); 154 } 155 156 /* Parse the config file. */ 157 $this->_xmlConfigTree = array(); 158 $root = $doc->root(); 159 if ($root->has_child_nodes()) { 160 $this->_parseLevel($this->_xmlConfigTree, $root->child_nodes(), ''); 161 } 162 } 163 164 return $this->_xmlConfigTree; 165 } 166 167 /** 168 * Returns the file content of the current configuration file. 169 * 170 * @return string The unparsed configuration file content. 171 */ 172 function getPHPConfig() 173 { 174 if (is_null($this->_oldConfig)) { 175 global $registry; 176 $path = $registry->get('fileroot', $this->_app) . '/config'; 177 if (file_exists($path . '/conf.php')) { 178 $this->_oldConfig = file_get_contents($path . '/conf.php'); 179 if (!empty($this->_oldConfig)) { 180 $this->_oldConfig = preg_replace('/<\?php\n?/', '', $this->_oldConfig); 181 $pos = strpos($this->_oldConfig, $this->_configBegin); 182 if ($pos !== false) { 183 $this->_preConfig = substr($this->_oldConfig, 0, $pos); 184 $this->_oldConfig = substr($this->_oldConfig, $pos); 185 } 186 $pos = strpos($this->_oldConfig, $this->_configEnd); 187 if ($pos !== false) { 188 $this->_postConfig = substr($this->_oldConfig, $pos + strlen($this->_configEnd)); 189 $this->_oldConfig = substr($this->_oldConfig, 0, $pos); 190 } 191 } 192 } else { 193 $this->_oldConfig = ''; 194 } 195 } 196 return $this->_oldConfig; 197 } 198 199 /** 200 * Generates the content of the application's configuration file. 201 * 202 * @param Variables $formvars The processed configuration form data. 203 * @param array $custom_conf Any settings that shall be included in the 204 * generated configuration. 205 * 206 * @return string The content of the generated configuration file. 207 */ 208 function generatePHPConfig($formvars, $custom_conf = null) 209 { 210 $this->readXMLConfig($custom_conf); 211 $this->getPHPConfig(); 212 213 $this->_phpConfig = "<?php\n"; 214 $this->_phpConfig .= $this->_preConfig; 215 $this->_phpConfig .= $this->_configBegin; 216 if (!empty($this->_versionTag)) { 217 $this->_phpConfig .= '// ' . $this->_versionTag; 218 } 219 $this->_generatePHPConfig($this->_xmlConfigTree, '', $formvars); 220 $this->_phpConfig .= $this->_configEnd; 221 $this->_phpConfig .= $this->_postConfig; 222 223 return $this->_phpConfig; 224 } 225 226 /** 227 * Generates the configuration file items for a part of the configuration 228 * tree. 229 * 230 * @access private 231 * 232 * @param array $section An associative array containing the part of the 233 * traversed XML configuration tree that should be 234 * processed. 235 * @param string $prefix A configuration prefix determining the current 236 * position inside the configuration file. This 237 * prefix will be translated to keys of the $conf 238 * array in the generated configuration file. 239 * @param Variables $formvars The processed configuration form data. 240 */ 241 function _generatePHPConfig($section, $prefix, $formvars) 242 { 243 if (!is_array($section)) { 244 return; 245 } 246 247 foreach ($section as $name => $configitem) { 248 $prefixedname = empty($prefix) ? $name : $prefix . '|' . $name; 249 $configname = str_replace('|', '__', $prefixedname); 250 $quote = !isset($configitem['quote']) || $configitem['quote'] !== false; 251 if ($configitem == 'placeholder') { 252 $this->_phpConfig .= '$conf[\'' . str_replace('|', '\'][\'', $prefix) . "'] = array();\n"; 253 } elseif (isset($configitem['switch'])) { 254 $val = $formvars->getExists($configname, $wasset); 255 if (!$wasset) { 256 $val = isset($configitem['default']) ? $configitem['default'] : null; 257 } 258 if (isset($configitem['switch'][$val])) { 259 $value = $val; 260 if ($quote && $value != 'true' && $value != 'false') { 261 $value = "'" . $value . "'"; 262 } 263 $this->_generatePHPConfig($configitem['switch'][$val]['fields'], $prefix, $formvars); 264 } 265 } elseif (isset($configitem['_type'])) { 266 $val = $formvars->getExists($configname, $wasset); 267 if (!$wasset) { 268 $val = isset($configitem['default']) ? $configitem['default'] : null; 269 } 270 271 $type = $configitem['_type']; 272 switch ($type) { 273 case 'multienum': 274 if (is_array($val)) { 275 $encvals = array(); 276 foreach ($val as $v) { 277 $encvals[] = $this->_quote($v); 278 } 279 $arrayval = "'" . implode('\', \'', $encvals) . "'"; 280 if ($arrayval == "''") { 281 $arrayval = ''; 282 } 283 } else { 284 $arrayval = ''; 285 } 286 $value = 'array(' . $arrayval . ')'; 287 break; 288 289 case 'boolean': 290 if (is_bool($val)) { 291 $value = $val ? 'true' : 'false'; 292 } else { 293 $value = ($val == 'on') ? 'true' : 'false'; 294 } 295 break; 296 297 case 'stringlist': 298 $values = explode(',', $val); 299 if (!is_array($values)) { 300 $value = "array('" . $this->_quote(trim($values)) . "')"; 301 } else { 302 $encvals = array(); 303 foreach ($values as $v) { 304 $encvals[] = $this->_quote(trim($v)); 305 } 306 $arrayval = "'" . implode('\', \'', $encvals) . "'"; 307 if ($arrayval == "''") { 308 $arrayval = ''; 309 } 310 $value = 'array(' . $arrayval . ')'; 311 } 312 break; 313 314 case 'int': 315 if ($val !== '') { 316 $value = (int)$val; 317 } 318 break; 319 320 case 'octal': 321 $value = sprintf('0%o', octdec($val)); 322 break; 323 324 case 'header': 325 case 'description': 326 break; 327 328 default: 329 if ($val != '') { 330 $value = $val; 331 if ($quote && $value != 'true' && $value != 'false') { 332 $value = "'" . $this->_quote($value) . "'"; 333 } 334 } 335 break; 336 } 337 } else { 338 $this->_generatePHPConfig($configitem, $prefixedname, $formvars); 339 } 340 341 if (isset($value)) { 342 $this->_phpConfig .= '$conf[\'' . str_replace('__', '\'][\'', $configname) . '\'] = ' . $value . ";\n"; 343 } 344 unset($value); 345 } 346 } 347 348 /** 349 * Parses one level of the configuration XML tree into the associative 350 * array containing the traversed configuration tree. 351 * 352 * @access private 353 * 354 * @param array &$conf The already existing array where the processed 355 * XML tree portion should be appended to. 356 * @param array $children An array containing the XML nodes of the level 357 * that should be parsed. 358 * @param string $ctx A string representing the current position 359 * (context prefix) inside the configuration XML 360 * file. 361 */ 362 function _parseLevel(&$conf, $children, $ctx) 363 { 364 require_once 'Horde/Text/Filter.php'; 365 366 foreach ($children as $node) { 367 if ($node->type != XML_ELEMENT_NODE) { 368 continue; 369 } 370 $name = $node->get_attribute('name'); 371 $desc = Text_Filter::filter($node->get_attribute('desc'), 'linkurls', array('callback' => 'Horde::externalUrl')); 372 $required = !($node->get_attribute('required') == 'false'); 373 $quote = !($node->get_attribute('quote') == 'false'); 374 if (!empty($ctx)) { 375 $curctx = $ctx . '|' . $name; 376 } else { 377 $curctx = $name; 378 } 379 380 switch ($node->tagname) { 381 case 'configdescription': 382 if (empty($name)) { 383 $name = md5(microtime()); 384 } 385 $conf[$name] = array('_type' => 'description', 386 'desc' => Text_Filter::filter($this->_default($curctx, $this->_getNodeOnlyText($node)), 'linkurls', array('callback' => 'Horde::externalUrl'))); 387 break; 388 389 case 'configheader': 390 if (empty($name)) { 391 $name = md5(microtime()); 392 } 393 $conf[$name] = array('_type' => 'header', 394 'desc' => $this->_default($curctx, $this->_getNodeOnlyText($node))); 395 break; 396 397 case 'configswitch': 398 $values = $this->_getSwitchValues($node, $ctx); 399 if ($quote) { 400 $default = $this->_default($curctx, $this->_getNodeOnlyText($node)); 401 } else { 402 $default = $this->_defaultRaw($curctx, $this->_getNodeOnlyText($node)); 403 } 404 if ($default === '') { 405 $default = key($values); 406 } 407 if (is_bool($default)) { 408 $default = $default ? 'true' : 'false'; 409 } 410 $conf[$name] = array('desc' => $desc, 411 'switch' => $values, 412 'default' => $default); 413 break; 414 415 case 'configenum': 416 $values = $this->_getEnumValues($node); 417 if ($quote) { 418 $default = $this->_default($curctx, $this->_getNodeOnlyText($node)); 419 } else { 420 $default = $this->_defaultRaw($curctx, $this->_getNodeOnlyText($node)); 421 } 422 if ($default === '') { 423 $default = key($values); 424 } 425 if (is_bool($default)) { 426 $default = $default ? 'true' : 'false'; 427 } 428 $conf[$name] = array('_type' => 'enum', 429 'required' => $required, 430 'quote' => $quote, 431 'values' => $values, 432 'desc' => $desc, 433 'default' => $default); 434 break; 435 436 case 'configlist': 437 $default = $this->_default($curctx, null); 438 if ($default === null) { 439 $default = $this->_getNodeOnlyText($node); 440 } elseif (is_array($default)) { 441 $default = implode(', ', $default); 442 } 443 $conf[$name] = array('_type' => 'stringlist', 444 'required' => $required, 445 'desc' => $desc, 446 'default' => $default); 447 break; 448 449 case 'configmultienum': 450 $values = $this->_getEnumValues($node); 451 require_once 'Horde/Array.php'; 452 $conf[$name] = array('_type' => 'multienum', 453 'required' => $required, 454 'values' => $values, 455 'desc' => $desc, 456 'default' => Horde_Array::valuesToKeys($this->_default($curctx, explode(',', $this->_getNodeOnlyText($node))))); 457 break; 458 459 case 'configpassword': 460 $conf[$name] = array('_type' => 'password', 461 'required' => $required, 462 'desc' => $desc, 463 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node))); 464 break; 465 466 case 'configstring': 467 $conf[$name] = array('_type' => 'text', 468 'required' => $required, 469 'desc' => $desc, 470 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node))); 471 if ($conf[$name]['default'] === false) { 472 $conf[$name]['default'] = 'false'; 473 } elseif ($conf[$name]['default'] === true) { 474 $conf[$name]['default'] = 'true'; 475 } 476 break; 477 478 case 'configboolean': 479 $default = $this->_getNodeOnlyText($node); 480 if (empty($default) || $default === 'false') { 481 $default = false; 482 } else { 483 $default = true; 484 } 485 $conf[$name] = array('_type' => 'boolean', 486 'required' => $required, 487 'desc' => $desc, 488 'default' => $this->_default($curctx, $default)); 489 break; 490 491 case 'configinteger': 492 $values = $this->_getEnumValues($node); 493 $conf[$name] = array('_type' => 'int', 494 'required' => $required, 495 'values' => $values, 496 'desc' => $desc, 497 'default' => $this->_default($curctx, $this->_getNodeOnlyText($node))); 498 if ($node->get_attribute('octal') == 'true' && 499 $conf[$name]['default'] != '') { 500 $conf[$name]['_type'] = 'octal'; 501 $conf[$name]['default'] = sprintf('0%o', $this->_default($curctx, octdec($this->_getNodeOnlyText($node)))); 502 } 503 break; 504 505 case 'configphp': 506 $conf[$name] = array('_type' => 'php', 507 'required' => $required, 508 'quote' => false, 509 'desc' => $desc, 510 'default' => $this->_defaultRaw($curctx, $this->_getNodeOnlyText($node))); 511 break; 512 513 case 'configsql': 514 $conf[$node->get_attribute('switchname')] = $this->_configSQL($ctx, $node); 515 break; 516 517 case 'configvfs': 518 $conf[$node->get_attribute('switchname')] = $this->_configVFS($ctx, $node); 519 break; 520 521 case 'configsection': 522 $conf[$name] = array(); 523 $cur = &$conf[$name]; 524 if ($node->has_child_nodes()) { 525 $this->_parseLevel($cur, $node->child_nodes(), $curctx); 526 } 527 break; 528 529 case 'configtab': 530 $key = md5(microtime()); 531 $conf[$key] = array('tab' => $name, 532 'desc' => $desc); 533 if ($node->has_child_nodes()) { 534 $this->_parseLevel($conf, $node->child_nodes(), $ctx); 535 } 536 break; 537 538 case 'configplaceholder': 539 $conf[md5(microtime())] = 'placeholder'; 540 break; 541 542 default: 543 $conf[$name] = array(); 544 $cur = &$conf[$name]; 545 if ($node->has_child_nodes()) { 546 $this->_parseLevel($cur, $node->child_nodes(), $curctx); 547 } 548 break; 549 } 550 } 551 } 552 553 /** 554 * Returns the configuration tree for an SQL backend configuration to 555 * replace a <configsql> tag. 556 * Subnodes will be parsed and added to both the Horde defaults and the 557 * Custom configuration parts. 558 * 559 * @access private 560 * 561 * @param string $ctx The context of the <configsql> tag. 562 * @param DomNode $node The DomNode representation of the <configsql> 563 * tag. 564 * @param string $switchname If DomNode is not set, the value of the 565 * tag's switchname attribute. 566 * 567 * @return array An associative array with the SQL configuration tree. 568 */ 569 function _configSQL($ctx, $node = null, $switchname = 'driverconfig') 570 { 571 $persistent = array( 572 '_type' => 'boolean', 573 'required' => false, 574 'desc' => 'Request persistent connections?', 575 'default' => $this->_default($ctx . '|persistent', false)); 576 $hostspec = array( 577 '_type' => 'text', 578 'required' => true, 579 'desc' => 'Database server/host', 580 'default' => $this->_default($ctx . '|hostspec', '')); 581 $username = array( 582 '_type' => 'text', 583 'required' => true, 584 'desc' => 'Username to connect to the database as', 585 'default' => $this->_default($ctx . '|username', '')); 586 $password = array( 587 '_type' => 'text', 588 'required' => false, 589 'desc' => 'Password to connect with', 590 'default' => $this->_default($ctx . '|password', '')); 591 $database = array( 592 '_type' => 'text', 593 'required' => true, 594 'desc' => 'Database name to use', 595 'default' => $this->_default($ctx . '|database', '')); 596 $socket = array( 597 '_type' => 'text', 598 'required' => false, 599 'desc' => 'Location of UNIX socket', 600 'default' => $this->_default($ctx . '|socket', '')); 601 $port = array( 602 '_type' => 'int', 603 'required' => false, 604 'desc' => 'Port the DB is running on, if non-standard', 605 'default' => $this->_default($ctx . '|port', null)); 606 $protocol = array( 607 'desc' => 'How should we connect to the database?', 608 'default' => $this->_default($ctx . '|protocol', 'unix'), 609 'switch' => array( 610 'unix' => array( 611 'desc' => 'UNIX Sockets', 612 'fields' => array( 613 'socket' => $socket)), 614 'tcp' => array( 615 'desc' => 'TCP/IP', 616 'fields' => array( 617 'port' => $port)))); 618 $mysql_protocol = $protocol; 619 $mysql_protocol['switch']['tcp']['fields']['port']['default'] = $this->_default($ctx . '|port', 3306); 620 $charset = array( 621 '_type' => 'text', 622 'required' => true, 623 'desc' => 'Internally used charset', 624 'default' => $this->_default($ctx . '|charset', 'iso-8859-1')); 625 626 $oci8_fields = array( 627 'persistent' => $persistent, 628 'username' => $username, 629 'password' => $password); 630 if (function_exists('oci_connect')) { 631 $oci8_fields['database'] = array( 632 '_type' => 'text', 633 'required' => true, 634 'desc' => 'Database name or Easy Connect parameter', 635 'default' => $this->_default($ctx . '|database', 'horde')); 636 } else { 637 $oci8_fields['hostspec'] = array( 638 '_type' => 'text', 639 'required' => true, 640 'desc' => 'Database name or Easy Connect parameter', 641 'default' => $this->_default($ctx . '|hostspec', 'horde')); 642 } 643 $oci8_fields['charset'] = $charset; 644 645 $custom_fields = array( 646 'required' => true, 647 'desc' => 'What database backend should we use?', 648 'default' => $this->_default($ctx . '|phptype', 'false'), 649 'switch' => array( 650 'false' => array( 651 'desc' => '[None]', 652 'fields' => array()), 653 'dbase' => array( 654 'desc' => 'dBase', 655 'fields' => array( 656 'database' => array( 657 '_type' => 'text', 658 'required' => true, 659 'desc' => 'Absolute path to the database file', 660 'default' => $this->_default($ctx . '|database', '')), 661 'mode' => array( 662 '_type' => 'enum', 663 'desc' => 'The mode to open the file with', 664 'values' => array( 665 0 => 'Read Only', 666 2 => 'Read Write'), 667 'default' => $this->_default($ctx . '|mode', 2)), 668 669 'charset' => $charset)), 670 'ibase' => array( 671 'desc' => 'Firebird/InterBase', 672 'fields' => array( 673 'dbsyntax' => array( 674 '_type' => 'enum', 675 'desc' => 'The database syntax variant to use', 676 'required' => false, 677 'values' => array( 678 'ibase' => 'InterBase', 679 'firebird' => 'Firebird'), 680 'default' => $this->_default($ctx . '|dbsyntax', 'firebird')), 681 'persistent' => $persistent, 682 'hostspec' => $hostspec, 683 'username' => $username, 684 'password' => $password, 685 'database' => $database, 686 'buffers' => array( 687 '_type' => 'int', 688 'desc' => 'The number of database buffers to allocate', 689 'required' => false, 690 'default' => $this->_default($ctx . '|buffers', null)), 691 'dialect' => array( 692 '_type' => 'int', 693 'desc' => 'The default SQL dialect for any statement executed within a connection.', 694 'required' => false, 695 'default' => $this->_default($ctx . '|dialect', null)), 696 'role' => array( 697 '_type' => 'text', 698 'desc' => 'Role', 699 'required' => false, 700 'default' => $this->_default($ctx . '|role', null)), 701 'charset' => $charset)), 702 'fbsql' => array( 703 'desc' => 'Frontbase', 704 'fields' => array( 705 'persistent' => $persistent, 706 'hostspec' => $hostspec, 707 'username' => $username, 708 'password' => $password, 709 'database' => $database, 710 'charset' => $charset)), 711 'ifx' => array( 712 'desc' => 'Informix', 713 'fields' => array( 714 'persistent' => $persistent, 715 'username' => $username, 716 'password' => $password, 717 'database' => $database, 718 'charset' => $charset)), 719 'msql' => array( 720 'desc' => 'mSQL', 721 'fields' => array( 722 'persistent' => $persistent, 723 'hostspec' => $hostspec, 724 'username' => $username, 725 'password' => $password, 726 'port' => $port, 727 'database' => $database, 728 'charset' => $charset)), 729 'mssql' => array( 730 'desc' => 'MS SQL Server', 731 'fields' => array( 732 'persistent' => $persistent, 733 'hostspec' => $hostspec, 734 'username' => $username, 735 'password' => $password, 736 'port' => $port, 737 'database' => $database, 738 'charset' => $charset)), 739 'mysql' => array( 740 'desc' => 'MySQL', 741 'fields' => array( 742 'persistent' => $persistent, 743 'hostspec' => $hostspec, 744 'username' => $username, 745 'password' => $password, 746 'protocol' => $mysql_protocol, 747 'database' => $database, 748 'charset' => $charset)), 749 'mysqli' => array( 750 'desc' => 'MySQL (mysqli)', 751 'fields' => array( 752 'persistent' => $persistent, 753 'hostspec' => $hostspec, 754 'username' => $username, 755 'password' => $password, 756 'port' => $port, 757 'socket' => $socket, 758 'database' => $database, 759 'charset' => $charset)), 760 'oci8' => array( 761 'desc' => 'Oracle', 762 'fields' => $oci8_fields), 763 'odbc' => array( 764 'desc' => 'ODBC', 765 'fields' => array( 766 'persistent' => $persistent, 767 'username' => $username, 768 'password' => $password, 769 'hostspec' => array( 770 '_type' => 'text', 771 'desc' => 'DSN', 772 'default' => $this->_default($ctx . '|hostspec', '')), 773 'dbsyntax' => array( 774 '_type' => 'enum', 775 'desc' => 'The database syntax variant to use', 776 'required' => false, 777 'values' => array( 778 'sql92' => 'SQL92', 779 'access' => 'Access', 780 'db2' => 'DB2', 781 'solid' => 'Solid', 782 'navision' => 'Navision', 783 'mssql' => 'MS SQL Server', 784 'sybase' => 'Sybase', 785 'mysql' => 'MySQL', 786 'mysqli' => 'MySQL (mysqli)', 787 ), 788 'default' => $this->_default($ctx . '|dbsyntax', 'sql92')), 789 'cursor' => array( 790 '_type' => 'enum', 791 'desc' => 'Cursor type', 792 'quote' => false, 793 'required' => false, 794 'values' => array( 795 'null' => 'None', 796 'SQL_CUR_DEFAULT' => 'Default', 797 'SQL_CUR_USE_DRIVER' => 'Use Driver', 798 'SQL_CUR_USE_ODBC' => 'Use ODBC', 799 'SQL_CUR_USE_IF_NEEDED' => 'Use If Needed'), 800 'default' => $this->_default($ctx . '|cursor', null)), 801 'charset' => $charset)), 802 'pgsql' => array( 803 'desc' => 'PostgreSQL', 804 'fields' => array( 805 'persistent' => $persistent, 806 'hostspec' => $hostspec, 807 'username' => $username, 808 'password' => $password, 809 'protocol' => $protocol, 810 'database' => $database, 811 'charset' => $charset)), 812 'sqlite' => array( 813 'desc' => 'SQLite', 814 'fields' => array( 815 'database' => array( 816 '_type' => 'text', 817 'required' => true, 818 'desc' => 'Absolute path to the database file', 819 'default' => $this->_default($ctx . '|database', '')), 820 'mode' => array( 821 '_type' => 'text', 822 'desc' => 'The mode to open the file with', 823 'default' => $this->_default($ctx . '|mode', '0644')), 824 'charset' => $charset)), 825 'sybase' => array( 826 'desc' => 'Sybase', 827 'fields' => array( 828 'persistent' => $persistent, 829 'hostspec' => $hostspec, 830 'username' => $username, 831 'password' => $password, 832 'database' => $database, 833 'appname' => array( 834 '_type' => 'text', 835 'desc' => 'Application Name', 836 'required' => false, 837 'default' => $this->_default($ctx . '|appname', '')), 838 'charset' => $charset)))); 839 840 if (isset($node) && $node->get_attribute('baseconfig') == 'true') { 841 return $custom_fields; 842 } 843 844 $config = array( 845 'desc' => 'Driver configuration', 846 'default' => $this->_default($ctx . '|' . (isset($node) ? $node->get_attribute('switchname') : $switchname), 'horde'), 847 'switch' => array( 848 'horde' => array( 849 'desc' => 'Horde defaults', 850 'fields' => array()), 851 'custom' => array( 852 'desc' => 'Custom parameters', 853 'fields' => array( 854 md5(microtime()) => array( 855 '_type' => 'description', 856 'desc' => 'Any parameters that the storage driver needs.'), 857 'phptype' => $custom_fields)))); 858 859 if (isset($node) && $node->has_child_nodes()) { 860 $cur = array(); 861 $this->_parseLevel($cur, $node->child_nodes(), $ctx); 862 $config['switch']['horde']['fields'] = array_merge($config['switch']['horde']['fields'], $cur); 863 $config['switch']['custom']['fields'] = array_merge($config['switch']['custom']['fields'], $cur); 864 } 865 866 return $config; 867 } 868 869 /** 870 * Returns the configuration tree for a VFS backend configuration to 871 * replace a <configvfs> tag. 872 * Subnodes will be parsed and added to both the Horde defaults and the 873 * Custom configuration parts. 874 * 875 * @access private 876 * 877 * @param string $ctx The context of the <configvfs> tag. 878 * @param DomNode $node The DomNode representation of the <configvfs> 879 * tag. 880 * 881 * @return array An associative array with the VFS configuration tree. 882 */ 883 function _configVFS($ctx, $node) 884 { 885 $sql = $this->_configSQL($ctx . '|params'); 886 $config = 887 array( 888 'desc' => 'What VFS driver should we use?', 889 'default' => $this->_default($ctx . '|' . $node->get_attribute('switchname'), 'horde'), 890 'switch' => array( 891 'none' => array( 892 'desc' => 'None', 893 'fields' => array()), 894 'horde' => array( 895 'desc' => 'Horde defaults', 896 'fields' => array()), 897 'file' => array( 898 'desc' => 'Files on the local system', 899 'fields' => array( 900 'params' => array( 901 'vfsroot' => array( 902 '_type' => 'text', 903 'desc' => 'Where on the real filesystem should Horde use as root of the virtual filesystem?', 904 'default' => $this->_default($ctx . '|params|vfsroot', '/tmp'))))), 905 'sql' => array( 906 'desc' => 'SQL database', 907 'fields' => array( 908 'params' => array( 909 'driverconfig' => $sql))))); 910 911 $cases = $this->_getSwitchValues($node, $ctx . '|params'); 912 foreach ($cases as $case => $fields) { 913 if (isset($config['switch'][$case])) { 914 $config['switch'][$case]['fields']['params'] = array_merge($config['switch'][$case]['fields']['params'], $fields['fields']); 915 } 916 } 917 918 return $config; 919 } 920 921 /** 922 * Returns a certain value from the current configuration array or 923 * a default value, if not found. 924 * 925 * @access private 926 * 927 * @param string $ctx A string representing the key of the 928 * configuration array to return. 929 * @param mixed $default The default value to return if the key wasn't 930 * found. 931 * 932 * @return mixed Either the value of the configuration array's requested 933 * key or the default value if the key wasn't found. 934 */ 935 function _default($ctx, $default) 936 { 937 $ctx = explode('|', $ctx); 938 $ptr = $this->_currentConfig; 939 for ($i = 0; $i < count($ctx); $i++) { 940 if (!isset($ptr[$ctx[$i]])) { 941 return $default; 942 } else { 943 $ptr = $ptr[$ctx[$i]]; 944 } 945 } 946 if (is_string($ptr)) { 947 return String::convertCharset($ptr, 'iso-8859-1'); 948 } else { 949 return $ptr; 950 } 951 } 952 953 /** 954 * Returns a certain value from the current configuration file or 955 * a default value, if not found. 956 * It does NOT return the actual value, but the PHP expression as used 957 * in the configuration file. 958 * 959 * @access private 960 * 961 * @param string $ctx A string representing the key of the 962 * configuration array to return. 963 * @param mixed $default The default value to return if the key wasn't 964 * found. 965 * 966 * @return mixed Either the value of the configuration file's requested 967 * key or the default value if the key wasn't found. 968 */ 969 function _defaultRaw($ctx, $default) 970 { 971 $ctx = explode('|', $ctx); 972 $pattern = '/^\$conf\[\'' . implode("'\]\['", $ctx) . '\'\] = (.*);$/m'; 973 if (preg_match($pattern, $this->getPHPConfig(), $matches)) { 974 return $matches[1]; 975 } 976 return $default; 977 } 978 979 /** 980 * Returns the content of all text node children of the specified node. 981 * 982 * @access private 983 * 984 * @param DomNode $node A DomNode object whose text node children to return. 985 * 986 * @return string The concatenated values of all text nodes. 987 */ 988 function _getNodeOnlyText($node) 989 { 990 $text = ''; 991 if (!$node->has_child_nodes()) { 992 return $node->get_content(); 993 } 994 foreach ($node->child_nodes() as $tnode) { 995 if ($tnode->type == XML_TEXT_NODE) { 996 $text .= $tnode->content; 997 } 998 } 999 1000 return trim($text); 1001 } 1002 1003 /** 1004 * Returns an associative array containing all possible values of the 1005 * specified <configenum> tag. 1006 * The keys contain the actual enum values while the values contain their 1007 * corresponding descriptions. 1008 * 1009 * @access private 1010 * 1011 * @param DomNode $node The DomNode representation of the <configenum> tag 1012 * whose values should be returned. 1013 * 1014 * @return array An associative array with all possible enum values. 1015 */ 1016 function _getEnumValues($node) 1017 { 1018 $values = array(); 1019 if (!$node->has_child_nodes()) { 1020 return array(); 1021 } 1022 foreach ($node->child_nodes() as $vnode) { 1023 if ($vnode->type == XML_ELEMENT_NODE && 1024 $vnode->tagname == 'values') { 1025 if (!$vnode->has_child_nodes()) { 1026 return array(); 1027 } 1028 foreach ($vnode->child_nodes() as $value) { 1029 if ($value->type == XML_ELEMENT_NODE) { 1030 if ($value->tagname == 'configspecial') { 1031 return $this->_handleSpecials($value); 1032 } elseif ($value->tagname == 'value') { 1033 $text = $value->get_content(); 1034 $desc = $value->get_attribute('desc'); 1035 if (!empty($desc)) { 1036 $values[$text] = $desc; 1037 } else { 1038 $values[$text] = $text; 1039 } 1040 } 1041 } 1042 } 1043 } 1044 } 1045 return $values; 1046 } 1047 1048 /** 1049 * Returns a multidimensional associative array representing the specified 1050 * <configswitch> tag. 1051 * 1052 * @access private 1053 * 1054 * @param DomNode &$node The DomNode representation of the <configswitch> 1055 * tag to process. 1056 * 1057 * @return array An associative array representing the node. 1058 */ 1059 function _getSwitchValues(&$node, $curctx) 1060 { 1061 if (!$node->has_child_nodes()) { 1062 return array(); 1063 } 1064 $values = array(); 1065 foreach ($node->child_nodes() as $case) { 1066 if ($case->type == XML_ELEMENT_NODE) { 1067 $name = $case->get_attribute('name'); 1068 $values[$name] = array(); 1069 $values[$name]['desc'] = $case->get_attribute('desc'); 1070 $values[$name]['fields'] = array(); 1071 if ($case->has_child_nodes()) { 1072 $this->_parseLevel($values[$name]['fields'], $case->child_nodes(), $curctx); 1073 } 1074 } 1075 } 1076 return $values; 1077 } 1078 1079 /** 1080 * Returns an associative array containing the possible values of a 1081 * <configspecial> tag as used inside of enum configurations. 1082 * 1083 * @access private 1084 * 1085 * @param DomNode $node The DomNode representation of the <configspecial> 1086 * tag. 1087 * 1088 * @return array An associative array with the possible values. 1089 */ 1090 function _handleSpecials($node) 1091 { 1092 switch ($node->get_attribute('name')) { 1093 case 'list-horde-apps': 1094 global $registry; 1095 require_once 'Horde/Array.php'; 1096 $apps = Horde_Array::valuesToKeys($registry->listApps(array('hidden', 'notoolbar', 'active'))); 1097 asort($apps); 1098 return $apps; 1099 break; 1100 1101 case 'list-horde-languages': 1102 return array_map(create_function('$val', 'return preg_replace(array("/&#x([0-9a-f]{4});/ie", "/(&[^;]+;)/e"), array("String::convertCharset(pack(\"H*\", \"$1\"), \"ucs-2\", \"' . NLS::getCharset() . '\")", "String::convertCharset(html_entity_decode(\"$1\", ENT_COMPAT, \"iso-8859-1\"), \"iso-8859-1\", \"' . NLS::getCharset() . '\")"), $val);'), $GLOBALS['nls']['languages']); 1103 break; 1104 1105 case 'list-blocks': 1106 require_once 'Horde/Block/Collection.php'; 1107 $collection = &Horde_Block_Collection::singleton('portal'); 1108 return $collection->getBlocksList(); 1109 1110 case 'list-client-fields': 1111 global $registry; 1112 $f = array(); 1113 if ($registry->hasMethod('clients/getClientSource')) { 1114 $addressbook = $registry->call('clients/getClientSource'); 1115 $fields = $registry->call('clients/fields', array($addressbook)); 1116 if (!is_a($fields, 'PEAR_Error')) { 1117 foreach ($fields as $field) { 1118 $f[$field['name']] = $field['label']; 1119 } 1120 } 1121 } 1122 return $f; 1123 break; 1124 } 1125 1126 return array(); 1127 } 1128 1129 /** 1130 * Returns the specified string with escaped single quotes 1131 * 1132 * @access private 1133 * 1134 * @param string $string A string to escape. 1135 * 1136 * @return string The specified string with single quotes being escaped. 1137 */ 1138 function _quote($string) 1139 { 1140 return str_replace("'", "\'", $string); 1141 } 1142 1143 } 1144 1145 /** 1146 * A Horde_Form:: form that implements a user interface for the config 1147 * system. 1148 * 1149 * @author Chuck Hagenbuch <chuck@horde.org> 1150 * @since Horde 3.0 1151 * @package Horde_Framework 1152 */ 1153 class ConfigForm extends Horde_Form { 1154 1155 /** 1156 * Don't use form tokens for the configuration form - while 1157 * generating configuration info, things like the Token system 1158 * might not work correctly. This saves some headaches. 1159 * 1160 * @var boolean 1161 */ 1162 var $_useFormToken = false; 1163 1164 /** 1165 * Contains the Horde_Config object that this form represents. 1166 * 1167 * @var Horde_Config 1168 */ 1169 var $_xmlConfig; 1170 1171 /** 1172 * Contains the Variables object of this form. 1173 * 1174 * @var Variables 1175 */ 1176 var $_vars; 1177 1178 /** 1179 * Constructor. 1180 * 1181 * @param Variables &$vars The Variables object of this form. 1182 * @param string $app The name of the application that this 1183 * configuration form is for. 1184 */ 1185 function ConfigForm(&$vars, $app) 1186 { 1187 parent::Horde_Form($vars); 1188 1189 $this->_xmlConfig = &new Horde_Config($app); 1190 $this->_vars = &$vars; 1191 $config = $this->_xmlConfig->readXMLConfig(); 1192 $this->addHidden('', 'app', 'text', true); 1193 $this->_buildVariables($config); 1194 } 1195 1196 /** 1197 * Builds the form based on the specified level of the configuration tree. 1198 * 1199 * @access private 1200 * 1201 * @param array $config The portion of the configuration tree for that 1202 * the form fields should be created. 1203 * @param string $prefix A string representing the current position 1204 * inside the configuration tree. 1205 */ 1206 function _buildVariables($config, $prefix = '') 1207 { 1208 if (!is_array($config)) { 1209 return; 1210 } 1211 foreach ($config as $name => $configitem) { 1212 $prefixedname = empty($prefix) ? $name : $prefix . '|' . $name; 1213 $varname = str_replace('|', '__', $prefixedname); 1214 $description = null; 1215 if ($configitem == 'placeholder') { 1216 continue; 1217 } elseif (isset($configitem['tab'])) { 1218 $this->setSection($configitem['tab'], $configitem['desc']); 1219 } elseif (isset($configitem['switch'])) { 1220 $selected = $this->_vars->getExists($varname, $wasset); 1221 $var_params = array(); 1222 $select_option = true; 1223 if (is_bool($configitem['default'])) { 1224 $configitem['default'] = $configitem['default'] ? 'true' : 'false'; 1225 } 1226 foreach ($configitem['switch'] as $option => $case) { 1227 $var_params[$option] = $case['desc']; 1228 if ($option == $configitem['default']) { 1229 $select_option = false; 1230 if (!$wasset) { 1231 $selected = $option; 1232 } 1233 } 1234 } 1235 $v = &$this->addVariable($configitem['desc'], $varname, 'enum', true, false, null, array($var_params, $select_option)); 1236 if (array_key_exists('default', $configitem)) { 1237 $v->setDefault($configitem['default']); 1238 } 1239 $v_action = &Horde_Form_Action::factory('reload'); 1240 $v->setAction($v_action); 1241 if (isset($selected) && isset($configitem['switch'][$selected])) { 1242 $this->_buildVariables($configitem['switch'][$selected]['fields'], $prefix); 1243 } 1244 } elseif (isset($configitem['_type'])) { 1245 $required = (isset($configitem['required'])) ? $configitem['required'] : true; 1246 $type = $configitem['_type']; 1247 // FIXME: multienum fields can well be required, meaning that 1248 // you need to select at least one entry. Changing this before 1249 // Horde 4.0 would break a lot of configuration files though. 1250 if ($type == 'multienum' || $type == 'header' || 1251 $type == 'description') { 1252 $required = false; 1253 } 1254 if ($type == 'multienum' || $type == 'enum') { 1255 $var_params = array($configitem['values']); 1256 } else { 1257 $var_params = array(); 1258 } 1259 if ($type == 'php') { 1260 $type = 'text'; 1261 $description = 'Enter a valid PHP expression.'; 1262 } 1263 $v = &$this->addVariable($configitem['desc'], $varname, $type, $required, false, $description, $var_params); 1264 if (isset($configitem['default'])) { 1265 $v->setDefault($configitem['default']); 1266 } 1267 } else { 1268 $this->_buildVariables($configitem, $prefixedname); 1269 } 1270 } 1271 } 1272 1273 } 1274 1275 class Horde_Config_Document extends Horde_Config_Node { 1276 1277 function factory($file) 1278 { 1279 if (function_exists('domxml_open_file')) { 1280 return domxml_open_file($file); 1281 } elseif (version_compare(phpversion(), '5', '>=')) { 1282 return $doc = new Horde_Config_Document($file); 1283 } else { 1284 Horde::fatal('DOM support not present.', __FILE__, __LINE__); 1285 } 1286 } 1287 1288 function Horde_Config_Document($filename) 1289 { 1290 $this->node = new DOMDocument(); 1291 $this->node->load($filename); 1292 } 1293 1294 function root() 1295 { 1296 return $root = new Horde_Config_Element($this->node->documentElement); 1297 } 1298 1299 } 1300 1301 class Horde_Config_Node { 1302 1303 var $node; 1304 1305 function Horde_Config_Node($aDomNode) {$this->node=$aDomNode;} 1306 1307 function __get($name) 1308 { 1309 switch ($name) { 1310 case 'type': 1311 return $this->node->nodeType; 1312 1313 case 'tagname': 1314 return $this->node->tagName; 1315 1316 case 'content': 1317 return $this->node->textContent; 1318 1319 default: 1320 return false; 1321 } 1322 } 1323 1324 function child_nodes() 1325 { 1326 $nodeList = $this->node->childNodes; 1327 $nodeSet = array(); 1328 if (isset($nodeList)) { 1329 $i = 0; 1330 while ($node = $nodeList->item($i)) { 1331 $nodeSet[] = new Horde_Config_Element($node); 1332 $i++; 1333 } 1334 } 1335 return $nodeSet; 1336 } 1337 1338 function first_child() 1339 { 1340 return new Horde_Config_Element($this->node->firstChild); 1341 } 1342 1343 function get_content() 1344 { 1345 return $this->node->textContent; 1346 } 1347 1348 function has_child_nodes() 1349 { 1350 return $this->node->hasChildNodes(); 1351 } 1352 1353 function next_sibling() 1354 { 1355 return new Horde_Config_Element($this->node->nextSibling); 1356 } 1357 1358 function node_value() 1359 { 1360 return $this->node->nodeValue; 1361 } 1362 1363 } 1364 1365 class Horde_Config_Element extends Horde_Config_Node { 1366 1367 function get_attribute($name) 1368 { 1369 return $this->node->getAttribute($name); 1370 } 1371 1372 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |