Completed
Push — master ( 1c5abd...27ccf0 )
by Pablo
9s
created

PagerfantaExtension::createRouteGenerator()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 50
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 2 Features 2
Metric Value
c 6
b 2
f 2
dl 0
loc 50
rs 6.7272
cc 7
eloc 32
nc 7
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Pagerfanta package.
5
 *
6
 * (c) Pablo Díez <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WhiteOctober\PagerfantaBundle\Twig;
13
14
use Pagerfanta\PagerfantaInterface;
15
use Symfony\Component\DependencyInjection\ContainerInterface;
16
use Symfony\Component\PropertyAccess\PropertyAccess;
17
use Symfony\Component\PropertyAccess\PropertyPath;
18
19
/**
20
 * PagerfantaExtension.
21
 *
22
 * @author Pablo Díez <[email protected]>
23
 */
24
class PagerfantaExtension extends \Twig_Extension
25
{
26
    private $container;
27
28
    /**
29
     * Constructor.
30
     *
31
     * @param ContainerInterface $container A container.
32
     */
33
    public function __construct(ContainerInterface $container)
34
    {
35
        $this->container = $container;
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function getFunctions()
42
    {
43
        return array(
44
            new \Twig_SimpleFunction('pagerfanta', array($this, 'renderPagerfanta'), array('is_safe' => array('html'))),
45
            new \Twig_SimpleFunction('pagerfanta_page_url', array($this, 'getPageUrl')),
46
        );
47
    }
48
49
    /**
50
     * Renders a pagerfanta.
51
     *
52
     * @param PagerfantaInterface $pagerfanta The pagerfanta.
53
     * @param string              $viewName   The view name.
54
     * @param array               $options    An array of options (optional).
55
     *
56
     * @return string The pagerfanta rendered.
57
     */
58
    public function renderPagerfanta(PagerfantaInterface $pagerfanta, $viewName = null, array $options = array())
59
    {
60
        if (null === $viewName) {
61
            $viewName = $this->container->getParameter('white_october_pagerfanta.default_view');
62
        }
63
64
        $routeGenerator = $this->createRouteGenerator($options);
65
66
        return $this->container->get('white_october_pagerfanta.view_factory')->get($viewName)->render($pagerfanta, $routeGenerator, $options);
67
    }
68
69
    /**
70
     * Generates the url for a given page in a pagerfanta instance.
71
     *
72
     * @param \Pagerfanta\PagerfantaInterface $pagerfanta
73
     * @param $page
74
     * @param array $options
75
     *
76
     * @return string The url of the given page
77
     *
78
     * @throws \InvalidArgumentException
79
     */
80
    public function getPageUrl(PagerfantaInterface $pagerfanta, $page, array $options = array())
81
    {
82
        if ($page < 0 || $page > $pagerfanta->count()) {
83
            throw new \InvalidArgumentException("Page '{$page}' is out of bounds");
84
        }
85
86
        $routeGenerator = $this->createRouteGenerator($options);
87
88
        return $routeGenerator($page);
89
    }
90
91
    /**
92
     * Creates an anonymous function which returns the URL for a given page.
93
     *
94
     * @param array $options
95
     *
96
     * @return callable
97
     *
98
     * @throws \Exception
99
     */
100
    private function createRouteGenerator($options = array())
101
    {
102
        $options = array_replace(array(
103
                'routeName'     => null,
104
                'routeParams'   => array(),
105
                'pageParameter' => '[page]',
106
                'omitFirstPage' => true
107
            ), $options);
108
109
        $router = $this->container->get('router');
110
111
        if (null === $options['routeName']) {
112
            if (null !== $requestStack = $this->container->get('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
113
                $request = $requestStack->getCurrentRequest();
114
            } else {
115
                // Symfony 2.3 compatibility
116
                $request = $this->container->get('request');
117
            }
118
119
            $options['routeName'] = $request->attributes->get('_route');
120
            if ('_internal' === $options['routeName']) {
121
                throw new \Exception('PagerfantaBundle can not guess the route when used in a subrequest');
122
            }
123
124
            // make sure we read the route parameters from the passed option array
125
            $defaultRouteParams = array_merge($request->query->all(), $request->attributes->get('_route_params', array()));
126
127
            if (array_key_exists('routeParams', $options)) {
128
                $options['routeParams'] = array_merge($defaultRouteParams, $options['routeParams']);
129
            } else {
130
                $options['routeParams'] = $defaultRouteParams;
131
            }
132
        }
133
134
        $routeName = $options['routeName'];
135
        $routeParams = $options['routeParams'];
136
        $pagePropertyPath = new PropertyPath($options['pageParameter']);
137
        $omitFirstPage = $options['omitFirstPage'];
138
139
        return function($page) use($router, $routeName, $routeParams, $pagePropertyPath, $omitFirstPage) {
140
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
141
            if($omitFirstPage){
142
                $propertyAccessor->setValue($routeParams, $pagePropertyPath, $page > 1 ? $page : null);
143
            } else {
144
                $propertyAccessor->setValue($routeParams, $pagePropertyPath, $page);
145
            }
146
147
            return $router->generate($routeName, $routeParams);
148
        };
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public function getName()
155
    {
156
        return 'pagerfanta';
157
    }
158
}
159