Overview

Packages

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