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:
Complex classes like AbstractRouteRepository 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 AbstractRouteRepository, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 33 | abstract class AbstractRouteRepository extends SortableRepository |
||
| 34 | { |
||
| 35 | /** |
||
| 36 | * @var string The main entity class |
||
| 37 | */ |
||
| 38 | protected $mainEntityClass = 'Zikula\RoutesModule\Entity\RouteEntity'; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var string The default sorting field/expression |
||
| 42 | */ |
||
| 43 | protected $defaultSortingField = 'sort'; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var CollectionFilterHelper |
||
| 47 | */ |
||
| 48 | protected $collectionFilterHelper = null; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Retrieves an array with all fields which can be used for sorting instances. |
||
| 52 | * |
||
| 53 | * @return array Sorting fields array |
||
| 54 | */ |
||
| 55 | public function getAllowedSortingFields() |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Returns the default sorting field. |
||
| 83 | * |
||
| 84 | * @return string |
||
| 85 | */ |
||
| 86 | public function getDefaultSortingField() |
||
| 90 | |||
| 91 | /** |
||
| 92 | * Sets the default sorting field. |
||
| 93 | * |
||
| 94 | * @param string $defaultSortingField |
||
| 95 | * |
||
| 96 | * @return void |
||
| 97 | */ |
||
| 98 | public function setDefaultSortingField($defaultSortingField) |
||
| 104 | |||
| 105 | /** |
||
| 106 | * Returns the collection filter helper. |
||
| 107 | * |
||
| 108 | * @return CollectionFilterHelper |
||
| 109 | */ |
||
| 110 | public function getCollectionFilterHelper() |
||
| 114 | |||
| 115 | /** |
||
| 116 | * Sets the collection filter helper. |
||
| 117 | * |
||
| 118 | * @param CollectionFilterHelper $collectionFilterHelper |
||
| 119 | * |
||
| 120 | * @return void |
||
| 121 | */ |
||
| 122 | public function setCollectionFilterHelper($collectionFilterHelper) |
||
| 128 | |||
| 129 | |||
| 130 | /** |
||
| 131 | * Updates the creator of all objects created by a certain user. |
||
| 132 | * |
||
| 133 | * @param integer $userId The userid of the creator to be replaced |
||
| 134 | * @param integer $newUserId The new userid of the creator as replacement |
||
| 135 | * @param TranslatorInterface $translator Translator service instance |
||
| 136 | * @param LoggerInterface $logger Logger service instance |
||
| 137 | * @param CurrentUserApiInterface $currentUserApi CurrentUserApi service instance |
||
| 138 | * |
||
| 139 | * @return void |
||
| 140 | * |
||
| 141 | * @throws InvalidArgumentException Thrown if invalid parameters are received |
||
| 142 | */ |
||
| 143 | View Code Duplication | public function updateCreator($userId, $newUserId, TranslatorInterface $translator, LoggerInterface $logger, CurrentUserApiInterface $currentUserApi) |
|
| 162 | |||
| 163 | /** |
||
| 164 | * Updates the last editor of all objects updated by a certain user. |
||
| 165 | * |
||
| 166 | * @param integer $userId The userid of the last editor to be replaced |
||
| 167 | * @param integer $newUserId The new userid of the last editor as replacement |
||
| 168 | * @param TranslatorInterface $translator Translator service instance |
||
| 169 | * @param LoggerInterface $logger Logger service instance |
||
| 170 | * @param CurrentUserApiInterface $currentUserApi CurrentUserApi service instance |
||
| 171 | * |
||
| 172 | * @return void |
||
| 173 | * |
||
| 174 | * @throws InvalidArgumentException Thrown if invalid parameters are received |
||
| 175 | */ |
||
| 176 | View Code Duplication | public function updateLastEditor($userId, $newUserId, TranslatorInterface $translator, LoggerInterface $logger, CurrentUserApiInterface $currentUserApi) |
|
| 195 | |||
| 196 | /** |
||
| 197 | * Deletes all objects created by a certain user. |
||
| 198 | * |
||
| 199 | * @param integer $userId The userid of the creator to be removed |
||
| 200 | * @param TranslatorInterface $translator Translator service instance |
||
| 201 | * @param LoggerInterface $logger Logger service instance |
||
| 202 | * @param CurrentUserApiInterface $currentUserApi CurrentUserApi service instance |
||
| 203 | * |
||
| 204 | * @return void |
||
| 205 | * |
||
| 206 | * @throws InvalidArgumentException Thrown if invalid parameters are received |
||
| 207 | */ |
||
| 208 | View Code Duplication | public function deleteByCreator($userId, TranslatorInterface $translator, LoggerInterface $logger, CurrentUserApiInterface $currentUserApi) |
|
| 225 | |||
| 226 | /** |
||
| 227 | * Deletes all objects updated by a certain user. |
||
| 228 | * |
||
| 229 | * @param integer $userId The userid of the last editor to be removed |
||
| 230 | * @param TranslatorInterface $translator Translator service instance |
||
| 231 | * @param LoggerInterface $logger Logger service instance |
||
| 232 | * @param CurrentUserApiInterface $currentUserApi CurrentUserApi service instance |
||
| 233 | * |
||
| 234 | * @return void |
||
| 235 | * |
||
| 236 | * @throws InvalidArgumentException Thrown if invalid parameters are received |
||
| 237 | */ |
||
| 238 | View Code Duplication | public function deleteByLastEditor($userId, TranslatorInterface $translator, LoggerInterface $logger, CurrentUserApiInterface $currentUserApi) |
|
| 255 | |||
| 256 | /** |
||
| 257 | * Adds an array of id filters to given query instance. |
||
| 258 | * |
||
| 259 | * @param array $idList The array of ids to use to retrieve the object |
||
| 260 | * @param QueryBuilder $qb Query builder to be enhanced |
||
| 261 | * |
||
| 262 | * @return QueryBuilder Enriched query builder instance |
||
| 263 | * |
||
| 264 | * @throws InvalidArgumentException Thrown if invalid parameters are received |
||
| 265 | */ |
||
| 266 | protected function addIdListFilter($idList, QueryBuilder $qb) |
||
| 283 | |||
| 284 | /** |
||
| 285 | * Selects an object from the database. |
||
| 286 | * |
||
| 287 | * @param mixed $id The id (or array of ids) to use to retrieve the object (optional) (default=0) |
||
| 288 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 289 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 290 | * |
||
| 291 | * @return array|routeEntity Retrieved data array or routeEntity instance |
||
| 292 | */ |
||
| 293 | public function selectById($id = 0, $useJoins = true, $slimMode = false) |
||
| 299 | |||
| 300 | /** |
||
| 301 | * Selects a list of objects with an array of ids |
||
| 302 | * |
||
| 303 | * @param mixed $idList The array of ids to use to retrieve the objects (optional) (default=0) |
||
| 304 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 305 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 306 | * |
||
| 307 | * @return ArrayCollection Collection containing retrieved routeEntity instances |
||
| 308 | */ |
||
| 309 | public function selectByIdList($idList = [0], $useJoins = true, $slimMode = false) |
||
| 320 | |||
| 321 | /** |
||
| 322 | * Adds where clauses excluding desired identifiers from selection. |
||
| 323 | * |
||
| 324 | * @param QueryBuilder $qb Query builder to be enhanced |
||
| 325 | * @param array $excludesions Array of ids to be excluded from selection |
||
| 326 | * |
||
| 327 | * @return QueryBuilder Enriched query builder instance |
||
| 328 | */ |
||
| 329 | protected function addExclusion(QueryBuilder $qb, array $exclusions = []) |
||
| 338 | |||
| 339 | /** |
||
| 340 | * Returns query builder for selecting a list of objects with a given where clause. |
||
| 341 | * |
||
| 342 | * @param string $where The where clause to use when retrieving the collection (optional) (default='') |
||
| 343 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 344 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 345 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 346 | * |
||
| 347 | * @return QueryBuilder Query builder for the given arguments |
||
| 348 | */ |
||
| 349 | public function getListQueryBuilder($where = '', $orderBy = '', $useJoins = true, $slimMode = false) |
||
| 358 | |||
| 359 | /** |
||
| 360 | * Selects a list of objects with a given where clause. |
||
| 361 | * |
||
| 362 | * @param string $where The where clause to use when retrieving the collection (optional) (default='') |
||
| 363 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 364 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 365 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 366 | * |
||
| 367 | * @return ArrayCollection Collection containing retrieved routeEntity instances |
||
| 368 | */ |
||
| 369 | View Code Duplication | public function selectWhere($where = '', $orderBy = '', $useJoins = true, $slimMode = false) |
|
| 377 | |||
| 378 | /** |
||
| 379 | * Returns query builder instance for retrieving a list of objects with a given where clause and pagination parameters. |
||
| 380 | * |
||
| 381 | * @param QueryBuilder $qb Query builder to be enhanced |
||
| 382 | * @param integer $currentPage Where to start selection |
||
| 383 | * @param integer $resultsPerPage Amount of items to select |
||
| 384 | * |
||
| 385 | * @return Query Created query instance |
||
| 386 | */ |
||
| 387 | public function getSelectWherePaginatedQuery(QueryBuilder $qb, $currentPage = 1, $resultsPerPage = 25) |
||
| 397 | |||
| 398 | /** |
||
| 399 | * Selects a list of objects with a given where clause and pagination parameters. |
||
| 400 | * |
||
| 401 | * @param string $where The where clause to use when retrieving the collection (optional) (default='') |
||
| 402 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 403 | * @param integer $currentPage Where to start selection |
||
| 404 | * @param integer $resultsPerPage Amount of items to select |
||
| 405 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 406 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 407 | * |
||
| 408 | * @return array Retrieved collection and amount of total records affected by this query |
||
| 409 | */ |
||
| 410 | View Code Duplication | public function selectWherePaginated($where = '', $orderBy = '', $currentPage = 1, $resultsPerPage = 25, $useJoins = true, $slimMode = false) |
|
| 417 | |||
| 418 | /** |
||
| 419 | * Selects entities by a given search fragment. |
||
| 420 | * |
||
| 421 | * @param string $fragment The fragment to search for |
||
| 422 | * @param array $exclude List with identifiers to be excluded from search |
||
| 423 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 424 | * @param integer $currentPage Where to start selection |
||
| 425 | * @param integer $resultsPerPage Amount of items to select |
||
| 426 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 427 | * |
||
| 428 | * @return array Retrieved collection and amount of total records affected by this query |
||
| 429 | */ |
||
| 430 | public function selectSearch($fragment = '', $exclude = [], $orderBy = '', $currentPage = 1, $resultsPerPage = 25, $useJoins = true) |
||
| 445 | |||
| 446 | /** |
||
| 447 | * Performs a given database selection and post-processed the results. |
||
| 448 | * |
||
| 449 | * @param Query $query The Query instance to be executed |
||
| 450 | * @param boolean $isPaginated Whether the given query uses a paginator or not (optional) (default=false) |
||
| 451 | * |
||
| 452 | * @return array Retrieved collection and (for paginated queries) the amount of total records affected |
||
| 453 | */ |
||
| 454 | public function retrieveCollectionResult(Query $query, $isPaginated = false) |
||
| 472 | |||
| 473 | /** |
||
| 474 | * Returns query builder instance for a count query. |
||
| 475 | * |
||
| 476 | * @param string $where The where clause to use when retrieving the object count (optional) (default='') |
||
| 477 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=false) |
||
| 478 | * |
||
| 479 | * @return QueryBuilder Created query builder instance |
||
| 480 | */ |
||
| 481 | public function getCountQuery($where = '', $useJoins = false) |
||
| 502 | |||
| 503 | /** |
||
| 504 | * Selects entity count with a given where clause. |
||
| 505 | * |
||
| 506 | * @param string $where The where clause to use when retrieving the object count (optional) (default='') |
||
| 507 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=false) |
||
| 508 | * @param array $parameters List of determined filter options |
||
| 509 | * |
||
| 510 | * @return integer Amount of affected records |
||
| 511 | */ |
||
| 512 | public function selectCount($where = '', $useJoins = false, $parameters = []) |
||
| 524 | |||
| 525 | |||
| 526 | /** |
||
| 527 | * Checks for unique values. |
||
| 528 | * |
||
| 529 | * @param string $fieldName The name of the property to be checked |
||
| 530 | * @param string $fieldValue The value of the property to be checked |
||
| 531 | * @param integer $excludeId Id of routes to exclude (optional) |
||
| 532 | * |
||
| 533 | * @return boolean Result of this check, true if the given route does not already exist |
||
| 534 | */ |
||
| 535 | public function detectUniqueState($fieldName, $fieldValue, $excludeId = 0) |
||
| 551 | |||
| 552 | /** |
||
| 553 | * Builds a generic Doctrine query supporting WHERE and ORDER BY. |
||
| 554 | * |
||
| 555 | * @param string $where The where clause to use when retrieving the collection (optional) (default='') |
||
| 556 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 557 | * @param boolean $useJoins Whether to include joining related objects (optional) (default=true) |
||
| 558 | * @param boolean $slimMode If activated only some basic fields are selected without using any joins (optional) (default=false) |
||
| 559 | * |
||
| 560 | * @return QueryBuilder Query builder instance to be further processed |
||
| 561 | */ |
||
| 562 | public function genericBaseQuery($where = '', $orderBy = '', $useJoins = true, $slimMode = false) |
||
| 596 | |||
| 597 | /** |
||
| 598 | * Adds ORDER BY clause to given query builder. |
||
| 599 | * |
||
| 600 | * @param QueryBuilder $qb Given query builder instance |
||
| 601 | * @param string $orderBy The order-by clause to use when retrieving the collection (optional) (default='') |
||
| 602 | * |
||
| 603 | * @return QueryBuilder Query builder instance to be further processed |
||
| 604 | */ |
||
| 605 | protected function genericBaseQueryAddOrderBy(QueryBuilder $qb, $orderBy = '') |
||
| 641 | |||
| 642 | /** |
||
| 643 | * Retrieves Doctrine query from query builder. |
||
| 644 | * |
||
| 645 | * @param QueryBuilder $qb Query builder instance |
||
| 646 | * |
||
| 647 | * @return Query Query instance to be further processed |
||
| 648 | */ |
||
| 649 | public function getQueryFromBuilder(QueryBuilder $qb) |
||
| 655 | |||
| 656 | /** |
||
| 657 | * Helper method to add join selections. |
||
| 658 | * |
||
| 659 | * @return String Enhancement for select clause |
||
| 660 | */ |
||
| 661 | protected function addJoinsToSelection() |
||
| 667 | |||
| 668 | /** |
||
| 669 | * Helper method to add joins to from clause. |
||
| 670 | * |
||
| 671 | * @param QueryBuilder $qb Query builder instance used to create the query |
||
| 672 | * |
||
| 673 | * @return QueryBuilder The query builder enriched by additional joins |
||
| 674 | */ |
||
| 675 | protected function addJoinsToFrom(QueryBuilder $qb) |
||
| 680 | } |
||
| 681 |
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.