Overview

Packages

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

Classes

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

Exceptions

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