Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
4
// | PHP version 4.0                                                      |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2003 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.0 of the PHP license,       |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
17
// |          Bertrand Mansion <bmansion@mamasam.com>                     |
18
// +----------------------------------------------------------------------+
19
//
20
// $Id$
21
 
22
require_once('HTML/QuickForm/element.php');
23
 
24
/**
25
 * Class to dynamically create an HTML SELECT
26
 *
27
 * @author       Adam Daniel <adaniel1@eesus.jnj.com>
28
 * @author       Bertrand Mansion <bmansion@mamasam.com>
29
 * @version      1.0
30
 * @since        PHP4.04pl1
31
 * @access       public
32
 */
33
class HTML_QuickForm_select extends HTML_QuickForm_element {
34
 
35
    // {{{ properties
36
 
37
    /**
38
     * Contains the select options
39
     *
40
     * @var       array
41
     * @since     1.0
42
     * @access    private
43
     */
44
    var $_options = array();
45
 
46
    /**
47
     * Default values of the SELECT
48
     *
49
     * @var       array
50
     * @since     1.0
51
     * @access    private
52
     */
53
    var $_values = null;
54
 
55
    // }}}
56
    // {{{ constructor
57
 
58
    /**
59
     * Class constructor
60
     *
61
     * @param     string    Select name attribute
62
     * @param     mixed     Label(s) for the select
63
     * @param     mixed     Data to be used to populate options
64
     * @param     mixed     Either a typical HTML attribute string or an associative array
65
     * @since     1.0
66
     * @access    public
67
     * @return    void
68
     */
69
    public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null) {
70
        parent::__construct($elementName, $elementLabel, $attributes);
71
        $this->_persistantFreeze = true;
72
        $this->_type = 'select';
73
        if (isset($options)) {
74
            $this->load($options);
75
        }
76
    } //end constructor
77
 
78
    /**
79
     * Old syntax of class constructor. Deprecated in PHP7.
80
     *
81
     * @deprecated since Moodle 3.1
82
     */
83
    public function HTML_QuickForm_select($elementName=null, $elementLabel=null, $options=null, $attributes=null) {
84
        debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
85
        self::__construct($elementName, $elementLabel, $attributes);
86
    }
87
 
88
    // }}}
89
    // {{{ apiVersion()
90
 
91
    /**
92
     * Returns the current API version
93
     *
94
     * @since     1.0
95
     * @access    public
96
     * @return    double
97
     */
98
    function apiVersion()
99
    {
100
        return 2.3;
101
    } //end func apiVersion
102
 
103
    // }}}
104
    // {{{ setSelected()
105
 
106
    /**
107
     * Sets the default values of the select box
108
     *
109
     * @param     mixed    $values  Array or comma delimited string of selected values
110
     * @since     1.0
111
     * @access    public
112
     * @return    void
113
     */
114
    function setSelected($values)
115
    {
116
        if (is_string($values) && $this->getMultiple()) {
117
            $values = preg_split("/[ ]?,[ ]?/", $values);
118
        }
119
        if (is_array($values)) {
120
            $this->_values = array_values($values);
121
        } else {
122
            $this->_values = array($values);
123
        }
124
    } //end func setSelected
125
 
126
    // }}}
127
    // {{{ getSelected()
128
 
129
    /**
130
     * Returns an array of the selected values
131
     *
132
     * @since     1.0
133
     * @access    public
134
     * @return    array of selected values
135
     */
136
    function getSelected()
137
    {
138
        return $this->_values;
139
    } // end func getSelected
140
 
141
    // }}}
142
    // {{{ setName()
143
 
144
    /**
145
     * Sets the input field name
146
     *
147
     * @param     string    $name   Input field name attribute
148
     * @since     1.0
149
     * @access    public
150
     * @return    void
151
     */
152
    function setName($name)
153
    {
154
        $this->updateAttributes(array('name' => $name));
155
    } //end func setName
156
 
157
    // }}}
158
    // {{{ getName()
159
 
160
    /**
161
     * Returns the element name
162
     *
163
     * @since     1.0
164
     * @access    public
165
     * @return    string
166
     */
167
    function getName()
168
    {
169
        return $this->getAttribute('name');
170
    } //end func getName
171
 
172
    // }}}
173
    // {{{ getPrivateName()
174
 
175
    /**
176
     * Returns the element name (possibly with brackets appended)
177
     *
178
     * @since     1.0
179
     * @access    public
180
     * @return    string
181
     */
182
    function getPrivateName()
183
    {
184
        if ($this->getAttribute('multiple')) {
185
            return $this->getName() . '[]';
186
        } else {
187
            return $this->getName();
188
        }
189
    } //end func getPrivateName
190
 
191
    // }}}
192
    // {{{ setValue()
193
 
194
    /**
195
     * Sets the value of the form element
196
     *
197
     * @param     mixed    $values  Array or comma delimited string of selected values
198
     * @since     1.0
199
     * @access    public
200
     * @return    void
201
     */
202
    function setValue($value)
203
    {
204
        $this->setSelected($value);
205
    } // end func setValue
206
 
207
    // }}}
208
    // {{{ getValue()
209
 
210
    /**
211
     * Returns an array of the selected values
212
     *
213
     * @since     1.0
214
     * @access    public
215
     * @return    array of selected values
216
     */
217
    function getValue()
218
    {
219
        return $this->_values;
220
    } // end func getValue
221
 
222
    // }}}
223
    // {{{ setSize()
224
 
225
    /**
226
     * Sets the select field size, only applies to 'multiple' selects
227
     *
228
     * @param     int    $size  Size of select  field
229
     * @since     1.0
230
     * @access    public
231
     * @return    void
232
     */
233
    function setSize($size)
234
    {
235
        $this->updateAttributes(array('size' => $size));
236
    } //end func setSize
237
 
238
    // }}}
239
    // {{{ getSize()
240
 
241
    /**
242
     * Returns the select field size
243
     *
244
     * @since     1.0
245
     * @access    public
246
     * @return    int
247
     */
248
    function getSize()
249
    {
250
        return $this->getAttribute('size');
251
    } //end func getSize
252
 
253
    // }}}
254
    // {{{ setMultiple()
255
 
256
    /**
257
     * Sets the select mutiple attribute
258
     *
259
     * @param     bool    $multiple  Whether the select supports multi-selections
260
     * @since     1.2
261
     * @access    public
262
     * @return    void
263
     */
264
    function setMultiple($multiple)
265
    {
266
        if ($multiple) {
267
            $this->updateAttributes(array('multiple' => 'multiple'));
268
        } else {
269
            $this->removeAttribute('multiple');
270
        }
271
    } //end func setMultiple
272
 
273
    // }}}
274
    // {{{ getMultiple()
275
 
276
    /**
277
     * Returns the select mutiple attribute
278
     *
279
     * @since     1.2
280
     * @access    public
281
     * @return    bool    true if multiple select, false otherwise
282
     */
283
    function getMultiple()
284
    {
285
        return (bool)$this->getAttribute('multiple');
286
    } //end func getMultiple
287
 
288
    // }}}
289
    // {{{ addOption()
290
 
291
    /**
292
     * Adds a new OPTION to the SELECT
293
     *
294
     * @param     string    $text       Display text for the OPTION
295
     * @param     string    $value      Value for the OPTION
296
     * @param     mixed     $attributes Either a typical HTML attribute string
297
     *                                  or an associative array
298
     * @since     1.0
299
     * @access    public
300
     * @return    void
301
     */
302
    function addOption($text, $value, $attributes=null)
303
    {
304
        if (null === $attributes) {
305
            $attributes = array('value' => $value);
306
        } else {
307
            $attributes = $this->_parseAttributes($attributes);
308
            if (isset($attributes['selected'])) {
309
                // the 'selected' attribute will be set in toHtml()
310
                $this->_removeAttr('selected', $attributes);
311
                if (is_null($this->_values)) {
312
                    $this->_values = array($value);
313
                } elseif (!in_array($value, $this->_values)) {
314
                    $this->_values[] = $value;
315
                }
316
            }
317
            $this->_updateAttrArray($attributes, array('value' => $value));
318
        }
319
        $this->_options[] = array('text' => $text, 'attr' => $attributes);
320
    } // end func addOption
321
 
322
    // }}}
323
    // {{{ loadArray()
324
 
325
    /**
326
     * Loads the options from an associative array
327
     *
328
     * @param     array    $arr     Associative array of options
329
     * @param     mixed    $values  (optional) Array or comma delimited string of selected values
330
     * @since     1.0
331
     * @access    public
332
     * @return    PEAR_Error on error or true
333
     * @throws    PEAR_Error
334
     */
335
    function loadArray($arr, $values=null)
336
    {
337
        if (!is_array($arr)) {
338
            return self::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array');
339
        }
340
        if (isset($values)) {
341
            $this->setSelected($values);
342
        }
343
        foreach ($arr as $key => $val) {
344
            // Warning: new API since release 2.3
345
            $this->addOption($val, $key);
346
        }
347
        return true;
348
    } // end func loadArray
349
 
350
    // }}}
351
    // {{{ loadDbResult()
352
 
353
    /**
354
     * Loads the options from DB_result object
355
     *
356
     * If no column names are specified the first two columns of the result are
357
     * used as the text and value columns respectively
358
     * @param     object    $result     DB_result object
359
     * @param     string    $textCol    (optional) Name of column to display as the OPTION text
360
     * @param     string    $valueCol   (optional) Name of column to use as the OPTION value
361
     * @param     mixed     $values     (optional) Array or comma delimited string of selected values
362
     * @since     1.0
363
     * @access    public
364
     * @return    PEAR_Error on error or true
365
     * @throws    PEAR_Error
366
     */
367
    function loadDbResult(&$result, $textCol=null, $valueCol=null, $values=null)
368
    {
369
        if (!is_object($result) || !is_a($result, 'db_result')) {
370
            return self::raiseError('Argument 1 of HTML_Select::loadDbResult is not a valid DB_result');
371
        }
372
        if (isset($values)) {
373
            $this->setValue($values);
374
        }
375
        $fetchMode = ($textCol && $valueCol) ? DB_FETCHMODE_ASSOC : DB_FETCHMODE_ORDERED;
376
        while (is_array($row = $result->fetchRow($fetchMode)) ) {
377
            if ($fetchMode == DB_FETCHMODE_ASSOC) {
378
                $this->addOption($row[$textCol], $row[$valueCol]);
379
            } else {
380
                $this->addOption($row[0], $row[1]);
381
            }
382
        }
383
        return true;
384
    } // end func loadDbResult
385
 
386
    // }}}
387
    // {{{ loadQuery()
388
 
389
    /**
390
     * Queries a database and loads the options from the results
391
     *
392
     * @param     mixed     $conn       Either an existing DB connection or a valid dsn
393
     * @param     string    $sql        SQL query string
394
     * @param     string    $textCol    (optional) Name of column to display as the OPTION text
395
     * @param     string    $valueCol   (optional) Name of column to use as the OPTION value
396
     * @param     mixed     $values     (optional) Array or comma delimited string of selected values
397
     * @since     1.1
398
     * @access    public
399
     * @return    void
400
     * @throws    PEAR_Error
401
     */
402
    function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null)
403
    {
404
        if (is_string($conn)) {
405
            require_once('DB.php');
406
            $dbConn = &DB::connect($conn, true);
407
            if (DB::isError($dbConn)) {
408
                return $dbConn;
409
            }
410
        } elseif (is_subclass_of($conn, "db_common")) {
411
            $dbConn = &$conn;
412
        } else {
413
            return self::raiseError('Argument 1 of HTML_Select::loadQuery is not a valid type');
414
        }
415
        $result = $dbConn->query($sql);
416
        if (DB::isError($result)) {
417
            return $result;
418
        }
419
        $this->loadDbResult($result, $textCol, $valueCol, $values);
420
        $result->free();
421
        if (is_string($conn)) {
422
            $dbConn->disconnect();
423
        }
424
        return true;
425
    } // end func loadQuery
426
 
427
    // }}}
428
    // {{{ load()
429
 
430
    /**
431
     * Loads options from different types of data sources
432
     *
433
     * This method is a simulated overloaded method.  The arguments, other than the
434
     * first are optional and only mean something depending on the type of the first argument.
435
     * If the first argument is an array then all arguments are passed in order to loadArray.
436
     * If the first argument is a db_result then all arguments are passed in order to loadDbResult.
437
     * If the first argument is a string or a DB connection then all arguments are
438
     * passed in order to loadQuery.
439
     * @param     mixed     $options     Options source currently supports assoc array or DB_result
440
     * @param     mixed     $param1     (optional) See function detail
441
     * @param     mixed     $param2     (optional) See function detail
442
     * @param     mixed     $param3     (optional) See function detail
443
     * @param     mixed     $param4     (optional) See function detail
444
     * @since     1.1
445
     * @access    public
446
     * @return    PEAR_Error on error or true
447
     * @throws    PEAR_Error
448
     */
449
    function load(&$options, $param1=null, $param2=null, $param3=null, $param4=null)
450
    {
451
        switch (true) {
452
            case is_array($options):
453
                return $this->loadArray($options, $param1);
454
                break;
455
            case (is_a($options, 'db_result')):
456
                return $this->loadDbResult($options, $param1, $param2, $param3);
457
                break;
458
            case (is_string($options) && !empty($options) || is_subclass_of($options, "db_common")):
459
                return $this->loadQuery($options, $param1, $param2, $param3, $param4);
460
                break;
461
        }
462
    } // end func load
463
 
464
    // }}}
465
    // {{{ toHtml()
466
 
467
    /**
468
     * Returns the SELECT in HTML
469
     *
470
     * @since     1.0
471
     * @access    public
472
     * @return    string
473
     */
474
    function toHtml()
475
    {
476
        if ($this->_flagFrozen) {
477
            return $this->getFrozenHtml();
478
        } else {
479
            $tabs    = $this->_getTabs();
480
            $strHtml = '';
481
 
482
            if ($this->getComment() != '') {
483
                $strHtml .= $tabs . '<!-- ' . $this->getComment() . " //-->\n";
484
            }
485
 
486
            if (!$this->getMultiple()) {
487
                $attrString = $this->_getAttrString($this->_attributes);
488
            } else {
489
                $myName = $this->getName();
490
                $this->setName($myName . '[]');
491
                $attrString = $this->_getAttrString($this->_attributes);
492
                $this->setName($myName);
493
            }
494
            $strHtml .= $tabs . '<select' . $attrString . ">\n";
495
 
496
            foreach ($this->_options as $option) {
497
                if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) {
498
                    $this->_updateAttrArray($option['attr'], array('selected' => 'selected'));
499
                }
500
                $strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
501
                            $option['text'] . "</option>\n";
502
            }
503
 
504
            return $strHtml . $tabs . '</select>';
505
        }
506
    } //end func toHtml
507
 
508
    // }}}
509
    // {{{ getFrozenHtml()
510
 
511
    /**
512
     * Returns the value of field without HTML tags
513
     *
514
     * @since     1.0
515
     * @access    public
516
     * @return    string
517
     */
518
    function getFrozenHtml()
519
    {
520
        $value = array();
521
        if (is_array($this->_values)) {
522
            foreach ($this->_values as $key => $val) {
523
                for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
524
                    if ((string)$val == (string)$this->_options[$i]['attr']['value']) {
525
                        $value[$key] = $this->_options[$i]['text'];
526
                        break;
527
                    }
528
                }
529
            }
530
        }
531
        $html = empty($value)? '&nbsp;': join('<br />', $value);
532
        if ($this->_persistantFreeze) {
533
            $name = $this->getPrivateName();
534
            // Only use id attribute if doing single hidden input
535
            if (1 == count($value)) {
536
                $id     = $this->getAttribute('id');
537
                $idAttr = isset($id)? array('id' => $id): array();
538
            } else {
539
                $idAttr = array();
540
            }
541
            foreach ($value as $key => $item) {
542
                $html .= '<input' . $this->_getAttrString(array(
543
                             'type'  => 'hidden',
544
                             'name'  => $name,
545
                             'value' => $this->_values[$key]
546
                         ) + $idAttr) . ' />';
547
            }
548
        }
549
        return $html;
550
    } //end func getFrozenHtml
551
 
552
    // }}}
553
    // {{{ exportValue()
554
 
555
   /**
556
    * We check the options and return only the values that _could_ have been
557
    * selected. We also return a scalar value if select is not "multiple"
558
    */
559
    function exportValue(&$submitValues, $assoc = false)
560
    {
561
        $value = $this->_findValue($submitValues);
562
        if (is_null($value)) {
563
            $value = $this->getValue();
564
        } elseif(!is_array($value)) {
565
            $value = array($value);
566
        }
567
        if (is_array($value) && !empty($this->_options)) {
568
            $cleanValue = null;
569
            foreach ($value as $v) {
570
                for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
571
                    if ($v == $this->_options[$i]['attr']['value']) {
572
                        $cleanValue[] = $v;
573
                        break;
574
                    }
575
                }
576
            }
577
        } else {
578
            $cleanValue = $value;
579
        }
580
        if (is_array($cleanValue) && !$this->getMultiple()) {
581
            return $this->_prepareValue($cleanValue[0], $assoc);
582
        } else {
583
            return $this->_prepareValue($cleanValue, $assoc);
584
        }
585
    }
586
 
587
    // }}}
588
    // {{{ onQuickFormEvent()
589
 
590
    function onQuickFormEvent($event, $arg, &$caller)
591
    {
592
        if ('updateValue' == $event) {
593
            $value = $this->_findValue($caller->_constantValues);
594
            if (null === $value) {
595
                $value = $this->_findValue($caller->_submitValues);
596
                // Fix for bug #4465 & #5269
597
                // XXX: should we push this to element::onQuickFormEvent()?
598
                if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) {
599
                    $value = $this->_findValue($caller->_defaultValues);
600
                }
601
            }
602
            if (null !== $value) {
603
                $this->setValue($value);
604
            }
605
            return true;
606
        } else {
607
            return parent::onQuickFormEvent($event, $arg, $caller);
608
        }
609
    }
610
 
611
    // }}}
612
} //end class HTML_QuickForm_select
613
?>