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 AbstractZohoDao 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 AbstractZohoDao, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | abstract class AbstractZohoDao |
||
| 15 | { |
||
| 16 | const ON_DUPLICATE_THROW = 1; |
||
| 17 | const ON_DUPLICATE_MERGE = 2; |
||
| 18 | const MAX_GET_RECORDS = 200; |
||
| 19 | const MAX_GET_RECORDS_BY_ID = 100; |
||
| 20 | const MAX_SIMULTANEOUS_SAVE = 100; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * The class implementing API methods not directly related to a specific module. |
||
| 24 | * |
||
| 25 | * @var ZohoClient |
||
| 26 | */ |
||
| 27 | protected $zohoClient; |
||
| 28 | |||
| 29 | public function __construct(ZohoClient $zohoClient) |
||
| 33 | |||
| 34 | abstract protected function getModule(); |
||
| 39 | |||
| 40 | protected $flatFields; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * Returns a flat list of all fields. |
||
| 44 | * |
||
| 45 | * @return array The array of field names for a module |
||
| 46 | */ |
||
| 47 | protected function getFlatFields() |
||
| 58 | |||
| 59 | protected $duplicateCheck = self::ON_DUPLICATE_MERGE; |
||
| 60 | |||
| 61 | public function setDuplicateCheck($duplicateCheck) |
||
| 65 | |||
| 66 | protected $wfTrigger = false; |
||
| 67 | |||
| 68 | public function setWorkflowTrigger($wfTrigger) |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Parse a Zoho Response in order to retrieve one or several ZohoBeans from it. |
||
| 75 | * |
||
| 76 | * @param Response $zohoResponse The response returned by the ZohoClient->call() method |
||
| 77 | * |
||
| 78 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
| 79 | */ |
||
| 80 | protected function getBeansFromResponse(Response $zohoResponse) |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Convert an array of ZohoBeans into a SimpleXMLElement for use when inserting/updating related records. |
||
| 141 | * |
||
| 142 | * @param $zohoBeans ZohoBeanInterface[] |
||
| 143 | * |
||
| 144 | * @return \SimpleXMLElement The SimpleXMLElement containing the XML for a request |
||
| 145 | */ |
||
| 146 | public function toXmlRelatedRecords($zohoBeans) |
||
| 150 | |||
| 151 | /** |
||
| 152 | * Convert an array of ZohoBeans into a SimpleXMLElement. |
||
| 153 | * |
||
| 154 | * @param $zohoBeans ZohoBeanInterface[] |
||
| 155 | * |
||
| 156 | * @return \SimpleXMLElement The SimpleXMLElement containing the XML for a request |
||
| 157 | */ |
||
| 158 | public function toXml($zohoBeans, $isRelatedRecords = 0) |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Implements deleteRecords API method. |
||
| 224 | * |
||
| 225 | * @param string $id Zoho Id of the record to delete |
||
| 226 | * |
||
| 227 | * @throws ZohoCRMResponseException |
||
| 228 | */ |
||
| 229 | public function delete($id) |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Implements getRecordById API method. |
||
| 236 | * |
||
| 237 | * @param string|array $id Zoho Id of the record to retrieve OR an array of IDs |
||
| 238 | * |
||
| 239 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
| 240 | * |
||
| 241 | * @throws ZohoCRMResponseException |
||
| 242 | */ |
||
| 243 | public function getById($id) |
||
| 274 | |||
| 275 | /** |
||
| 276 | * Implements getRecords API method. |
||
| 277 | * |
||
| 278 | * @param $sortColumnString |
||
| 279 | * @param $sortOrderString |
||
| 280 | * @param \DateTime $lastModifiedTime |
||
| 281 | * @param $selectColumns |
||
| 282 | * @param $limit |
||
| 283 | * |
||
| 284 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
| 285 | * |
||
| 286 | * @throws ZohoCRMResponseException |
||
| 287 | */ |
||
| 288 | View Code Duplication | public function getRecords($sortColumnString = null, $sortOrderString = null, \DateTime $lastModifiedTime = null, $selectColumns = null, $limit = null) |
|
| 317 | |||
| 318 | /** |
||
| 319 | * Returns the list of deleted records. |
||
| 320 | * |
||
| 321 | * @param \DateTimeInterface|null $lastModifiedTime |
||
| 322 | * @param int $limit |
||
| 323 | * |
||
| 324 | * @return array |
||
| 325 | * |
||
| 326 | * @throws ZohoCRMResponseException |
||
| 327 | * @throws \Exception |
||
| 328 | */ |
||
| 329 | View Code Duplication | public function getDeletedRecordIds(\DateTimeInterface $lastModifiedTime = null, $limit = null) |
|
| 358 | |||
| 359 | /** |
||
| 360 | * Implements getRecords API method. |
||
| 361 | * |
||
| 362 | * @param string $id Zoho Id of the record to delete |
||
| 363 | * @param string $parentModule The parent module of the records |
||
| 364 | * @param int $limit The max number of records to fetch |
||
| 365 | * |
||
| 366 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
| 367 | * |
||
| 368 | * @throws ZohoCRMResponseException |
||
| 369 | */ |
||
| 370 | View Code Duplication | public function getRelatedRecords($id, $parentModule, $limit = null) |
|
| 399 | |||
| 400 | /** |
||
| 401 | * Implements searchRecords API method. |
||
| 402 | * |
||
| 403 | * @param string $searchCondition The search criteria formatted like |
||
| 404 | * @param int $limit The maximum number of beans returned from Zoho |
||
| 405 | * @param \DateTime $lastModifiedTime |
||
| 406 | * @param string $selectColumns The list |
||
| 407 | * |
||
| 408 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
| 409 | * |
||
| 410 | * @throws ZohoCRMResponseException |
||
| 411 | */ |
||
| 412 | View Code Duplication | public function searchRecords($searchCondition = null, $limit = null, \DateTime $lastModifiedTime = null, $selectColumns = null) |
|
| 441 | |||
| 442 | /** |
||
| 443 | * Implements insertRecords API method. |
||
| 444 | * |
||
| 445 | * WARNING : When setting wfTrigger to true, this method will use an API call per bean |
||
| 446 | * passed in argument. This is caused by Zoho limitation which forbids triggering any |
||
| 447 | * workflow when inserting several beans simultaneously. |
||
| 448 | * |
||
| 449 | * @param ZohoBeanInterface[] $beans The Zoho Beans to insert in the CRM |
||
| 450 | * @param bool $wfTrigger Whether or not the call should trigger the workflows related to a "created" event |
||
| 451 | * @param int $duplicateCheck 1 : Throwing error when a duplicate is found; 2 : Merging with existing duplicate |
||
| 452 | * @param bool $isApproval Whether or not to push the record into an approval sandbox first |
||
| 453 | * |
||
| 454 | * @throws ZohoCRMResponseException |
||
| 455 | */ |
||
| 456 | public function insertRecords($beans, $wfTrigger = null, $duplicateCheck = null, $isApproval = null) |
||
| 501 | |||
| 502 | /** |
||
| 503 | * Implements updateRecords API method. |
||
| 504 | * |
||
| 505 | * @param array $beans The list of beans to update. |
||
| 506 | * @param bool $wfTrigger Set value as true to trigger the workflow rule in Zoho |
||
| 507 | * |
||
| 508 | * @return Response The Response object |
||
| 509 | * |
||
| 510 | * @throws ZohoCRMException |
||
| 511 | */ |
||
| 512 | public function updateRecords(array $beans, $wfTrigger = null) |
||
| 565 | |||
| 566 | /** |
||
| 567 | * Implements uploadFile API method. |
||
| 568 | * |
||
| 569 | * @param string $id Zoho Id of the record to retrieve |
||
| 570 | * @param string|\SplFileInfo|resource|UriInterface $content Can be either the content to upload, a file information, a file handle, or the Uri of a remote file. |
||
| 571 | * @param string $filename The name (optional) under which the file will be stored by Zoho CRM. Mandatory if posting content as string. |
||
| 572 | * |
||
| 573 | * @return Response The Response object |
||
| 574 | * |
||
| 575 | * @throws ZohoCRMResponseException |
||
| 576 | */ |
||
| 577 | public function uploadFile($id, $content, $filename = null) |
||
| 581 | |||
| 582 | /** |
||
| 583 | * Implements downloadFile API method. |
||
| 584 | * |
||
| 585 | * @param string $id unique ID of the attachment |
||
| 586 | * |
||
| 587 | * @return Response The Response object |
||
| 588 | */ |
||
| 589 | public function downloadFile($id) |
||
| 593 | |||
| 594 | /** |
||
| 595 | * Saves the bean or array of beans passed in Zoho. |
||
| 596 | * It will perform an insert if the bean has no ZohoID or an update if the bean has a ZohoID. |
||
| 597 | * |
||
| 598 | * @param array|object $beans A bean or an array of beans. |
||
| 599 | * |
||
| 600 | * TODO: isApproval is not used by each module. |
||
| 601 | * TODO: wfTrigger only usable for a single record update/insert. |
||
| 602 | */ |
||
| 603 | public function save($beans, $wfTrigger = null, $duplicateCheck = null, $isApproval = false) |
||
| 631 | } |
||
| 632 |