Completed
Pull Request — master (#173)
by Javier
01:18
created

PagerfantaExtension::getRequest()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 4
nc 2
nop 0
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 Pagerfanta\View\ViewFactory;
16
use Symfony\Component\BrowserKit\Request;
17
use Symfony\Component\HttpFoundation\RequestStack;
18
use Symfony\Component\PropertyAccess\PropertyAccess;
19
use Symfony\Component\PropertyAccess\PropertyPath;
20
use Symfony\Component\Routing\RouterInterface;
21
22
/**
23
 * PagerfantaExtension.
24
 *
25
 * @author Pablo Díez <[email protected]>
26
 */
27
class PagerfantaExtension extends \Twig_Extension
28
{
29
    private $defaultView;
30
    private $viewFactory;
31
    private $router;
32
    private $requestStack;
33
    private $request;
34
35
    public function __construct($defaultView, ViewFactory $viewFactory, RouterInterface $router, RequestStack $requestStack)
36
    {
37
        $this->defaultView = $defaultView;
38
        $this->viewFactory = $viewFactory;
39
        $this->router = $router;
40
        $this->requestStack = $requestStack;
41
        $this->request = $request;
0 ignored issues
show
Bug introduced by
The variable $request does not exist. Did you mean $requestStack?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function getFunctions()
48
    {
49
        return array(
50
            new \Twig_SimpleFunction('pagerfanta', array($this, 'renderPagerfanta'), array('is_safe' => array('html'))),
51
            new \Twig_SimpleFunction('pagerfanta_page_url', array($this, 'getPageUrl')),
52
        );
53
    }
54
55
    /**
56
     * Renders a pagerfanta.
57
     *
58
     * @param PagerfantaInterface $pagerfanta The pagerfanta.
59
     * @param string|array        $viewName   The view name.
60
     * @param array               $options    An array of options (optional).
61
     *
62
     * @return string The pagerfanta rendered.
63
     */
64
    public function renderPagerfanta(PagerfantaInterface $pagerfanta, $viewName = null, array $options = array())
65
    {
66
        if (is_array($viewName)) {
67
            list($viewName, $options) = array(null, $viewName);
68
        }
69
70
        $viewName = $viewName ?: $this->defaultView;
71
72
        $routeGenerator = $this->createRouteGenerator($options);
73
74
        return $this->viewFactory->get($viewName)->render($pagerfanta, $routeGenerator, $options);
75
    }
76
77
    /**
78
     * Generates the url for a given page in a pagerfanta instance.
79
     *
80
     * @param \Pagerfanta\PagerfantaInterface $pagerfanta
81
     * @param $page
82
     * @param array $options
83
     *
84
     * @return string The url of the given page
85
     *
86
     * @throws \InvalidArgumentException
87
     */
88
    public function getPageUrl(PagerfantaInterface $pagerfanta, $page, array $options = array())
89
    {
90
        if ($page < 0 || $page > $pagerfanta->getNbPages()) {
91
            throw new \InvalidArgumentException("Page '{$page}' is out of bounds");
92
        }
93
94
        $routeGenerator = $this->createRouteGenerator($options);
95
96
        return $routeGenerator($page);
97
    }
98
99
    /**
100
     * Creates an anonymous function which returns the URL for a given page.
101
     *
102
     * @param array $options
103
     *
104
     * @return callable
105
     *
106
     * @throws \Exception
107
     */
108
    private function createRouteGenerator($options = array())
109
    {
110
        $options = array_replace(array(
111
                'routeName'     => null,
112
                'routeParams'   => array(),
113
                'pageParameter' => '[page]',
114
                'omitFirstPage' => false
115
            ), $options);
116
117
        $router = $this->router;
118
119
        if (null === $options['routeName']) {
120
            $request = $this->getRequest();
121
122
            $options['routeName'] = $request->attributes->get('_route');
123
            if ('_internal' === $options['routeName']) {
124
                throw new \Exception('PagerfantaBundle can not guess the route when used in a subrequest');
125
            }
126
127
            // make sure we read the route parameters from the passed option array
128
            $defaultRouteParams = array_merge($request->query->all(), $request->attributes->get('_route_params', array()));
129
130
            if (array_key_exists('routeParams', $options)) {
131
                $options['routeParams'] = array_merge($defaultRouteParams, $options['routeParams']);
132
            } else {
133
                $options['routeParams'] = $defaultRouteParams;
134
            }
135
        }
136
137
        $routeName = $options['routeName'];
138
        $routeParams = $options['routeParams'];
139
        $pagePropertyPath = new PropertyPath($options['pageParameter']);
140
        $omitFirstPage = $options['omitFirstPage'];
141
142
        return function($page) use($router, $routeName, $routeParams, $pagePropertyPath, $omitFirstPage) {
143
            $propertyAccessor = PropertyAccess::createPropertyAccessor();
144
            // don't set the page parameter if it is the first page and the omitFirstPage flag is true
145
            if(!$omitFirstPage || $page > 1 ){
146
                $propertyAccessor->setValue($routeParams, $pagePropertyPath, $page);
147
            }
148
149
            return $router->generate($routeName, $routeParams);
150
        };
151
    }
152
153
    public function setRequest(Request $request = null)
154
    {
155
        $this->request = $request;
156
    }
157
158
    /**
159
     * @return Request|null
160
     */
161
    private function getRequest()
162
    {
163
        if ($this->requestStack && $request = $this->requestStack->getCurrentRequest()) {
164
            return $request;
165
        }
166
167
        return $this->request;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function getName()
174
    {
175
        return 'pagerfanta';
176
    }
177
}
178