Skip to main content
2 of 2
deleted 2 characters in body
Marius
  • 198.5k
  • 55
  • 424
  • 833

As explained in the comments, I don't think there is a way to do this by using the cms pages because you have no layer model associated to the new products list. You only have layer models for the category context and the search context.
My solution (tested and works) involves writing a module that will list all the products marked as new in a page and having a layer model that handles the new products collection.
Here goes. be prepared it's a long one.
I called the extension StackExchange_NewProducts but feel free to change the name.
You will need the following files:

app/etc/modules/StackExchange_NewProducts.xml - the declaration file:

<?xml version="1.0"?>
<config>
    <modules>
        <StackExchange_NewProducts>
            <codePool>local</codePool>
            <active>true</active>
            <depends>
                <Mage_Catalog />
            </depends>
        </StackExchange_NewProducts>
    </modules>
</config>

app/code/local/StackExchange/NewProducts/etc/config.xml - the configuration file

<?xml version="1.0"?>
<config>
    <modules>
        <StackExchange_NewProducts>
            <version>1.0.0</version>
        </StackExchange_NewProducts>
    </modules>
    <global>
        <models>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Model</class>
            </stackexchange_newproducts>
        </models>
        <blocks>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Block</class>
            </stackexchange_newproducts>
        </blocks>
        <helpers>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Helper</class>
            </stackexchange_newproducts>
        </helpers>
        <events>
            <controller_front_init_routers> <!-- create a custom router to handle the 'new-products' url -->
                <observers>
                    <stackexchange_newproducts>
                        <class>StackExchange_NewProducts_Controller_Router</class>
                        <method>initControllerRouters</method>
                    </stackexchange_newproducts>
                </observers>
            </controller_front_init_routers>
        </events>
    </global>
    <frontend>
        <routers> <!-- declare a router -->
            <newproducts>
                <use>standard</use>
                <args>
                    <module>StackExchange_NewProducts</module>
                    <frontName>newproducts</frontName>
                </args>
            </newproducts>
        </routers>
        <layout>
            <updates>
                <stackexchange_newproducts>
                    <file>stackexchange_newproducts.xml</file>
                </stackexchange_newproducts>
            </updates>
        </layout>
    </frontend>
</config>

app/code/local/StackExchange/NewProducts/Controller/Router.php - the custom router that handles the url new-products and maps it to a controller and action

<?php
class StackExchange_NewProducts_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
    const NEW_PRODUCTS_URL_KEY = 'new-products';
    public function initControllerRouters($observer)
    {
        $front = $observer->getEvent()->getFront();
        $front->addRouter('stackexchange_newproducts', $this);
        return $this;
    }

    public function match(Zend_Controller_Request_Http $request)
    {
        if (!Mage::isInstalled()) {
            Mage::app()->getFrontController()->getResponse()
                ->setRedirect(Mage::getUrl('install'))
                ->sendResponse();
            exit;
        }
        $urlKey = trim($request->getPathInfo(), '/');
        if ($urlKey == self::NEW_PRODUCTS_URL_KEY) {
            $request->setModuleName('newproducts')
                ->setControllerName('index')
                ->setActionName('index');
            $request->setAlias(
                Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
                $urlKey
            );
            return true;
        }
        return false;
    }
}

app/code/local/StackExchange/NewProducts/controllers/IndexController.php - the actual controller that displays the new products

<?php
class StackExchange_NewProducts_IndexController extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();
    }
}

app/code/local/StackExchange/NewProducts/Helper/Data.php - the module general helper

<?php
class StackExchange_NewProducts_Helper_Data extends Mage_Core_Helper_Abstract
{

}

app/design/frontend/base/default/layout/stackexchange_newproducts.xml - the module layout file that defines the content of the page

<?xml version="1.0"?>
<layout>
    <newproducts_index_index>
        <reference name="root">
            <action method="setTemplate">
                <template>page/2columns-left.phtml</template>
            </action>
        </reference>
        <reference name="left">
            <block type="stackexchange_newproducts/layer_new" name="catalog.leftnav" before="-" template="catalog/layer/view.phtml" />
        </reference>
        <reference name="content">
            <block type="core/template" name="new_products_container" as="new_products_container" template="stackexchange_newproducts/container.phtml">
                <action method="setTitle" translate="title" module="stackexchange_newproducts">
                    <title>New Products</title>
                </action>
                <block type="stackexchange_newproducts/new" name="new_product" as="new_products" template="catalog/product/list.phtml">
                    <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
                        <block type="page/html_pager" name="product_list_toolbar_pager"/>
                    </block>
                    <action method="addColumnCountLayoutDepend"><layout>empty</layout><count>6</count></action>
                    <action method="addColumnCountLayoutDepend"><layout>one_column</layout><count>5</count></action>
                    <action method="addColumnCountLayoutDepend"><layout>two_columns_left</layout><count>4</count></action>
                    <action method="addColumnCountLayoutDepend"><layout>two_columns_right</layout><count>4</count></action>
                    <action method="addColumnCountLayoutDepend"><layout>three_columns</layout><count>3</count></action>
                    <action method="setToolbarBlockName"><name>product_list_toolbar</name></action>
                </block>
            </block>
        </reference>

    </newproducts_index_index>
</layout>

app/code/local/StackExchange/NewProducts/Block/New.php - the block that should render the new products collection:

<?php
class StackExchange_NewProducts_Block_New extends Mage_Catalog_Block_Product_List
{
    public function __construct()
    {
        parent::__construct();
    }
    public function getModuleName()
    {
        return 'Mage_Catalog';
    }
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $this->_productCollection = $this->getLayer()->getProductCollection();
        }
        return $this->_productCollection;
    }
    public function getLayer()
    {
        $layer = Mage::registry('current_layer');
        if ($layer) {
            return $layer;
        }
        return Mage::getSingleton('stackexchange_newproducts/layer');
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/New.php - the layer block that should be displayed on the left side (filters)

<?php
class StackExchange_NewProducts_Block_Layer_New extends Mage_Catalog_Block_Layer_View
{
    public function getLayer()
    {
        if (!$this->hasData('_layer')){
            $layer = Mage::getSingleton('stackexchange_newproducts/layer');
            $this->setData('_layer', $layer);
        }
        return $this->getData('_layer');
    }
    protected function _initBlocks()
    {
        parent::_initBlocks();
        $this->_attributeFilterBlockName    = 'stackexchange_newproducts/layer_filter_attribute';
        $this->_priceFilterBlockName        = 'stackexchange_newproducts/layer_filter_price';
        $this->_decimalFilterBlockName      = 'stackexchange_newproducts/layer_filter_decimal';
    }
    protected function _prepareLayout()
    {
        $stateBlock = $this->getLayout()->createBlock($this->_stateBlockName)
            ->setLayer($this->getLayer());
        $this->setChild('layer_state', $stateBlock);

        $filterableAttributes = $this->_getFilterableAttributes();
        foreach ($filterableAttributes as $attribute) {
            if ($attribute->getAttributeCode() == 'price') {
                $filterBlockName = $this->_priceFilterBlockName;
            } elseif ($attribute->getBackendType() == 'decimal') {
                $filterBlockName = $this->_decimalFilterBlockName;
            } else {
                $filterBlockName = $this->_attributeFilterBlockName;
            }

            $this->setChild($attribute->getAttributeCode() . '_filter',
                $this->getLayout()->createBlock($filterBlockName)
                    ->setLayer($this->getLayer())
                    ->setAttributeModel($attribute)
                    ->init());
        }

        $this->getLayer()->apply();
        return $this;
    }
}

now each attribute type needs a filter block associated to it:

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Attribute.php - general filter block for attributes

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Attribute extends Mage_Catalog_Block_Layer_Filter_Attribute
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_attribute';
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Decimal.php - filter block for decimal attributes

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Decimal extends Mage_Catalog_Block_Layer_Filter_Decimal
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_decimal';
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Price.php - filter block for price attribute

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Price extends Mage_Catalog_Block_Layer_Filter_Price
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_price';
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer.php - the layer model for handling new products

<?php
class StackExchange_NewProducts_Model_Layer extends Mage_Catalog_Model_Layer
{
    public function getStateKey()
    {
        if ($this->_stateKey === null) {
            $this->_stateKey = 'STORE_'.Mage::app()->getStore()->getId()
                . '_NEW_PRODUCTS_'
                . '_CUSTGROUP_' . Mage::getSingleton('customer/session')->getCustomerGroupId();
        }

        return $this->_stateKey;
    }

    public function getStateTags(array $additionalTags = array())
    {
        $additionalTags = array_merge($additionalTags, array('new_products'));
        return $additionalTags;
    }

    public function getProductCollection()
    {
        if (isset($this->_productCollections['new_products'])) {
            $collection = $this->_productCollections['new_products'];
        } else {
            $collection = $this->_getCollection();
            $this->prepareProductCollection($collection);
            $this->_productCollections['new_products'] = $collection;
        }

        return $collection;
    }
    public function prepareProductCollection($collection)
    {
        $collection
            ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
            ->addMinimalPrice()
            ->addFinalPrice()
            ->addTaxPercents()
            ->addUrlRewrite();

        Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
        Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
        return $this;
    }

    protected function _getCollection()
    {
        $todayStartOfDayDate  = Mage::app()->getLocale()->date()
            ->setTime('00:00:00')
            ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);

        $todayEndOfDayDate  = Mage::app()->getLocale()->date()
            ->setTime('23:59:59')
            ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);

        $collection = Mage::getModel('catalog/product')->getCollection()
            ->addStoreFilter()
            ->addAttributeToFilter('news_from_date', array('or'=> array(
                0 => array('date' => true, 'to' => $todayEndOfDayDate),
                1 => array('is' => new Zend_Db_Expr('null')))
            ), 'left')
            ->addAttributeToFilter('news_to_date', array('or'=> array(
                0 => array('date' => true, 'from' => $todayStartOfDayDate),
                1 => array('is' => new Zend_Db_Expr('null')))
            ), 'left')
            ->addAttributeToFilter(
                array(
                    array('attribute' => 'news_from_date', 'is'=>new Zend_Db_Expr('not null')),
                    array('attribute' => 'news_to_date', 'is'=>new Zend_Db_Expr('not null'))
                )
            )
            ->addAttributeToSort('news_from_date', 'desc');
        return $collection;
    }
}

Like each attribute needed a block for filters it also needs a model for handling filters:

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Attribute.php - the general attribute filter model

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer_Filter_Attribute
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Decimal.php - the decimal attributes filter model

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Decimal extends Mage_Catalog_Model_Layer_Filter_Attribute
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Price.php - the price attribute filter model

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Filter_Price
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Item.php - the filters require a collection of item objects. this is the item object - not sure if this is needed. I think that the default catalog item model can be used.

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Item extends Mage_Catalog_Model_Layer_Filter_Item
{

}

app/design/frontend/base/default/template/stackexchange_newproducts/container.phtml - a template file that acts as a container for the new products so you can set a title and show session messages.

<?php if ($this->getTitle()) : ?>
    <div class="page-title category-title">
        <h1><?php echo $this->getTitle() ?></h1>
    </div>
<?php endif;?>
<?php echo $this->getMessagesBlock()->getGroupedHtml() ?>
<?php echo $this->getChildHtml();?>

That's it. Clear the cache after you create all the files and disable the compilation.
Here is a screenshot of how it looks on my side
screenshot. (using ce 1.7 with sample data)

Marius
  • 198.5k
  • 55
  • 424
  • 833