- <?php
- namespace Knp\Component\Pager;
- use Symfony\Component\EventDispatcher\EventDispatcher;
- use Symfony\Component\EventDispatcher\EventDispatcherInterface;
- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
- use Knp\Component\Pager\Event\Subscriber\Paginate\PaginationSubscriber;
- use Knp\Component\Pager\Event\Subscriber\Sortable\SortableSubscriber;
- use Knp\Component\Pager\Event;
- /**
-  * Paginator uses event dispatcher to trigger pagination
-  * lifecycle events. Subscribers are expected to paginate
-  * wanted target and finally it generates pagination view
-  * which is only the result of paginator
-  */
- class Paginator implements PaginatorInterface
- {
-     /**
-      * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
-      */
-     protected $eventDispatcher;
-     /**
-      * Default options of paginator
-      *
-      * @var array
-      */
-     protected $defaultOptions = array(
-         self::PAGE_PARAMETER_NAME => 'page',
-         self::SORT_FIELD_PARAMETER_NAME => 'sort',
-         self::SORT_DIRECTION_PARAMETER_NAME => 'direction',
-         self::FILTER_FIELD_PARAMETER_NAME => 'filterParam',
-         self::FILTER_VALUE_PARAMETER_NAME => 'filterValue',
-         self::DISTINCT => true
-     );
-     /**
-      * Initialize paginator with event dispatcher
-      * Can be a service in concept. By default it
-      * hooks standard pagination subscriber
-      *
-      * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
-      */
-     public function __construct(EventDispatcherInterface $eventDispatcher = null)
-     {
-         $this->eventDispatcher = $eventDispatcher;
-         if (is_null($this->eventDispatcher)) {
-             $this->eventDispatcher = new EventDispatcher;
-             $this->eventDispatcher->addSubscriber(new PaginationSubscriber);
-             $this->eventDispatcher->addSubscriber(new SortableSubscriber);
-         }
-     }
-     /**
-      * Override the default paginator options
-      * to be reused for paginations
-      *
-      * @param array $options
-      */
-     public function setDefaultPaginatorOptions(array $options)
-     {
-         $this->defaultOptions = array_merge($this->defaultOptions, $options);
-     }
-     /**
-      * Paginates anything (depending on event listeners)
-      * into Pagination object, which is a view targeted
-      * pagination object (might be aggregated helper object)
-      * responsible for the pagination result representation
-      *
-      * @param mixed $target - anything what needs to be paginated
-      * @param integer $page - page number, starting from 1
-      * @param integer $limit - number of items per page
-      * @param array $options - less used options:
-      *     boolean $distinct - default true for distinction of results
-      *     string $alias - pagination alias, default none
-      *     array $whitelist - sortable whitelist for target fields being paginated
-      * @throws \LogicException
-      * @return \Knp\Component\Pager\Pagination\PaginationInterface
-      */
-     public function paginate($target, $page = 1, $limit = 10, array $options = array())
-     {
-         $page = (int) $page; 
-         $limit = intval(abs($limit));
-         if (!$limit) {
-             throw new \LogicException("Invalid item per page number, must be a positive number");
-         }
-         $offset = abs($page - 1) * $limit;
-         $options = array_merge($this->defaultOptions, $options);
-         // normalize default sort field
-         if (isset($options[self::DEFAULT_SORT_FIELD_NAME]) && is_array($options[self::DEFAULT_SORT_FIELD_NAME])) {
-             $options[self::DEFAULT_SORT_FIELD_NAME] = implode('+', $options[self::DEFAULT_SORT_FIELD_NAME]);
-         }
-         
-         // default sort field and direction are set based on options (if available)
-         if (!isset($_GET[$options[self::SORT_FIELD_PARAMETER_NAME]]) && isset($options[self::DEFAULT_SORT_FIELD_NAME])) {
-             $_GET[$options[self::SORT_FIELD_PARAMETER_NAME]] = $options[self::DEFAULT_SORT_FIELD_NAME];
-             
-             if (!isset($_GET[$options[self::SORT_DIRECTION_PARAMETER_NAME]])) {
-                 $_GET[$options[self::SORT_DIRECTION_PARAMETER_NAME]] = isset($options[self::DEFAULT_SORT_DIRECTION]) ? $options[self::DEFAULT_SORT_DIRECTION] : 'asc';
-             }
-         }
-         
-         // before pagination start
-         $beforeEvent = new Event\BeforeEvent($this->eventDispatcher);
-         $this->eventDispatcher->dispatch('knp_pager.before', $beforeEvent);
-         // items
-         $itemsEvent = new Event\ItemsEvent($offset, $limit);
-         $itemsEvent->options = &$options;
-         $itemsEvent->target = &$target;
-         $this->eventDispatcher->dispatch('knp_pager.items', $itemsEvent);
-         if (!$itemsEvent->isPropagationStopped()) {
-             throw new \RuntimeException('One of listeners must count and slice given target');
-         }
-         // pagination initialization event
-         $paginationEvent = new Event\PaginationEvent;
-         $paginationEvent->target = &$target;
-         $paginationEvent->options = &$options;
-         $this->eventDispatcher->dispatch('knp_pager.pagination', $paginationEvent);
-         if (!$paginationEvent->isPropagationStopped()) {
-             throw new \RuntimeException('One of listeners must create pagination view');
-         }
-         // pagination class can be different, with different rendering methods
-         $paginationView = $paginationEvent->getPagination();
-         $paginationView->setCustomParameters($itemsEvent->getCustomPaginationParameters());
-         $paginationView->setCurrentPageNumber($page);
-         $paginationView->setItemNumberPerPage($limit);
-         $paginationView->setTotalItemCount($itemsEvent->count);
-         $paginationView->setPaginatorOptions($options);
-         $paginationView->setItems($itemsEvent->items);
-         // after
-         $afterEvent = new Event\AfterEvent($paginationView);
-         $this->eventDispatcher->dispatch('knp_pager.after', $afterEvent);
-         return $paginationView;
-     }
-     /**
-      * Hooks in the given event subscriber
-      *
-      * @param \Symfony\Component\EventDispatcher\EventSubscriberInterface $subscriber
-      */
-     public function subscribe(EventSubscriberInterface $subscriber)
-     {
-         $this->eventDispatcher->addSubscriber($subscriber);
-     }
-     /**
-      * Hooks the listener to the given event name
-      *
-      * @param string $eventName
-      * @param object $listener
-      * @param integer $priority
-      */
-     public function connect($eventName, $listener, $priority = 0)
-     {
-         $this->eventDispatcher->addListener($eventName, $listener, $priority);
-     }
- }
-