Complex classes like QueryCompiler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use QueryCompiler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class QueryCompiler |
||
24 | { |
||
25 | /** |
||
26 | * Query types for parameter ordering. |
||
27 | */ |
||
28 | const SELECT_QUERY = 'select'; |
||
29 | const UPDATE_QUERY = 'update'; |
||
30 | const DELETE_QUERY = 'delete'; |
||
31 | const INSERT_QUERY = 'insert'; |
||
32 | |||
33 | /** |
||
34 | * Quotes names and expressions. |
||
35 | * |
||
36 | * @var Quoter |
||
37 | */ |
||
38 | private $quoter = null; |
||
39 | |||
40 | /** |
||
41 | * QueryCompiler constructor. |
||
42 | * |
||
43 | * @param Quoter $quoter |
||
44 | */ |
||
45 | public function __construct(Quoter $quoter) |
||
49 | |||
50 | /** |
||
51 | * Prefix associated with compiler. |
||
52 | * |
||
53 | * @return string |
||
54 | */ |
||
55 | public function getPrefix(): string |
||
59 | |||
60 | /** |
||
61 | * Reset table aliases cache, required if same compiler used twice. |
||
62 | * |
||
63 | * @return self |
||
64 | */ |
||
65 | public function resetQuoter(): QueryCompiler |
||
71 | |||
72 | /** |
||
73 | * Query query identifier, if identified stated as table - table prefix must be added. |
||
74 | * |
||
75 | * @param string $identifier Identifier can include simple column operations and functions, |
||
76 | * having "." in it will automatically force table prefix to first |
||
77 | * value. |
||
78 | * @param bool $isTable Set to true to let quote method know that identified is related |
||
79 | * to table name. |
||
80 | * |
||
81 | * @return string |
||
82 | */ |
||
83 | public function quote(string $identifier, bool $isTable = false): string |
||
91 | |||
92 | /** |
||
93 | * Sort list of parameters in dbms query specific order, query type must be provided. This |
||
94 | * method was used at times when delete and update queries supported joins, i might need to |
||
95 | * drop it now. |
||
96 | * |
||
97 | * @param string $queryType |
||
98 | * @param array $whereParameters |
||
99 | * @param array $onParameters |
||
100 | * @param array $havingParameters |
||
101 | * @param array $columnIdentifiers Column names (if any). |
||
102 | * |
||
103 | * @return array |
||
104 | */ |
||
105 | public function orderParameters( |
||
114 | |||
115 | /** |
||
116 | * Create insert query using table names, columns and rowsets. Must support both - single and |
||
117 | * batch inserts. |
||
118 | * |
||
119 | * @param string $table |
||
120 | * @param array $columns |
||
121 | * @param FragmentInterface[] $rowsets Every rowset has to be convertable into string. Raw data |
||
122 | * not allowed! |
||
123 | * |
||
124 | * @return string |
||
125 | * |
||
126 | * @throws CompilerException |
||
127 | */ |
||
128 | public function compileInsert(string $table, array $columns, array $rowsets): string |
||
153 | |||
154 | /** |
||
155 | * Create update statement. |
||
156 | * |
||
157 | * @param string $table |
||
158 | * @param array $updates |
||
159 | * @param array $whereTokens |
||
160 | * |
||
161 | * @return string |
||
162 | * |
||
163 | * @throws CompilerException |
||
164 | */ |
||
165 | public function compileUpdate(string $table, array $updates, array $whereTokens = []): string |
||
177 | |||
178 | /** |
||
179 | * Create delete statement. |
||
180 | * |
||
181 | * @param string $table |
||
182 | * @param array $whereTokens |
||
183 | * |
||
184 | * @return string |
||
185 | * |
||
186 | * @throws CompilerException |
||
187 | */ |
||
188 | public function compileDelete(string $table, array $whereTokens = []): string |
||
197 | |||
198 | /** |
||
199 | * Create select statement. Compiler must validly resolve table and column aliases used in |
||
200 | * conditions and joins. |
||
201 | * |
||
202 | * @param array $fromTables |
||
203 | * @param bool|string $distinct String only for PostgresSQL. |
||
204 | * @param array $columns |
||
205 | * @param array $joinTokens |
||
206 | * @param array $whereTokens |
||
207 | * @param array $havingTokens |
||
208 | * @param array $grouping |
||
209 | * @param array $ordering |
||
210 | * @param int $limit |
||
211 | * @param int $offset |
||
212 | * @param array $unionTokens |
||
213 | * |
||
214 | * @return string |
||
215 | * |
||
216 | * @throws CompilerException |
||
217 | */ |
||
218 | public function compileSelect( |
||
260 | |||
261 | /** |
||
262 | * Quote and wrap column identifiers (used in insert statement compilation). |
||
263 | * |
||
264 | * @param array $columnIdentifiers |
||
265 | * @param int $maxLength Automatically wrap columns. |
||
266 | * |
||
267 | * @return string |
||
268 | */ |
||
269 | protected function prepareColumns(array $columnIdentifiers, int $maxLength = 180): string |
||
276 | |||
277 | /** |
||
278 | * Prepare column values to be used in UPDATE statement. |
||
279 | * |
||
280 | * @param array $updates |
||
281 | * |
||
282 | * @return string |
||
283 | */ |
||
284 | protected function prepareUpdates(array $updates): string |
||
301 | |||
302 | /** |
||
303 | * Compile DISTINCT statement. |
||
304 | * |
||
305 | * @param mixed $distinct Not every DBMS support distinct expression, only Postgres does. |
||
306 | * |
||
307 | * @return string |
||
308 | */ |
||
309 | protected function compileDistinct($distinct): string |
||
317 | |||
318 | /** |
||
319 | * Compile table names statement. |
||
320 | * |
||
321 | * @param array $tables |
||
322 | * |
||
323 | * @return string |
||
324 | */ |
||
325 | protected function compileTables(array $tables): string |
||
334 | |||
335 | /** |
||
336 | * Compiler joins statement. |
||
337 | * |
||
338 | * @param array $joinTokens |
||
339 | * |
||
340 | * @return string |
||
341 | */ |
||
342 | protected function compileJoins(array $joinTokens): string |
||
352 | |||
353 | /** |
||
354 | * Compile union statement chunk. Keywords UNION and ALL will be included, this methods will |
||
355 | * automatically move every union on new line. |
||
356 | * |
||
357 | * @param array $unionTokens |
||
358 | * |
||
359 | * @return string |
||
360 | */ |
||
361 | protected function compileUnions(array $unionTokens): string |
||
375 | |||
376 | /** |
||
377 | * Compile ORDER BY statement. |
||
378 | * |
||
379 | * @param array $ordering |
||
380 | * |
||
381 | * @return string |
||
382 | */ |
||
383 | protected function compileOrdering(array $ordering): string |
||
392 | |||
393 | /** |
||
394 | * Compiler GROUP BY statement. |
||
395 | * |
||
396 | * @param array $grouping |
||
397 | * |
||
398 | * @return string |
||
399 | */ |
||
400 | protected function compileGrouping(array $grouping): string |
||
409 | |||
410 | /** |
||
411 | * Compile limit statement. |
||
412 | * |
||
413 | * @param int $limit |
||
414 | * @param int $offset |
||
415 | * |
||
416 | * @return string |
||
417 | */ |
||
418 | protected function compileLimit(int $limit, int $offset): string |
||
435 | |||
436 | /** |
||
437 | * Compile where statement. |
||
438 | * |
||
439 | * @param array $tokens |
||
440 | * |
||
441 | * @return string |
||
442 | * |
||
443 | * @throws CompilerException |
||
444 | */ |
||
445 | protected function compileWhere(array $tokens): string |
||
532 | |||
533 | /** |
||
534 | * Combine expression with prefix/postfix (usually SQL keyword) but only if expression is not |
||
535 | * empty. |
||
536 | * |
||
537 | * @param string $prefix |
||
538 | * @param string $expression |
||
539 | * @param string $postfix |
||
540 | * |
||
541 | * @return string |
||
542 | */ |
||
543 | protected function optional(string $prefix, string $expression, string $postfix = ''): string |
||
555 | |||
556 | /** |
||
557 | * Resolve operator value based on value value. ;). |
||
558 | * |
||
559 | * @param mixed $parameter |
||
560 | * @param string $operator |
||
561 | * |
||
562 | * @return string |
||
563 | */ |
||
564 | protected function prepareOperator($parameter, string $operator): string |
||
583 | |||
584 | /** |
||
585 | * Prepare value to be replaced into query (replace ?). |
||
586 | * |
||
587 | * @param mixed $value |
||
588 | * |
||
589 | * @return string |
||
590 | */ |
||
591 | protected function prepareValue($value): string |
||
600 | |||
601 | /** |
||
602 | * Prepare where fragment to be injected into statement. |
||
603 | * |
||
604 | * @param FragmentInterface $context |
||
605 | * |
||
606 | * @return string |
||
607 | */ |
||
608 | protected function prepareFragment(FragmentInterface $context): string |
||
622 | } |
||
623 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.