Subversion-Projekte lars-tiefland.niewerth

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
5 lars 1
<?php
2
// +---------------------------------------------------------------------+
3
// | PHP Version 4                                                       |
4
// +---------------------------------------------------------------------+
5
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group            |
6
// +---------------------------------------------------------------------+
7
// | This source file is subject to version 2.0 of the PHP license,      |
8
// | that is bundled with this package in the file LICENSE, and is       |
9
// | available at through the world-wide-web at                          |
10
// | http://www.php.net/license/2_02.txt.                                |
11
// | If you did not receive a copy of the PHP license and are unable to  |
12
// | obtain it through the world-wide-web, please send a note to         |
13
// | license@php.net so we can mail you a copy immediately.              |
14
// +---------------------------------------------------------------------+
15
// | Author: Bertrand Mansion <bmansion@mamasam.com>                     |
16
// +---------------------------------------------------------------------+
17
//
18
// $Id: Container.php,v 1.41 2006/05/30 06:37:28 aashley Exp $
19
 
20
require_once 'Config.php';
21
 
22
/**
23
* Interface for Config containers
24
*
25
* @author   Bertrand Mansion <bmansion@mamasam.com>
26
* @package  Config
27
*/
28
class Config_Container {
29
 
30
    /**
31
    * Container object type
32
    * Ex: section, directive, comment, blank
33
    * @var  string
34
    */
35
    var $type;
36
 
37
    /**
38
    * Container object name
39
    * @var  string
40
    */
41
    var $name = '';
42
 
43
    /**
44
    * Container object content
45
    * @var  string
46
    */
47
    var $content = '';
48
 
49
    /**
50
    * Container object children
51
    * @var  array
52
    */
53
    var $children = array();
54
 
55
    /**
56
    * Reference to container object's parent
57
    * @var  object
58
    */
59
    var $parent;
60
 
61
    /**
62
    * Array of attributes for this item
63
    * @var  array
64
    */
65
    var $attributes;
66
 
67
    /**
68
    * Unique id to differenciate nodes
69
    *
70
    * This is used to compare nodes
71
    * Will not be needed anymore when this class will use ZendEngine 2
72
    *
73
    * @var  int
74
    */
75
    var $_id;
76
 
77
    /**
78
    * Constructor
79
    *
80
    * @param  string  $type       Type of container object
81
    * @param  string  $name       Name of container object
82
    * @param  string  $content    Content of container object
83
    * @param  array   $attributes Array of attributes for container object
84
    */
85
    function Config_Container($type = 'section', $name = '', $content = '', $attributes = null)
86
    {
87
        $this->type       = $type;
88
        $this->name       = $name;
89
        $this->content    = $content;
90
        $this->attributes = $attributes;
91
        $this->parent     = null;
92
        if (version_compare(PHP_VERSION, '5.0.0', 'gt')) {
93
            $this->_id    = uniqid($name.$type, true);
94
        } else {
95
            $this->_id    = uniqid(substr($name.$type, 0, 114), true);
96
        }
97
    } // end constructor
98
 
99
    /**
100
    * Create a child for this item.
101
    * @param  string  $type       type of item: directive, section, comment, blank...
102
    * @param  mixed   $item       item name
103
    * @param  string  $content    item content
104
    * @param  array   $attributes item attributes
105
    * @param  string  $where      choose a position 'bottom', 'top', 'after', 'before'
106
    * @param  object  $target     needed if you choose 'before' or 'after' for where
107
    * @return object  reference to new item or Pear_Error
108
    */
109
    function &createItem($type, $name, $content, $attributes = null, $where = 'bottom', $target = null)
110
    {
111
        $item =& new Config_Container($type, $name, $content, $attributes);
112
        $result =& $this->addItem($item, $where, $target);
113
        return $result;
114
    } // end func &createItem
115
 
116
    /**
117
    * Adds an item to this item.
118
    * @param  object   $item      a container object
119
    * @param  string   $where     choose a position 'bottom', 'top', 'after', 'before'
120
    * @param  object   $target    needed if you choose 'before' or 'after' in $where
121
    * @return mixed    reference to added container on success, Pear_Error on error
122
    */
123
    function &addItem(&$item, $where = 'bottom', $target = null)
124
    {
125
        if ($this->type != 'section') {
126
            return PEAR::raiseError('Config_Container::addItem must be called on a section type object.', null, PEAR_ERROR_RETURN);
127
        }
128
        if (is_null($target)) {
129
            $target =& $this;
130
        }
131
        if (strtolower(get_class($target)) != 'config_container') {
132
            return PEAR::raiseError('Target must be a Config_Container object in Config_Container::addItem.', null, PEAR_ERROR_RETURN);
133
        }
134
 
135
        switch ($where) {
136
            case 'before':
137
                $index = $target->getItemIndex();
138
                break;
139
            case 'after':
140
                $index = $target->getItemIndex()+1;
141
                break;
142
            case 'top':
143
                $index = 0;
144
                break;
145
            case 'bottom':
146
                $index = -1;
147
                break;
148
            default:
149
                return PEAR::raiseError('Use only top, bottom, before or after in Config_Container::addItem.', null, PEAR_ERROR_RETURN);
150
        }
151
        if (isset($index) && $index >= 0) {
152
            array_splice($this->children, $index, 0, 'tmp');
153
        } else {
154
            $index = count($this->children);
155
        }
156
        $this->children[$index] =& $item;
157
        $this->children[$index]->parent =& $this;
158
 
159
        return $item;
160
    } // end func addItem
161
 
162
    /**
163
    * Adds a comment to this item.
164
    * This is a helper method that calls createItem
165
    *
166
    * @param  string    $content        Object content
167
    * @param  string    $where          Position : 'top', 'bottom', 'before', 'after'
168
    * @param  object    $target         Needed when $where is 'before' or 'after'
169
    * @return object  reference to new item or Pear_Error
170
    */
171
    function &createComment($content = '', $where = 'bottom', $target = null)
172
    {
173
        return $this->createItem('comment', null, $content, null, $where, $target);
174
    } // end func &createComment
175
 
176
    /**
177
    * Adds a blank line to this item.
178
    * This is a helper method that calls createItem
179
    *
180
    * @return object  reference to new item or Pear_Error
181
    */
182
    function &createBlank($where = 'bottom', $target = null)
183
    {
184
        return $this->createItem('blank', null, null, null, $where, $target);
185
    } // end func &createBlank
186
 
187
    /**
188
    * Adds a directive to this item.
189
    * This is a helper method that calls createItem
190
    *
191
    * @param  string    $name           Name of new directive
192
    * @param  string    $content        Content of new directive
193
    * @param  mixed     $attributes     Directive attributes
194
    * @param  string    $where          Position : 'top', 'bottom', 'before', 'after'
195
    * @param  object    $target         Needed when $where is 'before' or 'after'
196
    * @return object  reference to new item or Pear_Error
197
    */
198
    function &createDirective($name, $content, $attributes = null, $where = 'bottom', $target = null)
199
    {
200
        return $this->createItem('directive', $name, $content, $attributes, $where, $target);
201
    } // end func &createDirective
202
 
203
    /**
204
    * Adds a section to this item.
205
    *
206
    * This is a helper method that calls createItem
207
    * If the section already exists, it won't create a new one.
208
    * It will return reference to existing item.
209
    *
210
    * @param  string    $name           Name of new section
211
    * @param  array     $attributes     Section attributes
212
    * @param  string    $where          Position : 'top', 'bottom', 'before', 'after'
213
    * @param  object    $target         Needed when $where is 'before' or 'after'
214
    * @return object  reference to new item or Pear_Error
215
    */
216
    function &createSection($name, $attributes = null, $where = 'bottom', $target = null)
217
    {
218
        return $this->createItem('section', $name, null, $attributes, $where, $target);
219
    } // end func &createSection
220
 
221
    /**
222
    * Tries to find the specified item(s) and returns the objects.
223
    *
224
    * Examples:
225
    * $directives =& $obj->getItem('directive');
226
    * $directive_bar_4 =& $obj->getItem('directive', 'bar', null, 4);
227
    * $section_foo =& $obj->getItem('section', 'foo');
228
    *
229
    * This method can only be called on an object of type 'section'.
230
    * Note that root is a section.
231
    * This method is not recursive and tries to keep the current structure.
232
    * For a deeper search, use searchPath()
233
    *
234
    * @param  string    $type        Type of item: directive, section, comment, blank...
235
    * @param  mixed     $name        Item name
236
    * @param  mixed     $content     Find item with this content
237
    * @param  array     $attributes  Find item with attribute set to the given value
238
    * @param  int       $index       Index of the item in the returned object list. If it is not set, will try to return the last item with this name.
239
    * @return mixed  reference to item found or false when not found
240
    * @see &searchPath()
241
    */
242
    function &getItem($type = null, $name = null, $content = null, $attributes = null, $index = -1)
243
    {
244
        if ($this->type != 'section') {
245
            return PEAR::raiseError('Config_Container::getItem must be called on a section type object.', null, PEAR_ERROR_RETURN);
246
        }
247
        if (!is_null($type)) {
248
            $testFields[] = 'type';
249
        }
250
        if (!is_null($name)) {
251
            $testFields[] = 'name';
252
        }
253
        if (!is_null($content)) {
254
            $testFields[] = 'content';
255
        }
256
        if (!is_null($attributes) && is_array($attributes)) {
257
            $testFields[] = 'attributes';
258
        }
259
 
260
        $itemsArr = array();
261
        $fieldsToMatch = count($testFields);
262
        for ($i = 0, $count = count($this->children); $i < $count; $i++) {
263
            $match = 0;
264
            reset($testFields);
265
            foreach ($testFields as $field) {
266
                if ($field != 'attributes') {
267
                    if ($this->children[$i]->$field == ${$field}) {
268
                        $match++;
269
                    }
270
                } else {
271
                    // Look for attributes in array
272
                    $attrToMatch = count($attributes);
273
                    $attrMatch = 0;
274
                    foreach ($attributes as $key => $value) {
275
                        if (isset($this->children[$i]->attributes[$key]) &&
276
                            $this->children[$i]->attributes[$key] == $value) {
277
                            $attrMatch++;
278
                        }
279
                    }
280
                    if ($attrMatch == $attrToMatch) {
281
                        $match++;
282
                    }
283
                }
284
            }
285
            if ($match == $fieldsToMatch) {
286
                $itemsArr[] =& $this->children[$i];
287
            }
288
        }
289
        if ($index >= 0) {
290
            if (isset($itemsArr[$index])) {
291
                return $itemsArr[$index];
292
            } else {
293
                $return = false;
294
                return $return;
295
            }
296
        } else {
297
            if ($count = count($itemsArr)) {
298
                return $itemsArr[$count-1];
299
            } else {
300
                $return = false;
301
                return $return;
302
            }
303
        }
304
    } // end func &getItem
305
 
306
    /**
307
    * Finds a node using XPATH like format.
308
    *
309
    * The search format is an array:
310
    * array(item1, item2, item3, ...)
311
    *
312
    * Each item can be defined as the following:
313
    * item = 'string' : will match the container named 'string'
314
    * item = array('string', array('name' => 'xyz'))
315
    * will match the container name 'string' whose attribute name is equal to "xyz"
316
    * For example : <string name="xyz">
317
    *
318
    * @param    mixed   Search path and attributes
319
    *
320
    * @return   mixed   Config_Container object, array of Config_Container objects or false on failure.
321
    * @access   public
322
    */
323
    function &searchPath($args)
324
    {
325
        if ($this->type != 'section') {
326
            return PEAR::raiseError('Config_Container::searchPath must be called on a section type object.', null, PEAR_ERROR_RETURN);
327
        }
328
 
329
        $arg = array_shift($args);
330
 
331
        if (is_array($arg)) {
332
            $name = $arg[0];
333
            $attributes = $arg[1];
334
        } else {
335
            $name = $arg;
336
            $attributes = null;
337
        }
338
        // find all the matches for first..
339
        $match =& $this->getItem(null, $name, null, $attributes);
340
 
341
        if (!$match) {
342
            $return = false;
343
            return $return;
344
        }
345
        if (!empty($args)) {
346
            return $match->searchPath($args);
347
        }
348
        return $match;
349
    } // end func &searchPath
350
 
351
    /**
352
    * Return a child directive's content.
353
    *
354
    * This method can use two different search approach, depending on
355
    * the parameter it is given. If the parameter is an array, it will use
356
    * the {@link Config_Container::searchPath()} method. If it is a string,
357
    * it will use the {@link Config_Container::getItem()} method.
358
    *
359
    * Example:
360
    * <code>
361
    * require_once 'Config.php';
362
    * $ini = new Config();
363
    * $conf =& $ini->parseConfig('/path/to/config.ini', 'inicommented');
364
    *
365
    * // Will return the value found at :
366
    * // [Database]
367
    * // host=localhost
368
    * echo $conf->directiveContent(array('Database', 'host')));
369
    *
370
    * // Will return the value found at :
371
    * // date="dec-2004"
372
    * echo $conf->directiveContent('date');
373
    *
374
    * </code>
375
    *
376
    * @param    mixed   Search path and attributes or a directive name
377
    * @param    int     Index of the item in the returned directive list.
378
    *                   Eventually used if args is a string.
379
    *
380
    * @return   mixed   Content of directive or false if not found.
381
    * @access   public
382
    */
383
    function directiveContent($args, $index = -1)
384
    {
385
        if (is_array($args)) {
386
            $item =& $this->searchPath($args);
387
        } else {
388
            $item =& $this->getItem('directive', $args, null, null, $index);
389
        }
390
        if ($item) {
391
            return $item->getContent();
392
        }
393
        return false;
394
    } // end func getDirectiveContent
395
 
396
    /**
397
    * Returns how many children this container has
398
    *
399
    * @param  string    $type    type of children counted
400
    * @param  string    $name    name of children counted
401
    * @return int  number of children found
402
    */
403
    function countChildren($type = null, $name = null)
404
    {
405
        if (is_null($type) && is_null($name)) {
406
            return count($this->children);
407
        }
408
        $count = 0;
409
        if (isset($name) && isset($type)) {
410
            for ($i = 0, $children = count($this->children); $i < $children; $i++) {
411
                if ($this->children[$i]->name === $name &&
412
                    $this->children[$i]->type == $type) {
413
                    $count++;
414
                }
415
            }
416
            return $count;
417
        }
418
        if (isset($type)) {
419
            for ($i = 0, $children = count($this->children); $i < $children; $i++) {
420
                if ($this->children[$i]->type == $type) {
421
                    $count++;
422
                }
423
            }
424
            return $count;
425
        }
426
        if (isset($name)) {
427
            // Some directives can have the same name
428
            for ($i = 0, $children = count($this->children); $i < $children; $i++) {
429
                if ($this->children[$i]->name === $name) {
430
                    $count++;
431
                }
432
            }
433
            return $count;
434
        }
435
    } // end func &countChildren
436
 
437
    /**
438
    * Deletes an item (section, directive, comment...) from the current object
439
    * TODO: recursive remove in sub-sections
440
    * @return mixed  true if object was removed, false if not, or PEAR_Error if root
441
    */
442
    function removeItem()
443
    {
444
        if ($this->isRoot()) {
445
            return PEAR::raiseError('Cannot remove root item in Config_Container::removeItem.', null, PEAR_ERROR_RETURN);
446
        }
447
        $index = $this->getItemIndex();
448
        if (!is_null($index)) {
449
            array_splice($this->parent->children, $index, 1);
450
            return true;
451
        }
452
        return false;
453
    } // end func removeItem
454
 
455
    /**
456
    * Returns the item index in its parent children array.
457
    * @return int  returns int or null if root object
458
    */
459
    function getItemIndex()
460
    {
461
        if (is_object($this->parent)) {
462
            // This will be optimized with Zend Engine 2
463
            $pchildren =& $this->parent->children;
464
            for ($i = 0, $count = count($pchildren); $i < $count; $i++) {
465
                if ($pchildren[$i]->_id == $this->_id) {
466
                    return $i;
467
                }
468
            }
469
        }
470
        return;
471
    } // end func getItemIndex
472
 
473
    /**
474
    * Returns the item rank in its parent children array
475
    * according to other items with same type and name.
476
    * @param bool  count items differently by type
477
    * @return int  returns int or null if root object
478
    */
479
    function getItemPosition($byType = true)
480
    {
481
        if (is_object($this->parent)) {
482
            $pchildren =& $this->parent->children;
483
            for ($i = 0, $count = count($pchildren); $i < $count; $i++) {
484
                if ($pchildren[$i]->name == $this->name) {
485
                    if ($byType == true) {
486
                        if ($pchildren[$i]->type == $this->type) {
487
                            $obj[] =& $pchildren[$i];
488
                        }
489
                    } else {
490
                        $obj[] =& $pchildren[$i];
491
                    }
492
                }
493
            }
494
            for ($i = 0, $count = count($obj); $i < $count; $i++) {
495
                if ($obj[$i]->_id == $this->_id) {
496
                    return $i;
497
                }
498
            }
499
        }
500
        return;
501
    } // end func getItemPosition
502
 
503
    /**
504
    * Returns the item parent object.
505
    * @return object  returns reference to parent object or null if root object
506
    */
507
    function &getParent()
508
    {
509
        return $this->parent;
510
    } // end func &getParent
511
 
512
    /**
513
    * Returns the item parent object.
514
    * @return mixed  returns reference to child object or false if child does not exist
515
    */
516
    function &getChild($index = 0)
517
    {
518
        if (!empty($this->children[$index])) {
519
            return $this->children[$index];
520
        } else {
521
            return false;
522
        }
523
    } // end func &getChild
524
 
525
    /**
526
    * Set this item's name.
527
    * @return void
528
    */
529
    function setName($name)
530
    {
531
        $this->name = $name;
532
    } // end func setName
533
 
534
    /**
535
    * Get this item's name.
536
    * @return string    item's name
537
    */
538
    function getName()
539
    {
540
        return $this->name;
541
    } // end func getName
542
 
543
    /**
544
    * Set this item's content.
545
    * @return void
546
    */
547
    function setContent($content)
548
    {
549
        $this->content = $content;
550
    } // end func setContent
551
 
552
    /**
553
    * Get this item's content.
554
    * @return string    item's content
555
    */
556
    function getContent()
557
    {
558
        return $this->content;
559
    } // end func getContent
560
 
561
    /**
562
    * Set this item's type.
563
    * @return void
564
    */
565
    function setType($type)
566
    {
567
        $this->type = $type;
568
    } // end func setType
569
 
570
    /**
571
    * Get this item's type.
572
    * @return string    item's type
573
    */
574
    function getType()
575
    {
576
        return $this->type;
577
    } // end func getType
578
 
579
    /**
580
    * Set this item's attributes.
581
    * @param  array    $attributes        Array of attributes
582
    * @return void
583
    */
584
    function setAttributes($attributes)
585
    {
586
        $this->attributes = $attributes;
587
    } // end func setAttributes
588
 
589
    /**
590
    * Set this item's attributes.
591
    * @param  array    $attributes        Array of attributes
592
    * @return void
593
    */
594
    function updateAttributes($attributes)
595
    {
596
        if (is_array($attributes)) {
597
            foreach ($attributes as $key => $value) {
598
                $this->attributes[$key] = $value;
599
            }
600
        }
601
    } // end func updateAttributes
602
 
603
    /**
604
    * Get this item's attributes.
605
    * @return array    item's attributes
606
    */
607
    function getAttributes()
608
    {
609
        return $this->attributes;
610
    } // end func getAttributes
611
 
612
    /**
613
    * Get one attribute value of this item
614
    * @param  string   $attribute        Attribute key
615
    * @return mixed    item's attribute value
616
    */
617
    function getAttribute($attribute)
618
    {
619
        if (isset($this->attributes[$attribute])) {
620
            return $this->attributes[$attribute];
621
        }
622
        return null;
623
    } // end func getAttribute
624
 
625
    /**
626
    * Set a children directive content.
627
    * This is an helper method calling getItem and addItem or setContent for you.
628
    * If the directive does not exist, it will be created at the bottom.
629
    *
630
    * @param  string    $name        Name of the directive to look for
631
    * @param  mixed     $content     New content
632
    * @param  int       $index       Index of the directive to set,
633
    *                                in case there are more than one directive
634
    *                                with the same name
635
    * @return object    newly set directive
636
    */
637
    function &setDirective($name, $content, $index = -1)
638
    {
639
        $item =& $this->getItem('directive', $name, null, null, $index);
640
        if ($item === false || PEAR::isError($item)) {
641
            // Directive does not exist, will create one
642
            unset($item);
643
            return $this->createDirective($name, $content, null);
644
        } else {
645
            // Change existing directive value
646
            $item->setContent($content);
647
            return $item;
648
        }
649
    } // end func setDirective
650
 
651
    /**
652
    * Is this item root, in a config container object
653
    * @return bool    true if item is root
654
    */
655
    function isRoot()
656
    {
657
        if (is_null($this->parent)) {
658
            return true;
659
        }
660
        return false;
661
    } // end func isRoot
662
 
663
    /**
664
    * Call the toString methods in the container plugin
665
    * @param    string  $configType  Type of configuration used to generate the string
666
    * @param    array   $options     Specify special options used by the parser
667
    * @return   mixed   true on success or PEAR_ERROR
668
    */
669
    function toString($configType, $options = array())
670
    {
671
        $configType = strtolower($configType);
672
        if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) {
673
            return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::toString.", null, PEAR_ERROR_RETURN);
674
        }
675
        $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0];
676
        $className   = $GLOBALS['CONFIG_TYPES'][$configType][1];
677
        include_once($includeFile);
678
        $renderer = new $className($options);
679
        return $renderer->toString($this);
680
    } // end func toString
681
 
682
    /**
683
    * Returns a key/value pair array of the container and its children.
684
    *
685
    * Format : section[directive][index] = value
686
    * If the container has attributes, it will use '@' and '#'
687
    * index is here because multiple directives can have the same name.
688
    *
689
    * @param    bool    $useAttr        Whether to return the attributes too
690
    * @return array
691
    */
692
    function toArray($useAttr = true)
693
    {
694
        $array[$this->name] = array();
695
        switch ($this->type) {
696
            case 'directive':
697
                if ($useAttr && count($this->attributes) > 0) {
698
                    $array[$this->name]['#'] = $this->content;
699
                    $array[$this->name]['@'] = $this->attributes;
700
                } else {
701
                    $array[$this->name] = $this->content;
702
                }
703
                break;
704
            case 'section':
705
                if ($useAttr && count($this->attributes) > 0) {
706
                    $array[$this->name]['@'] = $this->attributes;
707
                }
708
                if ($count = count($this->children)) {
709
                    for ($i = 0; $i < $count; $i++) {
710
                        $newArr = $this->children[$i]->toArray($useAttr);
711
                        if (!is_null($newArr)) {
712
                            foreach ($newArr as $key => $value) {
713
                                if (isset($array[$this->name][$key])) {
714
                                    // duplicate name/type
715
                                    if (!is_array($array[$this->name][$key]) ||
716
                                        !isset($array[$this->name][$key][0])) {
717
                                        $old = $array[$this->name][$key];
718
                                        unset($array[$this->name][$key]);
719
                                        $array[$this->name][$key][0] = $old;
720
                                    }
721
                                    $array[$this->name][$key][] = $value;
722
                                } else {
723
                                    $array[$this->name][$key] = $value;
724
                                }
725
                            }
726
                        }
727
                    }
728
                }
729
                break;
730
            default:
731
                return null;
732
        }
733
        return $array;
734
    } // end func toArray
735
 
736
    /**
737
    * Writes the configuration to a file
738
    *
739
    * @param  mixed  $datasrc        Info on datasource such as path to the configuraton file or dsn...
740
    * @param  string $configType     Type of configuration
741
    * @param  array  $options        Options for writer
742
    * @access public
743
    * @return mixed     true on success or PEAR_ERROR
744
    */
745
    function writeDatasrc($datasrc, $configType, $options = array())
746
    {
747
        $configType = strtolower($configType);
748
        if (!isset($GLOBALS['CONFIG_TYPES'][$configType])) {
749
            return PEAR::raiseError("Configuration type '$configType' is not registered in Config_Container::writeDatasrc.", null, PEAR_ERROR_RETURN);
750
        }
751
        $includeFile = $GLOBALS['CONFIG_TYPES'][$configType][0];
752
        $className = $GLOBALS['CONFIG_TYPES'][$configType][1];
753
        include_once($includeFile);
754
 
755
        $writeMethodName = (version_compare(phpversion(), '5', '<')) ? 'writedatasrc' : 'writeDatasrc';
756
        if (in_array($writeMethodName, get_class_methods($className))) {
757
            $writer = new $className($options);
758
            return $writer->writeDatasrc($datasrc, $this);
759
        }
760
 
761
        // Default behaviour
762
        $fp = @fopen($datasrc, 'w');
763
        if ($fp) {
764
            $string = $this->toString($configType, $options);
765
            $len = strlen($string);
766
            @flock($fp, LOCK_EX);
767
            @fwrite($fp, $string, $len);
768
            @flock($fp, LOCK_UN);
769
            @fclose($fp);
770
            return true;
771
        } else {
772
            return PEAR::raiseError('Cannot open datasource for writing.', 1, PEAR_ERROR_RETURN);
773
        }
774
    } // end func writeDatasrc
775
} // end class Config_Container
776
?>