'HTML', 'formErrorsDisplayMethod' => 'HTML', 'errorAlertEnabled' => true, ); protected $_translationSection; protected $_translatorDisabled; protected $_hasTranslation; protected $_hasContentTranslation = true; protected $_contentFields; protected $_languageToolbarElementName = 'language'; protected $_ajaxValidation = true; protected $_cancelUrl; protected $_prependId = false; protected $_prependString; protected $_layout = 'default'; protected $_initializedRender = false; protected $_hiddenElements = array(); protected $_disabledInitRender = false; protected $_elementRemovableDecorators = array('HtmlTag', 'Label', 'DtDdWrapper'); protected $_groupRemovableDecorators = array('HtmlTag', 'Fieldset', 'DtDdWrapper'); protected $_defaults = array(); protected $_cmsItemId; protected $_primaryKey = array(); protected $_template; protected $_hasButtons = true; protected $_controllerAction; protected $_hasSpamProtection = false; protected $_spamProtectionType = self::SPAM_PROTECTION_COOKIE; protected $_spamProtectionMessage = 'Your data were not submitted'; protected $_spamProtectionField = array( 'label' => 'Leave Empty', 'name' => 'alternative_email_address', ); /** @var Qs_Form */ protected $_parentForm; public function init() { $this->_initPaths(); $this->_initCmsItemIdElement(); $this->_initPrimaryKeyElements(); $this->_initElements(); $this->_initControllerAction(); $this->_initSpamProtection(); $this->_initButtons(); return $this; } protected function _initPaths() { $this->addElementPrefixPath('Qs_Filter', 'Qs/Filter/', Zend_Form_Element::FILTER); $this->addElementPrefixPath('Zend_Validate', 'Zend/Validate/', 'validate'); $this->addElementPrefixPath('Zend_Validate_File', 'Zend/Validate/File', 'validate'); $this->addElementPrefixPath('Qs_Validate', 'Qs/Validate/', 'validate'); $this->addElementPrefixPath('Qs_Validate_File', 'Qs/Validate/File', 'validate'); $this->addElementPrefixPath('Qs_Form_Decorator', 'Qs/Form/Decorator/', 'decorator'); $this->addPrefixPath('Qs_Form_Element', 'Qs/Form/Element/', 'element'); $this->addPrefixPath('Qs_Form_Decorator', 'Qs/Form/Decorator/', 'decorator'); return $this; } public function addElement($element, $name = null, $options = null) { parent::addElement($element, $name, $options); if ($this->getTranslatorDisabled()) { if ($element instanceof Zend_Form_Element && null === $name) { $name = $element->getName(); } if (($element && $element instanceof Zend_Form_Element) || ($element = $this->getElement($name))) { $element->setDisableTranslator($this->getTranslatorDisabled()); } } return $this; } public function setOptions(array $options) { if (isset($options['defaults'])) { $this->_defaults = $options['defaults']; unset($options['defaults']); } return parent::setOptions($options); } protected function _initElements() { return $this; } protected function _initControllerAction() { if (null !== $this->_controllerAction && null === $this->getElement('action')) { $this->addElement('hidden', 'action', array('value' => $this->_controllerAction)); } return $this; } protected function _initLanguageToolbarElement() { if ($this->getContentFields() && ($name = $this->getLanguageToolbarElementName())) { $languageList = Qs_Db_Language::getList(); $this->addElement( 'radio', $name, [ 'label' => 'Languages:', 'multiOptions' => ['all' => 'All'] + Qs_Array::fetchPairs($languageList, ['name', 'title']), 'columns' => 1 + count($languageList), 'separator' => '', 'value' => 'all', 'description' => 'Please note that only the changes for the language chosen will be saved.', ] ); $this->addDisplayGroup(['language'], 'languageToolbar'); } return $this; } protected function _getDefaults() { return $this->_defaults; } public function setDefaults(array $defaults = array()) { $defaults = Qs_Array::mergeRecursive($this->_getDefaults(), $defaults); return parent::setDefaults($defaults); } public function setDefaultValue($name, $value) { $this->_defaults[$name] = $value; $this->setDefault($name, $value); } protected function _initButtons() { if (!$this->_hasButtons) { return $this; } $this->addElement( 'submit', 'btnSubmit', array( 'label' => 'Save', 'attribs' => array('class' => 'btn btn-primary'), ) ); $this->addElement( 'submit', 'btnCancel', array( 'label' => 'Cancel', 'attribs' => array( 'class' => 'btn', 'onclick' => "window.location.href = '" . htmlspecialchars($this->getCancelUrl()) . "';", 'helper' => 'formInputButton', ), ) ); $this->addDisplayGroup(array('btnSubmit', 'btnCancel'), 'submitGroup'); return $this; } protected function _initCmsItemIdElement() { if ($this->getCmsItemId()) { $this->addElement('hidden', '__idItem', array('value' => $this->getCmsItemId())); } return $this; } protected function _initPrimaryKeyElements() { foreach ($this->_primaryKey as $name => $value) { $this->addElement('hidden', $name, array('value' => $value)); } return $this; } public function setCmsItemId($id) { $this->_cmsItemId = $id; return $this; } public function getCmsItemId() { return $this->_cmsItemId; } public function setPrimaryKey(array $key) { $this->_primaryKey = $key; return $this; } public function getPrimaryKey() { return $this->_primaryKey; } public function setTemplate($template) { $this->_template = $template; return $this; } public function getTemplate() { return $this->_template; } public function getLanguageToolbarElementName() { return $this->_languageToolbarElementName; } /** * рендер контент полів форми згідно проперті Qs_Db_Obj::_contentFields * * Note: Опції встановлені для декораторів дісплей групи ігноруються, тому-що відбувається видалення, а потім * знову додавання вже без втановлених опцій * @return $this */ public function initContentFields() { $contentFields = $this->getContentFields(); $displayGroups = $this->getDisplayGroups(); $displayGroupElements = array(); $addDisplayGroupName = false; $addDisplayGroupDecorators = null; $this->_initLanguageToolbarElement(); /** @var Zend_Form_Element $element */ foreach ($this->getElements() as $element) { if ($element->getName() == $this->_languageToolbarElementName) { continue; } $parentElement = $element; $elementRemoved = false; foreach ($displayGroups as $displayGroupName => $displayGroup) { if ($this->getDisplayGroup($displayGroupName)) { if ($this->getDisplayGroup($displayGroupName)->getElement($element->getName())) { $this->getDisplayGroup($displayGroupName)->removeElement($element->getName()); $displayGroupElements[] = $element->getName(); $elementRemoved = true; } if (!$this->getDisplayGroup($displayGroupName)->getElements()) { $addDisplayGroupDecorators = $this->getDisplayGroup($displayGroupName)->getDecorators(); $this->removeDisplayGroup($displayGroupName); $addDisplayGroupName = $displayGroupName; } } } if (!$elementRemoved) { $this->removeElement($element->getName()); } if (!in_array($parentElement->getName(), $displayGroupElements)) { if (in_array($parentElement->getName(), $contentFields)) { $this->_renderElementByLanguages($parentElement); } else { $this->addElement($parentElement); } } if ($addDisplayGroupName) { $this->addDisplayGroup($displayGroupElements, $addDisplayGroupName); if ($addDisplayGroupDecorators) { $this->getDisplayGroup($addDisplayGroupName)->setDecorators($addDisplayGroupDecorators); } if (($groupContentElements = array_intersect($displayGroupElements, $contentFields))) { $displayGroup = $this->getDisplayGroup($addDisplayGroupName); foreach ($groupContentElements as $groupContentElementName) { foreach ($displayGroupElements as $groupElementName) { $groupElement = $displayGroup->getElement($groupElementName); if (in_array($groupElementName, $groupContentElements)) { $displayGroup->removeElement($groupElementName); if ($groupElement) { $this->removeElement($groupElementName); $this->_renderElementByLanguages($groupElement, $displayGroup); } } } } } $displayGroupElements = array(); $addDisplayGroupName = false; } } $this->_initTranslateExtensionResources(); return $this; } /** * @param Zend_Form_Element $parentElement * @param Zend_Form_DisplayGroup $displayGroup * * @return $this * @throws Zend_Form_Exception */ protected function _renderElementByLanguages(Zend_Form_Element $parentElement, Zend_Form_DisplayGroup $displayGroup = null) { $languageList = Qs_Db_Language::getList(); $selectedLanguage = $this->_getData('language', 'all'); $defaultLanguage = Qs_Db_Language::getDefault(); $parentElementName = $parentElement->getName(); $renderLabel = true; foreach ($languageList as $language) { $langDir = $language['dir']; $newElement = clone $parentElement; /** @var \Zend_Form_Element $subFormElement */ $newElementName = $parentElementName . '_' . $language['name']; /** @var \Zend_Form_Element $newElement */ $newElement->setName($newElementName); $newElement->getDecorator('HtmlTag') ->setOption('id', $parentElementName . '-' . $newElementName . '-element'); $newElement->setBelongsTo($parentElementName); $newElementHtmlPrefix = '' . strtoupper($language['shortTitle']) . ''; /** @var Qs_Form_Decorator_ViewHelper $newElementViewHelper */ if ($newElement instanceof \Qs_Form_Element_ExtendedImage) { $newElementViewHelper = $newElement->getDecorator('ExtendedImage'); $newElementViewHelper->setAdditionalHtml(array('beforeElement' => $newElementHtmlPrefix)); } elseif ($newElement instanceof \Qs_Form_Element_MultiText) { $newElementViewHelper = $newElement->getDecorator('MultiText'); $newElementViewHelper->setAdditionalHtml(array('beforeElement' => $newElementHtmlPrefix)); } elseif ($newElement instanceof \Qs_Form_Element_HtmlEditor) { /** @var \Qs_Form_Element_HtmlEditor $newElement */ $newElementViewHelper = $newElement->getDecorator('ViewHelper'); // $newElementViewHelper->setAdditionalHtmlBeforeElement($newElementHtmlPrefix); $newElement->setLanguagePrefix($newElementHtmlPrefix); if ($langDir) { $newElement->setScriptOption('contentsLangDirection', $langDir); $newElement->setAttrib('dir', $langDir); } } else { $newElementViewHelper = $newElement->getDecorator('ViewHelper'); $newElementViewHelper->setAdditionalHtmlBeforeElement($newElementHtmlPrefix); if ($langDir) { $newElement->setAttrib('dir', $langDir); } } // only default language is required if ($language['name'] != $defaultLanguage) { $newElement->setRequired(false); } $this->addElement($newElement); if ($displayGroup) { $displayGroup->addElement($this->getElement($newElement->getName())); } if (!$renderLabel) { /** @var Qs_Form_Decorator_Label $newElementLabelDecorator */ $newElementLabelDecorator = clone $newElement->getDecorator('Label'); $newElementLabelDecorator->setTagOption('class', 'hidden'); $newElement->addDecorator('Label', $newElementLabelDecorator); $newElement->setLabel(''); } $renderLabel = false; } return $this; } protected function _getData($field = null, $default = null) { $result = null; $method = $this->getMethod(); if (0 === strcasecmp($_SERVER['REQUEST_METHOD'], $method)) { if (false === $field) { $result = Qs_Request::get($method); } else { $method = 'get' . ucfirst(strtolower($method)) . 'Value'; $result = Qs_Request::$method($field); } } if (null === $result) { if (null === $field) { $result = $this->_defaults; } else { $result = Qs_Array::get($this->_defaults, $field); } } return (null === $result) ? $default : $result; } public function prependId($flag = true) { $this->_prependId = $flag; return $this; } public function setPrependString($value) { $this->_prependString = (string) $value; return $this; } public function getPrependString() { if (null === $this->_prependString) { $this->_prependString = $this->getId(); } return $this->_prependString; } public function getRequestValues() { $method = strtoupper($this->getAttrib('method')); return ('GET' == $method) ? $_GET : $_POST; } public function getValidationValues() { return Qs_Array::mergeAssoc($this->getValues(), $this->getRequestValues()); } protected function _prepareData($data = null) { if (null === $data) { $data = $this->getRequestValues(); } return $data; } public function setScriptOptions(array $options) { $this->_scriptOptions = $options; return $this; } public function getScriptOptions() { $this->_scriptOptions['prependId'] = $this->_prependId; $this->_scriptOptions['isErrors'] = $this->isErrors(); $this->_scriptOptions['requiredFiles'] = $this->_getRequiredFiles(); if (!array_key_exists('response', $this->_scriptOptions)) { $this->_scriptOptions['response']['formErrors'] = $this->getErrorMessages(); $this->_scriptOptions['response']['elementsErrors'] = $this->_getAjaxElementsErrors( $this, $this->getMessages(null, true) ); } return $this->_scriptOptions; } /** * @param null|Qs_Form $form * @return array */ protected function _getRequiredFiles(Qs_Form $form = null) { $files = array(); if (null === $form) { $form = $this; } foreach ($form as $element) { if ($element instanceof Zend_Form_Element_File) { /** @var $element Zend_Form_Element_File */ if ($element->isRequired() && !$element->getValue()) { $files[] = array( 'name' => $element->getName(), 'label' => $element->getLabel(), ); } } else if ($element instanceof Zend_Form) { /** @var $element Zend_Form */ $files = array_merge($files, $this->_getRequiredFiles($element)); } } return $files; } public function setScriptOption($name, $value) { $this->_scriptOptions[$name] = $value; return $this; } public function hasScriptOption($name) { return array_key_exists($name, $this->_scriptOptions); } public function getScriptOption($name) { if ($this->hasScriptOption($name)) { return $this->_scriptOptions[$name]; } return null; } public function getElementsErrorsDisplayMethod() { return Qs_Array::get($this->_scriptOptions, 'elementsErrorsDisplayMethod'); } public function setElementsErrorsDisplayMethod($method) { $method = strtoupper($method); if (!in_array($method, array('ALERT', 'HTML'))) { throw new Qs_Form_Exception('Invalid elementsErrorsDisplayMethod "' . $method . '"'); } $this->_scriptOptions['elementsErrorsDisplayMethod'] = $method; return $this; } public function getFormErrorsDisplayMethod() { return Qs_Array::get($this->_scriptOptions, 'formErrorsDisplayMethod'); } public function setFormErrorsDisplayMethod($method) { $method = strtoupper($method); if (!in_array($method, array('ALERT', 'HTML'))) { throw new Qs_Form_Exception('Invalid formErrorsDisplayMethod "' . $method . '"'); } $this->_scriptOptions['formErrorsDisplayMethod'] = $method; return $this; } protected function _setSubformErrors(Qs_Form $form, array $messages) { foreach ($messages as $elementName => $message) { if (null !== ($element = $form->getElement($elementName))) { if (is_array($message)) { $element->addErrors($message); } else { $element->addError($message); } } else if (null !== ($subForm = $form->getSubForm($elementName))) { $this->_setSubformErrors($subForm, $message); } else { if (is_array($message)) { $form->addErrors($message); } else { $form->addError($message); } } } return $this; } public function validate($data = null) { if (!$this->_validateSpamProtection()) { return false; } $data = $this->_prepareData($data); $valid = $this->isValid($data); foreach ($this->_formRules as $rule) { if (true !== ($res = call_user_func($rule, $data))) { if (is_array($res)) { $this->_setSubformErrors($this, $res); $valid = false; } else { throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . '. Form rule callback returned invalid value'); } } } if (!$valid) { $this->walk(function(Zend_Form_Element $element) { if ($element->hasErrors()) { $ulId = $element->getId() . '-errors'; $element->setAttrib('aria-describedby', $ulId); } }); } return $valid; } public function validatePartial($data = null) { if (!$this->_validateSpamProtection()) { return false; } $data = $this->_prepareData($data); $valid = $this->isValidPartial($data); foreach ($this->_formRules as $rule) { if (true !== ($res = call_user_func($rule, $data, true))) { // isXmlHttpRequest = true if (is_array($res)) { $res = array_intersect_key($res, $data); if (empty($res)) { continue; } } if (is_array($res)) { $this->_setSubformErrors($this, $res); $valid = false; } else { throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . '. Form rule callback returned invalid value'); } } } return $valid; } public function getAjaxData() { $this->setIgnoreFiles(true); $isArray = $this->isArray(); $this->setIsArray(false); $data = $this->getValues(); $this->setIsArray($isArray); foreach ($this as $item) { if ($item instanceof Qs_Form_Element_Autocomplete) { /** @var $item Qs_Form_Element_Autocomplete */ Qs_Array::set($data, $item->getFullyQualifiedDisplayName(), ''); Qs_Array::set($data, $item->getFullyQualifiedTitleName(), ''); } else if ( $item instanceof Qs_Form_Element_Checkbox || $item instanceof Zend_Form_Element_Radio || $item instanceof Qs_Form_Element_MultiCheckbox || $item instanceof Qs_Form_Element_MultiDraggableSelect || ($item instanceof Zend_Form_Element_Select && 'multiple' == strtolower($item->getAttrib('multiple'))) ) { /** @var $item Zend_Form_Element */ $name = $item->getName(); if ($item->isRequired() && null === Qs_Array::get($data, $name, null)) { Qs_Array::set($data, $name, ''); } } else if ($item instanceof Qs_Form_SubForm) { /** @var $item Qs_Form_SubForm */ $data[$item->getName()] = $item->getAjaxData(); } } return $data; } public function isValidAjax($data = null) { $_data = $this->getAjaxData(); $data = $this->_prepareData($data); $data = array_intersect_key($data, $_data); $data = Qs_Array::mergeRecursive($_data, $data); $valid = $this->isValidPartial($data); foreach ($this->_formRules as $rule) { if (true !== ($res = call_user_func($rule, $data, true))) { // isXmlHttpRequest = true if (is_array($res)) { $res = array_intersect_key($res, $data); if (empty($res)) { continue; } } if (is_array($res)) { $this->_setSubformErrors($this, $res); $valid = false; } else { throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . '. Form rule callback returned invalid value'); } } } return $valid; } protected function _getAjaxElementsErrors(Qs_Form $form, array $elementsErrors) { $errors = array(); /** @var Zend_Form_Element $element */ foreach ($form->getElements() as $name => $element) { if (isset($elementsErrors[$name])) { $pars = explode('_', get_class($element)); $elementErrors = array( 'type' => strtolower(array_pop($pars)), 'id' => $element->getId(), 'label' => $element->getLabel(), 'errors' => $elementsErrors[$name], ); if ($element instanceof Zend_Form_Element_Captcha) { /** @var $element Zend_Form_Element_Captcha */ /** @var $captcha Qs_Captcha_Image */ $captcha = $element->getCaptcha(); $elementErrors['captcha'] = array( 'id' => $captcha->generate(), 'src' => $captcha->getImgUrl() . $captcha->getId() . $captcha->getSuffix() ); if ($captcha->getRefreshUrl()) { $elementErrors['captcha']['href'] = $captcha->getRefreshUrl() . '?id=' . $captcha->getId(); } if (empty($elementErrors['label'])) { $elementErrors['label'] = 'Captcha'; /** @var $translator Zend_Translate_Adapter_Gettext */ $translator = $element->getTranslator(); if (null !== $translator) { $elementErrors['label'] = $translator->translate($elementErrors['label']); } } } $errors[] = $elementErrors; } } /** @var Qs_Form_SubForm $subForm */ foreach ($form->getSubForms() as $subFormName => $subForm) { if (isset($elementsErrors[$subFormName])) { $subForm->initRender(); $errors = array_merge( $errors, $this->_getAjaxElementsErrors($subForm, $elementsErrors[$subFormName]) ); } } return $errors; } public function validateAjax() { $result = array(); if (false === ($result['isValid'] = $this->isValidAjax())) { $result['formErrors'] = $this->getErrorMessages(); $result['elementsErrors'] = array(); $elementsErrors = $this->getMessages(null, true); if (!empty($elementsErrors)) { $this->initRender(); // /** @var $element Zend_Form_Element */ $result['elementsErrors'] = array_merge( $result['elementsErrors'], $this->_getAjaxElementsErrors($this, $elementsErrors) ); } } return $result; } protected function _recursiveFilter($filter, $value) { if (is_array($value)) { $cleanValues = array(); foreach ($value as $k => $v) { $cleanValues[$k] = $this->_recursiveFilter($filter, $v); } return $cleanValues; } else { return call_user_func($filter, $value); } } public function isSubmitted() { return 0 == strcasecmp($_SERVER['REQUEST_METHOD'], $this->getMethod()); } public function getCancelUrl() { if (null === $this->_cancelUrl) { $this->_cancelUrl = Qs_Constant::get('BASE_URL_LANGUAGE') . '/' . Qs_Constant::get('CURRENT_PAGE') . '?action=cancel'; if ($this->_getData('id')) { $this->_cancelUrl .= '&id=' . $this->_getData('id', 0); } } return $this->_cancelUrl; } public function setCancelUrl($url) { $this->_cancelUrl = $url; return $this; } /** * @param $rule * @return $this * @throws Zend_Form_Exception * @deprecated */ public function addFormRule($rule) { if (!is_callable($rule)) { // require_once 'Zend/Form/Exception.php'; throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . '. Callback function does not exist'); } $this->_formRules[] = $rule; return $this; } public function getHtmlTagOptions() { $idForm = $this->getAttrib('id'); if (!empty($idForm)) { $htmlTagOptions = array('tag' => 'dl', 'class' => $idForm . '_elements', 'id' => $idForm . '_elements'); } else { $htmlTagOptions = array('tag' => 'dl', 'class' => 'zend_form'); } return $htmlTagOptions; } public function loadDefaultDecorators() { if ($this->loadDefaultDecoratorsIsDisabled()) { return; } $decorators = $this->getDecorators(); if (empty($decorators)) { $this->addDecorator('FormElements') ->addDecorator('HtmlTag', $this->getHtmlTagOptions()) ->addDecorator('Form') ->addDecorator('FormErrors', array('placement' => Zend_Form_Decorator_Errors::PREPEND)); } } /** * @return Qs_View */ public function getView() { if (null === $this->_view) { $view = Qs_View::getInstance(); $this->setView($view); } return $this->_view; } public function render(Zend_View_Interface $view = null) { /*if (null !== $this->_template) { $this->initRender(); $this->removeContainers(); }*/ $this->initRender(); if (null !== $view) { $this->setView($view); } $content = ''; foreach ($this->getDecorators() as $decorator) { /** @var $decorator Zend_Form_Decorator_Abstract */ $decorator->setElement($this); if (method_exists($decorator, 'initRender')) { $decorator->initRender(); } $content = $decorator->render($content); } $this->_addResources(); return $content; } public function getElementsOrder() { return $this->_order; } public function setAjaxValidation($flag) { $this->_ajaxValidation = (bool) $flag; return $this; } public function getAjaxValidation() { return $this->_ajaxValidation; } public function setIgnoreFiles($flag) { foreach ($this->getElements() as $element) { if ($element instanceof Zend_Form_Element_File) { /** @var $element Zend_Form_Element_File */ $element->setIgnore($flag); } } return $this; } /** * @param $element Zend_Form_Element * @return Qs_Form */ protected function _elementInitRender($element) { foreach ($element->getDecorators() as $decorator) { /** @var $decorator Zend_Form_Decorator_Abstract */ if (method_exists($decorator, 'initRender')) { $decorator->setElement($element); $decorator->initRender(); } } return $this; } public function setInitializedRender($value = true) { $this->_initializedRender = (bool) $value; return $this; } public function getInitializedRender() { return $this->_initializedRender; } public function initRender() { if ($this->getInitializedRender()) { return $this; } $this->_prepareForm($this); $belongsTo = $this->getElementsBelongTo(); foreach ($this as $item) { // automatic set enctype multipart if (($item instanceof Zend_Form_Element_File) || (($item instanceof Zend_Form) && (Zend_Form::ENCTYPE_MULTIPART == $item->getEnctype())) || (($item instanceof Zend_Form_DisplayGroup) && (Zend_Form::ENCTYPE_MULTIPART == $item->getAttrib('enctype'))) ) { if ($this instanceof Zend_Form) { $this->setEnctype(Zend_Form::ENCTYPE_MULTIPART); } elseif ($this instanceof Zend_Form_DisplayGroup) { $this->setAttrib('enctype', Zend_Form::ENCTYPE_MULTIPART); } } // set belongs if ($item instanceof Zend_Form_Element) { /** @var $item Zend_Form_Element */ $item->setBelongsTo($belongsTo); if (method_exists($item, 'initRender')) { $item->initRender(); } } else if ($item instanceof Zend_Form) { /** @var $item Qs_Form */ if (!empty($belongsTo)) { if ($item->isArray()) { $name = $this->_mergeBelongsTo($belongsTo, $item->getElementsBelongTo()); $item->setElementsBelongTo($name, true); } else { $item->setElementsBelongTo($belongsTo, true); } } } else if ($item instanceof Zend_Form_DisplayGroup) { /** @var Zend_Form_Element $element */ foreach ($item as $element) { if (!empty($belongsTo)) { $element->setBelongsTo($belongsTo); if (method_exists($element, 'initRender')) { $item->initRender(); } } if ($element instanceof Zend_Form_Element_File) { if ($this instanceof Zend_Form) { $this->setEnctype(Zend_Form::ENCTYPE_MULTIPART); } else if ($this instanceof Zend_Form_DisplayGroup) { $this->setAttrib('enctype', Zend_Form::ENCTYPE_MULTIPART); } } $this->_elementInitRender($element); } } } if (!$this->_disabledInitRender) { //$this->_elementInitRender($this); /* перенесено в render() */ foreach ($this as $item) { if ($item instanceof Zend_Form) { continue; } $this->_elementInitRender($item); } } $this->setInitializedRender(); return $this; } protected function _prepareForm(Qs_Form $form, $belongsTo = array()) { if ($form instanceof Zend_Form && ($_belongsTo = $form->getElementsBelongTo())) { if (strpos($_belongsTo, '[')) { $_belongsTo .= '[]'; $parts = explode('[', str_replace(']', '', $_belongsTo)); $parts = array_filter($parts, 'strlen'); $belongsTo = array_merge($belongsTo, $parts); } else { $belongsTo[] = $_belongsTo; } } if ($this->_prependId) { $prefix = $form->getPrependString(); if (!empty($belongsTo)) { $prefix .= '-' . implode('-', $belongsTo); } $form->getDecorator('HtmlTag')->setOption('id', $prefix . '-elements'); } foreach ($form as $item) { if ($item instanceof Zend_Form_Element) { $this->_prepareElement($item, $belongsTo); } else if ($item instanceof Zend_Form) { $this->_prepareSubForm($item, $belongsTo); } else if ($item instanceof Zend_Form_DisplayGroup) { $this->_prepareDisplayGroup($item, $belongsTo); } } return $this; } public function getDisabledInitRender() { return $this->_disabledInitRender; } public function setDisabledInitRender($flag) { $this->_disabledInitRender = (bool) $flag; foreach ($this as $item) { if ($item instanceof Zend_Form) { /** @var Qs_Form $item */ $item->setDisabledInitRender($flag); } } return $this; } /** * @param $element Zend_Form_Element * @param $belongsTo * @return Qs_Form */ protected function _prepareElement($element, $belongsTo) { if (!$element->getAttrib('class')) { $class = $element->getType(); $class = str_replace('\\', '_', $class); if (false !== ($position = strpos($class, 'Form_Element_'))) { $class = substr($class, $position + 13); } $element->setAttrib('class', strtolower($class)); } if ('disabled' === $element->getAttrib('disabled') && false === strpos($element->getAttrib('class'), 'disabled')) { $element->setAttrib('class', $element->getAttrib('class') . ' disabled'); } if ($this->_prependId) { $elementBelongsTo = $element->getBelongsTo(); if (!empty($belongsTo) && empty($elementBelongsTo)) { $elementBelongsTo = $belongsTo; $belongsToString = array_shift($elementBelongsTo); if (!empty($elementBelongsTo)) { $belongsToString .= '[' . implode('][', $elementBelongsTo) . ']'; } $element->setBelongsTo($belongsToString); } $element->setAttrib('id', $this->getPrependString() . '-' . $element->getId()); array_unshift($belongsTo, $this->getPrependString()); } if ($belongsTo) { if (($htmlTag = $element->getDecorator('HtmlTag')) && ($id = $htmlTag->getOption('id'))) { $htmlTag->setOption('id', implode('-', $belongsTo) . '-'. $element->getName() . '-element'); } } return $this; } protected function _getIdFromName($name) { $id = $name; if (substr($id, -2) == '[]') { $id = substr($id, 0, strlen($id) - 2); } if (strstr($id, ']')) { $id = trim($id, ']'); $id = str_replace('][', '-', $id); $id = str_replace('[', '-', $id); } return $id; } /** * @param $element Zend_Form_Element | Zend_Form * @param $belongsTo array * @return Qs_Form */ protected function _prepareContainersIds($element, $belongsTo) { $prefixId = ''; if ($this->_prependId) { $prefixId = $this->getPrependString() . '-'; } if (!empty($belongsTo)) { $prefixId .= implode('-', $belongsTo) . '-'; } if (!empty($prefixId)) { /** @var $dtDdWrapper Qs_Form_Decorator_DtDdWrapper */ if (($dtDdWrapper = $element->getDecorator('DtDdWrapper'))) { $dtDdWrapper->setDtAttrib('id', $prefixId . $element->getName() . '-label'); $dtDdWrapper->setDdAttrib('id', $prefixId . $element->getName() . '-element'); } /** @var $fieldSet Zend_Form_Decorator_FieldSet */ if (($fieldSet = $element->getDecorator('FieldSet'))) { $fieldSet->setOption('id', $prefixId . 'fieldset-' . $element->getName()); } } return $this; } /** * @param $element Zend_Form_Element * @param $belongsTo * @return Qs_Form */ protected function _prepareDisplayGroup($element, $belongsTo) { $this->_prepareContainersIds($element, $belongsTo); foreach ($element as $item) { if ($item instanceof Zend_Form_Element) { $this->_prepareElement($item, $belongsTo); } elseif ($item instanceof Zend_Form) { $this->_prepareSubForm($item, $belongsTo); } elseif ($item instanceof Zend_Form_DisplayGroup) { $this->_prepareDisplayGroup($item, $belongsTo); } } return $this; } /** * @param Qs_Form_SubForm $form * @param array $belongsTo * @return Qs_Form */ protected function _prepareSubForm(Qs_Form_SubForm $form, $belongsTo) { $form->prependId($this->_prependId); $form->setPrependString($this->getPrependString()); $this->_prepareContainersIds($form, $belongsTo); return $this; } public function setElementRemovableDecorators(array $decorators) { $this->_elementRemovableDecorators = $decorators; return $this; } public function setGroupRemovableDecorators(array $decorators) { $this->_groupRemovableDecorators = $decorators; return $this; } public function unsetElementRemovableDecorator($spec) { return $this->_unsetRemovableDecorator('element', $spec); } public function unsetGroupRemovableDecorator($spec) { return $this->_unsetRemovableDecorator('group', $spec); } protected function _unsetRemovableDecorator($type, $spec) { $decorators = &$this->{"_{$type}RemovableDecorators"}; if (is_string($spec)) { $spec = array($spec); } foreach ($spec as $name) { if (!is_string($name)) { throw new Qs_Form_Exception('Invalid type in decorator name'); } if (false !== ($key = array_search($name, $decorators))) { unset($decorators[$key]); } } return $this; } public function removeContainers() { $this->removeDecorator('HtmlTag'); foreach ($this as $item) { /** @var $item Qs_Form */ if ($item instanceof Qs_Form) { $item->removeContainers(); continue; } else if ($item instanceof Zend_Form_DisplayGroup) { foreach ($this->_groupRemovableDecorators as $name) { $item->removeDecorator($name); } } else if ($item instanceof Zend_Form_Element) { foreach ($this->_elementRemovableDecorators as $name) { $item->removeDecorator($name); } } } return $this; } public function __clone() { $elements = array(); foreach ($this->getElements() as $name => $element) { $elements[] = clone $element; } $this->setElements($elements); $decorators = array(); foreach ($this->getDecorators() as $decorator) { $decorators[] = clone $decorator; } $this->setDecorators($decorators); $subForms = array(); foreach ($this->getSubForms() as $name => $subForm) { $subForms[$name] = clone $subForm; } $this->setSubForms($subForms); $displayGroups = array(); foreach ($this->_displayGroups as $group) { /** @var Zend_Form_DisplayGroup $clone */ $clone = clone $group; $elements = array(); foreach ($clone->getElements() as $name => $e) { $elements[] = $this->getElement($name); } $clone->setElements($elements); $displayGroups[] = $clone; } $this->setDisplayGroups($displayGroups); } public function addGlobalFilter() { $arguments = func_get_args(); foreach ($this->getElements() as $element) { call_user_func_array(array($element, 'addFilter'), $arguments); } return $this; } public function setHasButtons($hasButtons) { $this->_hasButtons = $hasButtons; return $this; } public function getHasButtons() { return $this->_hasButtons; } /** * Merges given two belongsTo (array notation) strings * * @param string $baseBelongsTo * @param string $belongsTo * @return string */ protected function _mergeBelongsTo($baseBelongsTo, $belongsTo) { $endOfArrayName = strpos($belongsTo, '['); if ($endOfArrayName === false) { return $baseBelongsTo . '[' . $belongsTo . ']'; } $arrayName = substr($belongsTo, 0, $endOfArrayName); return $baseBelongsTo . '[' . $arrayName . ']' . substr($belongsTo, $endOfArrayName); } protected function _initSpamProtection() { if ($this->_hasSpamProtection) { if (self::SPAM_PROTECTION_COOKIE == $this->_spamProtectionType) { $this->_initCookieProtection(); } else { $this->_initEmptyFieldProtection(); } } return $this; } protected function _initCookieProtection() { $cookieUrl = Qs_SiteMap::findFirst(null, array('type' => 'FormCookie\\'), null, 'url'); if (!$cookieUrl) { throw new Qs_Form_Exception('Page for cookie protection is not found!'); } $cookieUrl .= '?form=' . rawurlencode($this->getId()); /** @var Qs_Doc $doc */ $doc = Zend_Registry::get('doc'); $doc->addStylesheet($cookieUrl, array('skipPacking' => true)); return $this; } protected function _initEmptyFieldProtection() { $field = $this->_spamProtectionField; $this->addElement('text', $field['name'], array('label' => $field['label'])); $element = $this->getElement($field['name']); if (($label = $element->getDecorator('Label'))) { /** @var Qs_Form_Decorator_Label $label */ $label->setTagOption('class', $field['name']); } if (($htmlTag = $element->getDecorator('HtmlTag'))) { /** @var Qs_Form_Decorator_HtmlTag $htmlTag */ $htmlTag->setOption('class', $field['name']); } return $this; } protected function _validateSpamProtection() { if ($this->_hasSpamProtection) { if (self::SPAM_PROTECTION_COOKIE == $this->_spamProtectionType) { $method = '_validateCookieProtection'; } else if (self::SPAM_PROTECTION_EMPTY_FIELD == $this->_spamProtectionType) { $method = '_validateEmptyFieldProtection'; } else { throw new Qs_Form_Exception('Unknown spam protections validation method'); } if (!$this->{$method}()) { $this->addError($this->_spamProtectionMessage); return false; } } return true; } protected function _validateCookieProtection() { if (!App\FormCookie\View::getCookie($this->getId())) { return false; } return true; } protected function _validateEmptyFieldProtection() { if ('' != Qs_Request::getRequestValue($this->_spamProtectionField['name'])) { return false; } return true; } /** * @return Qs_Doc */ protected function getDoc() { /** @var Qs_Doc $doc */ $doc = Zend_Registry::get('doc'); return $doc; } protected function _addResources() { return $this; } protected function _initTranslateExtensionResources() { if ($this->getHasTranslation() && ($contentFields = $this->getContentFields()) && ($languageToolbar = $this->getElement($this->getLanguageToolbarElementName())) ) { $languageList = Qs_Db_Language::getList(); $options = [ 'formId' => $this->getId(), 'languageToolbarContainerId' => $languageToolbar->getId() . '-element', 'contentFields' => $contentFields, 'languageList' => Qs_Array::fetchCol($languageList, 'name'), ]; $this->setScriptOption('translateExtension', $options); $this->setScriptOption( 'onErrorCallback', ['fn' => 'qs.form.TranslateExtension.onErrorCallback', 'args' => [$this->getId()]] ); } return $this; } public function addSubForm(Zend_Form $form, $name, $order = null) { $name = (string) $name; foreach ($this->_loaders as $type => $loader) { $loaderPaths = $loader->getPaths(); foreach ($loaderPaths as $prefix => $paths) { foreach ($paths as $path) { $form->addPrefixPath($prefix, $path, $type); } } } if (!empty($this->_elementPrefixPaths)) { foreach ($this->_elementPrefixPaths as $spec) { list($prefix, $path, $type) = array_values($spec); $form->addElementPrefixPath($prefix, $path, $type); } } if (!empty($this->_displayGroupPrefixPaths)) { foreach ($this->_displayGroupPrefixPaths as $spec) { list($prefix, $path) = array_values($spec); $form->addDisplayGroupPrefixPath($prefix, $path); } } if (null !== $order) { $form->setOrder($order); } if (($oldName = $form->getName()) && $oldName !== $name && $oldName === $form->getElementsBelongTo()) { $form->setElementsBelongTo($name); } $form->setName($name); if ($this->getTranslatorDisabled()) { $form->setDisableTranslator($this->getTranslatorDisabled()); } $form->setParentForm($this); $this->_subForms[$name] = $form; $this->_order[$name] = $order; $this->_orderUpdated = true; return $this; } public function setParentForm(Qs_Form $form) { $this->_parentForm = $form; return $this; } public function hasParentForm() { return (bool) $this->_parentForm; } public function getFullId() { $id = $this->getId(); if ('' != $id && $this->hasParentForm() && $this->_parentForm->hasParentForm()) { $parentId = $this->_parentForm->getFullId(); if ($parentId) { $id = $parentId . '-' . $id; } } return $id; } public function getFullName() { $fullName = ''; $form = $this; do { $name = $form->getName(); $form = $form->_parentForm; $fullName = (($form && $form->_parentForm) ? '[' . $name . ']' : $name) . $fullName; } while ($form); return $fullName; } /** * @param $callback * @param Zend_Form|Zend_Form_DisplayGroup|null $form * @return $this * @throws Exception */ public function walk($callback, $form = null) { if (null == $form) { $form = $this; } foreach ($form as $item) { if ($item instanceof Zend_Form_Element) { if (false === call_user_func($callback, $item)) { return false; } } elseif ($item instanceof Zend_Form_DisplayGroup || $item instanceof Zend_Form) { if (false === $this->walk($callback, $item)) { return false; } } else { throw new Exception('Unknown form item ' . get_class($item)); } } return true; } protected function translate($text) { if ($this->getTranslator()) { return $this->getTranslator()->translate($text); } return $text; } /** * Retrieve translator object * * @return Zend_Translate|null */ public function getTranslator() { if ($this->translatorIsDisabled()) { return null; } if (null === $this->_translator) { $this->_translator = Qs_Translate::getTranslator($this->getTranslationSection()); } return $this->_translator; } public function getHasTranslation() { return $this->_hasTranslation; } public function setHasTranslation($hasTranslation) { $this->_hasTranslation = $hasTranslation; return $this; } public function getContentFields() { return $this->_contentFields; } public function setContentFields($contentFields) { $this->_contentFields = $contentFields; return $this; } public function getTranslatorDisabled() { return $this->_translatorDisabled; } public function setTranslatorDisabled($translatorDisabled) { $this->_translatorDisabled = (bool) $translatorDisabled; return $this; } public function getHasContentTranslation() { return $this->_hasContentTranslation; } public function setHasContentTranslation($hasContentTranslation) { $this->_hasContentTranslation = $hasContentTranslation; return $this; } public function getTranslationSection() { return $this->_translationSection; } public function setTranslationSection($translationSection) { $this->_translationSection = $translationSection; return $this; } }