Index: .updates/custom-404-page.sql =================================================================== --- .updates/custom-404-page.sql (revision 0) +++ .updates/custom-404-page.sql (revision 134) @@ -0,0 +1,35 @@ +SET AUTOCOMMIT=0; +START TRANSACTION; + + +-- Page: "page-not-found" (id = 563, idParent = 0) ------------------------------------------------ + +INSERT INTO `qs_Page` (`alias`, `handler`, `bodyTemplate`, `showInSiteMap`, `showInMenu`, `showInFooter`, `enabled`, `allowDelete`, `isSecure`, `isIndexing`, `showInDropdowns`, `isRoot`, `hasBlocks`, `final`, `system`, `redirect`, `redirectType`, `redirectPageId`, `redirectStatus`, `redirectAlias`, `customOptions`,`headerImage`, `added`, `changed`, `sorter`) VALUES +('page-not-found', 'site', 'default.tpl', 'n', 'n', 'n', 'y', 'n', 'n', 'n', 'n', 'n', 'y', 'n', 'n', 'n', '', '0', '301', '', '{"is404Page":1}', '', '2014-09-08 06:31:50', '2014-09-08 06:34:05', 98482738); +SET @pageId563 := LAST_INSERT_ID(); +INSERT INTO `qs_PageContent` (`title`, `menuTitle`, `header`, `language`, `idPage`) VALUES ('', 'Page Not Found', '', 'eng', @pageId563); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showInSiteMap', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showInMenu', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showInFooter', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'enabled', 'n', 'y'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'allowDelete', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'isSecure', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'isIndexing', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'final', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'system', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'redirect', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'allowSubpages', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'isAdditional', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showInCtrlMenu', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'requireSu', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'isAccountNavigation', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showInDropdowns', 'n', 'n'); +INSERT INTO `qs_PageOption` (`idPage`, `name`, `show`, `value`) VALUES (@pageId563, 'showSideBlock', 'n', 'n'); +INSERT INTO `qs_HtmlBlock` (`added`) VALUES ('2014-09-08 06:34:05'); +SET @htmlBlockId2441 := LAST_INSERT_ID(); +INSERT INTO `qs_HtmlBlockContent` (`idBlock`, `language`, `content`, `rawContent`, `added`, `changed`) VALUES (@htmlBlockId2441, 'eng', '

The page you were looking for was not found. This may be the result of an outdated link or a page that has been moved. Try searching for the topic you were looking for by using the Site Search box at the top of the page. You can also refer to the site map to try to find the topic you are looking for.

\n', 'The page you were looking for was not found. This may be the result of an outdated link or a page that has been moved. Try searching for the topic you were looking for by using the Site Search box at the top of the page. You can also refer to the site map to try to find the topic you are looking for.', '2014-09-08 06:34:05', '2014-09-08 06:34:05'); +INSERT INTO `qs_PageItem` (`idGroup`, `type`, `number`, `allowDelete`, `sorter`, `added`, `changed`, `idPage`) VALUES ('1', 'HtmlBlock_', @htmlBlockId2441, 'y', '0', '2014-09-08 06:34:05', '2014-09-08 06:34:05', @pageId563); +SET @pageItemId3628 := LAST_INSERT_ID(); +INSERT INTO `qs_PageItemConfig` (`idItem`, `name`, `value`) VALUES (@pageItemId3628, 'placeholders', ''); + +COMMIT; Index: site/Qs/ViewController.php =================================================================== --- site/Qs/ViewController.php (revision 133) +++ site/Qs/ViewController.php (revision 134) @@ -1212,11 +1212,23 @@ return true; } + protected function _loadConfigMessage($key) + { + $this->_messageTemplates[$key] = $this->getConfigArray('messages')[$key]; + return $this; + } + + protected function trigger404() + { + $this->_doc->display404(); + return $this; + } + protected function _addViewItem() { $item = $this->getData(); if (!$this->_isItemAccessible($item)) { - $this->_doc->display404(); + return $this->trigger404(); } $this->_prepareViewItem($item); $this->_addItem($item); Index: site/App/NotFound/View.php =================================================================== --- site/App/NotFound/View.php (revision 133) +++ site/App/NotFound/View.php (revision 134) @@ -130,11 +130,37 @@ $this->_logNotFound(); header('HTTP/1.0 404 Not Found'); if (!Qs_Request::isXmlHttpRequest()) { - $this->_options['alias'] = CURRENT_PAGE; - $this->_doc->assign('item', new Qs_Doc_Item($this->_options)); + $pageAlias = Qs_SiteMap::findFirst(['xIs404Page' => '1'], null, null, 'fullAlias'); + if ($pageAlias) { + $html = $this->_renderCustom404($pageAlias); + } else { + $html = $this->_renderDefault404(); + } + if (Qs_Constant::get('COMPRESS_HTML')) { + $html = Qs_Packer_Html::compressHtml($html, false); + } $this->_doc->sendHeaders(); - echo $this->_doc->fetch($this->getTemplate('view.tpl')); + echo $html; } exit; } + + protected function _renderCustom404($pageAlias) + { + $page = Qs_SiteMap::getPage($pageAlias); + $items = (array) $page['items']; + unset($page['items']); + $handlerClass = 'App_Doc_' . ucfirst($page['handler']); + $this->_doc = new $handlerClass($page); + $this->_doc->renderPageItems($items); + return $this->_doc->__toString(); + } + + protected function _renderDefault404() + { + $this->_options['alias'] = CURRENT_PAGE; + $this->_doc->assign('item', new Qs_Doc_Item($this->_options)); + $this->_doc->sendHeaders(); + return $this->_doc->fetch($this->getTemplate('view.tpl')); + } } Index: site/App/ECommerce/Product/config.php =================================================================== --- site/App/ECommerce/Product/config.php (revision 133) +++ site/App/ECommerce/Product/config.php (revision 134) @@ -1,5 +1,7 @@ true, 'resourceName' => 'ECommerce_Product', @@ -8,5 +10,11 @@ 'itemsName' => 'Products', 'image' => array('width' => 710, 'height' => 533, 'resizeMethodAlias' => '', 'resizeMethod' => 'inner'), - 'imageContainer' => 'product-images' + 'imageContainer' => 'product-images', + + 'messages' => [ + ProductView::MSG_NOT_FOUND_REDIRECT => 'The Product you are searching for is currently not available.
' + . 'Please check back later as our inventory is constantly changing and this item may be available soon. ' + . 'Meanwhile please feel free to review other products we have to offer.' + ] ); \ No newline at end of file Index: site/App/ECommerce/Product/Category/config.php =================================================================== --- site/App/ECommerce/Product/Category/config.php (revision 133) +++ site/App/ECommerce/Product/Category/config.php (revision 134) @@ -1,5 +1,7 @@ true, 'resourceName' => 'ECommerce_Product_Category', @@ -10,5 +12,11 @@ 'subItemName' => 'Subcategory', 'subItemsName' => 'Subcategories', - 'image' => array('width' => 264, 'height' => 148, 'resizeMethodAlias' => '', 'resizeMethod' => 'inner') -); \ No newline at end of file + 'image' => array('width' => 264, 'height' => 148, 'resizeMethodAlias' => '', 'resizeMethod' => 'inner'), + + 'messages' => [ + CategoryView::MSG_NOT_FOUND_REDIRECT => 'The Category you are searching for is currently not available.
' + . 'Please check back later as our inventory is constantly changing and this item may be available soon. ' + . 'Meanwhile please feel free to review other products we have to offer.' + ] +); Index: site/App/ECommerce/Product/Category/View.php =================================================================== --- site/App/ECommerce/Product/Category/View.php (revision 133) +++ site/App/ECommerce/Product/Category/View.php (revision 134) @@ -7,10 +7,19 @@ */ class App_ECommerce_Product_Category_View extends App_ECommerce_Product_Category_Abstract_View { + const MSG_NOT_FOUND_REDIRECT = 'msgNotFoundRedirect'; + protected $_actions = array('list', 'tree'); protected $_hasLog = true; protected $_logIgnoredControllers = array('App_Cms_View', 'App_ECommerce_Product_View' => 'list'); + protected function _init() + { + parent::_init(); + $this->_loadConfigMessage(self::MSG_NOT_FOUND_REDIRECT); + return $this; + } + public function exec() { $alias = $this->getRestAlias(); @@ -20,7 +29,9 @@ } else { $this->_getDataObj()->setCategoryIdByAlias($alias); if (!$this->_getDataObj()->getCategoryId()) { - $this->_do404(); + $this->_setBackUrl(Qs_Request::getFinalBaseUrl()); + $this->_setBackMessage(self::MSG_NOT_FOUND_REDIRECT); + $this->_doBack(); } } } Index: site/App/ECommerce/Product/Category/Form/Config.php =================================================================== --- site/App/ECommerce/Product/Category/Form/Config.php (revision 133) +++ site/App/ECommerce/Product/Category/Form/Config.php (revision 134) @@ -7,7 +7,7 @@ $this->addElement( 'select', 'type', - array('label' => 'Type', 'multiOptions' => array('' => 'Defautl', 'detail' => 'Tree Navigation Only')) + array('label' => 'Type', 'multiOptions' => array('' => 'Default', 'detail' => 'Tree Navigation Only')) ); return $this; } Index: site/App/ECommerce/Product/View.php =================================================================== --- site/App/ECommerce/Product/View.php (revision 133) +++ site/App/ECommerce/Product/View.php (revision 134) @@ -1,12 +1,13 @@ _loadConfigMessage(self::MSG_NOT_FOUND_REDIRECT); + return $this; + } + protected function _initAction() { switch ($this->getConfig('forceAction')) { case 'view': if (count($this->_restParams) != 1) { - $this->_doc->display404(); + $this->trigger404(); } $this->_getDataObj()->setPrimaryKeyByAlias($this->_restParams[0]); $this->_action = 'view'; @@ -55,6 +63,15 @@ return $this; } + protected function trigger404() + { + $url = Qs_SiteMap::findFirst(null, ['type' => 'ECommerce_Product_Category_'], ['type' => ''], 'url'); + $this->_setBackUrl($url); + $this->_setBackMessage(self::MSG_NOT_FOUND_REDIRECT); + $this->_doBack(); + return $this; + } + protected function _hasSubCategories() { $categoryId = $this->_getDataObj()->getCategoryId();