vendor/knplabs/knp-components/src/Knp/Component/Pager/Paginator.php line 108

Open in your IDE?
  1. <?php
  2. namespace Knp\Component\Pager;
  3. use Symfony\Component\EventDispatcher\EventDispatcher;
  4. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Knp\Component\Pager\Event\Subscriber\Paginate\PaginationSubscriber;
  7. use Knp\Component\Pager\Event\Subscriber\Sortable\SortableSubscriber;
  8. use Knp\Component\Pager\Event;
  9. /**
  10.  * Paginator uses event dispatcher to trigger pagination
  11.  * lifecycle events. Subscribers are expected to paginate
  12.  * wanted target and finally it generates pagination view
  13.  * which is only the result of paginator
  14.  */
  15. class Paginator implements PaginatorInterface
  16. {
  17.     /**
  18.      * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
  19.      */
  20.     protected $eventDispatcher;
  21.     /**
  22.      * Default options of paginator
  23.      *
  24.      * @var array
  25.      */
  26.     protected $defaultOptions = array(
  27.         self::PAGE_PARAMETER_NAME => 'page',
  28.         self::SORT_FIELD_PARAMETER_NAME => 'sort',
  29.         self::SORT_DIRECTION_PARAMETER_NAME => 'direction',
  30.         self::FILTER_FIELD_PARAMETER_NAME => 'filterParam',
  31.         self::FILTER_VALUE_PARAMETER_NAME => 'filterValue',
  32.         self::DISTINCT => true
  33.     );
  34.     /**
  35.      * Initialize paginator with event dispatcher
  36.      * Can be a service in concept. By default it
  37.      * hooks standard pagination subscriber
  38.      *
  39.      * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $eventDispatcher
  40.      */
  41.     public function __construct(EventDispatcherInterface $eventDispatcher null)
  42.     {
  43.         $this->eventDispatcher $eventDispatcher;
  44.         if (is_null($this->eventDispatcher)) {
  45.             $this->eventDispatcher = new EventDispatcher;
  46.             $this->eventDispatcher->addSubscriber(new PaginationSubscriber);
  47.             $this->eventDispatcher->addSubscriber(new SortableSubscriber);
  48.         }
  49.     }
  50.     /**
  51.      * Override the default paginator options
  52.      * to be reused for paginations
  53.      *
  54.      * @param array $options
  55.      */
  56.     public function setDefaultPaginatorOptions(array $options)
  57.     {
  58.         $this->defaultOptions array_merge($this->defaultOptions$options);
  59.     }
  60.     /**
  61.      * Paginates anything (depending on event listeners)
  62.      * into Pagination object, which is a view targeted
  63.      * pagination object (might be aggregated helper object)
  64.      * responsible for the pagination result representation
  65.      *
  66.      * @param mixed $target - anything what needs to be paginated
  67.      * @param integer $page - page number, starting from 1
  68.      * @param integer $limit - number of items per page
  69.      * @param array $options - less used options:
  70.      *     boolean $distinct - default true for distinction of results
  71.      *     string $alias - pagination alias, default none
  72.      *     array $whitelist - sortable whitelist for target fields being paginated
  73.      * @throws \LogicException
  74.      * @return \Knp\Component\Pager\Pagination\PaginationInterface
  75.      */
  76.     public function paginate($target$page 1$limit 10, array $options = array())
  77.     {
  78.         $page = (int) $page
  79.         $limit intval(abs($limit));
  80.         if (!$limit) {
  81.             throw new \LogicException("Invalid item per page number, must be a positive number");
  82.         }
  83.         $offset abs($page 1) * $limit;
  84.         $options array_merge($this->defaultOptions$options);
  85.         // normalize default sort field
  86.         if (isset($options[self::DEFAULT_SORT_FIELD_NAME]) && is_array($options[self::DEFAULT_SORT_FIELD_NAME])) {
  87.             $options[self::DEFAULT_SORT_FIELD_NAME] = implode('+'$options[self::DEFAULT_SORT_FIELD_NAME]);
  88.         }
  89.         
  90.         // default sort field and direction are set based on options (if available)
  91.         if (!isset($_GET[$options[self::SORT_FIELD_PARAMETER_NAME]]) && isset($options[self::DEFAULT_SORT_FIELD_NAME])) {
  92.             $_GET[$options[self::SORT_FIELD_PARAMETER_NAME]] = $options[self::DEFAULT_SORT_FIELD_NAME];
  93.             
  94.             if (!isset($_GET[$options[self::SORT_DIRECTION_PARAMETER_NAME]])) {
  95.                 $_GET[$options[self::SORT_DIRECTION_PARAMETER_NAME]] = isset($options[self::DEFAULT_SORT_DIRECTION]) ? $options[self::DEFAULT_SORT_DIRECTION] : 'asc';
  96.             }
  97.         }
  98.         
  99.         // before pagination start
  100.         $beforeEvent = new Event\BeforeEvent($this->eventDispatcher);
  101.         $this->eventDispatcher->dispatch('knp_pager.before'$beforeEvent);
  102.         // items
  103.         $itemsEvent = new Event\ItemsEvent($offset$limit);
  104.         $itemsEvent->options = &$options;
  105.         $itemsEvent->target = &$target;
  106.         $this->eventDispatcher->dispatch('knp_pager.items'$itemsEvent);
  107.         if (!$itemsEvent->isPropagationStopped()) {
  108.             throw new \RuntimeException('One of listeners must count and slice given target');
  109.         }
  110.         // pagination initialization event
  111.         $paginationEvent = new Event\PaginationEvent;
  112.         $paginationEvent->target = &$target;
  113.         $paginationEvent->options = &$options;
  114.         $this->eventDispatcher->dispatch('knp_pager.pagination'$paginationEvent);
  115.         if (!$paginationEvent->isPropagationStopped()) {
  116.             throw new \RuntimeException('One of listeners must create pagination view');
  117.         }
  118.         // pagination class can be different, with different rendering methods
  119.         $paginationView $paginationEvent->getPagination();
  120.         $paginationView->setCustomParameters($itemsEvent->getCustomPaginationParameters());
  121.         $paginationView->setCurrentPageNumber($page);
  122.         $paginationView->setItemNumberPerPage($limit);
  123.         $paginationView->setTotalItemCount($itemsEvent->count);
  124.         $paginationView->setPaginatorOptions($options);
  125.         $paginationView->setItems($itemsEvent->items);
  126.         // after
  127.         $afterEvent = new Event\AfterEvent($paginationView);
  128.         $this->eventDispatcher->dispatch('knp_pager.after'$afterEvent);
  129.         return $paginationView;
  130.     }
  131.     /**
  132.      * Hooks in the given event subscriber
  133.      *
  134.      * @param \Symfony\Component\EventDispatcher\EventSubscriberInterface $subscriber
  135.      */
  136.     public function subscribe(EventSubscriberInterface $subscriber)
  137.     {
  138.         $this->eventDispatcher->addSubscriber($subscriber);
  139.     }
  140.     /**
  141.      * Hooks the listener to the given event name
  142.      *
  143.      * @param string $eventName
  144.      * @param object $listener
  145.      * @param integer $priority
  146.      */
  147.     public function connect($eventName$listener$priority 0)
  148.     {
  149.         $this->eventDispatcher->addListener($eventName$listener$priority);
  150.     }
  151. }