'%itemName% has been added', 'msgUpdated' => '%itemName% has been updated', 'msgReordered' => '%itemsName% have been reordered', 'msgDeleted' => '%itemName% has been deleted', 'msgLocked' => '"%itemTitle%" %itemName% is currently being edited by "%firstName% %lastName%" %userRoleTitle%. Please try again later.', 'msgDataUnavailable' => '%itemName% is not available', ); protected $_pageHeaderTemplates = array( 'headerNew' => 'Add New %itemName%', 'headerEdit' => 'Edit %itemName%', 'headerReorder' => 'Reorder %itemsName%', 'headerView' => 'View %itemName%', ); /** * Rewrite for _pageHeaderTemplates * * @var array */ protected $_pageHeaderTemplatesMap = array( 'headerUpdate' => 'headerEdit', 'headerInsert' => 'headerNew' ); protected $_sessionName; protected static $_translatorDefault; protected static $_classNameTemplates = array( 'List' => '%item%List', ); public function __construct($options = array()) { $this->setOptions(Qs_Options::mergeConstructorOptions($this, $options)); $this->_init(); } protected function _init() { $this->_setupLockObj(); return $this; } public function exec() { $this->_initAction(); $this->_callAction(); $this->_addResources(); return $this; } protected function _addResources() { $this->_doc->addCriticalStylesheets($this->getOption('criticalStylesheets', [])); $this->_doc->addNonCriticalStylesheets($this->getOption('nonCriticalStylesheets', [])); $this->_doc->addScripts($this->getOption('scripts', [])); return $this; } protected function _addMessageTemplate($key, $text) { $this->_messageTemplates[$key] = $text; return $this; } protected function translate($text) { if ($this->_getTranslator()) { return $this->_getTranslator()->translate($text); } return $text; } protected function _getListOptions() { $options = array( 'restParams' => $this->getRestParams(), 'templatePath' => $this->_getTemplatePath(), 'translator' => $this->_getTranslator(), 'primaryKey' => array_values($this->getPrimary()), 'idItem' => $this->getIdItem(), ); return $options; } protected function _getClassNamePrefix() { return substr(get_class($this), 0, -4); } protected function _getSubName() { $className = substr(get_class($this), 0, -4); $separator = (false === strpos($className, '\\')) ? '_' : '\\'; $nameParts = explode($separator, $className); do { $name = array_pop($nameParts); } while ('' === $name || 'Admin' === $name); return $name; } protected function _getClassName($type, $prefix = null) { $type = ucfirst($type); if (null === $prefix) { $prefix = $this->_getClassNamePrefix(); } if (false !== strpos($prefix, '\\') && isset(self::$_classNameTemplates[$type])) { $type = str_replace('%item%', $this->_getSubName(), self::$_classNameTemplates[$type]); } return $prefix . $type; } protected function _getListClassName() { return $this->_getClassName('List'); } /** * @return Qs_ViewController_List */ protected function _getList() { if (null === $this->_list) { $className = $this->_getListClassName(); if (!class_exists($className)) { $className = 'Qs_ViewController_List'; } $this->_list = new $className($this->_getListOptions()); } return $this->_list; } protected function _getLogClassName() { return $this->_getClassName('Log'); } protected function _getLogOptions() { $options = array( 'role' => $this->_doc->getAuth()->getRole(), 'roleId' => $this->_doc->getAuthData('id'), 'sessionId' => Zend_Session::getId(), 'ip' => $_SERVER['REMOTE_ADDR'], 'controller' => get_class($this), 'config' => $this->getConfig() ); if ($this->_hasDataObj()) { $primaryKey = $this->_getDataObj()->getPrimaryKeyArray(); $options['objectId'] = reset($primaryKey) ?: null; } return $options; } protected function _getLog() { if (null === $this->_log) { $className = $this->_getLogClassName(); if (!class_exists($className)) { $className = 'Qs_ViewController_Log'; } $this->_log = new $className($this->_getLogOptions()); if (!empty($this->_logIgnoredControllers)) { $this->_log->addIgnoredControllers($this->_logIgnoredControllers); } } return $this->_log; } protected function _log() { if ($this->_hasLog && Qs_ViewController_Log::getEnabled() && $this->_hasDataObj()) { $this->_getLog()->write($this->_action, $this->_getDataObj()->getObjectInfo()); } return $this; } protected function _setMessage($messageString, $messageKey = null) { if ($messageKey === null) { $keys = array_keys($this->_messageTemplates); $messageKey = current($keys); } if (!isset($this->_messageTemplates[$messageKey])) { throw new Qs_ViewController_Exception("No message template exists for key '$messageKey'"); } $this->_messageTemplates[$messageKey] = $messageString; return $this; } protected function _setMessages(array $messages) { foreach ($messages as $key => $message) { $this->_setMessage($message, $key); } return $this; } protected function _getMessagePlaceholders() { return $this->_messagePlaceholders; } protected function _setHeader() { if ($this->_hasDataObj() && $this->_doc->hasAuth() && get_class($this->_doc->getAuth()) == 'App_Admin_Auth') { $key = 'header' . ucfirst($this->_action); $header = $this->_createHeader($key); if ($header) { $this->_doc->setHeader($header); } } return $this; } protected function _callAction() { if (null === $this->_action) { return $this; } $this->_initActionMethod(); if (method_exists($this, $this->_actionMethod)) { $this->_setHeader(); $this->{$this->_actionMethod}(); } else if (Qs_Request::isXmlHttpRequest()) { Qs_Debug::log('Action method not found: ' . get_class($this) . '->' . $this->_actionMethod); return false; } else { throw new Zend_Exception('Action method not found: ' . get_class($this) . '->' . $this->_actionMethod); } return $this; } public function setIdItem($id) { $this->_idItem = (int) $id; return $this; } public function getIdItem() { return $this->_idItem; } protected function _initAction() { if (empty($this->_action)) { if (isset($_REQUEST['action']) && !empty($_REQUEST['action'])) { if (isset($_REQUEST['__idItem']) && !empty($_REQUEST['__idItem'])) { if ($_REQUEST['__idItem'] == $this->getIdItem()) { $this->_action = $_REQUEST['action']; } } else { $this->_action = $_REQUEST['action']; } } if (empty($this->_action) || !in_array($this->_action, $this->_actions)) { $this->_action = $this->_defaultAction; } } if (!in_array($this->_action, $this->_actions)){ $this->_action = reset($this->_actions); } return $this; } protected function _initActionMethod() { $this->_actionMethod = '_do' . ucfirst($this->_action); if (Qs_Request::isXmlHttpRequest()) { if (isset($_REQUEST['__idItem']) && !empty($_REQUEST['__idItem']) && $_REQUEST['__idItem'] == $this->getIdItem()) { $this->_actionMethod .= 'Ajax'; } else if (!isset($_REQUEST['__idItem'])) { $this->_actionMethod .= 'Ajax'; } } return $this; } protected function _initPrimaryKey() { $_primaryKey = array(); $primary = $this->_getDataObj()->getPrimary(); if (is_array($primary) && !empty($primary)) { foreach ($primary as $name) { $value = Qs_Request::getRequestValue($name); if ($value) { $_primaryKey[$name] = $value; } } } if (!empty($_primaryKey)) { $this->_primaryKey = $_primaryKey; $this->_getDataObj()->setPrimaryKey($_primaryKey); } return $this; } protected function _setCompressJson($flag) { $this->_compressJson = (bool) $flag; return $this; } protected function _getCompressJson() { if (null === $this->_compressJson) { if (strpos(Qs_Request::getHeader('ACCEPT-ENCODING'), 'gzip') === false) { $this->_setCompressJson(false); } else { $this->_setCompressJson(true); } } return $this->_compressJson; } protected function _getDataObjClass() { $class = get_class($this); if (false !== ($pos = strrpos($class, 'View'))) { $class = substr($class, 0, $pos) . 'Obj'; } return $class; } protected function _hasDataObj() { if (null !== $this->_dataObj) { return true; } return class_exists($this->_getDataObjClass()); } protected function _getDataObj() { if (null === $this->_dataObj) { $class = $this->_getDataObjClass(); if (!class_exists($class)) { throw new Qs_ViewController_Exception('Data object is not defined ' . $class); } $this->setDataObj(new $class()); $this->_initPrimaryKey(); } return $this->_dataObj; } public function setDataObj($dataObj) { if (!($dataObj instanceof Qs_DataObj_Interface)) { throw new Qs_ViewController_Exception('Data object is not instance of Qs_DataObj_Interface'); } $this->_dataObj = $dataObj; return $this; } /** * @param array $data * @param null|string $jsonpCallback */ protected function _displayJson($data, $jsonpCallback = null) { header('Cache-Control: no-store, no-cache, must-revalidate, private'); header('Pragma: no-cache'); header('Content-Type: application/x-javascript; charset=utf-8'); $json = json_encode($data); if (null !== $jsonpCallback) { $json = $jsonpCallback . '(' . $json . ');'; } if ($this->_getCompressJson()) { header('Content-Encoding: gzip'); $json = gzencode($json, 9); } die($json); } protected function _saveBackUrl() { $this->_setBackUrl(Qs_Request::getUrl()); return $this; } protected function _setBackUrl($backUrl, $sessionName = null) { if (is_null($sessionName)) { $sessionName = $this->getSessionName(); } $session = new Qs_Session_Namespace($sessionName); $session->backUrl = $backUrl; return $this; } public function setDoc($doc) { $this->_doc = $doc; return $this; } public function setConfig(array $config) { $this->_config = new Zend_Config(Qs_Array::mergeRecursive($this->getConfig()->toArray(), $config)); return $this; } public function setOptions($options) { if (isset($options['options'])) { unset($options['options']); } foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (method_exists($this, $method)) { $this->$method($value); } else { $this->_options[$key] = $value; } } return $this; } public function getOption($name, $default = null) { return Qs_Array::get($this->_options, $name, $default); } public function setOption($name, $value) { $this->_options[$name] = $value; return $this; } public function setRestAlias($restAlias, $updateRestParams = true) { $this->_restAlias = $restAlias; if ($updateRestParams && !empty($restAlias)) { $restParams = preg_split($this->_getRestParamsPattern(), $restAlias); foreach ($restParams as &$param) { $param = rawurldecode($param); } $this->setRestParams($restParams); } return $this; } protected function _setRestParamsPattern($pattern) { $this->_restParamsPattern = $pattern; return $this; } protected function _getRestParamsPattern() { if (null === $this->_restParamsPattern) { $this->_setRestParamsPattern('/\//'); } return $this->_restParamsPattern; } public function getRestParam($name) { if (array_key_exists($name, $this->_restParams)) { return $this->_restParams[$name]; } return null; } public function getRestParams() { return $this->_restParams; } public function setRestParams(array $restParams) { $this->_restParams = $restParams; return $this; } public function getRestAlias() { return $this->_restAlias; } protected function _getBackUrl($sessionName = null, $defaultUrl = null) { if (is_null($sessionName)){ $sessionName = $this->getSessionName(); } $session = new Qs_Session_Namespace($sessionName); if (isset($session->backUrl)) { return $session->backUrl; } return (null !== $defaultUrl) ? $defaultUrl : $this->url(); } protected function _getDefaultLinks() { $links = array(); if (false !== array_search('new', $this->_actions)) { $links['new'] = 'Add New ' . $this->getConfig('itemName'); } if (false !== array_search('reorder', $this->_actions)) { $links['reorder'] = 'Reorder ' . $this->getConfig('itemsName'); } return $links; } protected function _getLinks() { if (empty($this->_links)) { $links = $this->_getDefaultLinks(); $this->_addLinks($links); } return $this->_links; } protected function _addLinks(array $links) { foreach ($links as $action => $spec) { $title = $url = ''; if (!is_numeric($action)) { if (!in_array($action, $this->_actions)) { continue; } if ('reorder' == $action && $this->_getDataObj()->getReorderOptionsCount() < 2) { continue; } } if (is_string($spec)) { $this->_addLink($spec, $this->url(array('action' => $action))); } elseif (is_array($spec)) { $attribs = array(); $options = array(); if (!array_key_exists('url', $spec)) { $url = $this->url(array('action' => $action)); } if (!array_key_exists('title', $spec)) { $title = ucfirst($action); } extract($spec); $this->_addLink($title, $url, $attribs, $options); } elseif ($spec instanceof LinkInterface) { $this->_addLink($spec); } } return $this; } protected function _addLink($title, $url = null, $attribs = array(), $_options = array()) { if ($title instanceof LinkInterface) { $this->_links[] = $title; return $this; } $defaultOptions = array( 'delimiter' => ' | ' ); $options = array_merge($defaultOptions, $_options); if (null === $this->_links) { $this->_links = array(); } $link = array( 'title' => $this->translate($title), 'url' => $url, 'attribs' => $attribs, 'options' => $options, ); $this->_links[] = $link; return $this; } public function getTemplate($template, $logNotFound = true) { $_template = Qs_SiteMap::getTemplate($template, $this->_getTemplatePath()); if (false === $_template && $logNotFound) { $message = 'Template "' . $template . '" not found in paths: "' . implode('", "', (array)$this->_getTemplatePath()) . '".'; Qs_Debug::log($message); } return $_template; } protected function _getTemplatePath() { if (null === $this->_templatePath) { $class = get_class($this); $this->_templatePath = substr($class, 0, -4); if ('App_' === ($prefix = substr($this->_templatePath, 0, 4)) || 'App\\' === $prefix) { $this->_templatePath = substr($this->_templatePath, 4); } $this->_templatePath = rtrim($this->_templatePath, '_\\'); $this->_templatePath = array(str_replace(array('_', '\\'), '/', $this->_templatePath), 'ViewController'); } return $this->_templatePath; } protected function _addTemplatePath($path) { $paths = $this->_getTemplatePath(); array_unshift($paths, $path); $paths = array_unique($paths); $this->_setTemplatePath($paths); return $this; } protected function _setTemplatePath($path) { $this->_templatePath = $path; return $this; } protected function _getPage4SaveMessage() { $backUrl = $this->_getBackUrl(); if (empty($backUrl)) { return Qs_Constant::get('CURRENT_PAGE'); } $info = Qs_Url::parse($backUrl); return $info['alias']; } protected function _getFormOptions($type = null) { $options = array( 'method' => 'post', 'action' => $this->url(), 'attribs' => array( 'id' => strtolower($this->getApplicationName()) . '-form', 'class' => strtolower($this->getApplicationName()) . '_form', ), ); if ($this->_translatorIsDisabled()) { $options['translatorDisabled'] = $this->_translatorIsDisabled(); } else { $options['translationSection'] = $this->_getTranslationSection(); } if (($itemId = $this->getIdItem())) { $options['cmsItemId'] = $itemId; } if ($this->_hasDataObj() && ($obj = $this->_getDataObj())) { $options['primaryKey'] = $obj->getPrimaryKeyArray(); $options['hasTranslation'] = $obj->hasTranslation(); $options['contentFields'] = $obj->getContentFields(); } if (false !== ($template = $this->getTemplate('form.tpl', false))) { $options['template'] = $template; } if (in_array($type, ['new', 'edit']) && ($sessionName = Qs_Request::getGetValue('sessionName'))) { $options['action'] = $this->url(compact('sessionName')); if (empty($options['cancelUrl'])) { $options['cancelUrl'] = $this->_getBackUrl($sessionName); } } return $options; } protected function _initFromForm(Qs_Form $form) { $data = $form->getValues(); $this->_getDataObj()->initFromForm($data); return $this; } protected function _addFormItem(Qs_Form $form) { $this->_addItem(array('tpl' => $this->getTemplate('text.tpl'), 'text' => $form->render())); return $this; } protected function _getData4Form() { return $this->_getDataObj()->getData4Form(); } /** * @param $type * @param array $options * @throws Qs_ViewController_Exception * @return Qs_Form */ protected function _getFormInstance($type, array $options = array()) { if (($class = $this->_getFormClassName($type)) && class_exists($class)) { return new $class(array_merge($this->_getFormOptions($type), $options)); } return null; } protected function _getFormClassName($type) { $type = ucfirst($type); if (false !== strpos(get_class($this), '\\')) { $type .= 'Form'; } $class = Qs_SiteMap::getSubClass($this->_getClassNamePrefix(), 'Form_' . $type); return $class; } protected function _getNewForm(array $options = array()) { $form = $this->_getFormInstance('new', $options); if ($form->getHasContentTranslation() && $this->_getDataObj()->hasTranslation() && $this->_getDataObj()->getContentFields()) { $form->setDefault('language', 'all'); $form->initContentFields(); } return $form; } protected function _getEditForm(array $options = array()) { $form = $this->_getFormInstance('edit', $options); if ($form->getHasContentTranslation() && $this->_getDataObj()->hasTranslation() && $this->_getDataObj()->getContentFields()) { $form->initContentFields(); } return $form; } protected function _doNew() { $form = $this->_getNewForm(); $form->setDefaults(); $this->_addFormItem($form); $this->_postNew(); return $this; } protected function _doEdit() { if (null === ($data = $this->_getData4Form())) { $this->_setBackError(static::MSG_DATA_UNAVAILABLE); $this->_doBack(); } if (!$this->_lock()) { $this->_setBackAttention($this->_createMessage(static::MSG_LOCKED, $this->_getLocker())); $this->_doBack(); } $form = $this->_getEditForm(array('defaults' => $data)); $form->setDefaults(); $this->_addFormItem($form); $this->_postEdit(); return $this; } protected function _doInsert() { $form = $this->_getNewForm(); if ($form->validate()) { $this->_initFromForm($form); if (false === $this->_getDataObj()->insert()) { $this->_setBackErrors($this->_getDataObj()->getErrors()); } else { $this->_postInsert(); $this->_setBackMessage(static::MSG_ADDED); } $this->_doBack(); } else { $this->_addFormItem($form); } return $this; } protected function _doInsertAjax() { $form = $this->_getNewForm(); $this->_displayJson($form->validateAjax()); } protected function _doUpdateAjax() { if ($this->_isLocked()) { $data = array('isLocked' => true, 'error' => $this->_createMessage(static::MSG_LOCKED, $this->_getLocker())); } else { $form = $this->_getEditForm(); $data = $form->validateAjax(); } $this->_displayJson($data); } protected function _doUpdate() { if (null === $this->_getDataObj()->getData()) { $this->_setBackError(static::MSG_DATA_UNAVAILABLE); $this->_doBack(); } if ($this->_isLocked()) { $this->_setBackAttention($this->_createMessage(static::MSG_LOCKED, $this->_getLocker())); $this->_doBack(); } $form = $this->_getEditForm(); if ($form->validate()) { $this->_initFromForm($form); if (false === $this->_getDataObj()->update()) { $this->_setBackErrors($this->_getDataObj()->getErrors()); } else { $this->_postUpdate(); $this->_unlock(); $this->_setBackMessage(static::MSG_UPDATED); } $this->_doBack(); } else { $this->_addFormItem($form); } return $this; } protected function _setDisableTranslator($flag) { $this->_translatorDisabled = (bool) $flag; return $this; } protected function _translatorIsDisabled() { return $this->_translatorDisabled; } protected function _getTranslator() { if ($this->_translatorIsDisabled()) { return null; } if (null === $this->_translator) { $this->_translator = Qs_Translate::getTranslator($this->_getTranslationSection()); } return $this->_translator; } // public static function getDefaultTranslator() // { // if (null === static::$_translatorDefault) { // if (Zend_Registry::isRegistered('Zend_Translate')) { // /** @var $translator Zend_Translate */ // $translator = Zend_Registry::get('Zend_Translate'); // if ($translator instanceof Zend_Translate_Adapter) { // return $translator; // } elseif ($translator instanceof Zend_Translate) { // return $translator->getAdapter(); // } // } // } // return static::$_translatorDefault; // } //todo:check is need protected function getMessageTemplateVariables($template) { $matches = []; if (!preg_match_all('/%([^%]+)%/', $template, $matches)) { return []; } return $matches[1]; } protected function setMessagePlaceholder($name, $value) { $this->_messagePlaceholders[$name] = $value; return $this; } protected function getMessagePlaceholderValue($name) { if (array_key_exists($name, $this->_messagePlaceholders)) { return $this->_messagePlaceholders[$name]; } $method = 'get' . ucfirst($name); if (method_exists($this, $method)) { return $this->$method(); } $configValue = $this->getConfig($name); if (is_scalar($configValue)) { return $configValue; } return null; } protected function _renderMessage($template, array $placeholders = null) { // $template = $this->_translate($template); $messageVariables = $this->getMessageTemplateVariables($template); if (empty($messageVariables)) { return $template; } if (null === $placeholders) { $placeholders = []; foreach ($messageVariables as $name) { $placeholders[$name] = $this->getMessagePlaceholderValue($name); // $placeholders[$name] = $this->_translate($this->getMessagePlaceholderValue($name)); } } else { $placeholders = array_merge( array_fill_keys($messageVariables, ''), Qs_Array::map($placeholders, $messageVariables) ); } $keys = array_map(function ($value) { return "%{$value}%"; }, array_keys($placeholders)); $template = str_replace($keys, $placeholders, $template); // todo: check for double translation return $this->_translate($template); } protected function renderError($messageKey, array $messagePlaceholders = null) { return $this->_doc->renderError($this->_createMessage($messageKey, $messagePlaceholders)); } protected function renderMessage($messageKey, array $messagePlaceholders = null) { return $this->_doc->renderMessage($this->_createMessage($messageKey, $messagePlaceholders)); } protected function renderAttention($messageKey, array $messagePlaceholders = null) { return $this->_doc->renderAttention($this->_createMessage($messageKey, $messagePlaceholders)); } protected function _createMessage($messageKey, array $messagePlaceholders = null) { if (isset($this->_messageTemplates[$messageKey])) { return $this->_renderMessage($this->_messageTemplates[$messageKey], $messagePlaceholders); } return null; } protected function _createHeader($headerKey) { if (!empty($this->_pageHeaderTemplatesMap) && array_key_exists($headerKey, $this->_pageHeaderTemplatesMap)) { $headerKey = $this->_pageHeaderTemplatesMap[$headerKey]; } if (!isset($this->_pageHeaderTemplates[$headerKey])) { return null; } return $this->_renderMessage($this->_pageHeaderTemplates[$headerKey]); } protected function _setDocMessage($messageKey, $type) { if (array_key_exists($messageKey, $this->_messageTemplates)) { $text = $this->_createMessage($messageKey); } else { $text = $this->_translate($messageKey); } // if ($translator = $this->_getTranslator()) { // $text = $translator->translate($text); // } $sessionName = $this->_getPage4SaveMessage(); $session = new Qs_Session_Namespace($sessionName); if (isset($session->{$type})) { if (is_array($session->{$type})) { $session->{$type}[] = $text; } else { $session->{$type} = array($session->{$type}, $text); } } else { $session->{$type} = $text; } return $this; } protected function _setBackMessage($messageKey) { $this->_setDocMessage($messageKey, Qs_Doc::MESSAGE_BOX_MESSAGE); return $this; } protected function _setBackErrors(array $errors) { foreach ($errors as $error) { $this->_setBackError($error); } return $this; } protected function _setBackError($messageKey) { $this->_setDocMessage($messageKey, Qs_Doc::MESSAGE_BOX_ERROR); return $this; } protected function _setBackAttention($messageKey) { $this->_setDocMessage($messageKey, Qs_Doc::MESSAGE_BOX_ATTENTION); return $this; } protected function _getReorderForm(array $options = array()) { $form = $this->_getFormInstance('reorder', $options); return $form; } protected function _doReorder() { $options = array('orderOptions' => $this->_getDataObj()->getReorderOptions()); $form = $this->_getReorderForm($options); $this->_addFormItem($form); $this->_postReorder(); return $this; } protected function _doUpdateOrder() { $form = $this->_getReorderForm(); $form->validate(); $order = $form->getValue('order'); $this->_getDataObj()->updateOrder($order); $this->_setBackMessage(static::MSG_REORDERED); $this->_postUpdateOrder(); $this->_doBack(); } protected function _doChangeOption() { if (null === $this->_getDataObj()->getData()) { $this->_setBackError(static::MSG_DATA_UNAVAILABLE); $this->_doBack(); } if ($this->_isLocked()) { $this->_setBackAttention($this->_createMessage(static::MSG_LOCKED, $this->_getLocker())); } else { if ($this->_getDataObj()->changeEnumOption(Qs_Request::getRequestValue('name'))) { $this->_postChangeOption(); } else { $this->_setBackErrors($this->_getDataObj()->getErrors()); } } $this->_doBack(); } /** * Change enum option and reload cell content using ajax * * REQUEST param string $name property name * REQUEST param string $cell column name * @throws Qs_ViewController_Exception */ protected function _doChangeOptionAjax() { $response = []; $name = Qs_Request::getRequestValue('name'); $cell = Qs_Request::getRequestValue('cell'); if (null === $this->_getDataObj()->getData()) { $response['isError'] = true; $response['message'] = $this->_createMessage(static::MSG_DATA_UNAVAILABLE); } elseif ($this->_isLocked()) { $response['isError'] = true; $response['message'] = $this->_createMessage(static::MSG_LOCKED, $this->_getLocker()); } else { if (!$this->_getDataObj()->changeEnumOption($name)) { $errors = $this->_getDataObj()->getErrors(); $response['isError'] = true; $response['message'] = $errors ? implode("\n", $errors) : 'Error'; } else { $rowData = $this->_getDataObj()->clearData()->getData(); $this->_postChangeOption(); $list = $this->_getList(); $list->setIsDisabledLimit(true); if ($cell) { $list->setColumns([$list->getColumn($cell)]); } $list->setList([$rowData]); $item = $list->toArray(); $this->_prepareItem($item); $this->_doc->assign('item', new Qs_Doc_Item($item)); $response['html'] = $this->_doc->fetchTemplate($item['tpl']); } } $this->_displayJson($response); } protected function _do404() { $this->_doc->display404(); return $this; } protected function _addLinksItem(array $links = null, $item = array()) { if (null === $links) { $links = $this->_getLinks(); } if (!$this->_hasLinks || empty($links)) { return $this; } $defaultItem = array( 'tpl' => $this->getTemplate('list-links.tpl'), 'attribs' => array( 'id' => str_replace(array('_', '\\'), '-', substr(strtolower(get_class($this)), 0, -4) . 'links'), 'class' => 'nav nav-pills top-links' ) ); $item = Qs_Array::mergeRecursive($defaultItem, $item); $item['links'] = $links; $this->_addItem($item); return $this; } protected function _prepareItem(array &$item) { if (empty($item['config'])) { $item['config'] = $this->getConfig()->toArray(); } $item['templatePath'] = $this->_getTemplatePath(); $item['translator'] = $this->_getTranslator(); return $this; } protected function _addItem($item, $groupName = null) { $groupName = $groupName ? $groupName : $this->getGroupName(); $this->_prepareItem($item); $this->_doc->addItem($item, $groupName); return $this; } protected function _getListItem() { $list = $this->_getList(); $list->setList($this->_getDataObj()->setSelectOptions($list->getSelectOptions())->getList()); $list->setListSelect($this->_getDataObj()->getListSelect()); return $list->toArray(); } protected function _addListItem() { $this->_initListRedirection(); $item = $this->_getListItem(); $this->_initListPageNumber($item); $this->_addLinksItem(); $this->_addItem($item); return $this; } protected function _initListPageNumber(array $listItem) { if ($this->getOption('groupName') == Qs_Doc::ITEM_GROUP_MAIN && ($page = Qs_Array::get($listItem, 'paginator[current]')) && $page > 1 ) { $this->_doc->setPageNumber($page); } return $this; } protected function _initListRedirection() { $list = $this->_getList(); $list->getEventManager()->attach('redirect', function (Zend\EventManager\Event $e) { if (null === ($code = $e->getParam('code'))) { Qs_Http::redirect($e->getParam('url')); } else { Qs_Http::redirect($e->getParam('url'), $code); } }); if (1 == ($pageNumber = $list->parsePageNumber())) { $list->getEventManager()->trigger('redirect', null, ['url' => $list->getPaginatorUrl(true)]); } else { $list->setPageNumber($pageNumber); } if ($list->getDefaultIpp() == Qs_Request::getGetValue('ipp')) { $list->getEventManager()->trigger('redirect', null, ['url' => Qs_Request::getUrlExclude('ipp')]); } return $this; } protected function _addFilterItem() { if ($this->_hasFilter) { $form = $this->_getFilterForm(); if ($form->validate($form->getValidationValues())) { $filter = $form->getValues(); $this->_getDataObj()->addFilter($filter); $this->_getList()->addUrlVariables(array_keys($filter)); } $this->_addFormItem($form); } return $this; } protected function _doList() { $this->_saveBackUrl(); $this->_addFilterItem(); $this->_addListItem(); $this->_postList(); return $this; } protected function _prepareViewItem(array &$item) { $item['tpl'] = $this->getTemplate('view.tpl'); if (empty($item['backUrl'])) { $item['backUrl'] = ($backUrl = $this->_getBackUrl(CURRENT_PAGE_FINAL)) ? $backUrl : CURRENT_PAGE_FINAL; } return $this; } protected function getData() { return $this->_getDataObj()->getData(); } protected function _isItemAccessible(array $item) { if (empty($item) || (array_key_exists('enabled', $item) && 'y' != $item['enabled'])) { return false; } return true; } protected function _addViewItem() { $item = $this->getData(); if (!$this->_isItemAccessible($item)) { $this->_doc->display404(); } $this->_prepareViewItem($item); $this->_addItem($item); $this->_initDetailsPage($item); return $this; } protected function _doView() { $this->_addViewItem(); $this->_postView(); return $this; } protected function _initDetailsPage(array $item) { $this->_initPageSeo($item); return $this; } protected function _initPageSeo(array $item) { $title = null; if (!empty($item['title'])) { $title = $item['title']; $this->_doc->setHeader($title); } if (!empty($item['metaTitle'])) { $title = $item['metaTitle']; } if ($title) { $this->_doc->appendTitle($title); } if (!empty($item['metaKeywords'])) { $this->_doc->setKeywords($item['metaKeywords']); } if (!empty($item['metaDescription'])) { $this->_doc->setDescription($item['metaDescription']); } return $this; } protected function _postView() { $this->_log(); return $this; } protected function _doRowPreview() { $this->_doRowPreviewAjax(); exit; } protected function _doRowPreviewAjax() { $response = array('isValid' => false); if ($this->_getDataObj()->getPrimaryKey() && ($row = $this->_getRowPreviewData()) && ($html = $this->_getList()->renderRowPreview($row)) ) { $response['html'] = $html; $response['isValid'] = true; $this->_log(); // -- reverted rev 4262 } $this->_displayJson($response); exit; } protected function _getRowPreviewData() { $data = $this->_getDataObj()->getData(); if ($data) { $data['config'] = $this->getConfig()->toArray(); } return $data; } protected function _doMultiAction() { $this->_doMultiActionAjax(); exit; } protected function _doMultiActionAjax() { exit; } protected function _getFilterFormOptions() { $options = array( 'filterFields' => $this->_getFilterFields(), 'method' => 'get', 'id' => strtolower($this->getApplicationName()) . '-filter-form', 'class' => 'filter_form clearfix', ); if ($this->_translatorIsDisabled()) { $options['translatorDisabled'] = $this->_translatorIsDisabled(); } return $options; } protected function _getFilterForm() { if (null === ($form = $this->_getFormInstance('filter', $this->_getFilterFormOptions()))) { $form = new Qs_Form_Filter(array_merge($this->_getFormOptions(), $this->_getFilterFormOptions())); } return $form; } protected function _getFilterFields() { if (null === $this->_filterFields) { $this->_filterFields = array(); $filterFields = Qs_Array::collapse($this->_getDataObj()->getFilterFields()); $filterFields = array_unique(array_values($filterFields)); foreach (array_keys($filterFields) as $index) { if (is_scalar($filterFields[$index])) { $this->_filterFields[] = ucfirst( preg_replace('/([a-z])([A-Z])/', '$1 $2', $filterFields[$index]) ); } } } return $this->_filterFields; } protected function _doDelete() { if (null === $this->_getDataObj()->getData()) { $this->_setBackError(static::MSG_DATA_UNAVAILABLE); $this->_doBack(); } if ($this->_isLocked()) { $this->_setBackAttention($this->_createMessage(static::MSG_LOCKED, $this->_getLocker())); $this->_doBack(); } if (false === $this->_getDataObj()->delete()) { $this->_setBackErrors($this->_getDataObj()->getErrors()); } else { $this->_postDelete(); $this->_setBackMessage(static::MSG_DELETED); } $this->_doBack(); } protected function _doCancel() { $this->_unlock(); $this->_doBack(); } protected function _doBack() { $backUrl = $this->_getBackUrl(); if (empty($backUrl)) { Qs_Http::redirect($this->url()); } else { $this->_clearBackUrl(); Qs_Http::redirect($backUrl); } } protected function _clearBackUrl($sessionName = null) { if (is_null($sessionName)){ $sessionName = CURRENT_PAGE; } $session = new Qs_Session_Namespace($sessionName); $session->backUrl = null; return $this; } public function getPrimaryKey() { if (null === $this->_primaryKey) { $this->_getDataObj(); // init Data Obj if (null !== $this->_dataObj) { $this->_initPrimaryKey(); } } return $this->_primaryKey; } public function setPrimaryKey($key) { $this->_primaryKey = $key; return $this; } public function getPrimary() { return $this->_getDataObj()->getPrimary(); } protected function _getTranslationSection() { if (null === $this->_translationSection) { $this->_translationSection = strtolower($this->getApplicationName()); } return $this->_translationSection; } public function getTranslationSection() { return $this->_getTranslationSection(); } public function getApplicationName() { if (null === $this->_applicationName) { $this->_applicationName = Qs_Application::getNameFromInstance($this); } return $this->_applicationName; } public function url($options = array()) { $parts = array(); $parts[] = Qs_Constant::get('BASE_URL_LANGUAGE') . '/'; $parts[] = Qs_Constant::get('CURRENT_PAGE'); if (!empty($options)) { $parts[] = '?' . http_build_query($options); } return implode('', $parts); } public function redirect($url, $code = 301) { if (is_array($url)) { $url = $this->url($url); } Qs_Http::redirect($url, $code); } public function finalUrl($options = array()) { $parts = array(); $parts[] = Qs_Constant::get('BASE_URL_LANGUAGE') . '/'; $parts[] = Qs_Constant::get('CURRENT_PAGE_FINAL'); if (!empty($options)) { $parts[] = '?' . http_build_query($options); } return implode('', $parts); } public function setAction($action) { if (!in_array($action, $this->_actions)) { throw new Qs_ViewController_Exception('Unknown action "' . $action . '"'); } $this->_action = $action; return $this; } public function setDefaultAction($action) { if (!in_array($action, $this->_actions)) { throw new Qs_ViewController_Exception('Unknown action "' . $action . '"'); } $this->_defaultAction = $action; return $this; } public function getConfigForm(array $options = array()) { return $this->_getFormInstance('config', $options); } public function hasConfigForm() { return ($this->_hasConfigForm && class_exists($this->_getFormClassName('config'))); } protected function _sendMail($options) { $requiredOptions = array('from', 'to', 'subject', 'body'); $diff = array_diff_key(array_combine($requiredOptions, array_fill(0, count($requiredOptions), '')), $options); if (!empty($diff)) { throw new Qs_ViewController_Exception('Qs_ViewController::_sendMail. Missed required options: ' . implode(', ', array_keys($diff))); } $from = $to = $subject = $body = ''; extract($options); $mail = new Qs_Mail(); $mail->setFrom($from); $mail->setSubject($subject); Qs_Mail::cutImageBaseUrl($body, constant('BASE_URL')); $mail->setHtml($body, null, constant('WWW_PATH')); $mail->addTo($to); return $mail->send(); } protected function _setupLockObj() { if (!$this->getConfig('hasLock')) { return $this; } $timeout = $this->getConfig('lockObjectTimeout'); if (null !== $timeout) { $this->_doc->getLockObj()->setTimeout($timeout); } return $this; } protected function _isLocked() { if (!$this->getConfig('hasLock')) { return false; } $resourceName = $this->_getDataObj()->getResourceName(); $objectId = $this->_getDataObj()->getObjectId(); return $this->_doc->getLockObj()->isLocked($resourceName, $objectId); } /** * @return int */ protected function _getLockRefreshTimeout() { $timeout = (int) $this->getConfig('lockRefreshTimeout'); if (!$timeout) { $timeout = (int) App_Settings_Obj::get('lockRefreshTimeout'); } return $timeout; } /** * @return bool */ protected function _lock() { if (!$this->getConfig('hasLock')) { return true; } $resourceName = $this->_getDataObj()->getResourceName(); $objectId = $this->_getDataObj()->getObjectId(); if ($this->_doc->getLockObj()->lock($resourceName, $objectId)) { $this->_doc->addScript('js/lib/lock.js'); $options = array( 'resourceName' => $resourceName, 'objectId' => $objectId, 'refreshTimeout' => $this->_getLockRefreshTimeout(), 'url' => ((0 === strpos(CURRENT_PAGE, 'admin/')) ? 'admin/' : '') . '__lock-object', ); $this->_doc->addInitObject('Qs_Lock', array($options)); return true; } return false; } /** * @return bool */ protected function _unlock() { if (!$this->getConfig('hasLock')) { return true; } $resource = $this->_getDataObj()->getResourceName(); $idObject = $this->_getDataObj()->getObjectId(); return $this->_doc->getLockObj()->unlock($resource, $idObject); } protected function _getLocker() { if (!$this->getConfig('hasLock')) { return array(); } $resource = $this->_getDataObj()->getResourceName(); $idObject = $this->_getDataObj()->getObjectId(); $locker = $this->_doc->getLockObj()->getLockerData($resource, $idObject); if (!empty($locker)) { $object = $this->_getDataObj()->getObjectInfo(); if (array_key_exists('itemTitle', $object)) { $locker['itemTitle'] = $object['itemTitle']; } } return $locker; } protected function _postList() { $this->_log(); return $this; } protected function _postNew() { $this->_log(); return $this; } protected function _postInsert() { $this->_log(); return $this; } protected function _postEdit() { $this->_log(); return $this; } protected function _postUpdate() { $this->_log(); return $this; } protected function _postDelete() { $this->_log(); return $this; } protected function _postChangeOption() { $this->_log(); return $this; } protected function _postReorder() { $this->_log(); return $this; } protected function _postUpdateOrder() { $this->_log(); return $this; } public function setHasLog($hasLog) { $this->_hasLog = $hasLog; return $this; } public function getHasLog() { return $this->_hasLog; } /** * Return menu items for virtual menu * @return array */ public function getMenu() { Qs_Debug::log('Not implemented'); return array(); } public static function getPage($field = null, $default = null) { $page = Qs_SiteMap::findFirst(null, array('type' => Qs_SiteMap::classToType(get_called_class()))); return (empty($page)) ? $default : Qs_Array::get($page, $field, $default); } protected function _doRenderFormPart() { exit; } protected function _doRenderFormPartAjax() { $formPart = Qs_Request::getPostValue('formPart'); $formPartAction = Qs_Request::getPostValue('formPartAction', ''); $method = '_initFormPart' . ucfirst($formPart) . ucfirst($formPartAction); $defaults = Qs_Request::getPost(); if (method_exists($this, $method)) { $this->$method($defaults); } $this->_doc->clearInitFunctions()->clearInlineScripts()->clearScripts()->clearAllStylesheets(); $form = $this->_getEditForm(['defaults' => $defaults]); $form->setDefaults(); if (!($part = $form->getSubForm($formPart))) { throw new \Exception('Undefined form part: ' . $formPart); } $response = [ 'html' => '
' . $part->render() . '
', 'scripts' => $this->_doc->renderInitFunctions() ]; $this->_displayJson($response); } /** * @param mixed $sessionName * @return $this */ public function setSessionName($sessionName) { $this->_sessionName = $sessionName; return $this; } /** * @return mixed */ public function getSessionName() { if (null === $this->_sessionName) { if (null === ($this->_sessionName = Qs_Request::getGetValue('sessionName'))) { $this->_sessionName = CURRENT_PAGE; } } return $this->_sessionName; } public static function getBackUrl() { return static::getPage('url') . '?action=back'; } protected function _doExportCsv() { $dataObj = $this->_getDataObj(); if ($dataObj->hasFilter()) { $form = $this->_getFilterForm(); if ($form->validate()) { $dataObj->addFilter($form->getValues()); } } $options = ['order' => [$this->_getList()->getOrderBy()]]; $dataObj->setSelectOptions($options); $stmt = $dataObj->getList4ExportStatement(); $rowCallback = function () use ($stmt, $dataObj) { $row = $stmt->fetch(); if ($row) { $dataObj->prepareExportRow($row); } return $row; }; $helper = new ExportCsv([ 'fileName' => $this->_translate($this->getConfig('itemsName')) . ' {date}.csv', 'columns' => $this->_translate($dataObj->getExportColumns()), 'rowCallback' => $rowCallback, ]); $this->_postExportCsv(); $helper->export(); } protected function _postExportCsv() { $this->_log(); return $this; } protected function _translate($text) { if ($translator = $this->_getTranslator()) { if (is_array($text)) { foreach ($text as &$value) { $value = $this->_translate($value); } } else { $text = $translator->translate($text); } } return $text; } public function getGroupName() { return $this->_groupName; } public function setGroupName($groupName) { $this->_groupName = $groupName; return $this; } }