1 | <?php |
||||
2 | /** |
||||
3 | * EGroupware Addressbook |
||||
4 | * |
||||
5 | * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License |
||||
6 | * @package importexport |
||||
7 | * @link http://www.egroupware.org |
||||
8 | * @author Cornelius Weiss <[email protected]> |
||||
9 | * @copyright Cornelius Weiss <[email protected]> |
||||
10 | * @version $Id$ |
||||
11 | */ |
||||
12 | |||||
13 | use EGroupware\Api; |
||||
14 | |||||
15 | /** |
||||
16 | * class import_csv for addressbook |
||||
17 | */ |
||||
18 | class addressbook_import_contacts_csv extends importexport_basic_import_csv { |
||||
19 | |||||
20 | /** |
||||
21 | * conditions for actions |
||||
22 | * |
||||
23 | * @var array |
||||
24 | */ |
||||
25 | protected static $conditions = array( 'exists', 'equal' ); |
||||
26 | |||||
27 | /** |
||||
28 | * @var addressbook_bo |
||||
29 | */ |
||||
30 | private $bocontacts; |
||||
31 | |||||
32 | /** |
||||
33 | * For figuring out if a contact has changed |
||||
34 | * |
||||
35 | * @var Api\Contacts\Tracking |
||||
36 | */ |
||||
37 | protected $tracking; |
||||
38 | |||||
39 | /** |
||||
40 | * @var boolean If import file has no type, it can generate a lot of warnings. |
||||
41 | * Users don't like this, so we only warn once. |
||||
42 | */ |
||||
43 | private $type_warned = false; |
||||
44 | |||||
45 | /** |
||||
46 | * To empty addressbook before importing, we actually keep track of |
||||
47 | * what's imported and delete the others to keep history. |
||||
48 | * |
||||
49 | * @var type |
||||
50 | */ |
||||
51 | private $ids = array(); |
||||
52 | |||||
53 | /** |
||||
54 | * imports entries according to given definition object. |
||||
55 | * @param resource $_stream |
||||
56 | * @param string $_charset |
||||
57 | * @param definition $_definition |
||||
0 ignored issues
–
show
|
|||||
58 | */ |
||||
59 | public function import( $_stream, importexport_definition $_definition ) { |
||||
60 | parent::import($_stream, $_definition); |
||||
61 | |||||
62 | if($_definition->plugin_options['empty_addressbook']) |
||||
0 ignored issues
–
show
The property
plugin_options does not exist on importexport_definition . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
63 | { |
||||
64 | $this->empty_addressbook($this->user, $this->ids); |
||||
65 | } |
||||
66 | } |
||||
67 | |||||
68 | /** |
||||
69 | * imports entries according to given definition object. |
||||
70 | * @param resource $_stream |
||||
71 | * @param string $_charset |
||||
72 | * @param definition $_definition |
||||
73 | */ |
||||
74 | public function init(importexport_definition &$_definition ) { |
||||
75 | |||||
76 | // fetch the addressbook bo |
||||
77 | $this->bocontacts = new addressbook_bo(); |
||||
78 | |||||
79 | // Get the tracker for changes |
||||
80 | $this->tracking = new Api\Contacts\Tracking($this->bocontacts); |
||||
81 | |||||
82 | $this->lookups = array( |
||||
83 | 'tid' => array('n'=>'contact') |
||||
84 | ); |
||||
85 | foreach($this->bocontacts->content_types as $tid => $data) |
||||
86 | { |
||||
87 | $this->lookups['tid'][$tid] = $data['name']; |
||||
88 | } |
||||
89 | |||||
90 | // Try and set a default type, for use if file does not specify |
||||
91 | if(!$this->lookups['tid'][Api\Contacts\Storage::DELETED_TYPE] && count($this->lookups['tid']) == 1 || |
||||
0 ignored issues
–
show
|
|||||
92 | $this->lookups['tid'][Api\Contacts\Storage::DELETED_TYPE] && count($this->lookups['tid']) == 2) |
||||
93 | { |
||||
94 | reset($this->lookups['tid']); |
||||
95 | $this->default_type = key($this->lookups['tid']); |
||||
0 ignored issues
–
show
|
|||||
96 | } |
||||
97 | |||||
98 | |||||
99 | // set contact owner |
||||
100 | $contact_owner = isset( $_definition->plugin_options['contact_owner'] ) ? |
||||
0 ignored issues
–
show
The property
plugin_options does not exist on importexport_definition . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
101 | $_definition->plugin_options['contact_owner'] : $this->user; |
||||
102 | |||||
103 | // Check to make sure target addressbook is valid |
||||
104 | if(!in_array($contact_owner, array_keys($this->bocontacts->get_addressbooks(Api\Acl::ADD)))) |
||||
105 | { |
||||
106 | $this->warnings[0] = lang("Unable to import into %1, using %2", |
||||
0 ignored issues
–
show
|
|||||
107 | $contact_owner . ' ('.Api\Accounts::username($record->owner) . ')', |
||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with $contact_owner . ' (' . ...e($record->owner) . ')' .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
Comprehensibility
Best Practice
introduced
by
|
|||||
108 | Api\Accounts::username($this->user) |
||||
109 | ); |
||||
110 | $contact_owner = 'personal'; |
||||
111 | } |
||||
112 | |||||
113 | // Import into importer's personal addressbook |
||||
114 | if($contact_owner == 'personal') |
||||
115 | { |
||||
116 | $contact_owner = $this->user; |
||||
117 | } |
||||
118 | $this->user = $contact_owner; |
||||
119 | } |
||||
120 | |||||
121 | /** |
||||
122 | * Import a single record |
||||
123 | * |
||||
124 | * You don't need to worry about mappings or translations, they've been done already. |
||||
125 | * You do need to handle the conditions and the actions taken. |
||||
126 | * |
||||
127 | * Updates the count of actions taken |
||||
128 | * |
||||
129 | * @return boolean success |
||||
130 | */ |
||||
131 | protected function import_record(importexport_iface_egw_record &$record, &$import_csv) |
||||
132 | { |
||||
133 | // Set owner, unless it's supposed to come from CSV file |
||||
134 | if($this->definition->plugin_options['owner_from_csv'] && $record->owner) { |
||||
0 ignored issues
–
show
The property
owner does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
135 | if(!is_numeric($record->owner)) { |
||||
136 | // Automatically handle text owner without explicit translation |
||||
137 | $new_owner = importexport_helper_functions::account_name2id($record->owner); |
||||
138 | if($new_owner == '') { |
||||
139 | $this->errors[$import_csv->get_current_position()] = lang( |
||||
140 | 'Unable to convert "%1" to account ID. Using plugin setting (%2) for owner.', |
||||
141 | $record->owner, |
||||
0 ignored issues
–
show
The call to
lang() has too many arguments starting with $record->owner .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||
142 | Api\Accounts::username($this->user) |
||||
143 | ); |
||||
144 | $record->owner = $this->user; |
||||
0 ignored issues
–
show
The property
owner does not exist on importexport_iface_egw_record . Since you implemented __set , consider adding a @property annotation.
Loading history...
|
|||||
145 | } else { |
||||
146 | $record->owner = $new_owner; |
||||
147 | } |
||||
148 | } |
||||
149 | } else { |
||||
150 | $record->owner = $this->user; |
||||
151 | } |
||||
152 | |||||
153 | // Check that owner (addressbook) is allowed |
||||
154 | if(!array_key_exists($record->owner, $this->bocontacts->get_addressbooks())) |
||||
155 | { |
||||
156 | $this->errors[$import_csv->get_current_position()] = lang("Unable to import into %1, using %2", |
||||
157 | Api\Accounts::username($record->owner), |
||||
158 | Api\Accounts::username($this->user) |
||||
159 | ); |
||||
160 | $record->owner = $this->user; |
||||
161 | } |
||||
162 | |||||
163 | // Do not allow owner == 0 (accounts) without an account_id |
||||
164 | // It causes the contact to be filed as an account, and can't delete |
||||
165 | if(!$record->owner && !$record->account_id) |
||||
0 ignored issues
–
show
The property
account_id does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
166 | { |
||||
167 | $record->owner = $GLOBALS['egw_info']['user']['account_id']; |
||||
168 | } |
||||
169 | |||||
170 | // Do not import into non-existing type, warn and change |
||||
171 | if(!$record->tid || !$this->lookups['tid'][$record->tid]) |
||||
0 ignored issues
–
show
The property
tid does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
172 | { |
||||
173 | // Avoid lots of warnings about type (2 types are contact and deleted) |
||||
174 | if($record->tid && !$this->type_warned[$record->tid] && !$this->lookups['tid'][$record->tid] ) |
||||
175 | { |
||||
176 | $this->warnings[$import_csv->get_current_position()] = lang('Unknown type %1, imported as %2',$record->tid,lang($this->lookups['tid']['n'])); |
||||
0 ignored issues
–
show
|
|||||
177 | $this->type_warned[$record->tid] = true; |
||||
178 | } |
||||
179 | $record->tid = $this->default_type; |
||||
0 ignored issues
–
show
The property
tid does not exist on importexport_iface_egw_record . Since you implemented __set , consider adding a @property annotation.
Loading history...
|
|||||
180 | } |
||||
181 | |||||
182 | // Also handle categories in their own field |
||||
183 | $record_array = $record->get_record_array(); |
||||
184 | $more_categories = array(); |
||||
185 | foreach($this->definition->plugin_options['field_mapping'] as $field_name) { |
||||
186 | if(!array_key_exists($field_name, $record_array) || |
||||
187 | substr($field_name,0,3) != 'cat' || !$record->$field_name || $field_name == 'cat_id') continue; |
||||
188 | list(, $cat_id) = explode('-', $field_name); |
||||
189 | if(is_numeric($record->$field_name) && $record->$field_name != 1) { |
||||
190 | // Column has a single category ID |
||||
191 | $more_categories[] = $record->$field_name; |
||||
192 | } elseif($record->$field_name == '1' || |
||||
193 | (!is_numeric($record->$field_name) && strtolower($record->$field_name) == strtolower(lang('Yes')))) { |
||||
194 | // Each category got its own column. '1' is the database value, lang('yes') is the human value |
||||
195 | $more_categories[] = $cat_id; |
||||
196 | } else { |
||||
197 | // Text categories |
||||
198 | $more_categories = array_merge($more_categories, importexport_helper_functions::cat_name2id(is_array($record->$field_name) ? $record->$field_name : explode(',',$record->$field_name), $cat_id)); |
||||
199 | } |
||||
200 | } |
||||
201 | if(count($more_categories) > 0) $record->cat_id = array_merge(is_array($record->cat_id) ? $record->cat_id : explode(',',$record->cat_id), $more_categories); |
||||
0 ignored issues
–
show
The property
cat_id does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
The property
cat_id does not exist on importexport_iface_egw_record . Since you implemented __set , consider adding a @property annotation.
Loading history...
|
|||||
202 | |||||
203 | // Private set but missing causes hidden entries |
||||
204 | if(array_key_exists('private', $record_array) && (!isset($record_array['private']) || $record_array['private'] == '')) unset($record->private); |
||||
0 ignored issues
–
show
The property
private does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
205 | |||||
206 | // Format birthday as backend requires - converter should give timestamp |
||||
207 | if($record->bday && is_numeric($record->bday)) |
||||
0 ignored issues
–
show
The property
bday does not exist on importexport_iface_egw_record . Since you implemented __get , consider adding a @property annotation.
Loading history...
|
|||||
208 | { |
||||
209 | $time = new Api\DateTime($record->bday); |
||||
210 | $record->bday = $time->format('Y-m-d'); |
||||
0 ignored issues
–
show
The property
bday does not exist on importexport_iface_egw_record . Since you implemented __set , consider adding a @property annotation.
Loading history...
|
|||||
211 | } |
||||
212 | |||||
213 | if ( $this->definition->plugin_options['conditions'] ) { |
||||
214 | foreach ( $this->definition->plugin_options['conditions'] as $condition ) { |
||||
215 | $contacts = array(); |
||||
216 | switch ( $condition['type'] ) { |
||||
217 | // exists |
||||
218 | case 'exists' : |
||||
219 | if($record_array[$condition['string']]) { |
||||
220 | $searchcondition = array( $condition['string'] => $record_array[$condition['string']]); |
||||
221 | // if we use account_id for the condition, we need to set the owner for filtering, as this |
||||
222 | // enables Api\Contacts\Storage to decide what backend is to be used |
||||
223 | if ($condition['string']=='account_id') $searchcondition['owner']=0; |
||||
224 | $contacts = $this->bocontacts->search( |
||||
225 | //array( $condition['string'] => $record[$condition['string']],), |
||||
226 | '', |
||||
227 | $this->definition->plugin_options['update_cats'] == 'add' ? false : true, |
||||
228 | '', '', '', false, 'AND', false, |
||||
229 | $searchcondition |
||||
230 | ); |
||||
231 | } |
||||
232 | if ( is_array( $contacts ) && count( array_keys( $contacts ) ) >= 1 ) { |
||||
233 | // apply action to all contacts matching this exists condition |
||||
234 | $action = $condition['true']; |
||||
235 | foreach ( (array)$contacts as $contact ) { |
||||
236 | $record->id = $contact['id']; |
||||
237 | if ( $this->definition->plugin_options['update_cats'] == 'add' ) { |
||||
238 | if ( !is_array( $contact['cat_id'] ) ) $contact['cat_id'] = explode( ',', $contact['cat_id'] ); |
||||
239 | if ( !is_array( $record_array['cat_id'] ) ) $record->cat_id = explode( ',', $record->cat_id ); |
||||
240 | $record->cat_id = implode( ',', array_unique( array_merge( $record->cat_id, $contact['cat_id'] ) ) ); |
||||
241 | } |
||||
242 | $success = $this->action( $action['action'], $record, $import_csv->get_current_position() ); |
||||
243 | } |
||||
244 | } else { |
||||
245 | $action = $condition['false']; |
||||
246 | $success = ($this->action( $action['action'], $record, $import_csv->get_current_position() )); |
||||
247 | } |
||||
248 | break; |
||||
249 | case 'equal': |
||||
250 | // Match on field |
||||
251 | $result = $this->equal($record, $condition); |
||||
252 | if($result) |
||||
253 | { |
||||
254 | // Apply true action to any matching records found |
||||
255 | $action = $condition['true']; |
||||
256 | $success = ($this->action( $action['action'], $record, $import_csv->get_current_position() )); |
||||
257 | } |
||||
258 | else |
||||
259 | { |
||||
260 | // Apply false action if no matching records found |
||||
261 | $action = $condition['false']; |
||||
262 | $success = ($this->action( $action['action'], $record, $import_csv->get_current_position() )); |
||||
263 | } |
||||
264 | break; |
||||
265 | |||||
266 | // not supported action |
||||
267 | default : |
||||
268 | die('condition / action not supported!!!'); |
||||
0 ignored issues
–
show
|
|||||
269 | } |
||||
270 | if ($action['stop']) break; |
||||
271 | } |
||||
272 | } else { |
||||
273 | // unconditional insert |
||||
274 | $success = $this->action( 'insert', $record, $import_csv->get_current_position() ); |
||||
275 | } |
||||
276 | return $success; |
||||
277 | } |
||||
278 | |||||
279 | /** |
||||
280 | * perform the required action |
||||
281 | * |
||||
282 | * @param int $_action one of $this->actions |
||||
283 | * @param importexport_iface_egw_record $record contact data for the action |
||||
284 | * @return bool success or not |
||||
285 | */ |
||||
286 | protected function action ( $_action, importexport_iface_egw_record &$record, $record_num = 0 ) { |
||||
287 | $_data = $record->get_record_array(); |
||||
288 | |||||
289 | // Make sure picture is loaded/updated |
||||
290 | if($_data['jpegphoto']) |
||||
291 | { |
||||
292 | $_data['photo_unchanged'] = false; |
||||
293 | } |
||||
294 | |||||
295 | switch ($_action) { |
||||
296 | case 'none' : |
||||
297 | return true; |
||||
298 | case 'delete': |
||||
299 | if($_data['id']) |
||||
300 | { |
||||
301 | if ( $this->dry_run ) { |
||||
302 | //print_r($_data); |
||||
303 | $this->results[$_action]++; |
||||
304 | return true; |
||||
305 | } |
||||
306 | $result = $this->bocontacts->delete($_data); |
||||
307 | if($result && $result === true) |
||||
0 ignored issues
–
show
|
|||||
308 | { |
||||
309 | $this->results[$_action]++; |
||||
310 | } |
||||
311 | else |
||||
312 | { |
||||
313 | // Failure of some kind - unknown cause |
||||
314 | $this->errors[$record_num] = lang('unable to delete'); |
||||
315 | } |
||||
316 | } |
||||
317 | break; |
||||
318 | case 'update' : |
||||
319 | // Only update if there are changes |
||||
320 | $old = $this->bocontacts->read($_data['id']); |
||||
321 | // if we get countrycodes as countryname, try to translate them -> the rest should be handled by bo classes. |
||||
322 | foreach(array('adr_one_', 'adr_two_') as $c_prefix) { |
||||
323 | if (strlen(trim($_data[$c_prefix.'countryname']))==2) |
||||
324 | $_data[$c_prefix.'countryname'] = $GLOBALS['egw']->country->get_full_name(trim($_data[$c_prefix.'countryname']), true); |
||||
325 | } |
||||
326 | // Don't change a user account into a contact |
||||
327 | if($old['owner'] == 0) { |
||||
328 | unset($_data['owner']); |
||||
329 | } elseif(!$this->definition->plugin_options['change_owner']) { |
||||
330 | // Don't change addressbook of an existing contact |
||||
331 | unset($_data['owner']); |
||||
332 | } |
||||
333 | |||||
334 | $this->ids[] = $_data['id']; |
||||
335 | |||||
336 | // Merge to deal with fields not in import record |
||||
337 | $_data = array_merge($old, $_data); |
||||
338 | $changed = $this->tracking->changed_fields($_data, $old); |
||||
339 | if(count($changed) == 0) { |
||||
340 | return true; |
||||
341 | } else { |
||||
342 | //error_log(__METHOD__.__LINE__.array2string($changed).' Old:'.$old['adr_one_countryname'].' ('.$old['adr_one_countrycode'].') New:'.$_data['adr_one_countryname'].' ('.$_data['adr_one_countryname'].')'); |
||||
343 | } |
||||
344 | |||||
345 | // Make sure n_fn gets updated |
||||
346 | unset($_data['n_fn']); |
||||
347 | |||||
348 | // Fall through |
||||
349 | case 'insert' : |
||||
350 | if($_action == 'insert') { |
||||
351 | // Addressbook backend doesn't like inserting with ID specified, it screws up the owner & etag |
||||
352 | unset($_data['id']); |
||||
353 | } |
||||
354 | if(!isset($_data['org_name'])) { |
||||
355 | // org_name is a trigger to update n_fileas |
||||
356 | $_data['org_name'] = ''; |
||||
357 | } |
||||
358 | |||||
359 | if ( $this->dry_run ) { |
||||
360 | //print_r($_data); |
||||
361 | $this->results[$_action]++; |
||||
362 | return true; |
||||
363 | } else { |
||||
364 | $result = $this->bocontacts->save( $_data, $this->is_admin); |
||||
365 | if(!$result) { |
||||
366 | $this->errors[$record_num] = $this->bocontacts->error; |
||||
367 | } else { |
||||
368 | $this->ids[] = $result; |
||||
369 | $this->results[$_action]++; |
||||
370 | // This does nothing (yet?) but update the identifier |
||||
371 | $record->save($result); |
||||
372 | } |
||||
373 | return $result; |
||||
374 | } |
||||
375 | default: |
||||
376 | throw new Api\Exception('Unsupported action: '. $_action); |
||||
377 | |||||
378 | } |
||||
379 | } |
||||
380 | |||||
381 | |||||
382 | /** |
||||
383 | * Delete all contacts from the addressbook, except the given list |
||||
384 | * |
||||
385 | * @param int $addressbook Addressbook to clear |
||||
386 | * @param array $ids Contacts to keep |
||||
387 | */ |
||||
388 | protected function empty_addressbook($addressbook, $ids) |
||||
389 | { |
||||
390 | // Get all IDs in addressbook |
||||
391 | $contacts = $this->bocontacts->search(array('owner' => $addressbook), true); |
||||
392 | $contacts = array_column($contacts, 'id'); |
||||
393 | |||||
394 | $delete = array_diff($contacts, $ids); |
||||
395 | |||||
396 | foreach($delete as $id) |
||||
397 | { |
||||
398 | if($this->dry_run || $this->bocontacts->delete($id)) |
||||
399 | { |
||||
400 | $this->results['deleted']++; |
||||
401 | } |
||||
402 | else |
||||
403 | { |
||||
404 | $this->warnings[] = lang('Unable to delete') . ': ' . Api\Link::title('addressbook', $id); |
||||
0 ignored issues
–
show
|
|||||
405 | } |
||||
406 | } |
||||
407 | } |
||||
408 | |||||
409 | /** |
||||
410 | * returns translated name of plugin |
||||
411 | * |
||||
412 | * @return string name |
||||
413 | */ |
||||
414 | public static function get_name() { |
||||
415 | return lang('Addressbook CSV import'); |
||||
416 | } |
||||
417 | |||||
418 | /** |
||||
419 | * returns translated (user) description of plugin |
||||
420 | * |
||||
421 | * @return string descriprion |
||||
422 | */ |
||||
423 | public static function get_description() { |
||||
424 | return lang("Imports contacts into your Addressbook from a CSV File. CSV means 'Comma Separated Values'. However in the options Tab you can also choose other seperators."); |
||||
425 | } |
||||
426 | |||||
427 | /** |
||||
428 | * retruns file suffix(s) plugin can handle (e.g. csv) |
||||
429 | * |
||||
430 | * @return string suffix (comma seperated) |
||||
431 | */ |
||||
432 | public static function get_filesuffix() { |
||||
433 | return 'csv'; |
||||
434 | } |
||||
435 | |||||
436 | /** |
||||
437 | * return etemplate components for options. |
||||
438 | * @abstract We can't deal with etemplate objects here, as an uietemplate |
||||
439 | * objects itself are scipt orientated and not "dialog objects" |
||||
440 | * |
||||
441 | * @return array ( |
||||
442 | * name => string, |
||||
443 | * content => array, |
||||
444 | * sel_options => array, |
||||
445 | * preserv => array, |
||||
446 | * ) |
||||
447 | */ |
||||
448 | public function get_options_etpl(importexport_definition &$definition=null) |
||||
449 | { |
||||
450 | // lets do it! |
||||
451 | } |
||||
452 | |||||
453 | /** |
||||
454 | * returns etemplate name for slectors of this plugin |
||||
455 | * |
||||
456 | * @return string etemplate name |
||||
457 | */ |
||||
458 | public function get_selectors_etpl() { |
||||
459 | // lets do it! |
||||
460 | } |
||||
461 | |||||
462 | /** |
||||
463 | * Returns warnings that were encountered during importing |
||||
464 | * Maximum of one warning message per record, but you can append if you need to |
||||
465 | * |
||||
466 | * @return Array ( |
||||
467 | * record_# => warning message |
||||
468 | * ) |
||||
469 | */ |
||||
470 | public function get_warnings() { |
||||
471 | return $this->warnings; |
||||
472 | } |
||||
473 | |||||
474 | /** |
||||
475 | * Returns errors that were encountered during importing |
||||
476 | * Maximum of one error message per record, but you can append if you need to |
||||
477 | * |
||||
478 | * @return Array ( |
||||
479 | * record_# => error message |
||||
480 | * ) |
||||
481 | */ |
||||
482 | public function get_errors() { |
||||
483 | return $this->errors; |
||||
484 | } |
||||
485 | |||||
486 | /** |
||||
487 | * Returns a list of actions taken, and the number of records for that action. |
||||
488 | * Actions are things like 'insert', 'update', 'delete', and may be different for each plugin. |
||||
489 | * |
||||
490 | * @return Array ( |
||||
491 | * action => record count |
||||
492 | * ) |
||||
493 | */ |
||||
494 | public function get_results() { |
||||
495 | return $this->results; |
||||
496 | } |
||||
497 | } |
||||
498 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths