Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
20 | class Builder |
||
21 | { |
||
22 | /** |
||
23 | * @var Router |
||
24 | */ |
||
25 | private $router; |
||
26 | |||
27 | /** |
||
28 | * The number of pages displayed in the navigation. |
||
29 | * |
||
30 | * @var int |
||
31 | */ |
||
32 | private $max_navigate; |
||
33 | |||
34 | /** |
||
35 | * Name of URL parameter for page number. |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | private $parameter_name; |
||
40 | |||
41 | /** |
||
42 | * @param Router $router Router service |
||
43 | * @param int $max_navigate Maximum showing navigation links in pagination |
||
44 | * @param string $parameter_name Name of URL parameter for page number |
||
45 | */ |
||
46 | 14 | public function __construct(Router $router, $max_navigate, $parameter_name) |
|
52 | |||
53 | /** |
||
54 | * @param int $total_pages Total available pages |
||
55 | * @param int $current_page The current page number |
||
56 | * |
||
57 | * @return Configuration |
||
58 | */ |
||
59 | 7 | public function paginate($total_pages = 1, $current_page = 1) |
|
66 | |||
67 | /** |
||
68 | * @param QueryBuilder $query Query for select entities |
||
69 | * @param int $per_page Entities per page |
||
70 | * @param int $current_page The current page number |
||
71 | * |
||
72 | * @return Configuration |
||
73 | */ |
||
74 | 7 | public function paginateQuery(QueryBuilder $query, $per_page, $current_page = 1) |
|
75 | { |
||
76 | 7 | $counter = clone $query; |
|
77 | $total = $counter |
||
78 | 7 | ->select(sprintf('COUNT(%s)', current($query->getRootAliases()))) |
|
79 | 7 | ->getQuery() |
|
80 | 7 | ->getSingleScalarResult() |
|
81 | ; |
||
82 | |||
83 | 7 | $total_pages = (int) ceil($total / $per_page); |
|
84 | 7 | $current_page = $this->validateCurrentPage($current_page, $total_pages); |
|
85 | |||
86 | $query |
||
87 | 3 | ->setFirstResult(($current_page - 1) * $per_page) |
|
88 | 3 | ->setMaxResults($per_page) |
|
89 | ; |
||
90 | |||
91 | 3 | return $this->paginate($total_pages, $current_page); |
|
92 | } |
||
93 | |||
94 | /** |
||
95 | * @param Request $request Current HTTP request |
||
96 | * @param int $total_pages Total available pages |
||
97 | * @param string $parameter_name Name of URL parameter for page number |
||
98 | * @param int $reference_type The type of reference (one of the constants in UrlGeneratorInterface) |
||
99 | * |
||
100 | * @return Configuration |
||
101 | */ |
||
102 | 4 | View Code Duplication | public function paginateRequest( |
118 | |||
119 | /** |
||
120 | * @param Request $request Current HTTP request |
||
121 | * @param QueryBuilder $query Query for select entities |
||
122 | * @param int $per_page Entities per page |
||
123 | * @param string $parameter_name Name of URL parameter for page number |
||
124 | * @param int $reference_type The type of reference (one of the constants in UrlGeneratorInterface) |
||
125 | * |
||
126 | * @return Configuration |
||
127 | */ |
||
128 | 4 | View Code Duplication | public function paginateRequestQuery( |
129 | Request $request, |
||
130 | QueryBuilder $query, |
||
131 | $per_page, |
||
132 | $parameter_name = 'page', |
||
133 | $reference_type = UrlGeneratorInterface::ABSOLUTE_PATH |
||
134 | ) { |
||
135 | 4 | $parameter_name = $parameter_name ?: $this->parameter_name; |
|
136 | |||
137 | 4 | return $this->configureFromRequest( |
|
138 | 4 | $request, |
|
139 | 4 | $this->paginateQuery($query, $per_page, $request->get($parameter_name)), |
|
140 | 1 | $parameter_name, |
|
141 | 1 | $reference_type |
|
142 | ); |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * @param mixed $current_page |
||
147 | * @param int $total_pages |
||
148 | * |
||
149 | * @return int |
||
150 | */ |
||
151 | 11 | private function validateCurrentPage($current_page, $total_pages) |
|
152 | { |
||
153 | 11 | if ($current_page === null) { |
|
154 | 1 | return 1; |
|
155 | } |
||
156 | |||
157 | 10 | if (!is_int($current_page) && (!is_string($current_page) || !ctype_digit($current_page))) { |
|
158 | 2 | throw IncorrectPageNumberException::incorrect($current_page); |
|
159 | } |
||
160 | |||
161 | 8 | if ($current_page < 1 || $current_page > $total_pages) { |
|
162 | 5 | throw OutOfRangeException::out((int) $current_page, $total_pages); |
|
163 | } |
||
164 | |||
165 | 3 | return (int) $current_page; |
|
166 | } |
||
167 | |||
168 | /** |
||
169 | * @param Request $request |
||
170 | * @param Configuration $configuration |
||
171 | * @param string $parameter_name |
||
172 | * @param int $reference_type |
||
173 | * |
||
174 | * @return Configuration |
||
175 | */ |
||
176 | 2 | private function configureFromRequest( |
|
195 | } |
||
196 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.