ContactCSVBulkLoader   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 27
eloc 82
c 2
b 0
f 0
dl 0
loc 210
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
B processRecord() 0 34 8
B createRelationFromList() 0 25 7
A collateAddressData() 0 20 4
A findOrMakeLocation() 0 15 2
A importTagsList() 0 13 2
A createMemberObject() 0 12 2
A importListsList() 0 13 2
1
<?php
2
3
namespace SilverCommerce\ContactAdmin\Import;
4
5
use SilverStripe\ORM\DataObject;
6
use SilverStripe\Dev\CsvBulkLoader;
7
use SilverCommerce\ContactAdmin\Helpers\ContactHelper;
8
use SilverCommerce\ContactAdmin\Model\Contact;
9
use SilverCommerce\ContactAdmin\Model\ContactList;
10
use SilverCommerce\ContactAdmin\Model\ContactLocation;
11
use SilverCommerce\ContactAdmin\Model\ContactTag;
12
13
/**
14
 * Allow slightly more complex product imports from a CSV file
15
 *
16
 * @author i-lateral (http://www.i-lateral.com)
17
 * @package catalogue
18
 */
19
class ContactCSVBulkLoader extends CsvBulkLoader
20
{
21
    const ADDRESS_PREFIX = 'Address';
22
23
    public $columnMap = [
24
        "TagsList"              => '->importTagsList',
25
        "ListsList"              => '->importTagsList',
26
        "CreateMember"              => '->createMemberObject',
27
    ];
28
29
    public $duplicateChecks = [
30
        'ID'        => 'ID',
31
        'StockID'   => 'StockID'
32
    ];
33
34
    /**
35
     * Generate the selected relation from the provided array of values
36
     *
37
     * @param DataObject $object   The current object being imported
38
     * @param string $relation The name of the relation (eg Images)
39
     * @param array  $list     The list of values
40
     * @param string $class    The source class of the relation (eg SilverStripe\Assets\Image)
41
     * @param string $column   The name of the column to search for existing records
42
     * @param string $create   Create a new object if none found
43
     *
44
     * @return void
45
     */
46
    protected static function createRelationFromList(
47
        $object,
48
        $relation,
49
        $list,
50
        $class,
51
        $column,
52
        $create = false
53
    ) {
54
        if ($object->hasMethod($relation)) {
55
            $object->$relation()->removeAll();
56
57
            foreach ($list as $name) {
58
                $name = trim($name);
59
60
                if (!empty($name)) {
61
                    $obj = $class::get()->find($column, $name);
62
63
                    if (empty($obj) && $create) {
64
                        $obj = $class::create();
65
                        $obj->$column = $name;
66
                        $obj->write();
67
                    }
68
69
                    if (!empty($obj)) {
70
                        $object->$relation()->add($obj);
71
                    }
72
                }
73
            }
74
        }
75
    }
76
77
    /**
78
     * Collect the address data from the provided record array and return an
79
     * array of addresses
80
     *
81
     * @param array $record
82
     *
83
     * @return array
84
     */
85
    protected function collateAddressData(array $record)
86
    {
87
        $addresses = [];
88
89
        // Loop through all fields and find/compile addresses
90
        // denoted by a 'AddressX_XX' column
91
        foreach ($record as $key => $value) {
92
            if (strpos($key, self::ADDRESS_PREFIX) !== false) {
93
                $field_data = explode('_', $key);
94
                $pos = (int)substr($field_data[0], strlen(self::ADDRESS_PREFIX));
95
96
                if (!isset($addresses[$pos])) {
97
                    $addresses[$pos] = [];
98
                }
99
100
                $addresses[$pos][$field_data[1]] = $value;
101
            }
102
        }
103
104
        return $addresses;
105
    }
106
107
    /**
108
     * Either find (or create a new) contact location for the provided contact, in the defined position
109
     *
110
     * @param Contact $contact
111
     * @param array $address_data
112
     * @param int $pos
113
     *
114
     * @return ContactLocation
115
     */
116
    protected function findOrMakeLocation(Contact $contact, array $address_data, int $pos)
117
    {
118
        $location = $contact
119
            ->Locations()
120
            ->offsetGet($pos);
121
122
        if (empty($location)) {
123
            $location = ContactLocation::create();
124
            $location->ContactID = $contact->ID;
125
        }
126
127
        $location->update($address_data);
128
        $location->write();
129
130
        return $location;
131
    }
132
133
    /**
134
     * Overwrite processing of individual record so we can collect and process location
135
     * data to generate locations
136
     *
137
     * @param array $record
138
     * @param array $columnMap
139
     * @param BulkLoader_Result $results
0 ignored issues
show
Bug introduced by
The type SilverCommerce\ContactAd...mport\BulkLoader_Result was not found. Maybe you did not declare it correctly or list all dependencies?

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:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
140
     * @param boolean $preview
141
     *
142
     * @return int
143
     */
144
    public function processRecord($record, $columnMap, &$results, $preview = false)
145
    {
146
        $this->extend("onBeforeProcess", $record, $columnMap, $results, $preview);
147
148
        $objID = parent::processRecord($record, $columnMap, $results, $preview);
149
        $object = DataObject::get_by_id(Contact::class, $objID);
150
151
        if (!empty($object) && $object instanceof Contact) {
152
            $addresses = $this->collateAddressData($record);
153
            $i = 0;
154
155
            foreach ($addresses as $address_data) {
156
                if (empty($address_data['Address1']) && empty($address_data['PostCode'])) {
157
                    continue;
158
                }
159
160
                $this->findOrMakeLocation($object, $address_data, $i);
161
                $i++;
162
            }
163
        }
164
165
        $this->extend("onAfterProcess", $object, $record, $columnMap, $results, $preview);
166
167
        if (!empty($object)) {
168
            $object->destroy();
169
            unset($object);
170
        }
171
172
        // Reset default object class
173
        if (!empty($curr_class)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $curr_class seems to never exist and therefore empty should always be true.
Loading history...
174
            $this->objectClass = $curr_class;
175
        }
176
177
        return $objID;
178
    }
179
180
    public static function importTagsList(&$obj, $val, $record)
181
    {
182
        if (!$obj->exists()) {
183
            $obj->write();
184
        }
185
186
        self::createRelationFromList(
187
            $obj,
188
            'Tags',
189
            explode(",", $val),
190
            ContactTag::class,
191
            'Title',
192
            true
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $create of SilverCommerce\ContactAd...reateRelationFromList(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

192
            /** @scrutinizer ignore-type */ true
Loading history...
193
        );
194
    }
195
196
    public static function importListsList(&$obj, $val, $record)
197
    {
198
        if (!$obj->exists()) {
199
            $obj->write();
200
        }
201
202
        self::createRelationFromList(
203
            $obj,
204
            'Lists',
205
            explode(",", $val),
206
            ContactList::class,
207
            'Title',
208
            true
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $create of SilverCommerce\ContactAd...reateRelationFromList(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

208
            /** @scrutinizer ignore-type */ true
Loading history...
209
        );
210
    }
211
212
    /**
213
     * Generate a user account for this contact
214
     *
215
     * @return null
216
     */
217
    public static function createMemberObject(&$obj, $val, $record)
218
    {
219
        if (!$obj->exists()) {
220
            $obj->write();
221
        }
222
223
        $helper = ContactHelper::create()
224
            ->setContact($obj);
225
226
        $member = $helper->findOrMakeMember();
227
        $helper->setMember($member);
228
        $helper->linkMemberToGroups();
229
    }
230
}
231