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 |
||
| 32 | class QueryOperations { |
||
| 33 | |||
| 34 | /** |
||
| 35 | * |
||
| 36 | * @var RecordWrapper |
||
| 37 | */ |
||
| 38 | private $wrapper; |
||
| 39 | private $adapter; |
||
| 40 | private $queryParameters; |
||
| 41 | private $pendingMethod; |
||
| 42 | private $dynamicMethods = [ |
||
| 43 | "/(?<method>filterBy)(?<variable>[A-Z][A-Za-z]+){1}/", |
||
| 44 | "/(?<method>sort)(?<direction>Asc|Desc)?(By)(?<variable>[A-Z][A-Za-z]+){1}/", |
||
| 45 | "/(?<method>fetch)(?<first>First)?(With)(?<variable>[A-Za-z]+)/" |
||
| 46 | ]; |
||
| 47 | private $dataOperations; |
||
| 48 | private $driver; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * |
||
| 52 | * @param RecordWrapper $wrapper |
||
| 53 | * @param DriverAdapter $adapter |
||
|
|
|||
| 54 | * @param DataOperations $dataOperations |
||
| 55 | */ |
||
| 56 | 34 | public function __construct(RecordWrapper $wrapper, DataOperations $dataOperations, Driver $driver) { |
|
| 57 | 34 | $this->wrapper = $wrapper; |
|
| 58 | 34 | $this->adapter = $wrapper->getAdapter(); |
|
| 59 | 34 | $this->dataOperations = $dataOperations; |
|
| 60 | 34 | $this->driver = $driver; |
|
| 61 | 34 | } |
|
| 62 | |||
| 63 | 24 | public function doFetch($id = null) { |
|
| 64 | 24 | $parameters = $this->getFetchQueryParameters($id); |
|
| 65 | 24 | $data = $this->adapter->select($parameters); |
|
| 66 | 24 | $this->wrapper->setData($data); |
|
| 67 | 24 | $this->resetQueryParameters(); |
|
| 68 | 24 | return $this->wrapper; |
|
| 69 | } |
||
| 70 | |||
| 71 | 26 | private function getFetchQueryParameters($arg, $instantiate = true) { |
|
| 72 | 26 | if ($arg instanceof \ntentan\nibii\QueryParameters) { |
|
| 73 | 12 | return $arg; |
|
| 74 | } |
||
| 75 | |||
| 76 | 26 | $parameters = $this->getQueryParameters($instantiate); |
|
| 77 | |||
| 78 | 26 | if (is_numeric($arg)) { |
|
| 79 | 6 | $description = $this->wrapper->getDescription(); |
|
| 80 | 6 | $parameters->addFilter($description->getPrimaryKey()[0], $arg); |
|
| 81 | 6 | $parameters->setFirstOnly(true); |
|
| 82 | 22 | } else if (is_array($arg)) { |
|
| 83 | 6 | foreach ($arg as $field => $value) { |
|
| 84 | 6 | $parameters->addFilter($field, $value); |
|
| 85 | } |
||
| 86 | } |
||
| 87 | |||
| 88 | 26 | return $parameters; |
|
| 89 | } |
||
| 90 | |||
| 91 | /** |
||
| 92 | * |
||
| 93 | * @return \ntentan\nibii\QueryParameters |
||
| 94 | */ |
||
| 95 | 32 | private function getQueryParameters($instantiate = true) { |
|
| 96 | 32 | if ($this->queryParameters === null && $instantiate) { |
|
| 97 | 32 | $this->queryParameters = new QueryParameters($this->wrapper->getDBStoreInformation()['quoted_table']); |
|
| 98 | } |
||
| 99 | 32 | return $this->queryParameters; |
|
| 100 | } |
||
| 101 | |||
| 102 | 32 | private function resetQueryParameters() { |
|
| 103 | 32 | $this->queryParameters = null; |
|
| 104 | 32 | } |
|
| 105 | |||
| 106 | 10 | public function doFetchFirst($id = null) { |
|
| 107 | 10 | $this->getQueryParameters()->setFirstOnly(true); |
|
| 108 | 10 | return $this->doFetch($id); |
|
| 109 | } |
||
| 110 | |||
| 111 | 12 | public function doFields() { |
|
| 112 | 12 | $fields = []; |
|
| 113 | 12 | $arguments = func_get_args(); |
|
| 114 | 12 | foreach ($arguments as $argument) { |
|
| 115 | 12 | if (is_array($argument)) { |
|
| 116 | 6 | $fields = array_merge($fields, $argument); |
|
| 117 | } else { |
||
| 118 | 12 | $fields[] = $argument; |
|
| 119 | } |
||
| 120 | } |
||
| 121 | 12 | $this->getQueryParameters()->setFields($fields); |
|
| 122 | 12 | return $this->wrapper; |
|
| 123 | } |
||
| 124 | |||
| 125 | public function doSortBy($field, $direction = 'ASC') { |
||
| 126 | $this->getQueryParameters()->addSort($field, $direction); |
||
| 127 | } |
||
| 128 | |||
| 129 | 10 | private function getFilter($arguments) { |
|
| 130 | 10 | if (count($arguments) == 2 && is_array($arguments[1])) { |
|
| 131 | 2 | $filter = $arguments[0]; |
|
| 132 | 2 | $data = $arguments[1]; |
|
| 133 | } else { |
||
| 134 | 10 | $filter = array_shift($arguments); |
|
| 135 | 10 | $data = $arguments; |
|
| 136 | } |
||
| 137 | 10 | return ['filter' => $filter, 'data' => $data]; |
|
| 138 | } |
||
| 139 | |||
| 140 | 6 | View Code Duplication | public function doFilter() { |
| 141 | 6 | $arguments = func_get_args(); |
|
| 142 | 6 | $details = $this->getFilter($arguments); |
|
| 143 | 6 | $this->getQueryParameters()->setFilter($details['filter'], $details['data']); |
|
| 144 | 6 | return $this->wrapper; |
|
| 145 | } |
||
| 146 | |||
| 147 | 4 | View Code Duplication | public function doFilterBy() { |
| 148 | 4 | $arguments = func_get_args(); |
|
| 149 | 4 | $details = $this->getFilter($arguments); |
|
| 150 | 4 | $this->getQueryParameters()->addFilter($details['filter'], $details['data']); |
|
| 151 | 4 | return $this->wrapper; |
|
| 152 | } |
||
| 153 | |||
| 154 | 6 | public function doUpdate($data) { |
|
| 161 | |||
| 162 | 2 | public function doDelete($args = null) { |
|
| 163 | 2 | $this->driver->beginTransaction(); |
|
| 164 | 2 | $parameters = $this->getFetchQueryParameters($args); |
|
| 165 | |||
| 166 | 2 | if ($parameters === null) { |
|
| 167 | $primaryKey = $this->wrapper->getDescription()->getPrimaryKey(); |
||
| 168 | $parameters = $this->getQueryParameters(); |
||
| 169 | $data = $this->wrapper->getData(); |
||
| 170 | $keys = []; |
||
| 171 | |||
| 172 | foreach ($data as $datum) { |
||
| 187 | |||
| 188 | 10 | public function runDynamicMethod($arguments) { |
|
| 206 | |||
| 207 | 10 | public function initDynamicMethod($method) { |
|
| 220 | |||
| 221 | public function doCount() { |
||
| 224 | |||
| 225 | public function doLimit($numItems) { |
||
| 229 | |||
| 230 | public function doOffset($offset) { |
||
| 234 | |||
| 235 | public function doWith($model) { |
||
| 239 | |||
| 240 | } |
||
| 241 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.
Consider the following example. The parameter
$italyis not defined by the methodfinale(...).The most likely cause is that the parameter was removed, but the annotation was not.