Complex classes like ArticleDataProvider 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 ArticleDataProvider, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 36 | class ArticleDataProvider implements DataProviderInterface, AliasDataProviderInterface |
||
| 37 | { |
||
| 38 | /** |
||
| 39 | * @var Manager |
||
| 40 | */ |
||
| 41 | protected $searchManager; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var DocumentManagerInterface |
||
| 45 | */ |
||
| 46 | protected $documentManager; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @var LazyLoadingValueHolderFactory |
||
| 50 | */ |
||
| 51 | protected $proxyFactory; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * @var ReferenceStoreInterface |
||
| 55 | */ |
||
| 56 | private $referenceStore; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * @var string |
||
| 60 | */ |
||
| 61 | protected $articleDocumentClass; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * @var int |
||
| 65 | */ |
||
| 66 | protected $defaultLimit; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @param Manager $searchManager |
||
| 70 | * @param DocumentManagerInterface $documentManager |
||
| 71 | * @param LazyLoadingValueHolderFactory $proxyFactory |
||
| 72 | * @param ReferenceStoreInterface $referenceStore |
||
| 73 | * @param string $articleDocumentClass |
||
| 74 | * @param int $defaultLimit |
||
| 75 | 15 | */ |
|
| 76 | public function __construct( |
||
| 91 | |||
| 92 | /** |
||
| 93 | * {@inheritdoc} |
||
| 94 | */ |
||
| 95 | public function getConfiguration() |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Create new configuration-builder. |
||
| 102 | * |
||
| 103 | * @return BuilderInterface |
||
| 104 | */ |
||
| 105 | protected function getConfigurationBuilder() |
||
| 124 | |||
| 125 | /** |
||
| 126 | * {@inheritdoc} |
||
| 127 | */ |
||
| 128 | public function getDefaultPropertyParameter() |
||
| 132 | |||
| 133 | /** |
||
| 134 | * {@inheritdoc} |
||
| 135 | 11 | */ |
|
| 136 | public function resolveDataItems( |
||
| 159 | |||
| 160 | /** |
||
| 161 | * {@inheritdoc} |
||
| 162 | 2 | */ |
|
| 163 | public function resolveResourceItems( |
||
| 191 | |||
| 192 | /** |
||
| 193 | * {@inheritdoc} |
||
| 194 | */ |
||
| 195 | public function resolveDatasource($datasource, array $propertyParameter, array $options) |
||
| 199 | |||
| 200 | /** |
||
| 201 | * Returns flag "hasNextPage". |
||
| 202 | * It combines the limit/query-count with the page and page-size. |
||
| 203 | * |
||
| 204 | * @param \Countable $queryResult |
||
| 205 | * @param int $limit |
||
| 206 | * @param int $page |
||
| 207 | * @param int $pageSize |
||
| 208 | * |
||
| 209 | * @return bool |
||
| 210 | 13 | */ |
|
| 211 | private function hasNextPage(\Countable $queryResult, $limit, $page, $pageSize) |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Creates search for filters and returns search-result. |
||
| 223 | * |
||
| 224 | * @param array $filters |
||
| 225 | * @param int $limit |
||
| 226 | * @param int $page |
||
| 227 | * @param int $pageSize |
||
| 228 | * @param string $locale |
||
| 229 | * |
||
| 230 | * @return \Countable |
||
| 231 | 13 | */ |
|
| 232 | private function getSearchResult(array $filters, $limit, $page, $pageSize, $locale) |
||
| 249 | |||
| 250 | /** |
||
| 251 | * Initialize search with neccesary queries. |
||
| 252 | * |
||
| 253 | * @param Search $search |
||
| 254 | * @param array $filters |
||
| 255 | * @param string $locale |
||
| 256 | * |
||
| 257 | * @return Search |
||
| 258 | 12 | */ |
|
| 259 | protected function createSearch(Search $search, array $filters, $locale) |
||
| 300 | |||
| 301 | /** |
||
| 302 | * Returns array with all types defined in property parameter. |
||
| 303 | * |
||
| 304 | * @param array $propertyParameter |
||
| 305 | * |
||
| 306 | * @return array |
||
| 307 | 13 | */ |
|
| 308 | private function getTypesProperty($propertyParameter) |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Returns excluded articles. |
||
| 325 | * |
||
| 326 | * @param array $filters |
||
| 327 | * @param PropertyParameter[] $propertyParameter |
||
| 328 | * |
||
| 329 | * @return array |
||
| 330 | 13 | */ |
|
| 331 | private function getExcludedFilter(array $filters, array $propertyParameter) |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Extension point to append order. |
||
| 345 | * |
||
| 346 | * @param array $sortBy |
||
| 347 | * @param string $sortMethod |
||
| 348 | * @param Search $search |
||
| 349 | * |
||
| 350 | * @return array parameters for query |
||
| 351 | */ |
||
| 352 | private function appendSortBy($sortBy, $sortMethod, $search) |
||
| 358 | |||
| 359 | /** |
||
| 360 | * Add the pagination to given query. |
||
| 361 | * |
||
| 362 | * @param Search $search |
||
| 363 | * @param int $pageSize |
||
| 364 | * @param int $page |
||
| 365 | * @param int $limit |
||
| 366 | 13 | */ |
|
| 367 | private function addPagination(Search $search, $pageSize, $page, $limit) |
||
| 390 | |||
| 391 | /** |
||
| 392 | * Add a boolean-query if filter exists. |
||
| 393 | * |
||
| 394 | * @param string $filterName |
||
| 395 | * @param array $filters |
||
| 396 | * @param string $field |
||
| 397 | * @param string $operator |
||
| 398 | * @param BoolQuery $query |
||
| 399 | * @param int $queriesCount |
||
| 400 | 12 | */ |
|
| 401 | private function addBoolQuery($filterName, array $filters, $field, $operator, BoolQuery $query, &$queriesCount) |
||
| 408 | |||
| 409 | /** |
||
| 410 | * Returns boolean query for given fields and values. |
||
| 411 | * |
||
| 412 | * @param string $field |
||
| 413 | * @param array $values |
||
| 414 | * @param string $operator |
||
| 415 | * |
||
| 416 | * @return BoolQuery |
||
| 417 | */ |
||
| 418 | private function getBoolQuery($field, array $values, $operator) |
||
| 429 | |||
| 430 | /** |
||
| 431 | * Returns filter value. |
||
| 432 | * |
||
| 433 | * @param array $filters |
||
| 434 | * @param string $name |
||
| 435 | * @param mixed $default |
||
| 436 | * |
||
| 437 | * @return mixed |
||
| 438 | 12 | */ |
|
| 439 | private function getFilter(array $filters, $name, $default = null) |
||
| 447 | |||
| 448 | /** |
||
| 449 | * Returns true if filter-value exists. |
||
| 450 | * |
||
| 451 | * @param array $filters |
||
| 452 | * @param string $name |
||
| 453 | * |
||
| 454 | * @return bool |
||
| 455 | 12 | */ |
|
| 456 | private function hasFilter(array $filters, $name) |
||
| 460 | |||
| 461 | /** |
||
| 462 | * Returns Proxy document for uuid. |
||
| 463 | * |
||
| 464 | * @param string $uuid |
||
| 465 | * @param string $locale |
||
| 466 | * |
||
| 467 | * @return object |
||
| 468 | 2 | */ |
|
| 469 | private function getResource($uuid, $locale) |
||
| 487 | |||
| 488 | /** |
||
| 489 | * {@inheritdoc} |
||
| 490 | */ |
||
| 491 | public function getAlias() |
||
| 495 | } |
||
| 496 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.