Completed
Push — master ( 845964...864a7b )
by Louis
16s
created

PaginateHelper::paginateData()   F

Complexity

Conditions 16
Paths 1024

Size

Total Lines 80
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 80
rs 2.1086
c 0
b 0
f 0
cc 16
eloc 52
nc 1024
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace KI\CoreBundle\Helper;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\EntityRepository;
7
use Symfony\Component\HttpFoundation\JsonResponse;
8
use Symfony\Component\HttpFoundation\RequestStack;
9
use Symfony\Component\HttpFoundation\Response;
10
11
class PaginateHelper
12
{
13
    protected $manager;
14
    protected $request;
15
16
    public function __construct(EntityManager $manager)
0 ignored issues
show
Bug introduced by
You have injected the EntityManager via parameter $manager. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

The EntityManager might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
17
    {
18
        $this->manager = $manager;
19
    }
20
21
    public function setRequest(RequestStack $requestStack)
22
    {
23
        $this->request = $requestStack->getCurrentRequest();
24
    }
25
26
    /**
27
     * En fonction de la requête, récupère les données utiles à la pagination
28
     * @param  EntityRepository $repository Le repository sur lequel effectuer les comptes
29
     * @return array                        Les données de pagination (nombre de pages, etc.)
30
     */
31
    public function paginateData(EntityRepository $repository, array $findBy = [])
32
    {
33
        $queryBuilder = $repository->createQueryBuilder('o');
34
        $request = $this->request->query;
35
36
        // On s'assure de bien recevoir des arrays
37
        foreach ($findBy as $key => $value) {
38
            $findBy[$key] = array($value);
39
        }
40
41
        // On récupère les paramètres de la requête
42
        $page  = $request->has('page') ? $request->get('page') : 1;
43
        $limit = $request->has('limit') ? $request->get('limit') : 100;
44
        $sort  = $request->has('sort') ? $request->get('sort') : null;
45
46
        if ($sort === null) {
47
            $sortBy = ['id' => 'DESC'];
48
        } else {
49
            $sortBy = [];
50
51
            foreach (explode(',', $sort) as $value) {
52
                $order = preg_match('/^\-.*/isU', $value) ? 'DESC' : 'ASC';
53
                $field = preg_replace('/^\-/isU', '', $value);
54
                $sortBy[$field] = $order;
55
            }
56
        }
57
58
        foreach ($request->all() as $key => $values) {
59
            if ($key != 'page' && $key != 'limit' && $key != 'sort') {
60
                $findBy[$key] = explode(',', $values);
61
            }
62
        }
63
64
        // On compte le nombre total d'entrées dans la BDD
65
        $queryBuilder->select('count(o.id)');
66
        foreach ($findBy as $key => $values){
67
            $andCount = 0;
68
            $and = '';
69
            foreach($values as $value){
70
                if($andCount > 0){
71
                    $and .= ' OR ';
72
                }
73
                $and .= 'o.' . $key . ' = :' . $key . $andCount;
74
                $queryBuilder->setParameter($key . $andCount, $value);
75
76
                $andCount++;
77
            }
78
            $queryBuilder->andWhere($and);
79
        }
80
81
        foreach($sortBy as $field => $order){
82
            $queryBuilder->addOrderBy('o.' . $field, $order);
83
        }
84
85
        $count = $queryBuilder->getQuery()->getSingleScalarResult();
86
87
        // On vérifie que l'utilisateur ne fasse pas de connerie avec les variables
88
        $totalPages = ceil($count/$limit);
89
        $limit = min($limit, 10000);
90
        $limit = max($limit, 1);
91
        $page  = min($page, $totalPages);
92
        $page  = max($page, 1);
93
94
        $results = $queryBuilder->select('o')
95
                    ->setMaxResults($limit)
96
                    ->setFirstResult(($page - 1)*$limit)
97
                    ->getQuery()
98
                    ->getResult();
99
100
        return [
101
            'findBy'     => $findBy,
102
            'sortBy'     => $sortBy,
103
            'limit'      => $limit,
104
            'offset'     => ($page - 1)*$limit,
105
            'page'       => $page,
106
            'totalPages' => $totalPages,
107
            'count'      => $count,
108
            'results'    => $results,
109
        ];
110
    }
111
112
    /**
113
     * Génère les headers de pagination et renvoie la réponse
114
     * @param  array   $results    Les résultats à paginer
115
     * @param  integer $limit      Le nombre d'objets par page
116
     * @param  integer $page       Le numéro de la page en cours
117
     * @param  integer $totalPages Le nombre total de pages
118
     * @param  integer $count      Le nombre total d'objets
119
     * @return Response
120
     */
121
    public function paginateView($results, $limit, $page, $totalPages, $count)
122
    {
123
        // On prend l'url de la requête
124
        $baseUrl = '<'.str_replace($this->request->getBaseUrl(), '', $this->request->getRequestUri());
125
126
        // On enlève tous les paramètres GET de type "page" et "limit" précédents s'il y en avait
127
        $baseUrl = preg_replace('/[\?&](page|limit)=\d+/', '', $baseUrl);
128
        $baseUrl .= !preg_match('/\?/', $baseUrl) ? '?' : '&';
129
130
        // On va générer les notres pour les links
131
        $baseUrl .= 'page=';
132
        $links = [];
133
134
        // First
135
        $links[] = $baseUrl.'1'.'&limit='.$limit.'>;rel=first';
136
137
        // Previous
138 View Code Duplication
        if ($page > 1) {
139
            $links[] = $baseUrl.($page - 1).'&limit='.$limit.'>;rel=previous';
140
        }
141
142
        // Self
143
        $links[] = $baseUrl.$page.'&limit='.$limit.'>;rel=self';
144
145
        // Next
146 View Code Duplication
        if ($page < $totalPages) {
147
            $links[] = $baseUrl.($page + 1).'&limit='.$limit.'>;rel=next';
148
        }
149
150
        // Last
151
        $links[] = $baseUrl.$totalPages.'&limit='.$limit.'>;rel=last';
152
153
        return [
154
            $results,
155
            $links,
156
            $count
157
        ];
158
    }
159
}
160