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
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SIWECOS
    • 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

Exceptions

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