<?php

/**
 * Component to filter results by fields of the form sent.
 * Compatibility with Paginator Component.
 *
 * Licencied by Creative Commons 3.0
 *
 * @filesource
 * @copyright  Copyright 2012, Pedro Elsner (http://pedroelsner.com/)
 * @author     Pedro Elsner <pedro.elsner@gmail.com>
 * @license    Creative Commons 3.0 (http://creativecommons.org/licenses/by/3.0/)
 * @version    2.0
 */

/**
 * Application component class for return conditions array to cake model.
 * Provides basic functionality and encrypt or decrypt fields of the form sent.
 *
 * @use        Component
 * @package    filter_results
 * @subpackage filter_results.filter_results
 * @link       http://www.github.com/pedroelsner/filter_results/tree/2.0/Controller/Component/FilterResultsComponent.php
 */
class FilterResultsComponent extends Component
{

    /**
     * Control the number of instances
     *
     * @var int
     * @access public
     * @static
     * @since 1.0
     */
    public static $instances = 0;

    /**
     * Receive actual filter field for function self::_makeConditions()
     *
     * @var array
     * @access protected
     * @since 2.0
     */
    protected $_filter = array();

    /**
     * The instance number of component
     *
     * @var int
     * @access private
     * @since 1.0
     */
    private $_instance;

    /**
     * Default settings
     *
     * @var array
     * @access protected
     * @since 1.0
     */
    protected $_options = array(
        'auto' => array(
            'paginate' => false,
            'explode'  => true,
        ),
        'explode' => array(
            'character'   => ' ',
            'concatenate' => 'AND',
        ),
        'label' => array(
            'prefix'     => 'filter',
            'fieldModel' => 'field',
            'operator'   => 'operatior',
        ),
        'form' => array(
            'id' => 'form-filter-results',
        )
    );

    /**
     * Save controller's reference
     *
     * @var object
     * @access protected
     * @since 2.0
     */
    protected $_controller;

    /**
     * Save results of $this->make()
     *
     * @var array
     * @access protected
     * @since 1.0
     */
    protected $_conditions = array();

    /**
     * Save $controller->request->params without encrypt
     *
     * @var array
     * @access protected
     * @since 1.0
     */
    protected $_params = array();

    /**
     * Construct
     *
     * @access public
     * @since 1.0
     */
    public function __construct(ComponentCollection $collection, $settings = array())
    {
        $this->_instance = ++self::$instances;
        $this->_options = array_merge($this->_options, $settings);
    }

    /**
     * Clone
     *
     * @access public
     * @since 1.0
     */
    public function __clone()
    {
        $this->_instance = ++self::$instances;
        $this->_options['label']['prefix'] .= sprintf('_%s', $this->_instance);
    }

    /**
     * Executed before the Controller::beforeFiler()
     *
     * @param object $controller
     * @access public
     * @since 1.0
     */
    public function initialize(Controller $controller)
    {
        $this->controller = $controller;
    }

    /**
     * Executed after the Controller::beforeFiler(), but before execute the requested action
     *
     * @param object $controller
     * @access public
     * @since 1.0
     */
    public function startup(Controller $controller)
    {
    }

    /**
     * Executed before the Controller:beforeRender()
     *
     * @param object $controller
     * @access public
     * @since 1.0
     */
    public function beforeRender(Controller $controller)
    {
    }

    /**
     * Executed before the Controller:render()
     *
     * @param object $controller
     * @access public
     * @since 1.0
     */
    public function shutdown(Controller $controller)
    {
    }

    /**
     * Executed before the Controller:redirect()
     *
     * @param object  $controller
     * @param array   $url
     * @param string  $status
     * @param boolean $exit
     * @access public
     * @since 1.0
     */
    public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true)
    {
    }

    /**
     * Encripty the string sent
     *
     * @param string $string
     * @return string
     * @access protected
     * @since 1.0
     */
    protected function _encrypt($string)
    {
        return (!is_string($string)) ? '' : base64_encode(base64_encode($string));
    }

    /**
     * Decrypty the string sent
     *
     * @param  string $string
     * @return string
     * @access protected
     * @since  1.0
     */
    protected function _decrypt($string)
    {
        return (!is_string($string)) ? '' : base64_decode(base64_decode($string));
    }

    /**
     * Give the requested setting
     *
     * @param string $key
     * @param mixed  $option
     * @return mixed
     * @access public
     * @since 2.0
     */
    public function getOption($key, $option = null)
    {

        if (is_null($option)) {
            return (isset($this->_options[$key])) ? $this->_options[$key] : '';
        }

        return (isset($this->_options[$key][$option])) ? $this->_options[$key][$option] : '';
    }

    /**
     * Set the valid value for setting sent
     *
     * @param string $key
     * @param string $option
     * @param mixed  $value
     * @return boolean
     * @access public
     * @since 2.0
     */
    public function setOption($key, $option, $value)
    {

        switch ($key) {
            case 'filters':
                return false;
                break;

            case 'auto':
            case 'explode':
            case 'label':
                $this->_options[$key][$option] = $value;
                return true;
                break;

            default:
                return false;
                break;
        }
    }

    /**
     * Return conditions created by the function $this->make()
     *
     * @return array
     * @access public
     * @since 1.0
     */
    public function getConditions()
    {

        if (!is_array($this->_conditions)) {
            return $this->make();
        }

        if (count($this->_conditions) == 0) {
            return $this->make();
        }

        return $this->_conditions;
    }

    /**
     * HasField
     *
     * @param string $field
     * @return boolean
     * @access public
     * @since 1.0
     */
    public function hasField($field)
    {
        return $this->_searchField($field, $this->getOption('filters'));
    }

    /**
     * Search the specified field
     *
     * @param string $field
     * @param type   $filters
     * @return boolean
     * @access protected
     * @since 2.0
     */
    protected function _searchField($field, $filters)
    {

        $hasField = false;
        foreach ($filters as $key => $value) {
            switch (mb_strtolower($key)) {
                case 'not':
                case 'and':
                case 'or':
                    $hasField = $this->_searchField($field, $value);
                    break;

                default:
                    if (is_string($value)) {
                        if ($value == $field) {
                            $hasField = true;
                        }
                    }

                    if ($key == $field) {
                        $hasField = true;
                    }
            }
        }

        return $hasField;
    }

    /**
     * Return array select of the specified field
     *
     * @param string $field
     * @return mixed
     * @access public
     * @since 1.0
     */
    public function getFieldSelect($field)
    {

        $values = array();

        if ($this->hasField($field)) {
            $options = $this->_getFilterOptions($field, $this->getOption('filters'));
            $values += $this->_searchSelectOption($options);
        }

        return (count($values) == 0) ? null : $values;
    }

    /**
     * Search for possible values of specified field
     *
     * @param array $array
     * @return mixed
     * @access public
     * @since 2.0
     */
    public function _searchSelectOption($options)
    {

        if (!is_array($options)) {
            return array();
        }

        $result = array();

        foreach ($options as $key => $value) {
            if (isset($options[$key]['select'])) {
                if (is_array($options[$key]['select'])) {
                    $result += $options[$key]['select'];
                }
            } else {
                if (is_array($value)) {
                    $result += $this->_searchSelectOption($value);
                }
            }
        }

        return $result;
    }

    /**
     * Composite array values for selection in the form
     *
     * @param string $label
     * @param array  $values
     * @return array
     * @since 2.0
     */
    public function select($label, $values)
    {
        return array('' => $label) + $values;
    }
    /**
     * @deprecated 08-04-2012
     */
    public function values($label, $values)
    {
        return $this->values($label, $values);
    }
    /**
     * @deprecated 07-04-2012
     */
    public function merge($label, $values)
    {
        return $this->values($label, $values);
    }

    /**
     * Define one or more filters
     *
     * @param array $filters
     * @throws Exception When $filters is not be a array or string
     * @access public
     * @since 1.0
     */
    public function addFilters($filters = null)
    {

        if (!is_array($filters)) {
            if (!is_string($filters)) {
                throw new Exception(__('$filters type must be a array or string', true));
            }

            $filters = array($filters);
        }

        if ($this->getOption('filters')) {
            $this->_options['filters'] += $filters;
        } else {
            $this->_options['filters'] = $filters;
        }
    }

    /**
     * Main method
     * Do everiting to create conditions
     *
     * @return array
     * @access public
     * @since 1.0
     */
    public function make()
    {

        if (isset($this->controller->request->data[$this->getOption('label', 'prefix')])) {
            $this->_redirectToNamedUrl();
            return;
        }


        /**
         * Sent component to view
         */
        $name = 'FilterResults';
        if ($this->_instance > 1) {
            $name = $name . $this->_instance;
        }
        $this->controller->set($name, $this);

        if (count($this->controller->request->params['named']) == 0) {
            return array();
        }

        if ($this->_check() > 0) {

            $this->_conditions = $this->_filterFields($this->_options['filters']);

            if ($this->getOption('auto', 'paginate')) {
                $this->controller->Paginator->paginate['conditions'][] = $this->_conditions;
            }
            return $this->_conditions;
        }
    }

    /**
     * Make the URL with NAMED fields.
     * Like this: example.com/cake/posts/index/Search.keywords:mykeyword/Search.tag_id:3
     *
     * After, autoredirect to created URL
     *
     * @param array $url
     * @param array $get
     * @access protected
     * @since 2.0
     */
    protected function _redirectToNamedUrl($url = array(), $get = array())
    {

        foreach ($this->controller->request['url'] as $key => $value) {
            if ($key != 'url') {
                $get += array($key => $value);
            }
        }

        if (count($get) > 0) {
            $url['?'] = $get;
        }

        foreach ($this->controller->request->data[$this->getOption('label', 'prefix')] as $key => $value) {

            if (!is_array($value)) {
                $url[$this->_encrypt(sprintf('%s.%s', $this->getOption('label', 'prefix'), $key))] = $this->_encrypt($value);
            } else {
                foreach ($value as $k => $v) {
                    $url[$this->_encrypt(sprintf('%s.%s.%s', $this->getOption('label', 'prefix'), $key, $k))] = $this->_encrypt($v);
                }
            }
        }


        // Remove filters of NAMED
        $named = $this->controller->request->params['named'];
        foreach ($named as $key => $value) {
            if (!(strpos($this->_decrypt($key), sprintf('%s.', $this->getOption('label', 'prefix'))) === false)) {
                unset($named[$key]);
            }
        }
        // Remove 'page' param
        foreach ($named as $key => $value) {
            if ($key == 'page') {
                unset($named[$key]);
            }
        }

        // Keep application's NAMED params on redirect
        $url = array_merge($this->controller->request->params['pass'], $named, $url);

        $this->controller->redirect($url, null, true);
    }



    /**
     * Check if the URL contain some NAMED parameter.
     * If found then encrypt and store it.
     * Return count of NAMED parameters.
     *
     * @return int
     * @access protected
     * @since 1.0
     */
    protected function _check()
    {

        // Decrypt all NAMED parameters
        foreach ($this->controller->request->params['named'] as $key => $value) {
            $this->_params[$this->_decrypt($key)] = $this->_decrypt($value);
        }

        $count = 0;
        foreach ($this->_params as $key => $value) {
            if (strpos($key, $this->getOption('label', 'prefix')) > -1) {
                $count++;
            }
        }
        return $count;
    }

    /**
     * FilterFields
     *
     * @param array $filters
     * @param array $condition
     * @return array
     * @access protected
     * @since 1.0
     */
    protected function _filterFields($filters, $condition = array())
    {

        foreach ($filters as $key => $value) {

            switch (mb_strtolower($key, 'utf-8')) {
                case 'not':
                case 'and':
                case 'or':
                    $conditionOfFilter = $this->_filterFields($value);
                    if (count($conditionOfFilter) > 0) {
                        if (!isset($condition[$key])) {
                            $condition[$key] = $this->_filterFields($value);
                        } else {
                            $condition[$key] += $this->_filterFields($value);
                        }
                    }
                    break;

                default:
                    if (is_array($value)) {
                        $variavel = $this->_makeConditions($key, $value);
                        array_push($condition, $variavel);
                    } else {
                        $variavel = $this->_makeConditions($value);
                        array_push($condition, $variavel);
                    }
                    break;
            }
        }
        return $condition;
    }

    /**
     * Make conditions for the specified field sent
     *
     * @param array $field
     * @param array $options
     * @param array $condition
     * @access protected
     * @since 1.0
     */
    protected function _makeConditions($field, $options = null, $condition = array())
    {

        if (!isset($options)) {
            return $this->_makeConditionsWithoutOptions($field);
        }

        foreach ($options as $key => $value) {

            switch (mb_strtolower($key, 'utf-8')) {
                case 'not':
                case 'and':
                case 'or':
                    if (sizeof($this->_makeConditions($field, $value)) > 0) {
                        $condition += array(
                            $key => $this->_makeConditions($field, $value)
                        );
                    }
                    break;

                default:


                    $this->_filter = array();
                    $this->_filter['field'] = $field;

                    /**
                     * Check the parameter's value, if empty break
                     */
                    if (!$this->_hasFieldParams()) {
                        break;
                    }


                    /**
                     * Define defaults
                     */
                    if (is_array($value)) {
                        $this->_filter['fieldModel'] = $key;
                        $this->_filter += $value;
                    } else {
                        $this->_filter['fieldModel'] = (is_array($value)) ? $key : $value;
                    }

                    if (!isset($this->_filter['operator'])) {
                        $this->_filter['operator'] = '=';
                    }

                    $this->_filter['value.before'] = $this->_defaultOptionsValue('before');
                    $this->_filter['value.after']  = $this->_defaultOptionsValue('after');
                    $this->_filter['value.upper'] = !isset($this->_filter['value.upper']) ?
                            $this->_defaultOptionsValue('upper') : $this->_filter['value.upper'];

                    if (!isset($this->_filter['value'])) {
                        $this->_filter['value'] = $this->_getFieldParams();
                    } else {
                        if (is_array($this->_filter['value'])) {
                            $this->_filter['select'] = $this->_filter['value'];
                            $this->_filter['value'] = $this->_getFieldParams();
                        }
                    }

                    if (empty($this->_filter['value']) && $this->_filter['value'] !== '0') {
                        break;
                    }

                    $this->_filter['explode.concatenate'] = (isset($this->_filter['explode']['concatenate']))
                        ? $this->_filter['explode']['concatenate']
                        : $this->getOption('explode', 'concatenate');

                    $this->_filter['explode.character'] = (isset($this->_filter['explode']['character']))
                        ? $this->_filter['explode']['character']
                        : $this->getOption('explode', 'character');


                    if (!isset($this->_filter['explode'])) {
                        $this->_filter['explode'] = null;
                    } else {
                        if (is_array($this->_filter['explode'])) {
                            $this->_filter['explode'] = true;
                        }
                    }

                    switch (mb_strtolower($this->_filter['operator'], 'utf-8')) {
                        case 'between':
                            $condition += $this->_conditionsForOperatorBetween();
                            break;

                        default:

                            $condition[] = ($this->_isMayExplodeValue())
                                ? $this->_valueConcatenate()
                                : $this->_value();
                            $this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field']] = $this->_getFieldParams();
                            break;
                    }
            }
        }

        return $condition;
    }


    protected function _hasFieldParams($more = null, $between = false)
    {

        if ($between) {
            return isset($this->_params[sprintf('%s.%s-between', $this->getOption('label', 'prefix'), $this->_filter['field'])]);
        }

        if (is_null($more)) {
            return isset($this->_params[sprintf('%s.%s', $this->getOption('label', 'prefix'), $this->_filter['field'])]);
        } else {
            return isset($this->_params[sprintf('%s.%s.%s', $this->getOption('label', 'prefix'), $this->getOption('label', $more), $this->_filter['field'])]);
        }
    }

    protected function _getFieldParams($more = null, $between = false)
    {

        if (!$this->_hasFieldParams($more, $between)) {
            return '';
        }

        if ($between) {
            return $this->_params[sprintf('%s.%s-between', $this->getOption('label', 'prefix'), $this->_filter['field'])];
        }

        if (is_null($more)) {
            return $this->_params[sprintf('%s.%s', $this->getOption('label', 'prefix'), $this->_filter['field'])];
        } else {
            return $this->_params[sprintf('%s.%s.%s', $this->getOption('label', 'prefix'), $this->getOption('label', $more), $this->_filter['field'])];
        }
    }

    /**
     * Make conditions for fileds without specified parameters
     *
     * @param array $field
     * @return array
     * @access protected
     * @since 2.0
     */
    protected function _makeConditionsWithoutOptions($field)
    {

        $this->_filter = array();
        $this->_filter['field'] = $field;

        if (!$this->_hasFieldParams()) {
            return array();
        }

        if (!$this->_hasFieldParams('fieldModel')) {
            return array();
        }

        /**
         * Define defaults
         */
        $this->_filter['fieldModel'] = $this->_getFieldParams('fieldModel');
        $this->_filter['value']      = $this->_getFieldParams();

        $this->_filter['operator'] = ($this->_hasFieldParams('operator')) ? $this->_getFieldParams('operator') : 'like';

        $this->_filter['explode'] = true;
        $this->_filter['explode.concatenate'] = $this->getOption('explode', 'concatenate');
        $this->_filter['explode.character']   = $this->getOption('explode', 'character');

        switch (mb_strtolower($this->_filter['operator'], 'utf-8')) {
            case 'like':
            case 'not like':
                $this->_filter['value.before'] = '%';
                $this->_filter['value.after']  = '%';
                break;

            case 'likebegin':
            case 'like begin':
                $operator = 'LIKE';
                $this->_filter['value.after'] = '%';
                break;

            case 'likeend':
            case 'like end':
                $operator = 'LIKE';
                $this->_filter['value.before'] = '%';
                break;

            default:
                $this->_filter['value.before'] = '';
                $this->_filter['value.after']  = '';
                break;
        }


        $condition[] = ($this->_isMayExplodeValue())
            ? $this->_valueConcatenate()
            : $this->_value();

        $this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field']] = $this->_getFieldParams();

        $this->controller->request->data[$this->getOption('label', 'prefix')][$this->getOption('label', 'fieldModel')][$field] = $this->_getFieldParams('fieldModel');
        $this->controller->request->data[$this->getOption('label', 'prefix')][$this->getOption('label', 'operator')][$field]   = $this->_getFieldParams('operator');

        return $condition;
    }

    /**
     * Make the condition when operator='between'
     *
     * @return array
     * @access protected
     */
    protected function _conditionsForOperatorBetween()
    {

        if (count($this->_filter) == 0) {
            return array();
        }

        /**
         * Verifica a existencia dos dois parâmetros
         */
        if (!$this->_hasFieldParams() || !$this->_hasFieldParams(null, true)) {

            if ($this->_hasFieldParams()) {
                $$this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field']] = $this->_getFieldParams();
            }

            if ($this->_hasFieldParams(null, true)) {
                $$this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field'] . '-between'] = $this->_getFieldParams(null, true);
            }

            return array();
        }

        $this->_filter['value-between'] = $this->_getFieldParams(null, true);


        /**
         * Altera o formato da data para formato de banco
         */
        if (isset($this->_filter['between']['date'])) {
            if ($this->_filter['between']['date']) {
                $this->_filter['value']         = implode(preg_match("~\/~", $this->_filter['value'])         == 0 ? "/" : "-", array_reverse(explode(preg_match("~\/~", $this->_filter['value'])         == 0 ? "-" : "/", $this->_filter['value'])));
                $this->_filter['value-between'] = implode(preg_match("~\/~", $this->_filter['value-between']) == 0 ? "/" : "-", array_reverse(explode(preg_match("~\/~", $this->_filter['value-between']) == 0 ? "-" : "/", $this->_filter['value-between'])));
            }
        }

        $this->_filter['value']    = array($this->_filter['value'], $this->_filter['value-between']);
        $this->_filter['operator'] = 'BETWEEN ? AND ?';

        $condition = array(sprintf('%s %s', $this->_filter['fieldModel'], $this->_filter['operator']) => $this->_filter['value']);

        $this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field']]            = $this->_getFieldParams();
        $this->controller->request->data[$this->getOption('label', 'prefix')][$this->_filter['field'] . '-between'] = $this->_getFieldParams(null, true);

        return $condition;
    }

    /**
     * Return the default value of the specified option
     *
     * @param string $option
     * @return string
     * @access protected
     * @since 2.0
     */
    protected function _defaultOptionsValue($option)
    {

        $default = null;

        if (isset($this->_filter['value'])) {
            if (is_array($this->_filter['value'])) {
                if (isset($this->_filter['value'][$option])) {
                    $default = $this->_filter['value'][$option];
                }
            }
        }


        if ($default == null) {
            switch (mb_strtolower($this->_filter['operator'], 'utf-8')) {
                case 'like':
                case 'not like':
                    $default = '%';
                    break;

                default:
                    $default = '';
                    break;
            }

            if ($option == 'upper') {
                $default = 'false';
            }
        }

        return $default;
    }

    /**
     * Verify the permission to explode value
     *
     * @return boolean
     * @access protected
     * @since 2.0
     */
    protected function _isMayExplodeValue()
    {

        if (count($this->_filter) == 0) {
            return false;
        }

        if (is_null($this->_filter['explode'])) {

            switch (mb_strtolower($this->_filter['operator'], 'utf-8')) {
                case 'like':
                case 'not like':
                    return $this->getOption('auto', 'explode');
                    break;

                default:
                    break;
            }
        }

        if ($this->_filter['explode']) {
            return true;
        }

        return false;
    }

    /**
     * Composite value of condition
     *
     * @return array
     * @access protected
     * @since 2.0
     */
    protected function _value()
    {
        if (count($this->_filter) == 0) { return array(); }

        $val = ($this->_filter['value.upper'] == 'true') ?
                strtoupper($this->_filter['value']) :
                $this->_filter['value'];

        return array(
            sprintf('%s %s', $this->_filter['fieldModel'], $this->_filter['operator']) =>
            sprintf('%s%s%s', $this->_filter['value.before'], $val, $this->_filter['value.after'])
        );
    }

    /**
     * Explode and concatenate the values
     *
     * @return array
     * @access protected
     * @since 2.0
     */
    protected function _valueConcatenate()
    {
        $condition = array();
        $values = explode($this->_filter['explode.character'], $this->_filter['value']);

        if (count($values) > 1) {
            foreach ($values as $k => $v) {

                $v = ($this->_filter['value.upper'] == 'true') ?
                        strtoupper($v) : $v;
                $condition[$this->_filter['explode.concatenate']][$k] = array(
                    sprintf('%s %s', $this->_filter['fieldModel'], $this->_filter['operator']) =>
                    sprintf('%s%s%s', $this->_filter['value.before'], $v, $this->_filter['value.after'])
                );
            }
        } else {
            /*
             * Condicao original do plugin, alterada para forcar uppercase no banco
             * $condition = $this->_value();
             */
            $condition = array(sprintf('UPPER(%s) %s ', $this->_filter['fieldModel'], $this->_filter['operator']) =>
            sprintf('%s%s%s', $this->_filter['value.before'], strtoupper($this->_filter['value']), $this->_filter['value.after']));
        }

        return $condition;
    }

    /**
     * Get the fields of model automaticaly
     *
     * @return array
     * @access public
     * @since 1.0
     */
    public function getModelFields()
    {

        if (!isset($this->controller->uses[0])) {
            return array();
        }

        $fields = array();
        foreach ($this->controller->{$this->controller->uses[0]}->_schema as $key => $value) {
            $fields[sprintf('%s.%s', $this->controller->uses[0], $key)] = $key;
        }
        return $fields;
    }

    /**
     * getFieldOperator
     *
     * @param string $fieldName
     * @return string
     * @access public
     * @since 1.1
     */
    public function getFieldOperator($fieldName)
    {

        $options = $this->_getFilterOptions($fieldName, $this->getOption('filters'));

        if (is_array($options)) {
            foreach ($options as $key => $value) {
                if (isset($value['operator'])) {
                    return mb_strtolower($value['operator'], 'utf-8');
                }
            }
        }

        return '';
    }

    /**
     * Search Filter Options
     *
     * Retorna as opções do filtro
     *
     * @param string $field
     * @param type   $filters
     * @return array
     * @access protected
     * @since 2.0
     */
    protected function _getFilterOptions($field, $filters)
    {

        $return = array();
        foreach ($filters as $key => $value) {

            switch (mb_strtolower($key)) {
                case 'not':
                case 'and':
                case 'or':
                    $return = $this->_getFilterOptions($field, $value);
                    break;

                default:
                    if ($key == $field) {
                        $return = $value;
                    }
            }
        }

        return $return;
    }

    /**
     * Define paginator's options for CakePHP2.2+
     *
     * @param mixed $option
     * @param mixed $value
     * @access public
     * @since 2.0
     */
    public function setPaginate($option, $value = null)
    {
        $setting = (is_array($option)) ? $option : array($option => $value);
        if (!(is_array($setting))) return;

        $this->controller->paginate = array_merge($this->controller->paginate, $setting);
    }

    /**
     * Retorna um array com os dados da busca, como total de itens e total de páginas;
     * se for chamado antes do método paginate, o array vem nulo, pois ele só é montado
     * após a primeira busca
     */
    public function getPaginateParams()
    {
        return $this->controller->Components->getController()->request['paging'];
    }

    /**
     * Seta o indice da página a ser retornada pelo método paginate
     * @param unknown_type $value
     */
    public function setPage($value)
    {
        $this->controller->Components->load('Paginator', $this->paginate)->settings['page'] = $value;
    }
}

