'Member', AttendeeForm::TYPE_NONMEMBER => 'Nonmember', ]; protected $_mode = self::MODE_CHOOSE_TYPE; protected $_currentUserId; protected $_allowMembers; protected $_allowNonMembers; protected $_showStaticAttendeeType; protected $_deletedMemberAttendee; protected $_userAutocompleteUrl; protected $_allowDelete = true; protected $_index; public function init() { parent::init(); $this->_initDFRelations(); return $this; } public function isSubmitted() { $method = $this->getMethod(); if (0 == strcasecmp($_SERVER['REQUEST_METHOD'], $method)) { $data = \Qs_Request::get($method); $itemIdMatched = true; if (($itemId = $this->getCmsItemId())) { $itemIdMatched = (isset($data['__idItem']) && $data['__idItem'] == $itemId); } return ($itemIdMatched && (0 === strpos($data['action'], 'insert') || 0 === strpos($data['action'], 'update'))); } return false; } protected function _getRequestPrefix() { return "attendee[{$this->getIndex()}]"; } protected function _getSubData($field = null, $default = null) { $result = null; if ($this->isSubmitted()) { $request = \Qs_Array::get(\Qs_Request::get($this->getMethod()), $this->_getRequestPrefix()); if (false === $field) { $result = $request; } else { $result = \Qs_Array::get($request, $field); } } if (null === $result) { if (null === $field) { $result = $this->_defaults; } else { $result = \Qs_Array::get($this->_defaults, $field); } } return (null === $result) ? $default : $result; } protected function _initElements() { $mode = $this->getMode(); $this->addElement('hidden', 'mode', ['value' => $mode]); if (self::MODE_CURRENT_USER === $mode) { $this->_addCurrentUserElements(); } else { $this->_addDefaultElements(); } return $this; } protected function _addCurrentUserElements() { if ($this->getCurrentUserId()) { $this->addElement('hidden', 'type', ['value' => AttendeeForm::TYPE_MEMBER]); $this->addElement('hidden', 'id', ['value' => $this->getCurrentUserId()]); $this->_addMemberAdditionalFields(); } else { $this->addElement('hidden', 'type', ['value' => AttendeeForm::TYPE_NONMEMBER]); $attendType = $this->_getData('attendType'); $required = Qs_Request::isGet() || Qs_Request::getPostValue('action') == 'renderAttendee' || ($this->isSubmitted() && in_array($attendType, [NewForm::ATTEND_MYSELF, NewForm::ATTEND_MYSELF_OTHER])); $this->_addNonMemberFields($required); } return $this; } protected function _addDefaultElements() { $isSubmitted = $this->isSubmitted(); $allowMembers = (bool) $this->getAllowMembers(); $allowNonMembers = (bool) $this->getAllowNonMembers(); if ($allowMembers && $allowNonMembers) { $type = $this->_getSubData('type'); $this->addElement( 'radio', 'type', [ 'label' => 'Attendee Type', 'separator' => '   ', 'multiOptions' => self::$_typeTitles, 'required' => true, ] ); } else { $type = ($allowMembers && !$allowNonMembers) ? AttendeeForm::TYPE_MEMBER : AttendeeForm::TYPE_NONMEMBER; $this->addElement('hidden', 'type', ['value' => $type]); if ($this->getShowStaticAttendeeType()) { $this->addElement('static', 'typeTitle', ['label' => 'Attendee Type', 'value' => self::$_typeTitles[$type]]); } } $attendType = $this->_getData('attendType'); if ($allowMembers) { $required = ($isSubmitted && (NewForm::ATTEND_MYSELF_OTHER === $attendType || NewForm::ATTEND_OTHER === $attendType) && AttendeeForm::TYPE_MEMBER == $this->_getSubData('type') ); $this->addElement( 'autocomplete', 'id', [ 'label' => 'Member\'s Name', 'dataUrl' => $this->getUserAutocompleteUrl(), 'required' => $required, 'placeholder' => 'Autocomplete field', ] ); if (($userId = $this->_getSubData('id')) && false !== ($userName = UserObj::getAutocompleteItemTitle($userId)) ) { $this->getElement('id')->setTitle($userName); } if (($msg = $this->getDeletedMemberAttendee())) { $this->getElement('id')->setRequired(false); $this->getElement('id')->setDescription($msg); } else { $this->getElement('id')->getDecorator('label')->setOption('class', 'required'); } } if ($allowNonMembers) { $required = Qs_Request::isGet() || Qs_Request::getPostValue('action') == 'renderAttendee' || ($isSubmitted && (NewForm::ATTEND_MYSELF_OTHER === $attendType || NewForm::ATTEND_OTHER === $attendType) && AttendeeForm::TYPE_NONMEMBER === $type); $this->_addNonMemberFields($required); } else { $this->_addMemberAdditionalFields(); } if ($this->getAllowDelete() && ($allowMembers || $allowNonMembers)) { $this->addElement( 'button', 'delete', [ 'label' => 'Delete', 'class' => 'btn btn-danger', 'data-action' => 'delete', 'ignore' => true, ] ); } return $this; } protected function _addNonMemberFields($required) { $this->addElement('text', 'firstName', ['label' => 'First Name', 'required' => $required, 'filters' => ['StringTrim']]); $this->addElement('text', 'lastName', ['label' => 'Last Name', 'required' => $required, 'filters' => ['StringTrim']]); $this->addElement('text', 'email', ['label' => 'Email', 'required' => $required, 'filters' => ['StringTrim']]); $this->addElement('text', 'credentials', ['label' => 'Credentials', 'filters' => ['StringTrim'], 'required' => $required]); $this->addElement('text', 'company', ['label' => 'Institution/Employer', 'filters' => ['StringTrim']]); if ($this->getEventEntity()->hasProfession()) { $this->addProfession(); } if ($this->getEventEntity()->hasSpouse()) { $this->addSpouse(); } $this->addElement('text', 'address', ['label' => 'Address 1', 'required' => $required]); $this->addElement('text', 'address2', ['label' => 'Address 2']); $this->addElement('text', 'address3', ['label' => 'Address 3']); $this->addElement('text', 'city', ['label' => 'City', 'class' => 'city', 'required' => $required]); $this->addElement( 'countryState', 'state', [ 'label' => 'State/Province', 'class' => 'state', 'countryElement' => 'countryId', 'required' => $required, 'countryId' => Qs_Array::get($this->_defaults, 'countryId'), 'multiOptions' => ['' => 'Select One'] + (new StateModel())->getStates4Select(), ] ); $this->addElement( 'select', 'countryId', [ 'label' => 'Country', 'class' => 'country', 'required' => $required, 'multiOptions' => ['' => 'Select One'] + (new Qs_Db_Table('Country'))->get4Select(['id', 'name']), ] ); $this->addElement('zip', 'zip', ['label' => 'Zip', 'class' => 'zip', 'required' => $required]); $this->addElement('internationalTel', 'workPhone', ['label' => 'Work Phone Number', 'required' => $required]); $this->addElement('internationalTel', 'fax', ['label' => 'Fax Number']); $this->getElement('email')->addValidator('emailAddress'); $this->addDietarySpecialNeeds(); if ($this->getEventEntity()->hasAlaCarteItems()) { $this->addAlaCarteItems(); } if ($this->getEventEntity()->hasWorkshop()) { $this->addWorkshop(); } return $this; } public function initRender() { $attr = (self::MODE_CURRENT_USER === $this->getMode()) ? 'data-current-attendee' : 'data-attendee'; $this->getDecorator('Fieldset')->setOption($attr, $this->getIndex()); if ($this->_getFormHidden()) { $this->getDecorator('Fieldset')->setOption('class', 'hidden'); } return parent::initRender(); } protected function _getFormHidden() { $result = true; foreach ($this->getElements() as $element) { if (!($element instanceof Zend_Form_Element_Hidden)) { $result = false; break; } } return $result; } public function loadDefaultDecorators() { if (false == $this->loadDefaultDecoratorsIsDisabled() && null == $this->getDecorators()) { $this->addDecorator('FormElements') ->addDecorator('HtmlTag', ['tag' => 'dl']) ->addDecorator('Fieldset'); } return $this; } public function setMode($mode) { $this->_mode = $mode; return $this; } public function getMode() { return $this->_mode; } public function setCurrentUserId($currentUserId) { $this->_currentUserId = $currentUserId; return $this; } public function getCurrentUserId() { return $this->_currentUserId; } public function setAllowMembers($allowMembers) { $this->_allowMembers = $allowMembers; return $this; } public function getAllowMembers() { return $this->_allowMembers; } public function setAllowNonMembers($allowNonMembers) { $this->_allowNonMembers = $allowNonMembers; return $this; } public function getAllowNonMembers() { return $this->_allowNonMembers; } public function setUserAutocompleteUrl($userAutocompleteUrl) { $this->_userAutocompleteUrl = $userAutocompleteUrl; return $this; } public function getUserAutocompleteUrl() { if (null === $this->_userAutocompleteUrl) { throw new Qs_Exception_EmptyPropertyException($this, '_userAutocompleteUrl'); } return $this->_userAutocompleteUrl; } public function setIndex($index) { $this->_index = $index; return $this; } public function getIndex() { if (null === $this->_index) { throw new Qs_Exception_EmptyPropertyException($this, '_index'); } return $this->_index; } protected function _initDFRelations() { if (self::MODE_CHOOSE_TYPE !== $this->getMode() || $this->getElement('type') instanceof Zend_Form_Element_Hidden) { return $this; } $idx = $this->getIndex(); $namePrefix = 'attendee[' . $idx . ']'; $idPrefix = '#attendee-' . $idx . '-'; $nodes = []; $fields = array_diff( $this->getConfigArray('attendeeFields'), $this->getConfigArray('attendeeMemberFields') ); foreach ($fields as $field) { $nodes[] = "{$idPrefix}{$field}-label"; $nodes[] = "{$idPrefix}{$field}-element"; } $this->_dfRelations = [ [ 'node' => '[name="' . $namePrefix . '[type]"]:checked', 'group' => '[name="' . $namePrefix . '[type]"]', 'event' => 'change', 'rules' => [ [ 'value' => AttendeeForm::TYPE_MEMBER, 'nodes' => [$idPrefix . 'id-label', $idPrefix . 'id-element'], ], [ 'value' => AttendeeForm::TYPE_NONMEMBER, 'nodes' => $nodes, ], ], ], ]; return $this; } protected function _addResources() { if ($this->_dfRelations) { $dynamicFormOptions = [ 'relations' => $this->dfConvertRelations(), ]; /** @var $doc \Qs_Doc */ $doc = Zend_Registry::get('doc'); $doc->addScript('js/jquery.dynamicForm.js'); $doc->addInitFunction('$("#attendee-fieldset-' . $this->getIndex() . '").dynamicForm', [$dynamicFormOptions]); } return parent::_addResources(); } /** * @param string $name element name * @return string element label id (e.g. foo-label) */ protected function _dfGetElementLabelId($name) { return null; } /** * @param string $name element name * @return string element container id (e.g. foo-element) */ protected function _dfGetElementContainerId($name) { return null; } public function setAllowDelete($allowDelete) { $this->_allowDelete = $allowDelete; return $this; } public function getAllowDelete() { return $this->_allowDelete; } public function setShowStaticAttendeeType($showStaticAttendeeType) { $this->_showStaticAttendeeType = $showStaticAttendeeType; return $this; } public function getShowStaticAttendeeType() { return $this->_showStaticAttendeeType; } public function getDeletedMemberAttendee() { return $this->_deletedMemberAttendee; } public function setDeletedMemberAttendee($message) { $this->_deletedMemberAttendee = $message; return $this; } private function addDietarySpecialNeeds() { $this->addElement('textarea', 'dietarySpecialNeeds', ['label' => 'Dietary/Special Needs']); return $this; } protected function addProfession() { $this->addElement('text', 'profession', ['label' => 'Profession', 'filters' => ['StringTrim']]); return $this; } private function addSpouse() { $this->addElement('text', 'spouseFullName', ['label' => 'Spouse Full Name', 'filters' => ['StringTrim']]); return $this; } private function _addMemberAdditionalFields() { if ($this->getEventEntity()->hasProfession()) { $this->addProfession(); } if ($this->getEventEntity()->hasSpouse()) { $this->addSpouse(); } $this->addDietarySpecialNeeds(); if ($this->getEventEntity()->hasAlaCarteItems()) { $this->addAlaCarteItems(); } if ($this->getEventEntity()->hasWorkshop()) { $this->addWorkshop(); } return $this; } private function addAlaCarteItems() { switch ($this->getAlaCarteItemsType()) { case self::ACI_TYPE_CHECKBOX: return $this->addAlaCarteItemsAsCheckboxes(); case self::ACI_TYPE_TABLE: return $this->addAlaCarteItemsAsTable(); default: throw new Exception('Unsupported ACI_TYPE'); } } private function addAlaCarteItemsAsCheckboxes() { if (!($items = $this->getEventEntity()->getAlaCarteItems())) { return $this; } $multiOptions = []; foreach ($items as $item) { $multiOptions[$item['id']] = $item['title'] . ' - $' . number_format($item['price'], 2); } $this->addElement('multiCheckbox', 'alaCarteItems', [ 'label' => 'A La Carte Items', 'multiOptions' => $multiOptions, ]); return $this; } private function addAlaCarteItemsAsTable() { $name = 'alaCarteItems'; $options = [ 'name' => $name, 'label' => 'A La Carte Items', 'labelAttribs' => ['class' => 'form_header'], 'defaults' => Qs_Array::get($this->_defaults, $name, []), 'orientation' => AlaCarteItemsTable::ORIENTATION_HORIZONTAL, 'enabledHeaders' => true, 'itemClass' => AlaCarteItemsRow::class, 'sortable' => false, 'removable' => true, 'numerable' => true, 'itemName' => 'Item', 'itemsName' => 'Items', ]; $this->addSubForm(new AlaCarteItemsTable($options), $name); return $this; } private function addWorkshop() { if (!($this->getEventEntity()->hasWorkshop())) { return $this; } if ($this->getWorkshopType() == self::WORKSHOP_TYPE_TEXT) { $this->addElement('text', 'workshopTitle', ['label' => 'Workshop']); return $this; } if (!($workshops = $this->getEventEntity()->getWorkshops())) { return $this; } $multiSeparators = []; foreach ($workshops as $workshop) { if (!empty($workshop['description'])) { $multiSeparators[$workshop['id']]['afterLabel'] = $this->renderWorkshopOption($workshop); } } $this->addElement('radio', 'workshopId', [ 'label' => 'Workshop', 'multiOptions' => Qs_Array::fetchPairs($workshops, ['id', 'title']), 'separator' => '
', 'multiSeparators' => $multiSeparators, ]); return $this; } private function renderWorkshopOption($workshop) { $dialogId = 'workshop-dialog-' . $workshop['id']; $item = $workshop; $item['dialogId'] = $dialogId; $item['tpl'] = 'Event/workshop-dialog.tpl'; $this->getDoc()->addItem($item, 'AFTER_BODY'); $html = Html::renderContainer('a', 'read more', [ 'href' => '#' . $dialogId, 'role' => 'button', 'data-toggle' => 'modal', ]); $html = Html::renderContainer('span', '(' . trim($html) . ')', ['class' => 'workshop-info']); return $html; } }