Overview

Packages

  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Datatype
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cContentTypePifaForm
  • DefaultFormModule
  • DefaultFormProcessor
  • ExampleOptionsDatasource
  • MailedFormProcessor
  • Pifa
  • PifaAbstractFormModule
  • PifaAbstractFormProcessor
  • PifaAjaxHandler
  • PifaExporter
  • PifaExternalOptionsDatasourceInterface
  • PifaField
  • PifaFieldCollection
  • PifaForm
  • PifaFormCollection
  • PifaImporter
  • PifaLeftBottomPage
  • PifaRightBottomFormDataPage
  • PifaRightBottomFormExportPage
  • PifaRightBottomFormFieldsPage
  • PifaRightBottomFormImportPage
  • PifaRightBottomFormPage
  • SolrRightBottomPage

Exceptions

  • PifaDatabaseException
  • PifaException
  • PifaIllegalStateException
  • PifaMailException
  • PifaNotImplementedException
  • PifaNotYetStoredException
  • PifaValidationException
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
   1: <?php
   2: 
   3: /**
   4:  *
   5:  * @package Plugin
   6:  * @subpackage FormAssistant
   7:  * @version SVN Revision $Rev:$
   8:  * @author marcus.gnass
   9:  * @copyright four for business AG
  10:  * @link http://www.4fb.de
  11:  */
  12: 
  13: // assert CONTENIDO framework
  14: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
  15: 
  16: /**
  17:  * PIFA field item collection class.
  18:  * It's a kind of a model.
  19:  *
  20:  * @author marcus.gnass
  21:  */
  22: class PifaFieldCollection extends ItemCollection {
  23: 
  24:     /**
  25:      * Create an instance.
  26:      *
  27:      * @param mixed $where clause to be used to load items or false
  28:      */
  29:     public function __construct($where = false) {
  30:         parent::__construct(cRegistry::getDbTableName('pifa_field'), 'idfield');
  31:         $this->_setItemClass('PifaField');
  32:         if (false !== $where) {
  33:             $this->select($where);
  34:         }
  35:     }
  36: 
  37:     /**
  38:      * Reorders a forms fields according to the given.
  39:      *
  40:      * @param int $idform
  41:      * @param string $idfields containing a CSV list of idfield as integer
  42:      */
  43:     public static function reorder($idform, $idfields) {
  44:         $sql = "-- PifaFieldCollection::reorder()
  45:             UPDATE
  46:                 " . cRegistry::getDbTableName('pifa_field') . "
  47:             SET
  48:                 field_rank = FIND_IN_SET(idfield, '$idfields')
  49:             WHERE
  50:                 idform = $idform
  51:             ;";
  52: 
  53:         cRegistry::getDb()->query($sql);
  54:     }
  55: }
  56: 
  57: /**
  58:  * PIFA field item class.
  59:  * It's a kind of a model.
  60:  *
  61:  * @author marcus.gnass
  62:  */
  63: class PifaField extends Item {
  64: 
  65:     /**
  66:      * Size to use for VARCHAR fields.
  67:      * Remember: the maximum row size for the used table type, not counting
  68:      * BLOBs, is 65535.
  69:      *
  70:      * @var int
  71:      * @todo PIFA should be able to calculate the size for one record by the
  72:      *       size of its fields and handle it accordingly.
  73:      */
  74:     const VARCHAR_SIZE = 255;
  75: 
  76:     /**
  77:      * Input field for single-line text.
  78:      *
  79:      * @var int
  80:      */
  81:     const INPUTTEXT = 1;
  82: 
  83:     /**
  84:      * Input field for multi-line text.
  85:      *
  86:      * @var int
  87:      */
  88:     const TEXTAREA = 2;
  89: 
  90:     /**
  91:      * Input field for single-line password.
  92:      *
  93:      * @var int
  94:      */
  95:     const INPUTPASSWORD = 3;
  96: 
  97:     /**
  98:      * Radiobox.
  99:      *
 100:      * @var int
 101:      */
 102:     const INPUTRADIO = 4;
 103: 
 104:     /**
 105:      * Checkbox
 106:      *
 107:      * @var int
 108:      */
 109:     const INPUTCHECKBOX = 5;
 110: 
 111:     /**
 112:      * Selectbox allowing for selection of a single option.
 113:      *
 114:      * @var int
 115:      */
 116:     const SELECT = 6;
 117: 
 118:     /**
 119:      * Selectbox allowing for selection of multiple options.
 120:      *
 121:      * @var int
 122:      */
 123:     const SELECTMULTI = 7;
 124: 
 125:     /**
 126:      * Input field for date selection.
 127:      *
 128:      * @var int
 129:      */
 130:     const DATEPICKER = 8;
 131: 
 132:     /**
 133:      * Input field for file selection.
 134:      *
 135:      * @var int
 136:      */
 137:     const INPUTFILE = 9;
 138: 
 139:     /**
 140:      * Processbar.
 141:      *
 142:      * @var int
 143:      */
 144:     const PROCESSBAR = 10;
 145: 
 146:     /**
 147:      * Slider.
 148:      *
 149:      * @var int
 150:      */
 151:     const SLIDER = 11;
 152: 
 153:     // /**
 154:     // * Captcha.
 155:     // *
 156:     // * @var int
 157:     // */
 158:     // const CAPTCHA = 12;
 159: 
 160:     /**
 161:      * Button of type submit.
 162:      *
 163:      * @var int
 164:      */
 165:     const BUTTONSUBMIT = 13;
 166: 
 167:     /**
 168:      * Button of type reset.
 169:      *
 170:      * @var int
 171:      */
 172:     const BUTTONRESET = 14;
 173: 
 174:     /**
 175:      * General button.
 176:      *
 177:      * @deprecated use PifaField::BUTTON instead
 178:      * @var int
 179:      */
 180:     const BUTTONBACK = 15;
 181: 
 182:     /**
 183:      * General button.
 184:      *
 185:      * @var int
 186:      */
 187:     const BUTTON = 15;
 188: 
 189:     /**
 190:      *
 191:      * @var int
 192:      */
 193:     const MATRIX = 16;
 194: 
 195:     /**
 196:      * A text to be displayed between form fields.
 197:      * It's no form field on its own but should be handled like one.
 198:      *
 199:      * @var int
 200:      */
 201:     const PARA = 17;
 202: 
 203:     /**
 204:      * A hidden input field.
 205:      *
 206:      * @var int
 207:      */
 208:     const INPUTHIDDEN = 18;
 209: 
 210:     /**
 211:      * Begin of a fieldset.
 212:      *
 213:      * @var int
 214:      */
 215:     const FIELDSET_BEGIN = 19;
 216: 
 217:     /**
 218:      * End of a fieldset.
 219:      *
 220:      * @var int
 221:      */
 222:     const FIELDSET_END = 20;
 223: 
 224:     /**
 225:      * Button of type image (which is in fact a submit button).
 226:      *
 227:      * @var int
 228:      */
 229:     const BUTTONIMAGE = 21;
 230: 
 231:     /**
 232:      * The form fields value.
 233:      *
 234:      * @var mixed
 235:      */
 236:     private $_value = NULL;
 237: 
 238:     /**
 239:      * The file that was transmitted in case of INPUTFILE.
 240:      *
 241:      * @var array
 242:      */
 243:     private $_file = NULL;
 244: 
 245:     /**
 246:      * Create an instance.
 247:      *
 248:      * @param mixed $id ID of item to be loaded or false
 249:      */
 250:     public function __construct($id = false) {
 251:         parent::__construct(cRegistry::getDbTableName('pifa_field'), 'idfield');
 252:         $this->setFilters(array(), array());
 253:         if (false !== $id) {
 254:             $this->loadByPrimaryKey($id);
 255:         }
 256:     }
 257: 
 258:     /**
 259:      * Rule has to be stripslashed to allow regular expressions with
 260:      * backslashes.
 261:      *
 262:      * @see Item::getField()
 263:      */
 264:     function getField($field, $bSafe = true) {
 265:         $value = parent::getField($field, $bSafe);
 266:         if ('rule' === $field) {
 267:             $value = stripslashes($value);
 268:         }
 269:         return $value;
 270:     }
 271: 
 272:     /**
 273:      * Getter for protected prop.
 274:      */
 275:     public function getLastError() {
 276:         return $this->lasterror;
 277:     }
 278: 
 279:     /**
 280:      * Returns this fields stored value.
 281:      *
 282:      * @return mixed the $_value
 283:      */
 284:     public function getValue() {
 285:         return $this->_value;
 286:     }
 287: 
 288:     /**
 289:      *
 290:      * @param mixed $_value
 291:      */
 292:     public function setValue($value) {
 293:         $this->_value = $value;
 294:     }
 295: 
 296:     /**
 297:      * keys: name, tmp_name
 298:      *
 299:      * @return array the $_file
 300:      */
 301:     public function getFile() {
 302:         return $this->_file;
 303:     }
 304: 
 305:     /**
 306:      *
 307:      * @param array $_file
 308:      */
 309:     public function setFile(array $_file) {
 310:         $this->_file = $_file;
 311:     }
 312: 
 313:     /**
 314:      *
 315:      * @throws PifaValidationException if an error occured
 316:      */
 317:     public function validate() {
 318: 
 319:         // get value
 320:         $values = $this->getValue();
 321:         if (NULL === $values) {
 322:             $values = $this->get('default_value');
 323:         }
 324: 
 325:         // value could be an array (for form fields with suffix '[]')
 326:         // so make it an array anyway ...
 327:         if (!is_array($values)) {
 328:             $values = array(
 329:                 $values
 330:             );
 331:         }
 332: 
 333:         foreach ($values as $value) {
 334: 
 335:             // if (self::CAPTCHA == $this->get('field_type')) {
 336:             // // check for captcha
 337:             // $securimage = new Securimage(array(
 338:             // 'session_name' => cRegistry::getClientId() . 'frontend'
 339:             // ));
 340:             // $isValid = $securimage->check($value);
 341:             // } else
 342: 
 343:             if (1 === cSecurity::toInteger($this->get('obligatory')) && 0 === strlen($value)) {
 344:                 // check for obligatory & rule
 345:                 $isValid = false;
 346:             } else if (0 < strlen($this->get('rule')) && in_array(preg_match($this->get('rule'), $value), array(
 347:                 false,
 348:                 0
 349:             ))) {
 350:                 // check for rule
 351:                 $isValid = false;
 352:             } else {
 353:                 $isValid = true;
 354:             }
 355: 
 356:             // throw error
 357:             if (true !== $isValid) {
 358:                 $error_message = $this->get('error_message');
 359:                 if (NULL === $error_message) {
 360:                     // $error_message = 'invalid data';
 361:                     $error_message = '';
 362:                 }
 363:                 throw new PifaValidationException(array(
 364:                     $this->get('idfield') => $error_message
 365:                 ));
 366:             }
 367:         }
 368:     }
 369: 
 370:     /**
 371:      * Returns HTML for this form that should be displayed in frontend.
 372:      *
 373:      * @param array $errors to be displayed for form field
 374:      * @return string
 375:      */
 376:     public function toHtml(array $errors = NULL) {
 377:         $out = '';
 378:         switch (cSecurity::toInteger($this->get('field_type'))) {
 379: 
 380:             case self::FIELDSET_BEGIN:
 381: 
 382:                 // optional class for field
 383:                 if (0 < strlen(trim($this->get('css_class')))) {
 384:                     $class = ' class="' . implode(' ', explode(',', $this->get('css_class'))) . '"';
 385:                 }
 386:                 $out .= "\n\t<fieldset$class>";
 387:                 // add optional legend/description
 388:                 if (1 === cSecurity::toInteger($this->get('display_label'))) {
 389:                     $label = $this->get('label');
 390:                     $out .= "\n\t<legend>$label</legend>";
 391:                 }
 392: 
 393:                 return $out;
 394:                 break;
 395: 
 396:             case self::FIELDSET_END:
 397: 
 398:                 return "\n\t</fieldset>";
 399:                 break;
 400: 
 401:             default:
 402: 
 403:                 // build HTML content
 404:                 $content = array();
 405:                 try {
 406:                     $content[] = $this->_getElemLabel();
 407:                     $content[] = $this->_getElemField();
 408:                     $content[] = $this->_getElemHelp();
 409:                     $content[] = $this->_getElemScript();
 410:                     // add this fields error message
 411:                     if (isset($errors[$this->get('idfield')])) {
 412:                         $error = $errors[$this->get('idfield')];
 413:                         if (0 < strlen($error)) {
 414:                             $content[] = new cHTMLParagraph($error, 'pifa-error-message');
 415:                         }
 416:                     }
 417:                 } catch (PifaNotImplementedException $e) {
 418:                     return NULL; // PASS // warning?
 419:                 }
 420: 
 421:                 $content = array_filter($content);
 422:                 if (empty($content)) {
 423:                     return NULL; // PASS // warning?
 424:                 }
 425: 
 426:                 // CSS class for surrounding division
 427:                 $class = 'pifa-field-' . $this->get('field_type');
 428:                 // optional class for field
 429:                 if (0 < strlen(trim($this->get('css_class')))) {
 430:                     $class .= ' ' . implode(' ', explode(',', $this->get('css_class')));
 431:                 }
 432:                 // optional class for obligatory field
 433:                 if (true === (bool) $this->get('obligatory')) {
 434:                     $class .= ' pifa-obligatory';
 435:                 }
 436:                 // optional error class for field
 437:                 if (NULL !== $error) {
 438:                     $class .= ' pifa-error';
 439:                 }
 440: 
 441:                 // ID for surrounding division
 442:                 $id = 'pifa-field-' . $this->get('idfield');
 443: 
 444:                 // surrounding division
 445:                 $div = new cHTMLDiv($content, $class, $id);
 446: 
 447:                 return "\n\t" . $div->render();
 448:                 break;
 449:         }
 450:     }
 451: 
 452:     /**
 453:      *
 454:      * @return cHTMLLabel
 455:      * @todo should be private, right?
 456:      */
 457:     public function _getElemLabel() {
 458:         if (1 !== cSecurity::toInteger($this->get('display_label'))) {
 459:             return '';
 460:         }
 461: 
 462:         // get field data
 463:         $idfield = cSecurity::toInteger($this->get('idfield'));
 464:         $fieldType = cSecurity::toInteger($this->get('field_type'));
 465:         $label = $this->get('label');
 466: 
 467:         if (NULL === $label) {
 468:             return NULL;
 469:         }
 470: 
 471:         // buttons have no external label
 472:         // the label is instead used as element value (see _getElemField())
 473:         if (in_array($fieldType, array(
 474:             self::BUTTONSUBMIT,
 475:             self::BUTTONRESET,
 476:             self::BUTTON,
 477:             self::BUTTONIMAGE
 478:         ))) {
 479:             return NULL;
 480:         }
 481: 
 482:         // obligatory fields have an additional ' *'
 483:         if (true === (bool) $this->get('obligatory')) {
 484:             $label .= ' *';
 485:         }
 486: 
 487:         // add span to request new captcha code
 488:         // if (self::CAPTCHA===$fieldType) {
 489:         // $label .= '<br><br><span style="cursor: pointer;">New Captcha
 490:         // Code</span>';
 491:         // }
 492: 
 493:         $elemLabel = new cHTMLLabel($label, 'pifa-field-elm-' . $idfield, 'pifa-field-lbl');
 494:         if (self::INPUTRADIO === $fieldType) {
 495:             $elemLabel->removeAttribute('for');
 496:         }
 497:         // set ID (workaround: remove ID first!)
 498:         $elemLabel->removeAttribute('id');
 499: 
 500:         return $elemLabel;
 501:     }
 502: 
 503:     /**
 504:      * Creates the HTML for a form field.
 505:      *
 506:      * The displayed value of a form field can be set via a GET param whose name
 507:      * has to be the fields column name which is set if the form is displayed
 508:      * for the first time and user hasn't entered another value.
 509:      *
 510:      * @param bool $error if field elem should be displayed as erroneous
 511:      * @throws PifaNotImplementedException if field type is not implemented
 512:      * @return cHTMLTextbox cHTMLTextarea cHTMLPasswordbox cHTMLSpan
 513:      *         cHTMLSelectElement NULL cHTMLButton
 514:      * @todo should be private, right?
 515:      */
 516:     public function _getElemField() {
 517: 
 518:         // get field data
 519:         $idfield = cSecurity::toInteger($this->get('idfield'));
 520: 
 521:         $fieldType = cSecurity::toInteger($this->get('field_type'));
 522: 
 523:         $columnName = $this->get('column_name');
 524: 
 525:         $label = $this->get('label');
 526: 
 527:         $uri = $this->get('uri');
 528: 
 529:         // get option labels & values
 530:         // either from field or from external data source class
 531:         $optionClass = $this->get('option_class');
 532:         if (0 === strlen(trim($optionClass))) {
 533:             $optionLabels = $this->get('option_labels');
 534:             if (NULL !== $optionLabels) {
 535:                 $optionLabels = explode(',', $optionLabels);
 536:             }
 537:             $optionValues = $this->get('option_values');
 538:             if (NULL !== $optionValues) {
 539:                 $optionValues = explode(',', $optionValues);
 540:             }
 541:         } else {
 542:             $filename = Pifa::fromCamelCase($optionClass);
 543:             $filename = "extensions/class.pifa.$filename.php";
 544:             if (false === file_exists(Pifa::getPath() . $filename)) {
 545:                 $msg = Pifa::i18n('MISSING_EOD_FILE');
 546:                 $msg = sprintf($msg, $filename);
 547:                 throw new PifaException($msg);
 548:             }
 549:             plugin_include(Pifa::getName(), $filename);
 550:             if (false === class_exists($optionClass)) {
 551:                 $msg = Pifa::i18n('MISSING_EOD_CLASS');
 552:                 $msg = sprintf($msg, $optionClass);
 553:                 throw new PifaException($msg);
 554:             }
 555:             $dataSource = new $optionClass();
 556:             $optionLabels = $dataSource->getOptionLabels();
 557:             $optionValues = $dataSource->getOptionValues();
 558:         }
 559: 
 560:         // ID for field & FOR for label
 561:         $id = 'pifa-field-elm-' . $idfield;
 562: 
 563:         // get current value
 564:         $value = $this->getValue();
 565: 
 566:         // if no current value is given
 567:         if (NULL === $value) {
 568:             // the fields default value is used
 569:             $value = $this->get('default_value');
 570:             // which could be overwritten by a GET param
 571:             if (array_key_exists($columnName, $_GET)) {
 572:                 $value = $_GET[$columnName];
 573:                 // try to prevent XSS ... the lazy way ...
 574:                 $value = htmlentities($value, ENT_COMPAT | ENT_HTML401, 'UTF-8');
 575:             }
 576:         }
 577: 
 578:         switch ($fieldType) {
 579: 
 580:             case self::INPUTTEXT:
 581: 
 582:                 $elemField = new cHTMLTextbox($columnName);
 583:                 // set ID (workaround: remove ID first!)
 584:                 $elemField->removeAttribute('id')->setID($id);
 585:                 // due to a bug setting NULL as title leads to title="title"
 586:                 if (!is_null($this->get('default_value'))) {
 587:                     $elemField->setAttribute('title', $this->get('default_value'));
 588:                 }
 589:                 if (!is_null($value)) {
 590:                     $elemField->setValue($value);
 591:                 }
 592:                 break;
 593: 
 594:             case self::TEXTAREA:
 595: 
 596:                 $elemField = new cHTMLTextarea($columnName);
 597:                 // set ID (workaround: remove ID first!)
 598:                 $elemField->removeAttribute('id')->setID($id);
 599:                 if (!is_null($this->get('default_value'))) {
 600:                     $elemField->setAttribute('title', $this->get('default_value'));
 601:                 }
 602:                 if (!is_null($value)) {
 603:                     $elemField->setValue($value);
 604:                 }
 605:                 break;
 606: 
 607:             case self::INPUTPASSWORD:
 608: 
 609:                 $elemField = new cHTMLPasswordbox($columnName);
 610:                 // set ID (workaround: remove ID first!)
 611:                 $elemField->removeAttribute('id')->setID($id);
 612:                 if (!is_null($this->get('default_value'))) {
 613:                     $elemField->setAttribute('title', $this->get('default_value'));
 614:                 }
 615:                 if (!is_null($value)) {
 616:                     $elemField->setValue($value);
 617:                 }
 618:                 break;
 619: 
 620:             case self::INPUTRADIO:
 621:             case self::INPUTCHECKBOX:
 622: 
 623:                 $count = min(array(
 624:                     count($optionLabels),
 625:                     count($optionValues)
 626:                 ));
 627:                 $tmpHtml = '';
 628:                 for ($i = 0; $i < $count; $i++) {
 629:                     if (self::INPUTRADIO === $fieldType) {
 630:                         $elemField = new cHTMLRadiobutton($columnName, $optionValues[$i]);
 631:                     } else if (self::INPUTCHECKBOX === $fieldType) {
 632:                         $elemField = new cHTMLCheckbox($columnName . '[]', $optionValues[$i]);
 633:                     }
 634:                     if (!is_array($value)) {
 635:                         $value = explode(',', $value);
 636:                     }
 637:                     $elemField->setChecked(in_array($optionValues[$i], $value));
 638:                     $elemField->setLabelText($optionLabels[$i]);
 639:                     $tmpHtml .= $elemField->render();
 640:                 }
 641:                 $elemField = new cHTMLSpan($tmpHtml);
 642:                 break;
 643: 
 644:             case self::SELECT:
 645:             case self::SELECTMULTI:
 646: 
 647:                 $elemField = new cHTMLSelectElement($columnName);
 648: 
 649:                 // set ID (workaround: remove ID first!)
 650:                 $elemField->removeAttribute('id')->setID($id);
 651:                 $autofill = array();
 652:                 $count = min(array(
 653:                     count($optionLabels),
 654:                     count($optionValues)
 655:                 ));
 656: 
 657:                 for ($i = 0; $i < $count; $i++) {
 658:                     $autofill[$optionValues[$i]] = $optionLabels[$i];
 659:                 }
 660: 
 661:                 $elemField->autoFill($autofill);
 662:                 $elemField->setDefault($value);
 663: 
 664:                 break;
 665: 
 666:             case self::DATEPICKER:
 667: 
 668:                 // hidden field to post date in generic date format
 669:                 $hiddenField = new cHTMLHiddenField($columnName);
 670:                 $hiddenField->removeAttribute('id')->setID($id . '-hidden');
 671:                 if (!is_null($value)) {
 672:                     $hiddenField->setValue($value);
 673:                 }
 674: 
 675:                 // textbox to display date in localized date format
 676:                 $textbox = new cHTMLTextbox($columnName . '_visible');
 677:                 // set ID (workaround: remove ID first!)
 678:                 $textbox->removeAttribute('id')->setID($id);
 679: 
 680:                 // surrounding div
 681:                 $elemField = new cHTMLDiv(array(
 682:                     $hiddenField,
 683:                     $textbox
 684:                 ));
 685: 
 686:                 break;
 687: 
 688:             case self::INPUTFILE:
 689: 
 690:                 $elemField = new cHTMLUpload($columnName);
 691:                 // set ID (workaround: remove ID first!)
 692:                 $elemField->removeAttribute('id')->setID($id);
 693:                 break;
 694: 
 695:             case self::PROCESSBAR:
 696: 
 697:                 $elemField = NULL;
 698:                 // TODO PROCESSBAR is NYI
 699:                 // $elemField = new cHTML();
 700:                 break;
 701: 
 702:             case self::SLIDER:
 703: 
 704:                 $elemField = NULL;
 705:                 // TODO SLIDER is NYI
 706:                 // $elemField = new cHTML();
 707:                 break;
 708: 
 709:             // case self::CAPTCHA:
 710: 
 711:                 // // input
 712:                 // $elemField = new cHTMLTextbox($columnName);
 713:                 // // set ID (workaround: remove ID first!)
 714:                 // $elemField->removeAttribute('id')->setID($id);
 715:                 // if (NULL !== $value) {
 716:                 // $elemField->setValue($value);
 717:                 // }
 718: 
 719:                 // // surrounding div
 720:                 // // img src (front_content.php?securimage)
 721:                 // // will be caught by Pifa::afterLoadPlugins
 722:                 // $img = new cHTMLImage('front_content.php?securimage');
 723:                 // $img->setAttribute('alt', 'captcha');
 724:                 // $elemField = new cHTMLDiv(array($img, $elemField));
 725: 
 726:                 // break;
 727: 
 728:             case self::BUTTONSUBMIT:
 729:             case self::BUTTONRESET:
 730:             case self::BUTTON:
 731:             case self::BUTTONIMAGE:
 732:                 $modes = array(
 733:                     self::BUTTONSUBMIT => 'submit',
 734:                     self::BUTTONRESET => 'reset',
 735:                     self::BUTTON => 'button',
 736:                     self::BUTTONIMAGE => 'image'
 737:                 );
 738:                 $mode = $modes[$fieldType];
 739:                 $elemField = new cHTMLButton($columnName);
 740:                 // set ID (workaround: remove ID first!)
 741:                 $elemField->removeAttribute('id')->setID($id);
 742:                 $elemField->setMode($mode);
 743:                 if ('image' === $mode) {
 744:                     $elemField->setAttribute('src', $uri);
 745:                     $elemField->removeAttribute('value');
 746:                 } else {
 747:                     // set label or mode as value
 748:                     $elemField->setTitle($label? $label : $mode);
 749:                 }
 750:                 break;
 751: 
 752:             case self::MATRIX:
 753: 
 754:                 $elemField = NULL;
 755:                 // TODO MATRIX is NYI
 756:                 // $elemField = new cHTML();
 757:                 break;
 758: 
 759:             case self::PARA:
 760:                 $elemField = NULL;
 761:                 // TODO PARA is NYI
 762:                 // $elemField = new cHTML();
 763:                 break;
 764: 
 765:             case self::INPUTHIDDEN:
 766:                 $elemField = new cHTMLHiddenField($columnName);
 767:                 // set ID (workaround: remove ID first!)
 768:                 $elemField->removeAttribute('id')->setID($id);
 769:                 if (NULL !== $value) {
 770:                     $elemField->setValue($value);
 771:                 }
 772:                 break;
 773: 
 774:             default:
 775:                 $msg = Pifa::i18n('NOT_IMPLEMENTED_FIELDTYPE');
 776:                 $msg = sprintf($msg, $fieldType);
 777:                 throw new PifaNotImplementedException($msg);
 778:         }
 779: 
 780:         return $elemField;
 781:     }
 782: 
 783:     /**
 784:      *
 785:      * @return Ambigous <NULL, cHTMLParagraph>
 786:      * @todo should be private, right?
 787:      */
 788:     public function _getElemHelp() {
 789:         $helpText = $this->get('help_text');
 790: 
 791:         $p = NULL;
 792:         if (0 < strlen($helpText)) {
 793:             $p = new cHTMLParagraph($helpText, 'pifa-field-help');
 794:         }
 795: 
 796:         return $p;
 797:     }
 798: 
 799:     /**
 800:      *
 801:      * @return Ambigous <NULL, cHTMLScript>
 802:      * @todo should be private, right?
 803:      */
 804:     public function _getElemScript() {
 805: 
 806:         // ID for field & FOR for label
 807:         $idfield = cSecurity::toInteger($this->get('idfield'));
 808:         $fieldType = cSecurity::toInteger($this->get('field_type'));
 809: 
 810:         switch ($fieldType) {
 811:             case self::DATEPICKER:
 812:                 $sel = '#pifa-field-elm-' . $idfield;
 813:                 // dateFormat: 'yy-mm-dd', // could be different
 814:                 // altFormat as ISO_8601
 815:                 $script = "jQuery(function(){ jQuery('$sel').datepicker({
 816:                     altFormat: 'yy-mm-dd',
 817:                     altField: '$sel-hidden'
 818:                 });});";
 819:                 break;
 820:             // case self::CAPTCHA:
 821:             // $sel = '#pifa-field-' . $idfield . ' label';
 822:             // $newCaptchaCode = mi18n("NEW_CAPTCHA_CODE");
 823:             // $script = "jQuery(function(){\n";
 824:             // // implement captcha reload on click
 825:             // $script .= "jQuery('$sel').click(function (e) {\n";
 826:             // $script .= "e.preventDefault();\n";
 827:             // $script .= "var url = 'front_content.php?securimage&' +
 828:             // Math.random();\n";
 829:             // $script .= "jQuery(this).parent().find('img').attr('src',
 830:             // url);\n";
 831:             // $script .= "});\n";
 832:             // // append 'New Captcha Code' to label
 833:             // $script .= "jQuery('$sel').append('<br/><br/><span
 834:             // style=\"cursor:pointer\">$newCaptchaCode</span>');";
 835:             // $script .= "});\n";
 836:             // break;
 837:             default:
 838:                 $script = '';
 839:         }
 840: 
 841:         $elemScript = NULL;
 842:         if (0 < strlen($script)) {
 843:             $elemScript = new cHTMLScript();
 844:             $elemScript->setContent($script);
 845:         }
 846: 
 847:         return $elemScript;
 848:     }
 849: 
 850:     /**
 851:      * Returns an array containing all field type ids.
 852:      *
 853:      * @return array
 854:      */
 855:     public static function getFieldTypeIds() {
 856:         return array_keys(self::getFieldTypeNames());
 857:     }
 858: 
 859:     /**
 860:      * Returns an array containing all field type ids mapped to their names.
 861:      *
 862:      * The order of field types in this array influences the order of icons
 863:      * displayed in the backend for selection!
 864:      *
 865:      * @return array
 866:      */
 867:     public static function getFieldTypeNames() {
 868:         return array(
 869:             self::INPUTTEXT => Pifa::i18n('INPUTTEXT'),
 870:             self::TEXTAREA => Pifa::i18n('TEXTAREA'),
 871:             self::INPUTPASSWORD => Pifa::i18n('INPUTPASSWORD'),
 872:             self::INPUTRADIO => Pifa::i18n('INPUTRADIO'),
 873:             self::INPUTCHECKBOX => Pifa::i18n('INPUTCHECKBOX'),
 874:             self::SELECT => Pifa::i18n('SELECT'),
 875:             self::SELECTMULTI => Pifa::i18n('SELECTMULTI'),
 876:             self::DATEPICKER => Pifa::i18n('DATEPICKER'),
 877:             self::INPUTFILE => Pifa::i18n('INPUTFILE'),
 878:             self::PROCESSBAR => Pifa::i18n('PROCESSBAR'),
 879:             self::SLIDER => Pifa::i18n('SLIDER'),
 880:             // self::CAPTCHA => Pifa::i18n('CAPTCHA'),
 881:             // self::MATRIX => Pifa::i18n('MATRIX'),
 882:             self::PARA => Pifa::i18n('PARAGRAPH'),
 883:             self::INPUTHIDDEN => Pifa::i18n('INPUTHIDDEN'),
 884:             self::FIELDSET_BEGIN => Pifa::i18n('FIELDSET_BEGIN'),
 885:             self::FIELDSET_END => Pifa::i18n('FIELDSET_END'),
 886:             self::BUTTONSUBMIT => Pifa::i18n('BUTTONSUBMIT'),
 887:             self::BUTTONRESET => Pifa::i18n('BUTTONRESET'),
 888:             self::BUTTON => Pifa::i18n('BUTTON'),
 889:             self::BUTTONIMAGE => Pifa::i18n('BUTTONIMAGE')
 890:         );
 891:     }
 892: 
 893:     /**
 894:      * Return the field type name for the given field type id.
 895:      *
 896:      * @param int $fieldType
 897:      * @return string
 898:      */
 899:     public static function getFieldTypeName($fieldTypeId) {
 900:         $fieldTypeId = cSecurity::toInteger($fieldTypeId);
 901:         $fieldTypeNames = self::getFieldTypeNames();
 902: 
 903:         if (array_key_exists($fieldTypeId, $fieldTypeNames)) {
 904:             $fieldTypeName = $fieldTypeNames[$fieldTypeId];
 905:         } else {
 906:             $fieldTypeName = Pifa::i18n('UNKNOWN');
 907:         }
 908: 
 909:         return $fieldTypeName;
 910:     }
 911: 
 912:     /**
 913:      * Return this fields type name.
 914:      *
 915:      * @param int $fieldType
 916:      * @return string
 917:      */
 918:     public function getMyFieldTypeName() {
 919:         return self::getFieldTypeName($this->get('field_type'));
 920:     }
 921: 
 922:     /**
 923:      * Returns a string describing this fields database data type as used in
 924:      * MySQL CREATE and ALTER TABLE statements.
 925:      *
 926:      * @throws PifaException if field is not loaded
 927:      * @throws PifaException if field type is not implemented
 928:      */
 929:     public function getDbDataType() {
 930:         if (!$this->isLoaded()) {
 931:             $msg = Pifa::i18n('FIELD_LOAD_ERROR');
 932:             throw new PifaException($msg);
 933:         }
 934: 
 935:         $fieldType = cSecurity::toInteger($this->get('field_type'));
 936: 
 937:         switch ($fieldType) {
 938: 
 939:             // Text and password input fields can store a string of
 940:             // arbitrary length. Cause they are single lined it does not
 941:             // make sense to enable them storing more than 1023 characters
 942:             // though.
 943:             case self::INPUTTEXT:
 944:             case self::INPUTPASSWORD:
 945:             case self::INPUTHIDDEN:
 946:             case self::INPUTFILE:
 947: 
 948:                 return 'VARCHAR(' . self::VARCHAR_SIZE . ')';
 949: 
 950:             // A group of checkboxes can store multiple values. So this has
 951:             // to be implemented as a CSV string of max. 1023 characters.
 952:             case self::INPUTCHECKBOX:
 953: 
 954:                 return 'VARCHAR(' . self::VARCHAR_SIZE . ')';
 955: 
 956:             // Textareas are designed to store longer texts so I chose the
 957:             // TEXT data type to enable them storing up to 65535 characters.
 958:             case self::TEXTAREA:
 959: 
 960:                 return 'TEXT';
 961: 
 962:             // A group of radiobuttons or a select box can store a single
 963:             // value of a given set of options. This can be implemented
 964:             // as an enumeration.
 965:             case self::INPUTRADIO:
 966:             case self::SELECT:
 967:             case self::SELECTMULTI:
 968: 
 969:                 // $optionValues = $this->get('option_values');
 970:                 // $optionValues = explode(',', $optionValues);
 971:                 // array_map(function ($val) {
 972:                 // return "'$val'";
 973:                 // }, $optionValues);
 974:                 // $optionValues = join(',', $optionValues);
 975: 
 976:                 // return "ENUM($optionValues)";
 977: 
 978:                 // as long as the GUI does not offer an entry to define option
 979:                 // values when creating a new field assume VARCHAR as data type
 980:                 return 'VARCHAR(' . self::VARCHAR_SIZE . ')';
 981: 
 982:             // The datepicker can store a date having an optional time
 983:             // portion. I chose DATETIME as data type over TIMESTAMP due to
 984:             // its limitation of storing dates before 1970-01-01 although
 985:             // even DATETIME can't store dates before 1000-01-01.
 986:             case self::DATEPICKER:
 987: 
 988:                 return 'DATETIME';
 989: 
 990:             // Buttons don't have any values that should be stored.
 991:             case self::BUTTONSUBMIT:
 992:             case self::BUTTONRESET:
 993:             case self::BUTTON:
 994:             case self::BUTTONIMAGE:
 995: 
 996:                 return NULL;
 997: 
 998:             // TODO For some filed types I havn't yet decided which data
 999:             // type to use.
1000:             case self::PROCESSBAR:
1001:             case self::SLIDER:
1002:             // case self::CAPTCHA:
1003:             case self::MATRIX:
1004:             case self::PARA:
1005:             case self::FIELDSET_BEGIN:
1006:             case self::FIELDSET_END:
1007: 
1008:                 return NULL;
1009: 
1010:             default:
1011:                 $msg = Pifa::i18n('NOT_IMPLEMENTED_FIELDTYPE');
1012:                 $msg = sprintf($msg, $fieldType);
1013:                 // Util::logDump($this->values);
1014:                 throw new PifaException($msg);
1015:         }
1016:     }
1017: 
1018:     /**
1019:      * Deletes this form with all its fields and stored data.
1020:      * The forms data table is also dropped.
1021:      */
1022:     public function delete() {
1023:         $cfg = cRegistry::getConfig();
1024:         $db = cRegistry::getDb();
1025: 
1026:         if (!$this->isLoaded()) {
1027:             $msg = Pifa::i18n('FIELD_LOAD_ERROR');
1028:             throw new PifaException($msg);
1029:         }
1030: 
1031:         // update ranks of younger siblings
1032:         $sql = "-- PifaField->delete()
1033:             UPDATE
1034:                 " . cRegistry::getDbTableName('pifa_field') . "
1035:             SET
1036:                 field_rank = field_rank - 1
1037:             WHERE
1038:                 idform = " . cSecurity::toInteger($this->get('idform')) . "
1039:                 AND field_rank > " . cSecurity::toInteger($this->get('field_rank')) . "
1040:             ;";
1041:         if (false === $db->query($sql)) {
1042:             // false is returned if no fields were updated
1043:             // but that doesn't matter ...
1044:         }
1045: 
1046:         // delete field
1047:         $sql = "-- PifaField->delete()
1048:             DELETE FROM
1049:                 " . cRegistry::getDbTableName('pifa_field') . "
1050:             WHERE
1051:                 idfield = " . cSecurity::toInteger($this->get('idfield')) . "
1052:             ;";
1053:         if (false === $db->query($sql)) {
1054:             $msg = Pifa::i18n('FIELD_DELETE_ERROR');
1055:             throw new PifaException($msg);
1056:         }
1057: 
1058:         // drop column of data table
1059:         if (0 < strlen(trim($this->get('column_name')))) {
1060:             $pifaForm = new PifaForm($this->get('idform'));
1061: 
1062:             if (0 < strlen(trim($pifaForm->get('data_table')))) {
1063:                 $sql = "-- PifaField->delete()
1064:                     ALTER TABLE
1065:                         `" . cSecurity::toString($pifaForm->get('data_table')) . "`
1066:                     DROP COLUMN
1067:                         `" . cSecurity::toString($this->get('column_name')) . "`
1068:                     ;";
1069:                 if (false === $db->query($sql)) {
1070:                     $msg = Pifa::i18n('COLUMN_DROP_ERROR');
1071:                     throw new PifaException($msg);
1072:                 }
1073:             }
1074:         }
1075:     }
1076: 
1077:     /**
1078:      * Determines for which form field types which data should be editable in
1079:      * backend.
1080:      *
1081:      * @param string $columnName for data to edit
1082:      */
1083:     public function showField($columnName) {
1084:         $fieldType = $this->get('field_type');
1085:         $fieldType = cSecurity::toInteger($fieldType);
1086: 
1087:         switch ($columnName) {
1088: 
1089:             case 'idfield':
1090:             case 'idform':
1091:             case 'field_rank':
1092:             case 'field_type':
1093:                 // will never be editable directly
1094:                 return false;
1095: 
1096:             case 'column_name':
1097:                 return in_array($fieldType, array(
1098:                     self::INPUTTEXT,
1099:                     self::TEXTAREA,
1100:                     self::INPUTPASSWORD,
1101:                     self::INPUTRADIO,
1102:                     self::INPUTCHECKBOX,
1103:                     self::SELECT,
1104:                     self::SELECTMULTI,
1105:                     self::DATEPICKER,
1106:                     self::INPUTFILE,
1107:                     self::PROCESSBAR,
1108:                     self::SLIDER,
1109:                     // self::CAPTCHA,
1110:                     // self::BUTTONSUBMIT,
1111:                     // self::BUTTONRESET,
1112:                     // self::BUTTON,
1113:                     // self::BUTTONIMAGE,
1114:                     self::MATRIX,
1115:                     self::INPUTHIDDEN
1116:                     /*
1117:                     self::FIELDSET_BEGIN,
1118:                     self::FIELDSET_END
1119:                     */
1120:                 ));
1121: 
1122:             case 'label':
1123:             case 'display_label':
1124:                 return in_array($fieldType, array(
1125:                     self::INPUTTEXT,
1126:                     self::TEXTAREA,
1127:                     self::INPUTPASSWORD,
1128:                     self::INPUTRADIO,
1129:                     self::INPUTCHECKBOX,
1130:                     self::SELECT,
1131:                     self::SELECTMULTI,
1132:                     self::DATEPICKER,
1133:                     self::INPUTFILE,
1134:                     self::PROCESSBAR,
1135:                     self::SLIDER,
1136:                     // self::CAPTCHA,
1137:                     self::BUTTONSUBMIT,
1138:                     self::BUTTONRESET,
1139:                     self::BUTTON,
1140:                     // self::BUTTONIMAGE,
1141:                     self::MATRIX,
1142:                     self::PARA,
1143:                     // self::INPUTHIDDEN,
1144:                     self::FIELDSET_BEGIN
1145:                     /*
1146:                     self::FIELDSET_END
1147:                     */
1148:                     ));
1149: 
1150:             case 'default_value':
1151:                 return in_array($fieldType, array(
1152:                     self::INPUTTEXT,
1153:                     self::TEXTAREA,
1154:                     self::INPUTPASSWORD,
1155:                     self::INPUTRADIO,
1156:                     self::INPUTCHECKBOX,
1157:                     self::SELECT,
1158:                     self::SELECTMULTI,
1159:                     self::DATEPICKER,
1160:                     self::INPUTFILE,
1161:                     self::PROCESSBAR,
1162:                     self::SLIDER,
1163:                     // self::CAPTCHA,
1164:                     self::BUTTONSUBMIT,
1165:                     self::BUTTONRESET,
1166:                     self::BUTTON,
1167:                     // self::BUTTONIMAGE,
1168:                     self::MATRIX,
1169:                     self::INPUTHIDDEN
1170:                 ));
1171: 
1172:             case 'option_labels':
1173:             case 'option_values':
1174:             case 'option_class':
1175:                 return in_array($fieldType, array(
1176:                     self::INPUTRADIO,
1177:                     self::INPUTCHECKBOX,
1178:                     self::SELECT,
1179:                     self::SELECTMULTI
1180:                 ));
1181: 
1182:             case 'help_text':
1183:                 return in_array($fieldType, array(
1184:                     self::INPUTTEXT,
1185:                     self::TEXTAREA,
1186:                     self::INPUTPASSWORD,
1187:                     self::INPUTRADIO,
1188:                     self::INPUTCHECKBOX,
1189:                     self::SELECT,
1190:                     self::SELECTMULTI,
1191:                     self::DATEPICKER,
1192:                     self::INPUTFILE,
1193:                     self::PROCESSBAR,
1194:                     self::SLIDER,
1195:                     // self::CAPTCHA,
1196:                     self::BUTTONSUBMIT,
1197:                     self::BUTTONRESET,
1198:                     self::BUTTON,
1199:                     self::BUTTONIMAGE,
1200:                     self::MATRIX,
1201:                     self::PARA,
1202:                     self::FIELDSET_BEGIN
1203:                 ));
1204: 
1205:             case 'obligatory':
1206:                 return in_array($fieldType, array(
1207:                     self::INPUTTEXT,
1208:                     self::TEXTAREA,
1209:                     self::INPUTPASSWORD,
1210:                     self::INPUTRADIO,
1211:                     self::INPUTCHECKBOX,
1212:                     self::SELECT,
1213:                     self::SELECTMULTI,
1214:                     self::DATEPICKER,
1215:                     self::INPUTFILE,
1216:                     self::PROCESSBAR,
1217:                     self::SLIDER,
1218:                     // self::CAPTCHA,
1219:                     // self::BUTTONSUBMIT,
1220:                     // self::BUTTONRESET,
1221:                     // self::BUTTON,
1222:                     // self::BUTTONIMAGE,
1223:                     self::MATRIX,
1224:                     self::INPUTHIDDEN
1225:                 ));
1226: 
1227:             case 'rule':
1228:                 return in_array($fieldType, array(
1229:                     self::INPUTTEXT,
1230:                     self::TEXTAREA,
1231:                     self::INPUTPASSWORD,
1232:                     self::INPUTRADIO,
1233:                     self::INPUTCHECKBOX,
1234:                     self::SELECT,
1235:                     self::SELECTMULTI,
1236:                     self::DATEPICKER,
1237:                     self::INPUTFILE,
1238:                     self::PROCESSBAR,
1239:                     self::SLIDER,
1240:                     // self::CAPTCHA,
1241:                     // self::BUTTONSUBMIT,
1242:                     // self::BUTTONRESET,
1243:                     // self::BUTTON,
1244:                     // self::BUTTONIMAGE,
1245:                     self::MATRIX,
1246:                     self::INPUTHIDDEN
1247:                 ));
1248: 
1249:             case 'error_message':
1250:                 return in_array($fieldType, array(
1251:                     self::INPUTTEXT,
1252:                     self::TEXTAREA,
1253:                     self::INPUTPASSWORD,
1254:                     self::INPUTRADIO,
1255:                     self::INPUTCHECKBOX,
1256:                     self::SELECT,
1257:                     self::SELECTMULTI,
1258:                     self::DATEPICKER,
1259:                     self::INPUTFILE,
1260:                     self::PROCESSBAR,
1261:                     self::SLIDER,
1262:                     // self::CAPTCHA,
1263:                     // self::BUTTONSUBMIT,
1264:                     // self::BUTTONRESET,
1265:                     // self::BUTTON,
1266:                     // self::BUTTONIMAGE,
1267:                     self::MATRIX,
1268:                     self::INPUTHIDDEN
1269:                 ));
1270: 
1271:             case 'css_class':
1272:                 return in_array($fieldType, array(
1273:                     self::INPUTTEXT,
1274:                     self::TEXTAREA,
1275:                     self::INPUTPASSWORD,
1276:                     self::INPUTRADIO,
1277:                     self::INPUTCHECKBOX,
1278:                     self::SELECT,
1279:                     self::SELECTMULTI,
1280:                     self::DATEPICKER,
1281:                     self::INPUTFILE,
1282:                     self::PROCESSBAR,
1283:                     self::SLIDER,
1284:                     // self::CAPTCHA,
1285:                     self::BUTTONSUBMIT,
1286:                     self::BUTTONRESET,
1287:                     self::BUTTON,
1288:                     self::BUTTONIMAGE,
1289:                     self::MATRIX,
1290:                     self::PARA,
1291:                     self::FIELDSET_BEGIN
1292:                     /*
1293:                     self::INPUTHIDDEN
1294:                     */
1295:                 ));
1296: 
1297:             case 'uri':
1298:                 return in_array($fieldType, array(
1299:                     /*
1300:                     self::INPUTTEXT,
1301:                     self::TEXTAREA,
1302:                     self::INPUTPASSWORD,
1303:                     self::INPUTRADIO,
1304:                     self::INPUTCHECKBOX,
1305:                     self::SELECT,
1306:                     self::SELECTMULTI,
1307:                     self::DATEPICKER,
1308:                     self::INPUTFILE,
1309:                     self::PROCESSBAR,
1310:                     self::SLIDER,
1311:                     // self::CAPTCHA,
1312:                     self::BUTTONSUBMIT,
1313:                     self::BUTTONRESET,
1314:                     self::BUTTON,
1315:                     */
1316:                     self::BUTTONIMAGE,
1317:                     /*
1318:                     self::MATRIX,
1319:                     self::PARA,
1320:                     self::FIELDSET_BEGIN
1321:                     self::INPUTHIDDEN
1322:                     */
1323:                 ));
1324: 
1325:             default:
1326:                 $msg = Pifa::i18n('NOT_IMPLEMENTED_FIELDPROP');
1327:                 $msg = sprintf($msg, $columnName);
1328:                 throw new PifaException($msg);
1329:         }
1330:     }
1331: 
1332:     /**
1333:      *
1334:      * @return array
1335:      */
1336:     public function getOptions() {
1337:         $option_labels = $this->get('option_labels');
1338:         $option_values = $this->get('option_values');
1339: 
1340:         $out = array();
1341:         if (0 < strlen($option_labels . $option_values)) {
1342:             $option_labels = explode(',', $option_labels);
1343:             $option_values = explode(',', $option_values);
1344: 
1345:             // str_getcsv requires PHP 5.3 :(
1346:             // $option_labels = str_getcsv($option_labels);
1347:             // $option_values = str_getcsv($option_values);
1348: 
1349:             // instead replace commas stored as entities by real commas
1350:             $func = create_function('$v', 'return str_replace(\'&#44;\', \',\', $v);');
1351:             $option_labels = array_map($func, $option_labels);
1352:             $option_values = array_map($func, $option_values);
1353: 
1354:             foreach (array_keys($option_labels) as $key) {
1355:                 $out[] = array(
1356:                     'label' => $option_labels[$key],
1357:                     'value' => $option_values[$key]
1358:                 );
1359:             }
1360:         }
1361: 
1362:         return $out;
1363:     }
1364: }
1365: 
1366: ?>
1367: 
CMS CONTENIDO 4.9.4 API documentation generated by ApiGen 2.8.0