<?php
/**
 * An implementation of the general search object
 *
 * @package koubel homepage
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */

/**
 * Generic abstract search class
 *
 * Support for a simple and complex search, pagination.
 * This class will be inherited by blog entry search, etc.
 *
 * This class can be used from CLI, be aware, that sessions cannot be used for the
 * CLI SAPI.
 *
 * @package koubel homepage
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */
abstract class HomeWebApp_Model_Search
{
    /** a name for search session namespace */
    const SESSION_NAME = "homeWebSearch";

    /**
     * Parameters for a searching.
     * @var array
     */
    protected $_searchParams;

    /**
     * current page number
     */
    protected $_pageNumber;

    /**
     * items per page
     */
    protected $_perPageItems;

    /**
     * Paginator object
     * @var Zend_Paginator;
     */
    protected $_paginator;

    /**
     * session accessor for a searching
     * @var Zend_Session_Namespace
     */
    protected static $_searchSession;

    /**
     * Number of found items.
     * @var int
     */
    protected $_foundCount;

    /**
     * Sets session name and load seach parameters from the session,
     * if necessary.
     *
     */
    protected function __construct()
    {
        //get params from session
        //session must be started, it is OK, because session is started in the
        //factorySearch method
        $this->_searchParams =  isset(self::$_searchSession->searchParams) ? self::$_searchSession->searchParams : array();
    }

    /**
     * Set search parameters. The setter for $_searchParams.
     * @param array $arr array with search parameters
     */
    public function setParams(array $arr)
    {
        $this->_searchParams = $arr;
    }

    /**
     * Set pagination members.
     * @param int $pageNum current page number
     * @param int $itemsInPage items per page
     */
    public function setPageParams($pageNum,$itemsInPage)
    {
        $this->_pageNumber=$pageNum;
        $this->_perPageItems=$itemsInPage;
    }

    /**
     * Search items.
     * @return array|Zend_Paginator to array with found items if pagination
     * isn't used, Zend_Pagination otherwise
     */
    abstract public function searchItems();

    /**
     * Get number of found items. Getter for the $_foundCount.
     * @return int
     * @throws RuntimeException if $_foundCount isn't initialized
     */
    public function itemsCount()
    {
        if (!isset($this->_foundCount))
            throw new RuntimeException("number of found items isn't set, you must call searchItems()
                method first");

        return $this->_foundCount;
    }

    /**
     * Gets current paginator
     * @return Zend_Paginator
     */
    public function getPaginator()
    {
        return $this->_paginator;
    }
    
    /*
     * Saves information about current searching into the session.
     */
    public function saveToSession()
    {
        self::_logMessage(get_class($this)." ".__METHOD__);
        self::$_searchSession->searchParams=$this->_searchParams;
        self::$_searchSession->searchClassName=get_class($this);
    }

    /*
     * Clear information about current searching from the sessions.
     */
    public static function delFromSession()
    {
        self::_logMessage(get_class()." ".__METHOD__);

        /* we must create session namespace, because this static
           method can be called itself - without factory, which creates
           self::$_searchSession
        */
        if (php_sapi_name() != 'cli') {
            $sessionAccess = new Zend_Session_Namespace(self::SESSION_NAME);
            Zend_Session::namespaceUnset(self::SESSION_NAME);
        }
    }

    /**
     * use pagination or not?
     * @return bool
     */
    protected function _usePagination()
    {
        return isset($this->_pageNumber) && isset($this->_perPageItems);
    }

    /*
     * Send a message to log.
     * @param string $msg message
     */
    protected static function _logMessage($msg)
    {
        /* @var $appLog Zend_Log */
        $appLog = Zend_Controller_Front::getInstance()->getParam("bootstrap")
            ->getResource("log");
        $appLog->log($msg,Zend_log::DEBUG);
    }
}
