This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Wabel\Zoho\CRM; |
||
4 | |||
5 | use Wabel\Zoho\CRM\Exception\ZohoCRMException; |
||
6 | use Wabel\Zoho\CRM\Exception\ZohoCRMResponseException; |
||
7 | use Wabel\Zoho\CRM\Exception\ZohoCRMUpdateException; |
||
8 | use Wabel\Zoho\CRM\Request\Response; |
||
9 | |||
10 | /** |
||
11 | * Base class that provides access to Zoho through Zoho beans. |
||
12 | */ |
||
13 | abstract class AbstractZohoDao |
||
14 | { |
||
15 | const ON_DUPLICATE_THROW = 1; |
||
16 | const ON_DUPLICATE_MERGE = 2; |
||
17 | const MAX_GET_RECORDS = 200; |
||
18 | const MAX_GET_RECORDS_BY_ID = 100; |
||
19 | const MAX_SIMULTANEOUS_SAVE = 100; |
||
20 | |||
21 | /** |
||
22 | * The class implementing API methods not directly related to a specific module. |
||
23 | * |
||
24 | * @var ZohoClient |
||
25 | */ |
||
26 | protected $zohoClient; |
||
27 | |||
28 | public function __construct(ZohoClient $zohoClient) |
||
29 | { |
||
30 | $this->zohoClient = $zohoClient; |
||
31 | } |
||
32 | |||
33 | abstract protected function getModule(); |
||
34 | abstract protected function getSingularModuleName(); |
||
35 | abstract protected function getPluralModuleName(); |
||
36 | abstract protected function getBeanClassName(); |
||
37 | abstract protected function getFields(); |
||
38 | |||
39 | protected $flatFields; |
||
40 | |||
41 | /** |
||
42 | * Returns a flat list of all fields. |
||
43 | * |
||
44 | * @return array The array of field names for a module |
||
45 | */ |
||
46 | protected function getFlatFields() |
||
47 | { |
||
48 | if ($this->flatFields === null) { |
||
49 | $this->flatFields = array(); |
||
50 | foreach ($this->getFields() as $cat) { |
||
51 | $this->flatFields = array_merge($this->flatFields, $cat); |
||
52 | } |
||
53 | } |
||
54 | |||
55 | return $this->flatFields; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * Parse a Zoho Response in order to retrieve one or several ZohoBeans from it. |
||
60 | * |
||
61 | * @param Response $zohoResponse The response returned by the ZohoClient->call() method |
||
62 | * |
||
63 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
64 | */ |
||
65 | protected function getBeansFromResponse(Response $zohoResponse) |
||
66 | { |
||
67 | $beanClass = $this->getBeanClassName(); |
||
68 | $fields = $this->getFlatFields(); |
||
69 | |||
70 | $beanArray = array(); |
||
71 | |||
72 | foreach ($zohoResponse->getRecords() as $record) { |
||
73 | |||
74 | /** @var ZohoBeanInterface $bean */ |
||
75 | $bean = new $beanClass(); |
||
76 | |||
77 | // First, let's fill the ID. |
||
78 | // The ID is CONTACTID or ACCOUNTID or Id depending on the Zoho type. |
||
79 | $idName = strtoupper(rtrim($this->getModule(), 's')); |
||
80 | if (isset($record[$idName.'ID'])) { |
||
81 | $id = $record[$idName.'ID']; |
||
82 | } elseif (isset($record[$idName.'_ID'])) { |
||
83 | $id = $record[$idName.'_ID']; |
||
84 | } else { |
||
85 | $id = $record['Id']; |
||
86 | } |
||
87 | $bean->setZohoId($id); |
||
88 | $bean->setCreatedTime(\DateTime::createFromFormat('Y-m-d H:i:s', $record['Created Time'])); |
||
0 ignored issues
–
show
Security
Bug
introduced
by
![]() |
|||
89 | $bean->setModifiedTime(\DateTime::createFromFormat('Y-m-d H:i:s', $record['Modified Time'])); |
||
0 ignored issues
–
show
It seems like
\DateTime::createFromFor...ecord['Modified Time']) targeting DateTime::createFromFormat() can also be of type false ; however, Wabel\Zoho\CRM\ZohoBeanI...face::setModifiedTime() does only seem to accept object<DateTime> , did you maybe forget to handle an error condition?
![]() |
|||
90 | |||
91 | foreach ($record as $key => $value) { |
||
92 | if (isset($fields[$key])) { |
||
93 | $setter = $fields[$key]['setter']; |
||
94 | |||
95 | switch ($fields[$key]['type']) { |
||
96 | case 'Date': |
||
97 | if ($dateObj = \DateTime::createFromFormat('M/d/Y', $value)) { |
||
98 | $value = $dateObj; |
||
99 | } elseif ($dateObj = \DateTime::createFromFormat('Y-m-d', $value)) { |
||
100 | $value = $dateObj; |
||
101 | } else { |
||
102 | throw new ZohoCRMException('Unable to convert the Date field "'.$key."\" into a DateTime PHP object from the the record $id of the module ".$this->getModule().'.'); |
||
103 | } |
||
104 | break; |
||
105 | case 'DateTime': |
||
106 | $value = \DateTime::createFromFormat('Y-m-d H:i:s', $value); |
||
107 | break; |
||
108 | case 'Boolean': |
||
109 | $value = ($value == 'true'); |
||
110 | break; |
||
111 | default: |
||
112 | break; |
||
113 | } |
||
114 | $bean->$setter($value); |
||
115 | } |
||
116 | } |
||
117 | |||
118 | $beanArray[] = $bean; |
||
119 | } |
||
120 | |||
121 | return $beanArray; |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Convert an array of ZohoBeans into a SimpleXMLElement. |
||
126 | * |
||
127 | * @param $zohoBeans ZohoBeanInterface[] |
||
128 | * |
||
129 | * @return \SimpleXMLElement The SimpleXMLElement containing the XML for a request |
||
130 | */ |
||
131 | public function toXml($zohoBeans) |
||
132 | { |
||
133 | $module = $this->getModule(); |
||
134 | |||
135 | $no = 1; |
||
136 | $module = new \SimpleXMLElement("<$module/>"); |
||
137 | |||
138 | foreach ($zohoBeans as $zohoBean) { |
||
139 | if (!$zohoBean instanceof ZohoBeanInterface) { |
||
140 | throw new ZohoCRMException('Zoho beans sent to save must implement the ZohoBeanInterface.'); |
||
141 | } |
||
142 | |||
143 | $properties = $this->getFlatFields(); |
||
144 | $row = $module->addChild('row'); |
||
145 | $row->addAttribute('no', $no); |
||
146 | |||
147 | $fl = $row->addChild('FL', $zohoBean->getZohoId()); |
||
148 | $fl->addAttribute('val', 'Id'); |
||
149 | |||
150 | foreach ($properties as $name => $params) { |
||
151 | $camelCaseName = $params['name']; |
||
152 | $isDirty = $zohoBean->isDirty($camelCaseName); |
||
153 | if (!$isDirty) { |
||
154 | continue; |
||
155 | } |
||
156 | |||
157 | $getter = $params['getter']; |
||
158 | $value = $zohoBean->$getter(); |
||
159 | |||
160 | if (!empty($value) || is_bool($value)) { |
||
161 | |||
162 | // We convert the value back to a proper format if the Zoho Type is Date, DateTime or Boolean |
||
163 | switch ($params['type']) { |
||
164 | case 'Date': |
||
165 | /** @var \DateTime $value */ |
||
166 | $value = $value->format('m/d/Y'); |
||
167 | break; |
||
168 | case 'DateTime': |
||
169 | /** @var \DateTime $value */ |
||
170 | $value = $value->format('Y-m-d H:i:s'); |
||
171 | break; |
||
172 | case 'Boolean': |
||
173 | /** @var bool $value */ |
||
174 | $value = $value ? 'true' : 'false'; |
||
175 | break; |
||
176 | default: |
||
177 | break; |
||
178 | } |
||
179 | } |
||
180 | |||
181 | $fl = $row->addChild('FL', htmlspecialchars($value)); |
||
182 | $fl->addAttribute('val', $name); |
||
183 | } |
||
184 | ++$no; |
||
185 | } |
||
186 | |||
187 | return $module; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Implements deleteRecords API method. |
||
192 | * |
||
193 | * @param string $id Zoho Id of the record to delete |
||
194 | * |
||
195 | * @throws ZohoCRMResponseException |
||
196 | */ |
||
197 | public function delete($id) |
||
198 | { |
||
199 | $this->zohoClient->deleteRecords($this->getModule(), $id); |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * Implements getRecordById API method. |
||
204 | * |
||
205 | * @param string|array $id Zoho Id of the record to retrieve OR an array of IDs |
||
206 | * |
||
207 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
208 | * |
||
209 | * @throws ZohoCRMResponseException |
||
210 | */ |
||
211 | public function getById($id) |
||
212 | { |
||
213 | try { |
||
214 | $module = $this->getModule(); |
||
215 | $beans = []; |
||
216 | |||
217 | // If there's several IDs to process, we divide them by pools of 100 and implode them before requesting |
||
218 | if (is_array($id)) { |
||
219 | foreach (array_chunk($id, self::MAX_GET_RECORDS_BY_ID) as $pool) { |
||
220 | $idlist = implode(';', $pool); |
||
221 | $response = $this->zohoClient->getRecordById($module, $idlist); |
||
222 | $beans = array_merge($beans, $this->getBeansFromResponse($response)); |
||
223 | } |
||
224 | } |
||
225 | // if not, we simply request our record |
||
226 | else { |
||
227 | $response = $this->zohoClient->getRecordById($module, $id); |
||
228 | $beans = $this->getBeansFromResponse($response); |
||
229 | $beans = array_shift($beans); |
||
230 | } |
||
231 | |||
232 | return $beans; |
||
233 | } catch (ZohoCRMResponseException $e) { |
||
234 | // No records found? Let's return an empty array! |
||
235 | if ($e->getCode() == 4422) { |
||
236 | return array(); |
||
237 | } else { |
||
238 | throw $e; |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Implements getRecords API method. |
||
245 | * |
||
246 | * @param $sortColumnString |
||
247 | * @param $sortOrderString |
||
248 | * @param \DateTime $lastModifiedTime |
||
249 | * @param $selectColumns |
||
250 | * @param $limit |
||
251 | * |
||
252 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
253 | * |
||
254 | * @throws ZohoCRMResponseException |
||
255 | */ |
||
256 | public function getRecords($sortColumnString = null, $sortOrderString = null, \DateTime $lastModifiedTime = null, $selectColumns = null, $limit = null) |
||
257 | { |
||
258 | $globalResponse = array(); |
||
259 | |||
260 | do { |
||
261 | try { |
||
262 | $fromIndex = count($globalResponse) + 1; |
||
263 | $toIndex = $fromIndex + self::MAX_GET_RECORDS - 1; |
||
264 | |||
265 | if ($limit) { |
||
266 | $toIndex = min($limit, $toIndex); |
||
267 | } |
||
268 | |||
269 | $response = $this->zohoClient->getRecords($this->getModule(), $sortColumnString, $sortOrderString, $lastModifiedTime, $selectColumns, $fromIndex, $toIndex); |
||
0 ignored issues
–
show
It seems like
$lastModifiedTime defined by parameter $lastModifiedTime on line 256 can also be of type object<DateTime> ; however, Wabel\Zoho\CRM\ZohoClient::getRecords() does only seem to accept null|object<DateTimeInterface> , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
270 | $beans = $this->getBeansFromResponse($response); |
||
271 | } catch (ZohoCRMResponseException $e) { |
||
272 | // No records found? Let's return an empty array! |
||
273 | if ($e->getCode() == 4422) { |
||
274 | $beans = array(); |
||
275 | } else { |
||
276 | throw $e; |
||
277 | } |
||
278 | } |
||
279 | |||
280 | $globalResponse = array_merge($globalResponse, $beans); |
||
281 | } while (count($beans) == self::MAX_GET_RECORDS); |
||
282 | |||
283 | return $globalResponse; |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * Returns the list of deleted records. |
||
288 | * |
||
289 | * @param \DateTimeInterface|null $lastModifiedTime |
||
290 | * @param int $limit |
||
291 | * |
||
292 | * @return array |
||
293 | * |
||
294 | * @throws ZohoCRMResponseException |
||
295 | * @throws \Exception |
||
296 | */ |
||
297 | View Code Duplication | public function getDeletedRecordIds(\DateTimeInterface $lastModifiedTime = null, $limit = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
298 | { |
||
299 | $globalDeletedIDs = array(); |
||
300 | |||
301 | do { |
||
302 | try { |
||
303 | $fromIndex = count($globalDeletedIDs) + 1; |
||
304 | $toIndex = $fromIndex + self::MAX_GET_RECORDS - 1; |
||
305 | |||
306 | if ($limit) { |
||
0 ignored issues
–
show
The expression
$limit of type integer|null is loosely compared to true ; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
307 | $toIndex = min($limit - 1, $toIndex); |
||
308 | } |
||
309 | |||
310 | $response = $this->zohoClient->getDeletedRecordIds($this->getModule(), $lastModifiedTime, $fromIndex, $toIndex); |
||
311 | $deletedIDs = $response->getDeletedIds(); |
||
312 | } catch (ZohoCRMResponseException $e) { |
||
313 | // No records found? Let's return an empty array! |
||
314 | if ($e->getZohoCode() == 4422) { |
||
315 | $deletedIDs = array(); |
||
316 | } else { |
||
317 | throw $e; |
||
318 | } |
||
319 | } |
||
320 | |||
321 | $globalDeletedIDs = array_merge($globalDeletedIDs, $deletedIDs); |
||
322 | } while (count($deletedIDs) == self::MAX_GET_RECORDS); |
||
323 | |||
324 | return $globalDeletedIDs; |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * Implements getRecords API method. |
||
329 | * |
||
330 | * @param string $id Zoho Id of the record to delete |
||
331 | * @param string $parentModule The parent module of the records |
||
332 | * @param int $limit The max number of records to fetch |
||
333 | * |
||
334 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
335 | * |
||
336 | * @throws ZohoCRMResponseException |
||
337 | */ |
||
338 | View Code Duplication | public function getRelatedRecords($id, $parentModule, $limit = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
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. ![]() |
|||
339 | { |
||
340 | $globalResponse = array(); |
||
341 | |||
342 | do { |
||
343 | try { |
||
344 | $fromIndex = count($globalResponse) + 1; |
||
345 | $toIndex = $fromIndex + self::MAX_GET_RECORDS - 1; |
||
346 | |||
347 | if ($limit) { |
||
0 ignored issues
–
show
The expression
$limit of type integer|null is loosely compared to true ; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
348 | $toIndex = min($limit - 1, $toIndex); |
||
349 | } |
||
350 | |||
351 | $response = $this->zohoClient->getRelatedRecords($this->getModule(), $id, $parentModule, $fromIndex, $toIndex); |
||
352 | $beans = $this->getBeansFromResponse($response); |
||
353 | } catch (ZohoCRMResponseException $e) { |
||
354 | // No records found? Let's return an empty array! |
||
355 | if ($e->getCode() == 4422) { |
||
356 | $beans = array(); |
||
357 | } else { |
||
358 | throw $e; |
||
359 | } |
||
360 | } |
||
361 | |||
362 | $globalResponse = array_merge($globalResponse, $beans); |
||
363 | } while (count($beans) == self::MAX_GET_RECORDS); |
||
364 | |||
365 | return $globalResponse; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Implements searchRecords API method. |
||
370 | * |
||
371 | * @param string $searchCondition The search criteria formatted like |
||
372 | * @param int $limit The maximum number of beans returned from Zoho |
||
373 | * @param \DateTime $lastModifiedTime |
||
374 | * @param string $selectColumns The list |
||
375 | * |
||
376 | * @return ZohoBeanInterface[] The array of Zoho Beans parsed from the response |
||
377 | * |
||
378 | * @throws ZohoCRMResponseException |
||
379 | */ |
||
380 | public function searchRecords($searchCondition = null, $limit = null, \DateTime $lastModifiedTime = null, $selectColumns = null) |
||
381 | { |
||
382 | $globalResponse = array(); |
||
383 | |||
384 | do { |
||
385 | try { |
||
386 | $fromIndex = count($globalResponse) + 1; |
||
387 | $toIndex = $fromIndex + self::MAX_GET_RECORDS - 1; |
||
388 | |||
389 | if ($limit) { |
||
0 ignored issues
–
show
The expression
$limit of type integer|null is loosely compared to true ; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
390 | $toIndex = min($limit - 1, $toIndex); |
||
391 | } |
||
392 | |||
393 | $response = $this->zohoClient->searchRecords($this->getModule(), $searchCondition, $fromIndex, $toIndex, $lastModifiedTime, $selectColumns); |
||
0 ignored issues
–
show
It seems like
$selectColumns defined by parameter $selectColumns on line 380 can also be of type string ; however, Wabel\Zoho\CRM\ZohoClient::searchRecords() does only seem to accept null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
394 | $beans = $this->getBeansFromResponse($response); |
||
395 | } catch (ZohoCRMResponseException $e) { |
||
396 | // No records found? Let's return an empty array! |
||
397 | if ($e->getCode() == 4422) { |
||
398 | $beans = array(); |
||
399 | } else { |
||
400 | throw $e; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | $globalResponse = array_merge($globalResponse, $beans); |
||
405 | } while (count($beans) == self::MAX_GET_RECORDS); |
||
406 | |||
407 | return $globalResponse; |
||
408 | } |
||
409 | |||
410 | /** |
||
411 | * Implements insertRecords API method. |
||
412 | * |
||
413 | * WARNING : When setting wfTrigger to true, this method will use an API call per bean |
||
414 | * passed in argument. This is caused by Zoho limitation which forbids triggering any |
||
415 | * workflow when inserting several beans simultaneously. |
||
416 | * |
||
417 | * @param ZohoBeanInterface[] $beans The Zoho Beans to insert in the CRM |
||
418 | * @param bool $wfTrigger Whether or not the call should trigger the workflows related to a "created" event |
||
419 | * @param int $duplicateCheck 1 : Throwing error when a duplicate is found; 2 : Merging with existing duplicate |
||
420 | * @param bool $isApproval Whether or not to push the record into an approval sandbox first |
||
421 | * |
||
422 | * @throws ZohoCRMResponseException |
||
423 | */ |
||
424 | public function insertRecords($beans, $wfTrigger = null, $duplicateCheck = 2, $isApproval = null) |
||
425 | { |
||
426 | $records = []; |
||
427 | |||
428 | if ($wfTrigger) { |
||
429 | // If we trigger workflows, we trigger the insert of beans one by one. |
||
430 | foreach ($beans as $bean) { |
||
431 | $xmlData = $this->toXml([$bean]); |
||
432 | $response = $this->zohoClient->insertRecords($this->getModule(), $xmlData, $wfTrigger, $duplicateCheck, $isApproval); |
||
433 | $records = array_merge($records, $response->getRecords()); |
||
434 | } |
||
435 | View Code Duplication | } else { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
436 | // We can't pass more than 100 records to Zoho, so we split the request into pieces of 100 |
||
437 | foreach (array_chunk($beans, 100) as $beanPool) { |
||
438 | $xmlData = $this->toXml($beanPool); |
||
439 | $response = $this->zohoClient->insertRecords($this->getModule(), $xmlData, $wfTrigger, $duplicateCheck, $isApproval); |
||
440 | $records = array_merge($records, $response->getRecords()); |
||
441 | } |
||
442 | } |
||
443 | View Code Duplication | if (count($records) != count($beans)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
444 | throw new ZohoCRMException('Error while inserting beans in Zoho. '.count($beans).' passed in parameter, but '.count($records).' returned.'); |
||
445 | } |
||
446 | |||
447 | foreach ($beans as $key => $bean) { |
||
448 | $record = $records[$key]; |
||
449 | |||
450 | if ($wfTrigger && (!isset($record['Id']) || empty($record['Id']))) { |
||
451 | // This field is probably in error! |
||
452 | throw new ZohoCRMException('An error occurred while inserting records and triggering workflow: '.$record['message'], $record['code']); |
||
453 | } elseif (!$wfTrigger && substr($record['code'], 0, 1) != '2') { |
||
0 ignored issues
–
show
The expression
$wfTrigger of type boolean|null is loosely compared to false ; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.
If an expression can have both $a = canBeFalseAndNull();
// Instead of
if ( ! $a) { }
// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
![]() |
|||
454 | // This field is probably in error! |
||
455 | throw new ZohoCRMException('An error occurred while inserting records: '.$record['message'], $record['code']); |
||
456 | } |
||
457 | |||
458 | $bean->setZohoId($record['Id']); |
||
459 | $bean->setCreatedTime(\DateTime::createFromFormat('Y-m-d H:i:s', $record['Created Time'])); |
||
0 ignored issues
–
show
It seems like
\DateTime::createFromFor...record['Created Time']) targeting DateTime::createFromFormat() can also be of type false ; however, Wabel\Zoho\CRM\ZohoBeanInterface::setCreatedTime() does only seem to accept object<DateTime> , did you maybe forget to handle an error condition?
![]() |
|||
460 | if ($record['Modified Time']) { |
||
461 | $bean->setModifiedTime(\DateTime::createFromFormat('Y-m-d H:i:s', $record['Modified Time'])); |
||
0 ignored issues
–
show
It seems like
\DateTime::createFromFor...ecord['Modified Time']) targeting DateTime::createFromFormat() can also be of type false ; however, Wabel\Zoho\CRM\ZohoBeanI...face::setModifiedTime() does only seem to accept object<DateTime> , did you maybe forget to handle an error condition?
![]() |
|||
462 | } |
||
463 | } |
||
464 | } |
||
465 | |||
466 | /** |
||
467 | * Implements updateRecords API method. |
||
468 | * |
||
469 | * @param array $beans The list of beans to update. |
||
470 | * @param bool $wfTrigger Set value as true to trigger the workflow rule in Zoho |
||
471 | * |
||
472 | * @return Response The Response object |
||
473 | * |
||
474 | * @throws ZohoCRMException |
||
475 | */ |
||
476 | public function updateRecords(array $beans, $wfTrigger = null) |
||
477 | { |
||
478 | $records = []; |
||
479 | |||
480 | if ($wfTrigger) { |
||
481 | // If we trigger workflows, we trigger the insert of beans one by one. |
||
482 | foreach ($beans as $bean) { |
||
483 | $xmlData = $this->toXml([$bean]); |
||
484 | $response = $this->zohoClient->updateRecords($this->getModule(), $xmlData, $bean->getZohoId(), $wfTrigger); |
||
485 | $records = array_merge($records, $response->getRecords()); |
||
486 | } |
||
487 | View Code Duplication | } else { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
488 | // We can't pass more than 100 records to Zoho, so we split the request into pieces of 100 |
||
489 | foreach (array_chunk($beans, 100) as $beanPool) { |
||
490 | $xmlData = $this->toXml($beanPool); |
||
491 | $response = $this->zohoClient->updateRecords($this->getModule(), $xmlData, null, $wfTrigger); |
||
492 | $records = array_merge($records, $response->getRecords()); |
||
493 | } |
||
494 | } |
||
495 | View Code Duplication | if (count($records) != count($beans)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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. ![]() |
|||
496 | throw new ZohoCRMException('Error while inserting beans in Zoho. '.count($beans).' passed in parameter, but '.count($records).' returned.'); |
||
497 | } |
||
498 | |||
499 | $exceptions = new \SplObjectStorage(); |
||
500 | |||
501 | foreach ($beans as $key => $bean) { |
||
502 | $record = $records[$key]; |
||
503 | |||
504 | if ($wfTrigger && (!isset($record['Id']) || empty($record['Id']))) { |
||
505 | // This field is probably in error! |
||
506 | throw new ZohoCRMException('An error occurred while updating records and triggering workflow: '.$record['message'], $record['code']); |
||
507 | } elseif (!$wfTrigger && substr($record['code'], 0, 1) != '2') { |
||
0 ignored issues
–
show
The expression
$wfTrigger of type boolean|null is loosely compared to false ; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.
If an expression can have both $a = canBeFalseAndNull();
// Instead of
if ( ! $a) { }
// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
![]() |
|||
508 | // This field is probably in error! |
||
509 | $exceptions->attach($bean, new ZohoCRMException('An error occurred while updating records. '.(isset($record['message']) ? $record['message'] : ''), $record['code'])); |
||
510 | continue; |
||
511 | } |
||
512 | |||
513 | if ($record['Id'] != $bean->getZohoId()) { |
||
514 | // This field is probably in error! |
||
515 | $exceptions->attach($bean, new ZohoCRMException('An error occurred while updating records. The Zoho ID to update was '.$bean->getZohoId().', returned '.$record['Id'])); |
||
516 | continue; |
||
517 | } |
||
518 | |||
519 | if ($record['Modified Time']) { |
||
520 | $bean->setModifiedTime(\DateTime::createFromFormat('Y-m-d H:i:s', $record['Modified Time'])); |
||
521 | } |
||
522 | } |
||
523 | if ($exceptions->count() != 0) { |
||
524 | throw new ZohoCRMUpdateException($exceptions); |
||
525 | } |
||
526 | } |
||
527 | |||
528 | /** |
||
529 | * Implements uploadFile API method. |
||
530 | * |
||
531 | * @param string $id Zoho Id of the record to retrieve |
||
532 | * @param string $content The string containing the file |
||
533 | * |
||
534 | * @return Response The Response object |
||
535 | * |
||
536 | * @throws ZohoCRMResponseException |
||
537 | */ |
||
538 | public function uploadFile($id, $content) |
||
539 | { |
||
540 | return $this->zohoClient->uploadFile($this->getModule(), $id, $content); |
||
541 | } |
||
542 | |||
543 | /** |
||
544 | * Implements downloadFile API method. |
||
545 | * |
||
546 | * @param string $id unique ID of the attachment |
||
547 | * |
||
548 | * @return Response The Response object |
||
549 | */ |
||
550 | public function downloadFile($id) |
||
551 | { |
||
552 | return $this->zohoClient->downloadFile($this->getModule(), $id); |
||
553 | } |
||
554 | |||
555 | /** |
||
556 | * Saves the bean or array of beans passed in Zoho. |
||
557 | * It will perform an insert if the bean has no ZohoID or an update if the bean has a ZohoID. |
||
558 | * |
||
559 | * @param array|object $beans A bean or an array of beans. |
||
560 | * |
||
561 | * TODO: isApproval is not used by each module. |
||
562 | * TODO: wfTrigger only usable for a single record update/insert. |
||
563 | */ |
||
564 | public function save($beans, $wfTrigger = false, $duplicateCheck = self::ON_DUPLICATE_MERGE, $isApproval = false) |
||
565 | { |
||
566 | if (!is_array($beans)) { |
||
567 | $beans = [$beans]; |
||
568 | } |
||
569 | |||
570 | $toInsert = []; |
||
571 | $toUpdate = []; |
||
572 | |||
573 | foreach ($beans as $bean) { |
||
574 | if ($bean->getZohoId()) { |
||
575 | $toUpdate[] = $bean; |
||
576 | } else { |
||
577 | $toInsert[] = $bean; |
||
578 | } |
||
579 | } |
||
580 | |||
581 | if ($toInsert) { |
||
0 ignored issues
–
show
The expression
$toInsert of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
582 | $this->insertRecords($toInsert, $wfTrigger, $duplicateCheck, $isApproval); |
||
583 | } |
||
584 | if ($toUpdate) { |
||
0 ignored issues
–
show
The expression
$toUpdate of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
585 | $this->updateRecords($toUpdate, $wfTrigger); |
||
586 | } |
||
587 | } |
||
588 | } |
||
589 |