array('redirectAlias')); protected $_fileFields = array('headerImage'); public $itemName = 'Page'; public $itemsName = 'Pages'; public $idParent = 0; public static function getInstance() { if (null === self::$_instance) { self::$_instance = new self(); } return self::$_instance; } protected function _arrayParseTag2Url(array &$array, $fields = null) { if (null === $fields) { $fields = $this->_urlParseFields; } if (empty($fields) || !is_array($array) || empty($array)) { return false; } foreach ($fields as $key => $field) { if (is_scalar($field)) { if (isset($array[$field])) { $array[$field] = $this->_tag2BaseUrl($array[$field]); } } else { if (isset($array[$key])) { $this->_arrayParseTag2Url($array[$key], $field); } } } return true; } protected function _arrayParseUrl2Tag(&$array, $fields = null) { if (null === $fields) { $fields = $this->_urlParseFields; } if (empty($fields) || !is_array($array) || empty($array)) { return false; } foreach ($fields as $key => $field) { if (is_scalar($field)) { if (isset($array[$field])) { $array[$field] = $this->_baseUrl2Tag($array[$field]); } } else { if (isset($array[$key])) { $this->_arrayParseUrl2Tag($array[$key], $field); } } } return true; } protected function _join(Zend_Db_Select $select = null) { $select = parent::_join($select); $select->join( array('cDef' => $this->_getTableName('PageContent')), "cDef.idPage = {$this->_tableAlias}.id " . "AND cDef.language = " . $this->db->quote(Qs_Db_Language::getDefault()), array( 'ISNULL(c.title, cDef.title) AS title', 'ISNULL(c.menuTitle, cDef.menuTitle) AS menuTitle', 'ISNULL(c.header, cDef.header) AS header' ) ); $select->joinLeft(array('c' => $this->_getTableName('PageContent')), "c.idPage = {$this->_tableAlias}.id " . "AND c.language = " . $this->db->quote($this->getLanguage()), null); $select->joinLeft( array('dp' => $this->_getTableName('DraftPage')), "dp.id = {$this->_tableAlias}.id ", array( 'hasDraft' => new Zend_Db_Expr( "CASE WHEN dp.id IS NOT NULL AND dp.added <> dp.changed THEN 'y' ELSE 'n' END") ) ); return $select; } protected function _filterWhere(Zend_Db_Select $select) { if (!empty($this->_filterFields) && array_key_exists('query', $this->_filter)) { Qs_Db_Filter::where($select, $this->_filterFields, $this->_filter['query']); } foreach ($this->_filter as $field => $value) { if (empty($value)) { continue; } switch ($field) { case 'handler': $select->where("{$this->_tableAlias}.{$field} IN (" . $this->db->quote($value) . ')'); break; case 'system': $select->where("{$this->_tableAlias}.system = " . $this->db->quote($value)); break; case 'showInSiteMap': $select->where("{$this->_tableAlias}.showInSiteMap = " . $this->db->quote($value)); break; case 'showInMenu': $select->where("{$this->_tableAlias}.showInMenu = " . $this->db->quote($value)); break; case 'enabled': if (Qs_Version::compareVersion('2.3.0') <= 0) { $select->where("{$this->_tableAlias}.enabled = " . $this->db->quote($value)); } break; case 'showInFooter': if (Qs_Version::compareVersion('2.3.0') <= 0) { $select->where("{$this->_tableAlias}.showInFooter = " . $this->db->quote($value)); } break; default: break; } } return $select; } protected function _where(Zend_Db_Select $select = null) { if (null === $select) { $select = $this->select; } $select->where("{$this->_tableAlias}.alias IS NOT NULL"); if ($this->hasFilter()) { $this->_filterWhere($select); } return $select; } public function draftExists() { $key = $this->getPrimaryKey(); if (!is_array($key)) { $key = (array) $key; } $rows = call_user_func_array(array($this->tableDraftPage, 'find'), $key); if (count($rows)) { return true; } return false; } public function createDraft() { if (false === ($data = $this->_getDataEx())) { return false; } $this->deleteDraftItems($data['id']); $this->_saveDraftDataEx($data); return $this; } public function draftPageOptionExists() { if ($this->isCustomOptions(true)) { $options = $this->getMetaOptions($this->getPrimaryKey(), true, true); return !empty($options); } return true; } public function createPageOptionDraft() { $this->_deleteDraftMetaOptions($this->getPrimaryKey()); $select = $this->db->select(); $select->from( array('po' => $this->_getTableName('PageOption', true)), array('idPage', 'name', 'show', 'value') ); $select->where('idPage=' . $this->db->quote($this->getPrimaryKey(), Zend_Db::INT_TYPE)); $data = $this->db->fetchAll($select); if (false === $data) { return false; } $table = $this->_getTable('DraftPageOption', true); foreach ($data as $option) { $table->insert($option); } return $this; } public function getDraftMeta($idPage) { return $this->getMeta($idPage, true); } protected function _getMetaRow($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $rowset = $this->{"table{$draftPrefix}Page"}->find($idPage); if (!count($rowset)) { return false; } return $rowset->current(); } public function getMeta($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (!($row = $this->_getMetaRow($idPage, $draft))) { return false; } $data = $row->toArray(); $this->_arrayParseTag2Url($data, $this->_urlParseFields['meta']); $content = $this->{"table{$draftPrefix}PageContent"}->select() ->where('idPage = ? ', $idPage) ->where('language = ?', $this->language) ->query() ->fetch(); if (is_array($content) && !empty($content)) { $data = array_merge($data, $content); } return $data; } /** * @param int $level * @param array|string|Zend_Db_Expr|null $where [OPTIONAL] * @return array|bool */ public function getFilteredPages4Select($level = 1, $where = null) { $select = $this->getSelect4SiteMap(); if ($where) { $select->where(Qs_Db::getWhereSql($where)); } $siteMap = $this->getSiteMap(array('select' => $select)); $options = $this->_prepareParentOptions($siteMap, $level); return $options; } public function getPages4Select($level = 1, $where = null) { $_where = array(); if (!$this->_suMode) { $parts = array('' . $this->_tableAlias . '.system != \'y\''); if ($this->_primaryKey && 0 != ($redirectPageId = (int) $this->getDraftData('meta[redirectPageId]'))) { $parts[] = '' . $this->_tableAlias . '.id = ' . (int) $redirectPageId; } $_where[] = '(' . implode(' OR ', $parts) . ')'; } if ($where) { $_where[] = Qs_Db::getWhereSql($where); } return $this->getFilteredPages4Select($level, $_where); } public function getParent4Select($level = 1, $currPageId = null) { $currPageId = (null === $currPageId) ? $this->getPrimaryKey() : $currPageId; $select = $this->getSelect4SiteMap(); $select->where("{$this->_tableAlias}.id <> " . (int) $currPageId); $select->where("{$this->_tableAlias}.final <> 'y'"); $select->joinLeft( array('po' => $this->_getTableName('PageOption')), "(po.idPage = " . $this->tableAlias . ".id) AND (po.name = 'isAdditional')", array('isAdditional' => new Zend_Db_Expr('ISNULL(po.value, dpo.value)')) ); $select->joinLeft( array('dpo' => $this->_getTableName('DPageOption')), "dpo.name = 'isAdditional'", null ); $select->reset('order'); $select->order(array($this->_tableAlias . '.idParent', 'isAdditional', $this->_tableAlias . '.sorter')); $siteMap = $this->getSiteMap(array('select' => $select)); $options = $this->_prepareParentOptions($siteMap, $level); return $options; } protected function _prepareParentOptions($siteMap, $level = 0) { $options = array(); $additionalPages = array(); foreach ($siteMap as $page) { if ('y' == $page['isAdditional']) { $additionalPages[$page['id']] = str_repeat(' ', $level * 4) . $page['menuTitle']; if (isset($page['sub'])) { $subOptions = $this->_prepareParentOptions($page['sub'], $level + 1); $additionalPages = Qs_Array::mergeAssoc($additionalPages, $subOptions); } } else { $options[$page['id']] = str_repeat(' ', $level * 4) . $page['menuTitle']; if (isset($page['sub'])) { $subOptions = $this->_prepareParentOptions($page['sub'], $level + 1); $options = Qs_Array::mergeAssoc($options, $subOptions); } } } $options = Qs_Array::mergeAssoc($options, $additionalPages); return $options; } /** * @param array $options * @return Zend_Db_Select */ public function getSelect4SiteMap($options = array()) { if (isset($options['filter'])) { $_filter = $this->_filter; $this->setFilter($options['filter']); } $select = $this->select->reset(); foreach (array('from', 'join', 'where', 'group', 'having') as $name) { $method = '_' . ucfirst($name); $this->$method($select); } $select->order(array($this->_tableAlias . '.idParent', $this->_tableAlias . '.sorter')); if (isset($options['filter'])) { $this->_filter = $_filter; } return $select; } public function getAdditionalSelect4SiteMap($options = array()) { $select = $this->getSelect4SiteMap($options); if (!$this->isCustomOptions()) { return $select; } $select->reset('order'); $select->columns(array('isAdditional' => $this->_isAdditionalExpr())); $select->order(array('isAdditional', $this->_tableAlias . '.idParent', $this->_tableAlias . '.sorter')); return $select; } protected function _isAdditionalExpr() { $select = $this->_db->select(); $select->from(Qs_Db::getPair('zz_DPageOption', 'dpo'), 'ISNULL( po.value, dpo.value)'); $select->joinLeft( Qs_Db::getPair('zz_PageOption', 'po'), "po.idPage = Page.id AND po.name = 'isAdditional'", array() ); $select->where("dpo.name = 'isAdditional'"); return new Zend_Db_Expr('(' . $select . ')'); } public function getAllItems() { $select = $this->db->select(); $select->from($this->pairPageItem); $select->order(array('PageItem.idPage', 'PageItem.sorter')); return $this->db->fetchAll($select); } public function getAllItemConfigs() { $select = $this->db->select(); $select->from($this->pairPageItemConfig); return $this->db->fetchAll($select); } public function getAllMetaOptions() { static $data = null; if (null === $data) { $data = array(); $data['defaults'] = $this->getDefaultMetaPairs(); $select = $this->_db->select(); $select->from($this->_getTableName('PageOption', true)); $data['options'] = $this->_db->fetchAll($select); } return $data; } public function getSiteMap($options = array()) { if (empty($options) && empty($this->_filter) && null !== $this->_siteMap) { return $this->_siteMap; } $idParent = 0; if (!isset($options['select'])) { $select = $this->getSelect4SiteMap($options); } extract($options); $_list = $this->_db->fetchAssoc($select); if ($this->isCustomOptions()) { $metaOptions = $this->getAllMetaOptions(); foreach(array_keys($_list) as $k) { $_list[$k] = array_merge($metaOptions['defaults'], $_list[$k]); $this->_arrayParseTag2Url($_list[$k], $this->_urlParseFields['meta']); } foreach ($metaOptions['options'] as $option) { if (array_key_exists($option['idPage'], $_list)) { $_list[$option['idPage']][$option['name']] = $option['value']; } } } if (isset($full)) { // Item Options $itemConfigs = array(); $_itemConfigs = $this->getAllItemConfigs(); foreach ($_itemConfigs as $itemConfig) { if (!array_key_exists($itemConfig['idItem'], $itemConfigs)) { $itemConfigs[$itemConfig['idItem']] = array(); } Qs_Array::set($itemConfigs[$itemConfig['idItem']], $itemConfig['name'], $itemConfig['value']); } // Page Items $items = array(); $_items = $this->getAllItems(); foreach ($_items as $item) { if (array_key_exists($item['id'], $itemConfigs)) { $item['config'] = $itemConfigs[$item['id']]; } $items[$item['idPage']][] = $item; } foreach ($_list as &$page) { if (array_key_exists($page['id'], $items)) { $page['items'] = $items[$page['id']]; } } } $list = array(); foreach($_list as $v) { $list[$v['idParent']][$v['alias']] = $v; } $siteMap = (isset($list[$idParent])) ? $list[$idParent] : array(); unset($list[$idParent]); $parentAlias = ''; if (is_array($siteMap) && !empty($siteMap)) { $this->_prepareSiteMap($siteMap, $list, $parentAlias); } if (empty($options) && empty($this->_filter)) { $this->_siteMap = $siteMap; } return $siteMap; } protected function _prepareSiteMap(&$siteMap, &$list, $parentAlias = '') { foreach ($siteMap as $alias => &$page) { $this->_id2Page[$page['id']] =& $page; $page['fullAlias'] = rtrim($parentAlias, '/') . (($parentAlias) ? '/' : '') . $page['alias']; if (Qs_SiteMap::isSecurePage($page)) { $page['url'] = BASE_URL_LANGUAGE_HTTPS; } else { $page['url'] = BASE_URL_LANGUAGE_HTTP; } if ('y' != $page['isRoot']) { $page['url'] .= ((empty($page['fullAlias'])) ? '' : '/') . $page['fullAlias']; } if (empty($page['header'])) { $page['header'] = $page['title']; } if (empty($page['menuTitle'])) { $page['menuTitle'] = $page['header']; } if (isset($list[$page['id']])) { $page['sub'] = $list[$page['id']]; unset($list[$page['id']]); $this->_prepareSiteMap($page['sub'], $list, $page['fullAlias']); } } } public function getSiteMapPageCount($siteMap) { $count = count($siteMap); foreach ($siteMap as $page) { if (isset($page['sub'])) { $count += $this->getSiteMapPageCount($page['sub']); } } return $count; } public function getDItemType4Select() { if (null === $this->_itemTypes) { $select = $this->_db->select(); $select->from($this->_getTableName('DPageItemType'), array('type', 'title')); $select->order('sorter'); $this->_itemTypes = $this->_db->fetchPairs($select); foreach ($this->_itemTypes as $type => $title) { if (!$this->_itemTypeFileExists($type)) { Qs_Debug::log('Cms item "' . $type . '" not found'); unset($this->_itemTypes[$type]); } } } return $this->_itemTypes; } protected function _itemTypeFileExists($type) { $class = 'App_' . $type . 'View'; $file = BASE_PATH . '/' . str_replace('_', '/', $class) . '.php'; return file_exists($file); } public function getDraftItems($idPage) { return $this->getItems($idPage, true); } public function getItemsList($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $select = $this->db->select() ->from(array('i' => $this->_getTableName($draftPrefix . 'PageItem'))) ->join(array('g' => $this->_getTableName('DPageItemGroup')), 'g.id = i.idGroup', array('groupTitle' => 'g.title', 'groupName' => 'g.name')) ->where('i.idPage = ?', $idPage, Zend_Db::INT_TYPE) ->order(array('g.sorter', 'i.sorter')); $stmt = $select->query(); $items = $stmt->fetchAll(); $sorter = 0; foreach ($items as &$item) { $item['sorter'] = $sorter++; $item['config'] = $this->_getItemConfig($item['id'], $draft); } return $items; } public function getItems($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $_items = $this->getItemsList($idPage, $draft); $items = array(); foreach ($_items as $item) { if ($itemObject = $this->getItemObject($item['type'])){ $itemObject->setLanguage($this->language); $itemObject->setDraftPrefix($draftPrefix); $itemObject->setPrimaryKey($item['number']); $item['data'] = $itemObject->getData(); } $item['config'] = $this->_getItemConfig($item['id'], $draft); if (!isset($items[$item['groupName']])) { $items[$item['groupName']] = array(); } $items[$item['groupName']]['i'.$item['id']] = $item; } return $items; } public function getDraftItem($id) { return $this->getItem($id, true); } public function getDraftItemRow($id) { return $this->getItemRow($id, true); } public function getItemRow($id, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $rowset = $this->{"table{$draftPrefix}PageItem"}->find($id); if (!count($rowset)) { return false; } return $rowset->current(); } public function getItem($id, $draft = false) { if (! ($row = $this->getItemRow($id, $draft))) { return false; } $item = $row->toArray(); if ($itemObject = $this->getItemObject($item['type'])) { $draftPrefix = ($draft) ? 'Draft' : ''; $itemObject->setLanguage($this->language); $itemObject->setDraftPrefix($draftPrefix); $itemObject->setPrimaryKey($item['number']); $item['data'] = $itemObject->getData(); } $groupData = $this->getItemGroupById($item['idGroup']); if (!empty($groupData)) { $item['groupTitle'] = $groupData['title']; $item['groupName'] = $groupData['name']; } $item['config'] = $this->_getItemConfig($item['id'], $draft); return $item; } public function getItemGroupById($idGroup, $field = null) { $select = $this->db->select(); $select->from($this->pairDPageItemGroup, array('name', 'title')) ->where("DPageItemGroup.id = " . (int) $idGroup); $data = $this->db->fetchRow($select); if (null !== $field && !empty($data) && array_key_exists($field, $data)) { return $data[$field]; } return $data; } public function getItemObject($type) { $class = 'App_Cms_Item_' . rtrim($type, '_') . '_Obj'; $file = BASE_PATH . '/' . str_replace('_', '/', $class) . '.php'; if (!array_key_exists($class, $this->_itemObjects)) { if (!file_exists($file)) { $this->_itemObjects[$class] = null; } else { $this->_itemObjects[$class] = new $class(); } } if ($this->_itemObjects[$class]) { $this->_itemObjects[$class]->clearData(); } return $this->_itemObjects[$class]; } public function getDraftData($field = false) { return $this->getData($field, true); } public function getData($field = false, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $data = $this->{'_data' . $draftPrefix}; if (null == $data) { return null; } return Qs_Array::get($data, $field); } public function initDraftData() { $this->_data = $this->getDraftFromDb($this->getPrimaryKey()); } public function getDraftFromDb($idPage, $field = false) { $data = $this->getFromDb($idPage, $field, true); foreach ($this->_fileFields as $fieldName) { if (($file = Qs_Request::getPostValue($fieldName))) { $data[$fieldName] = $file; } else { if (isset($data['meta'][$fieldName])) { $data[$fieldName] = $data['meta'][$fieldName]; } } } return $data; } public function getFromDb($idPage, $field = false, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (null === $this->{'_data' . $draftPrefix}) { $this->{'_data' . $draftPrefix} = array(); if (false !== ($meta = $this->{"get{$draftPrefix}Meta"}($idPage))) { $options = $this->_getPageOptions($idPage, $meta, $draft); foreach ($options as $name => $option) { $meta[$name] = $option['value']; } $this->{'_data' . $draftPrefix}['meta'] = $meta; $items = $this->{"get{$draftPrefix}Items"}($idPage); $this->{'_data' . $draftPrefix} = array_merge($this->{'_data' . $draftPrefix}, $items); } } return Qs_Array::get($this->{'_data' . $draftPrefix}, $field); } public function draftHtmlBlock($idBlock) { $rowset = $this->tableHtmlBlock->find($idBlock); if (!count($rowset)) { return false; } $htmlBlockData = $rowset->current()->toArray(); unset($htmlBlockData['id']); $id_draft_block = $this->tableDraftHtmlBlock->insert($htmlBlockData); $contentItems = $this->tableHtmlBlockContent->select() ->where('idBlock = ?', $idBlock) ->query() ->fetchAll(); foreach ($contentItems as $data) { $data['idBlock'] = $id_draft_block; $this->tableDraftHtmlBlockContent->insert($data); } return $id_draft_block; } public function insertDefaultPage($defaults) { if (isset($defaults['meta'])) { $metaData = $defaults['meta']; } else { $metaData = array(); } if (!empty($defaults['options'])) { $metaOptions = array( 'methods' => array_fill(0, count($defaults['options']), 'insert'), 'options' => array_values($defaults['options']), ); $metaData = array_merge($metaData, $this->extractMeta($defaults['options'])); } else { $metaOptions = null; } $metaData['sorter'] = $this->_getSorter(); $metaData['language'] = DEFAULT_LANGUAGE; $id = $this->insertMeta($metaData); $this->_updateMetaOptions($metaOptions, false, $id); $itemData = array('idPage' => $id, 'type' => 'HtmlBlock_'); $this->insertItem($itemData); return $id; } public function insertDraftMeta($data = array()) { return $this->insertMeta($data, true); } public function insertMeta($data = array(), $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $data['idPage'] = $id = $this->{"table{$draftPrefix}Page"}->insert($data); $this->{"table{$draftPrefix}PageContent"}->insert($data); return $id; } public function insertDraftItem($data) { return $this->insertItem($data, true); } public function insertItem($data, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; unset($data['id']); $this->_db->beginTransaction(); if ($itemObject = $this->getItemObject($data['type'])){ $itemObject->setLanguage($this->language); $itemObject->setDraftPrefix($draftPrefix); $itemData = isset($data['data'])?$data['data']:array(); $data['number'] = $itemObject->insert($itemData); } if (!isset($data['sorter'])) { $idGroup = (isset($data['idGroup'])) ? $data['idGroup'] : 1; $data['sorter'] = 1 + $this->{"get{$draftPrefix}ItemSorter"}($data['idPage'], $idGroup); } $id = $this->{"table{$draftPrefix}PageItem"}->insert($data); $this->_db->commit(); $this->touch($draft); return $id; } public function getDraftItemSorter($idPage, $idGroup) { return $this->getItemSorter($idPage, $idGroup, true); } public function getItemSorter($idPage, $idGroup, $draft = true) { $draftPrefix = ($draft) ? 'Draft' : ''; $select = $this->_db->select(); $select->from($this->_getTableName($draftPrefix . 'PageItem'), 'MAX(sorter)'); $select->where('idPage = ' . $this->db->quote($idPage, Zend_Db::INT_TYPE)); $select->where('idGroup = ' . $this->db->quote($idGroup, Zend_Db::INT_TYPE)); $sorter = (int)$this->_db->fetchOne($select); return $sorter; } public function updateDraftItem($id, $type, $data) { return $this->updateItem($id, $type, $data, true); } public function updateItem($id, $type, $data, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (!($row = $this->{"get{$draftPrefix}ItemRow"}($id))) { return false; } $this->setPrimaryKey($row->idPage); if (isset($data['config']) && !empty($data['config'])) { $this->updateItemConfig($id, $data['config'], $draft); } $data['changed'] = date('Y-m-d H:i:s'); unset($data['id']); $row->setFromArray($data); $row->save(); if (isset($data['data'])) { if ($itemObject = $this->getItemObject($row->type)) { $itemObject->setLanguage($this->language); $itemObject->setDraftPrefix($draftPrefix); $itemObject->id = $row->number; $itemObject->update($data['data']); } } $this->touch($draft); return true; } public function updateItemConfig($id, array $data, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $data = Qs_Array::collapse($data); $sql = 'DELETE ' . 'FROM ' . $this->db->quoteIdentifier($this->_getTableName("{$draftPrefix}PageItemConfig", true)) . ' ' . 'WHERE idItem = ' . $this->db->quote($id, Qs_Db::INT_TYPE); $this->db->query($sql); foreach ($data as $name => $value) { $updateData = array( 'idItem' => $id, 'name' => $name, 'value' => $value ); $this->{"table{$draftPrefix}PageItemConfig"}->insert($updateData); } } public function updateDraftMeta($data = array()) { return $this->updateMeta($data, true); } protected function _metaOptionsFromForm($data = array(), $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $metaOptions = array(); if (false === ($oldValues = $this->getMetaOptions($this->getPrimaryKey(), $draft, true))) { $oldValues = array(); } $defOptions = $this->_getDefaultMetaOptions(); $avaliableOptions = array_keys($defOptions); $defValues = array_merge($defOptions, $oldValues); foreach ($avaliableOptions as $name) { if (!array_key_exists($name, $data)) { continue; } $allowName = $name . '4Dommy'; $method = array_key_exists($name, $oldValues) ? 'update' : 'insert'; $option = array(); $option['idPage'] = $this->getPrimaryKey(); $option['name'] = $name; $option['show'] = array_key_exists($allowName, $data) ? $data[$allowName] : $defValues[$name]['show']; $option['value'] = array_key_exists($name, $data) ? $data[$name] : $defValues[$name]['value']; $metaOptions['methods'][] = $method; $metaOptions['options'][] = $option; } return $metaOptions; } public function updateMeta($data = array(), $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if ($this->isCustomOptions($draft)) { $metaOptions = $this->_metaOptionsFromForm($data, $draft); } if (isset($data['redirect']) && isset($data['redirectType'])) { if ($data['redirectType'] == 'page' && isset($data['redirectPageId'])) { $data['redirectAlias'] = BASE_URL_LANGUAGE . '/' . Qs_SiteMap::findFirst(array('id' => $data['redirectPageId']), null, null, 'fullAlias'); } $data['redirectAlias'] = str_replace(BASE_URL_LANGUAGE, '{BASE_URL}', $data['redirectAlias']); } unset($data['id'], $data['idPage']); $this->{"table{$draftPrefix}Page"}->updateByKey($data, $this->getPrimaryKey()); $where = 'idPage = ' . $this->db->quote($this->getPrimaryKey(), Zend_Db::INT_TYPE) . ' ' . 'AND language = ' . $this->db->quote($this->getLanguage()); if ($row = $this->{"table{$draftPrefix}PageContent"}->fetchRow($where)) { $row->setFromArray($data); $row->save(); } else { $data['idPage'] = $this->getPrimaryKey(); $data['language'] = $this->getLanguage(); $this->{"table{$draftPrefix}PageContent"}->insert($data); } if (isset($metaOptions)) { $this->_updateMetaOptions($metaOptions, $draft); } $this->touch($draft); return true; } protected function _updateMetaOptions($metaOptions = array(), $draft = false, $idPage = null) { if (!$this->isCustomOptions($draft) || empty($metaOptions) || !isset($metaOptions['methods']) || !isset($metaOptions['options'])) { return false; } $idParent = ($idPage) ? intval($idPage) : $this->getPrimaryKey(); $draftPrefix = ($draft) ? 'Draft' : ''; $optionsTable = $this->_getTable($draftPrefix.'PageOption', true); foreach ($metaOptions['methods'] as $key => $method) { if ($method == 'insert') { if (!isset($metaOptions['options'][$key]['idPage'])) { $metaOptions['options'][$key]['idPage'] = $idParent; } $optionsTable->insert($metaOptions['options'][$key]); } else { $where = $this->db->quoteInto('(idPage=?) ', $idParent) . $this->db->quoteInto('AND (name=?)', $metaOptions['options'][$key]['name']); $optionsTable->update( $metaOptions['options'][$key], $where ); } } return true; } protected function _where4Sorter(Zend_Db_Select $select = null) { if (null === $select) { $select = $this->select; } $select->where("{$this->_tableAlias}.idParent = ?", $this->idParent); return $select; } public function deleteDraftItem($id_item) { return $this->deleteItem($id_item, true); } public function deleteItem($id_item, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (false === ($itemRow = $this->{"get{$draftPrefix}ItemRow"}($id_item))) { return false; }; if ($itemObject = $this->getItemObject($itemRow->type)){ $itemObject->setPrimaryKey($itemRow->number); $itemObject->setDraftPrefix($draftPrefix); $itemObject->delete(); } $this->{"table{$draftPrefix}PageItem"}->delete('id = ' . $this->db->quote($id_item, Zend_Db::INT_TYPE)); $this->{"table{$draftPrefix}PageItemConfig"}->delete('idItem = ' . $this->db->quote($id_item, Zend_Db::INT_TYPE)); $this->touch($draft); } public function getItemGroupNames() { if (null === $this->_itemGroupNames) { $frontendOptions = array( 'lifetime' => null, 'automatic_serialization' => true ); $backendOptions = array( 'cache_dir' => BASE_PATH . '/tmp/cache/', 'cache_file_perm' => 0664 ); $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); if(!$this->_itemGroupNames = $cache->load('PageItemGroupNames')) { $select = $this->_db->select(); $select->from($this->_getTableName('DPageItemGroup'), array('name', 'title')); $select->order('sorter'); $this->_itemGroupNames = $this->_db->fetchPairs($select); $cache->save($this->_itemGroupNames, 'PageItemGroupNames'); } } return $this->_itemGroupNames; } public function getGroupIdByName($name) { $select = $this->_db->select(); $select->from($this->_getTableName('DPageItemGroup'), array('id')); $select->where('name = ?', $name); return $this->_db->fetchOne($select); } public function reorderDraftItemsGroup($order) { if (!is_array($order) || empty($order)) { return false; } foreach ($order as $id => $sorter) { $this->tableDraftPageItem->update(array('sorter' => $sorter), 'id = ' . $this->db->quote($id, Zend_Db::INT_TYPE)); } $this->touchDraft(); } protected function _getDraftDataEx() { return $this->_getDataEx(true); } protected function _getDataEx($draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (null === $this->_dataEx) { $id = intval($this->getPrimaryKey()); if (!($rowMeta = $this->_getMetaRow($id, $draft))) { return false; }; $this->_dataEx = Qs_Array::exclude($rowMeta->toArray(), 'added', 'changed'); $this->_dataEx['content'] = array(); $stmt = $this->{"table{$draftPrefix}PageContent"}->select() ->where('idPage = ?', $id) ->query(); while ($row = $stmt->fetch()) { $this->_dataEx['content'][$row['language']] = Qs_Array::exclude($row, 'idPage', 'language', 'added', 'changed'); } $this->_dataEx['items'] = array(); $items = $this->_getPageItemsEx($id, $draft); foreach ($items as $row) { $item = Qs_Array::exclude($row, 'id', 'idPage', 'number', 'added', 'changed'); if ($itemObject = $this->getItemObject($row['type'])){ $itemObject->setDraftPrefix($draftPrefix); $itemObject->setPrimaryKey($row['number']); if ($data = $itemObject->getDataEx()) { $item['data'] = $data; } } $item['config'] = Qs_Array::expand($this->_getItemConfig($row['id'], $draft)); $this->_dataEx['items'][] = $item; } } return $this->_dataEx; } protected function _getPageItemsEx($pageId, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $select = $this->_db->select(); $select->from($this->_getPair("{$draftPrefix}PageItem")); $select->where('idPage = ?', $pageId, Qs_Db::INT_TYPE); return $this->_db->fetchAll($select); } protected function _getItemConfig($idItem, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $select = $this->db->select(); $select->from($this->{"pair{$draftPrefix}PageItemConfig"}, array('name', 'value')); $select->where("{$draftPrefix}PageItemConfig.idItem = " . $this->db->quote($idItem, Qs_Db::INT_TYPE)); $select->order($draftPrefix . 'PageItemConfig.id'); $data = $this->db->fetchPairs($select); $data = Qs_Array::expand($data); return $data; } protected function _isValidDataEx($data) { if (!is_array($data) || empty($data)) { return false; } $requiredFields = array('id', 'alias', 'content'); foreach ($requiredFields as $name) { if (!array_key_exists($name, $data)) { return false; } } if (!is_array($data['content']) || empty($data['content'])) { return false; } if (isset($data['items'])) { if (!is_array($data['items'])) { return false; } } return true; } protected function _saveDraftDataEx($data) { return $this->_saveDataEx($data, true); } protected function _saveDataEx($data, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; if (!$this->_isValidDataEx($data)) { throw new App_Cms_Exception('Invalid data array'); } $idPage = intval($data['id']); if (!$idPage) { unset($data['id']); } $this->_db->beginTransaction(); $idPage = $this->{"table{$draftPrefix}Page"}->save($data, $idPage); foreach ($data['content'] as $language => $content) { $content['idPage'] = $idPage; $content['language'] = $language; $this->{"table{$draftPrefix}PageContent"}->save($content, array($idPage, $language)); } if (!isset($data['items'])) { return $idPage; } foreach ($data['items'] as $item) { if ($itemObject = $this->getItemObject($item['type'])){ $itemObject->setDraftPrefix($draftPrefix); $item['number'] = $itemObject->insertDataEx($item['data']); } $item['idPage'] = $idPage; $idItem = $this->{"table{$draftPrefix}PageItem"}->insert($item); if (isset($item['config']) && !empty($item['config'])) { $this->updateItemConfig($idItem, $item['config'], $draft); } } $this->_db->commit(); return true; } public function publish() { if (false === ($data = $this->_getDataEx(true))) { return false; } if ($this->isCustomOptions(true)) { if (false === ($metaOptions = $this->_getMetaOptions4Publish())) { return false; } $this->_updateMetaOptions($metaOptions, false); } $this->_publishRedirection($data['id']); $this->deleteItems($data['id']); $this->_saveDataEx($data, false); $this->clearCache(); $this->_updateRoot(); $this->_updateHasBlocks(); $this->_handleFiles(); $event = new App_Cms_Event(array('pageId' => (int) $data['id'], 'pageData' => $data)); Qs_Event_Dispatcher::getInstance()->dispatch('postPublish', $event, $this); return true; } protected function _getMetaOptions4Publish() { $idPage = intval($this->getPrimaryKey()); $options = $this->getDraftMetaOptions($idPage, true); $oldOptions = $this->getMetaOptions($idPage, false, true); $metaOptions = array(); foreach ($options as $name => $option) { $method = array_key_exists($name, (array)$oldOptions) ? 'update' : 'insert'; unset($option['title']); $option['idPage'] = $idPage; $option['name'] = $name; $metaOptions['methods'][] = $method; $metaOptions['options'][] = $option; } return $metaOptions; } public function updateOrder(array $order) { parent::updateOrder($order); $this->_updateRoot(); } protected function deleteDraftItems($idPage) { return $this->deleteItems($idPage, true); } protected function deleteItems($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $list = $this->getItemsId($idPage, $draft); foreach ($list as $id_item) { $this->deleteItem($id_item, $draft); } } public function getItemsId($idPage, $draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $select = $this->db->select(); $select->from($this->{"pair{$draftPrefix}PageItem"}, 'id'); $select->where("idPage=?", $idPage, Zend_Db::INT_TYPE); $list = $this->db->fetchCol($select); return $list; } public function deleteDraft() { return $this->delete(true); } public function delete($draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $idPage = intval($this->getPrimaryKey()); if (false == $draft) { $this->_deleteRedirection($idPage); $this->_deleteFiles(); } $this->deleteItems($idPage, $draft); $this->{"table{$draftPrefix}Page"}->delete('id = ' . $idPage); $this->{"table{$draftPrefix}PageContent"}->delete('idPage = ' . $idPage); $this->_deleteMetaOptions($idPage, $draft); $eventName = ($draft) ? 'draftPostDelete' : 'postDelete'; $event = new App_Cms_Event(array('pageId' => $idPage)); Qs_Event_Dispatcher::getInstance()->dispatch($eventName, $event, $this); $this->clearCache(); return $this; } protected function _deleteDraftMetaOptions($idPage = false) { return $this->_deleteMetaOptions($idPage, true); } protected function _deleteMetaOptions($idPage = false, $draft = false) { if (!$this->isCustomOptions($draft)) { return true; } $idPage = ($idPage) ? $idPage : intval($this->getPrimaryKey()); $draftPrefix = ($draft) ? 'Draft' : ''; return $this->_getTable($draftPrefix.'PageOption', true)->delete('idPage='.$idPage); } public function getItemTypeTitle($name) { $types = $this->getDItemType4Select(); if (isset($types[$name])) { return $types[$name]; } return null; } public function getLanguageNames() { return array_keys(Qs_Db_Language::getList()); } public function getLanguages() { if (null === $this->_languages) { $this->_languages = Qs_Db_Language::getList(); } return $this->_languages; } protected function _getFullAliasById($id) { if (empty($this->_id2Page)) { $this->getSiteMap(); } if (isset($this->_id2Page[$id])) { return $this->_id2Page[$id]['fullAlias']; } return false; } public function getPageById($id) { return $this->_getPageById($id); } protected function _getPageById($id) { if (empty($this->_id2Page)) { $this->getSiteMap(); } if (isset($this->_id2Page[$id])) { return $this->_id2Page[$id]; } return false; } public function getNotTranslatedPages() { $select = $this->select->reset(); foreach (array('from', 'where', 'group', 'having') as $name) { $method = '_' . ucfirst($name); $this->$method($select); } $select->order(array($this->_tableAlias . '.idParent', $this->_tableAlias . '.sorter')); $select->join(array('cDef' => $this->_getTableName('PageContent')), "cDef.idPage = {$this->_tableAlias}.id " . "AND cDef.language = " . $this->db->quote(Qs_Db_Language::getDefault()), array('cDef.title')); $languages = Qs_Db_Language::getList(); unset($languages[Qs_Db_Language::getDefault()]); $languages = array_keys($languages); foreach ($languages as $language) { $select->joinLeft( array('c' . $language => $this->_getTableName('PageContent')), "c{$language}.idPage = {$this->_tableAlias}.id " . "AND c{$language}.language = " . $this->db->quote($language), array("IF (c{$language}.idPage IS NULL, 'n', 'y') as isContent" . ucfirst($language))); } $where = array(); foreach ($languages as $language) { $where [] = "(c{$language}.idPage IS NULL)"; } $select->where(implode(' OR ', $where)); $select->order(array($this->_tableAlias . '.idParent', $this->_tableAlias . '.sorter')); $_pages = $this->db->fetchAll($select); $siteMap = $this->getSiteMap(); foreach ($_pages as $page) { $this->_id2Page[$page['id']] = array_merge($this->_id2Page[$page['id']], $page, array('notTranslated' => 'y')); } $this->_prepareSiteMap4NotTranslatedPages($siteMap); return $siteMap; } protected function _prepareSiteMap4NotTranslatedPages(&$siteMap) { foreach ($siteMap as $alias => &$page) { if (isset($page['sub'])) { $this->_prepareSiteMap4NotTranslatedPages($page['sub']); } else { if (!(isset($page['notTranslated']) && 'y' == $page['notTranslated'])) { unset($siteMap[$alias]); } } } } public function clearCache() { $frontendOptions = array( 'lifetime' => null, 'automatic_serialization' => true ); $backendOptions = array( 'cache_dir' => BASE_PATH . '/tmp/cache/', 'cache_file_perm' => 0664 ); $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); foreach($this->_cacheId as $id) { $cache->remove($id); } } public function updateIndex($data) { $table = $this->_getTable("{$this->_tableAlias}Index"); $select = $this->_db->select(); $select->from($this->_getTableName("{$this->_tableAlias}Index"), array('id')); $select->where('url = ?', $data['url']); if (!($id = $this->db->fetchOne($select))) { $result = $table->insert($data); } else { $result = $table->updateByKey($data, $id); } return $result; } protected function _updateRoot() { $sql = 'UPDATE ' . $this->_db->quoteIdentifier($this->_tableName) . ' SET isRoot = \'n\''; $this->db->query($sql); $select = $this->db->select(); $select->from($this->pair, 'id'); $select->where('Page.idParent = 0'); if ($this->isCustomOptions()) { $select->join($this->pairDPageOption, 'DPageOption.name = \'isAdditional\'', array()) ->joinLeft($this->pairPageOption, 'Page.id = PageOption.idPage AND PageOption.name = DPageOption.name', array()) ->where('ISNULL(PageOption.value, DPageOption.value) = \'n\''); } $select->order('Page.sorter'); $select->limit(1); $rootId = $this->db->fetchOne($select); $sql = 'UPDATE ' . $this->_db->quoteIdentifier($this->_tableName) . ' ' . 'SET isRoot = \'y\' ' . 'WHERE id = ' . $this->db->quote($rootId, Qs_Db::INT_TYPE); $this->db->query($sql); } protected function _updateHasBlocks() { $select = $this->db->select(); $select->from($this->_tableName . 'Item', new Zend_Db_Expr('1')) ->where('idPage = ' . (int) $this->getPrimaryKey()); $hasBlocks = (bool) $this->db->fetchOne($select); $sql = 'UPDATE ' . $this->_db->quoteIdentifier($this->_tableName) . "SET hasBlocks = '" . (($hasBlocks) ? 'y' : 'n') . "' " . "WHERE id = " . (int) $this->getPrimaryKey(); $this->db->query($sql); } public function deleteIndex($idPage) { vdie('deleteIndex', $idPage); } public function reindexPage($idPage) { vdie('reindexPage', $idPage); } public function touchDraft() { return $this->touch(true); } public function touch($draft = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $this->{"table{$draftPrefix}Page"}->updateByKey(array('changed' => date('Y-m-d H:i:s')), $this->_primaryKey); return $this; } public function isCustomOptions($draft = false) { return true; } public function getDraftMetaOptions($idPage, $ignoreDefault = false) { return $this->getMetaOptions($idPage, true, $ignoreDefault); } public function getMetaOptions($idPage, $draft = false, $ignoreDefault = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $ignorePrefix = ($ignoreDefault) ? 'Clean' : ''; if (!isset($this->{"_data{$draftPrefix}{$ignorePrefix}MetaOptions"}[$idPage])) { $options = $this->_getPageOptions($idPage, null, $draft, $ignoreDefault); $this->{"_data{$draftPrefix}{$ignorePrefix}MetaOptions"}[$idPage] = $options; } else { $options = $this->{"_data{$draftPrefix}{$ignorePrefix}MetaOptions"}[$idPage]; } return $options; } protected function _getPageOptions($idPage, $meta = null, $draft = false, $ignoreDefault = false) { $draftPrefix = ($draft) ? 'Draft' : ''; $pageOptions = ($ignoreDefault) ? array() : $this->_getDefaultMetaOptions(); if (!$ignoreDefault) { if (null === $meta) { $meta = $this->_getMetaRow($idPage, $draft); $meta = ($meta) ? $meta->toArray() : array(); } foreach ($meta as $name => $value) { if (array_key_exists($name, $pageOptions)) { $pageOptions[$name]['value'] = $value; } } } if ($this->isCustomOptions($draft)) { $select = $this->db->select(); $select->from(array('po' => $this->_getTableName($draftPrefix.'PageOption', true))); $select->joinLeft( array('do' => $this->_getTableName('DPageOption'), true), "do.name = po.name", array('title') ); $select->where("po.idPage=?", intval($idPage)); $select->order('sorter'); $data = $this->db->fetchAll($select); foreach ($data as $option) { $pageOptions[$option['name']] = array( 'name' => $option['name'], 'show' => $option['show'], 'value' => $option['value'], 'title' => $option['title'], ); } } return ($ignoreDefault && empty($pageOptions)) ? false : $pageOptions; } protected function _getDefaultMetaOptions() { static $pageOptions = null; if (null === $pageOptions) { $pageOptions = array( 'showInSiteMap' => array('show' => 'y', 'value' => 'n', 'title' => 'Show in sitemap'), 'showInMenu' => array('show' => 'y', 'value' => 'n', 'title' => 'Show in menu'), 'showInFooter' => array('show' => 'y', 'value' => 'n', 'title' => 'Show in footer'), 'enabled' => array('show' => 'y', 'value' => 'y', 'title' => 'Show on user end'), 'allowDelete' => array('show' => 'n', 'value' => 'n', 'title' => 'Allow delete'), 'isSecure' => array('show' => 'n', 'value' => 'n', 'title' => 'Secure page'), 'isIndexing' => array('show' => 'n', 'value' => 'n', 'title' => 'Include this page in search results'), 'final' => array('show' => 'n', 'value' => 'n', 'title' => 'Final page'), 'system' => array('show' => 'n', 'value' => 'n', 'title' => 'System (hidden in admin end)'), ); if ($this->isCustomOptions()) { $availableOptions = $this->_get4Select( 'DPageOption', array('name','title','show','value'), true ); $pageOptions = array_merge($pageOptions, $availableOptions); } if (Qs_Version::compareVersion('2.3.0') > 0) { unset($pageOptions['showInFooter']); unset($pageOptions['enabled']); } } return $pageOptions; } public function getDefaultMetaPairs() { static $result = null; if (null === $result) { if ($this->isCustomOptions()) { $result = $this->_get4Select('DPageOption', array('name', 'value'), true, null, 'sorter'); } else { $result = array(); } } return (array) $result; } protected function extractMeta($options) { if (!is_array($options)) { return false; } $meta = array(); foreach ($options as $name => $option) { $meta[$name] = (is_array($option)) ? $option['value'] : $option; } return $meta; } public function isRedirectFields() { $redirectFields = array('redirect', 'redirectType', 'redirectPageId', 'redirectStatus', 'redirectAlias'); $metaData = $this->_getTable($this->_tableAlias)->getMetaData(); $diff = array_diff($redirectFields, array_keys($metaData)); if (empty($diff)) { return true; } return false; } public function getReorderOptions($keyColumn, $titleColumn, $isAdditional = null) { $select = $this->getListSelect(); if (0 === $this->idParent && null !== $isAdditional) { $select->joinLeft( array('po' => $this->_getTableName('PageOption')), "(po.idPage = " . $this->tableAlias . ".id) AND (po.name = 'isAdditional')", array('po.value') ); if (true === $isAdditional) { $select->where("po.value = 'y'"); } else { $select->where("po.value IS NULL OR po.value = 'n'"); } } $select = $this->_where4Sorter($select); $select->order($this->_tableAlias . '.sorter'); $list = $this->_db->fetchAll($select); $options = array(); foreach ($list as $row) { $options[$row[$keyColumn]] = $row[$titleColumn]; } return $options; } public function setRedirection($value) { $this->_hasRedirection = (bool) $value; return $this; } public function getRedirection() { return (false !== $this->_hasRedirection && Qs_Version::compareVersion('2.1.0') <= 0); } protected function _getRedirectionObj() { return new App_Redirection_Obj(); } protected function _deleteRedirection($idPage) { if ($this->getRedirection()) { $this->_getRedirectionObj()->removePageRedirection($idPage); return true; } return false; } protected function _publishRedirection($idPage) { if ($this->getRedirection()) { $this->_getRedirectionObj()->updatePageRedirection($idPage); return true; } return false; } public function setSuMode($suMode = true) { $this->_suMode = (bool) $suMode; return $this; } public function getSuMode() { return $this->_suMode; } public static function getImageHeaderExcludePageIds() { $pages = array(); $selectors = Zend_Registry::get('config')->app->cms->headerImageExcludePages->toArray(); if (is_array($selectors) && !empty($selectors)) { foreach ($selectors as $selector) { if (!empty($selector)) { if (is_array($selector)) { $selector = array_slice($selector, 0, 3); $selector = array_pad($selector, 3, null); $selector[] = 'id'; $id = call_user_func_array('Qs_SiteMap::find', $selector); } else { $id = Qs_SiteMap::find($selector, 'id'); } if (!empty($id)) { $pages[] = $id; } } } } return $pages; } }