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 |
||
| 41 | class CirclesMapper extends Mapper { |
||
| 42 | |||
| 43 | const TABLENAME = 'circles_circles'; |
||
| 44 | |||
| 45 | /** @var L10N */ |
||
| 46 | private $l10n; |
||
| 47 | |||
| 48 | /** @var MiscService */ |
||
| 49 | private $miscService; |
||
| 50 | |||
| 51 | public function __construct(IDBConnection $db, $l10n, $miscService) { |
||
| 56 | |||
| 57 | |||
| 58 | /** |
||
| 59 | * Returns all circle from a user point-of-view |
||
| 60 | * |
||
| 61 | * @param $userId |
||
| 62 | * @param $type |
||
| 63 | * @param string $name |
||
| 64 | * @param int $level |
||
| 65 | * @param int $circleId |
||
| 66 | * |
||
| 67 | * @return Circle[] |
||
| 68 | * @throws ConfigNoCircleAvailable |
||
| 69 | */ |
||
| 70 | public function findCirclesByUser($userId, $type, $name = '', $level = 0, $circleId = -1) { |
||
| 71 | |||
| 72 | $type = (int)$type; |
||
| 73 | $level = (int)$level; |
||
| 74 | $circleId = (int)$circleId; |
||
| 75 | $qb = $this->findCirclesByUserSql($userId, $type, $name, $level, $circleId); |
||
| 76 | $cursor = $qb->execute(); |
||
| 77 | |||
| 78 | $result = []; |
||
| 79 | while ($data = $cursor->fetch()) { |
||
| 80 | if ($name === '' || stripos($data['name'], $name) !== false) { |
||
| 81 | $circle = new Circle($this->l10n); |
||
| 82 | $result[] = $circle->fromArray($data); |
||
| 83 | } |
||
| 84 | } |
||
| 85 | $cursor->closeCursor(); |
||
| 86 | |||
| 87 | return $result; |
||
| 88 | } |
||
| 89 | |||
| 90 | |||
| 91 | /** |
||
| 92 | * Returns SQL for findCirclesByUser |
||
| 93 | * |
||
| 94 | * @param $userId |
||
| 95 | * @param $type |
||
| 96 | * @param $name |
||
| 97 | * @param $level |
||
| 98 | * @param $circleId |
||
| 99 | * |
||
| 100 | * @return IQueryBuilder |
||
| 101 | * @throws ConfigNoCircleAvailable |
||
| 102 | */ |
||
| 103 | private function findCirclesByUserSql($userId, $type, $name, $level, $circleId) { |
||
| 104 | $qb = $this->db->getQueryBuilder(); |
||
| 105 | $expr = $qb->expr(); |
||
| 106 | |||
| 107 | /** @noinspection PhpMethodParametersCountMismatchInspection */ |
||
| 108 | $qb->select( |
||
| 109 | 'c.id', 'c.name', 'c.description', 'c.type', 'c.creation', |
||
| 110 | 'u.joined', 'u.level', 'u.status' |
||
| 111 | ) |
||
| 112 | ->selectAlias('o.user_id', 'owner') |
||
| 113 | ->from(self::TABLENAME, 'c') |
||
| 114 | ->from(MembersMapper::TABLENAME, 'o') |
||
| 115 | ->where( |
||
| 116 | $expr->eq('c.id', 'o.circle_id'), |
||
| 117 | $expr->eq('o.level', $qb->createNamedParameter(Member::LEVEL_OWNER)) |
||
| 118 | ) |
||
| 119 | ->leftJoin( |
||
| 120 | 'c', MembersMapper::TABLENAME, 'u', |
||
| 121 | $expr->andX( |
||
| 122 | $expr->eq('c.id', 'u.circle_id'), |
||
| 123 | $expr->eq('u.user_id', $qb->createNamedParameter($userId)) |
||
| 124 | ) |
||
| 125 | ); |
||
| 126 | |||
| 127 | $this->buildWithMemberLevel($qb, 'u.level', $level); |
||
| 128 | $this->buildWithCircleId($qb, 'c.id', $circleId); |
||
| 129 | $this->buildWithOrXTypes($qb, $userId, $type, $name, $circleId); |
||
| 130 | |||
| 131 | // $qb->groupBy('c.id'); |
||
|
|
|||
| 132 | $qb->orderBy('c.name', 'ASC'); |
||
| 133 | |||
| 134 | return $qb; |
||
| 135 | } |
||
| 136 | |||
| 137 | |||
| 138 | /** |
||
| 139 | * @param IQueryBuilder $qb |
||
| 140 | * @param $userId |
||
| 141 | * @param $type |
||
| 142 | * @param $name |
||
| 143 | * @param $circleId |
||
| 144 | * |
||
| 145 | * @throws ConfigNoCircleAvailable |
||
| 146 | */ |
||
| 147 | private function buildWithOrXTypes(&$qb, $userId, $type, $name, $circleId) { |
||
| 167 | |||
| 168 | |||
| 169 | /** |
||
| 170 | * fill with sql conditions for each type of circles. |
||
| 171 | * |
||
| 172 | * @param $qb |
||
| 173 | * @param $userId |
||
| 174 | * @param $type |
||
| 175 | * @param $name |
||
| 176 | * @param $circleId |
||
| 177 | * |
||
| 178 | * @return array |
||
| 179 | */ |
||
| 180 | private function fillOrXTypes(&$qb, $userId, $type, $name, $circleId) { |
||
| 192 | |||
| 193 | /** |
||
| 194 | * @param IQueryBuilder $qb |
||
| 195 | * @param string $field |
||
| 196 | * @param int $circleId |
||
| 197 | */ |
||
| 198 | private function buildWithCircleId(IQueryBuilder & $qb, string $field, int $circleId) { |
||
| 206 | |||
| 207 | |||
| 208 | /** |
||
| 209 | * @param IQueryBuilder $qb |
||
| 210 | * @param string $field |
||
| 211 | * @param int $level |
||
| 212 | */ |
||
| 213 | private function buildWithMemberLevel(IQueryBuilder & $qb, string $field, int $level) { |
||
| 221 | |||
| 222 | |||
| 223 | /** |
||
| 224 | * @param IQueryBuilder $qb |
||
| 225 | * @param int $type |
||
| 226 | * @param int|string $userId |
||
| 227 | * |
||
| 228 | * @return \OCP\DB\QueryBuilder\ICompositeExpression |
||
| 229 | */ |
||
| 230 | private function generateTypeEntryForCirclePersonal(IQueryBuilder $qb, int $type, string $userId |
||
| 246 | |||
| 247 | /** |
||
| 248 | * @param IQueryBuilder $qb |
||
| 249 | * @param int $type |
||
| 250 | * @param int $circleId |
||
| 251 | * @param string $name |
||
| 252 | * |
||
| 253 | * @return string |
||
| 254 | */ |
||
| 255 | private function generateTypeEntryForCircleHidden( |
||
| 277 | |||
| 278 | |||
| 279 | /** |
||
| 280 | * @param IQueryBuilder $qb |
||
| 281 | * @param int $type |
||
| 282 | * |
||
| 283 | * @return string |
||
| 284 | */ |
||
| 285 | View Code Duplication | private function generateTypeEntryForCirclePrivate(IQueryBuilder $qb, int $type) { |
|
| 296 | |||
| 297 | |||
| 298 | /** |
||
| 299 | * @param IQueryBuilder $qb |
||
| 300 | * @param int $type |
||
| 301 | * |
||
| 302 | * @return string |
||
| 303 | */ |
||
| 304 | View Code Duplication | private function generateTypeEntryForCirclePublic(IQueryBuilder $qb, int $type) { |
|
| 315 | |||
| 316 | /** |
||
| 317 | * Returns details about a circle. |
||
| 318 | * |
||
| 319 | * @param string $userId |
||
| 320 | * @param int $circleId |
||
| 321 | * |
||
| 322 | * @return Circle |
||
| 323 | * @throws CircleDoesNotExistException |
||
| 324 | * @throws ConfigNoCircleAvailable |
||
| 325 | */ |
||
| 326 | public function getDetailsFromCircle($circleId, $userId) { |
||
| 342 | |||
| 343 | |||
| 344 | /** |
||
| 345 | * @param $circleName |
||
| 346 | * |
||
| 347 | * @return Circle|null |
||
| 348 | */ |
||
| 349 | public function getDetailsFromCircleByName($circleName) { |
||
| 370 | |||
| 371 | |||
| 372 | /** |
||
| 373 | * @param Circle $circle |
||
| 374 | * @param Member $owner |
||
| 375 | * |
||
| 376 | * @return bool |
||
| 377 | * @throws CircleAlreadyExistsException |
||
| 378 | */ |
||
| 379 | public function create( |
||
| 406 | |||
| 407 | |||
| 408 | /** |
||
| 409 | * remove a circle |
||
| 410 | * |
||
| 411 | * @param int $circleId |
||
| 412 | * |
||
| 413 | * @internal param Circle $circle |
||
| 414 | */ |
||
| 415 | View Code Duplication | public function destroy( |
|
| 429 | |||
| 430 | |||
| 431 | /** |
||
| 432 | * returns if the circle is already in database |
||
| 433 | * |
||
| 434 | * @param Circle $circle |
||
| 435 | * @param Member $owner |
||
| 436 | * |
||
| 437 | * @return bool |
||
| 438 | */ |
||
| 439 | public function isCircleUnique( |
||
| 459 | |||
| 460 | |||
| 461 | /** |
||
| 462 | * Return SQL for isCircleUnique(); |
||
| 463 | * |
||
| 464 | * @return IQueryBuilder |
||
| 465 | */ |
||
| 466 | private function isCircleUniqueSql() { |
||
| 481 | |||
| 482 | |||
| 483 | /** |
||
| 484 | * return if the personal circle is unique |
||
| 485 | * |
||
| 486 | * @param Circle $circle |
||
| 487 | * @param Member $owner |
||
| 488 | * |
||
| 489 | * @return bool |
||
| 490 | */ |
||
| 491 | private function isPersonalCircleUnique( |
||
| 508 | } |
||
| 509 | |||
| 510 |
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.