1 <?php
2 3 4 5 6 7 8 9 10 11 12
13 class CsvBulkLoader extends BulkLoader {
14
15 16 17 18 19
20 public $delimiter = ',';
21
22 23 24 25 26
27 public $enclosure = '"';
28
29 30 31 32
33 public = true;
34
35 protected function processAll($filepath, $preview = false) {
36 $results = new BulkLoader_Result();
37
38 $csv = new CSVParser($filepath, $this->delimiter, $this->enclosure);
39
40
41 if($this->columnMap) {
42 if($this->hasHeaderRow) $csv->mapColumns($this->columnMap);
43 else $csv->provideHeaderRow($this->columnMap);
44 }
45
46 foreach($csv as $row) {
47 $this->processRecord($row, $this->columnMap, $results, $preview);
48 }
49
50 return $results;
51 }
52
53 54 55 56
57 protected function processRecord($record, $columnMap, &$results, $preview = false) {
58 $class = $this->objectClass;
59
60
61 $existingObj = $this->findExistingObject($record, $columnMap);
62 $obj = ($existingObj) ? $existingObj : new $class();
63
64
65
66 $relations = array();
67 foreach($record as $fieldName => $val) {
68
69 if($this->isNullValue($val)) continue;
70
71
72 if(isset($this->relationCallbacks[$fieldName])) {
73
74
75 $relationName = $this->relationCallbacks[$fieldName]['relationname'];
76 if($this->hasMethod($this->relationCallbacks[$fieldName]['callback'])) {
77 $relationObj = $this->{$this->relationCallbacks[$fieldName]['callback']}($obj, $val, $record);
78 } elseif($obj->hasMethod($this->relationCallbacks[$fieldName]['callback'])) {
79 $relationObj = $obj->{$this->relationCallbacks[$fieldName]['callback']}($val, $record);
80 }
81 if(!$relationObj || !$relationObj->exists()) {
82 $relationClass = $obj->has_one($relationName);
83 $relationObj = new $relationClass();
84 $relationObj->write();
85 }
86 $obj->setComponent($relationName, $relationObj);
87 $obj->{"{$relationName}ID"} = $relationObj->ID;
88 $obj->write();
89 $obj->flushCache();
90
91 } elseif(strpos($fieldName, '.') !== false) {
92
93 list($relationName,$columnName) = explode('.', $fieldName);
94 $relationObj = $obj->getComponent($relationName);
95 $obj->setComponent($relationName, $relationObj);
96 $relationObj->write();
97 $obj->{"{$relationName}ID"} = $relationObj->ID;
98 $obj->write();
99 $obj->flushCache();
100 }
101
102 }
103
104
105 foreach($record as $fieldName => $val) {
106 if($this->isNullValue($val, $fieldName)) continue;
107 if(strpos($fieldName, '->') !== FALSE) {
108 $funcName = substr($fieldName, 2);
109 $this->$funcName($obj, $val, $record);
110 } else if($obj->hasMethod("import{$fieldName}")) {
111 $obj->{"import{$fieldName}"}($val, $record);
112 } else {
113 $obj->update(array($fieldName => $val));
114 }
115 }
116
117
118 $id = ($preview) ? 0 : $obj->write();
119
120
121 $message = '';
122
123
124 if($existingObj) {
125 $results->addUpdated($obj, $message);
126 } else {
127 $results->addCreated($obj, $message);
128 }
129
130 $objID = $obj->ID;
131
132 $obj->destroy();
133
134
135 unset($existingObj);
136 unset($obj);
137
138 return $objID;
139 }
140
141 142 143 144 145 146 147
148 public function findExistingObject($record) {
149 $SNG_objectClass = singleton($this->objectClass);
150
151
152 foreach($this->duplicateChecks as $fieldName => $duplicateCheck) {
153 if(is_string($duplicateCheck)) {
154 $SQL_fieldName = Convert::raw2sql($duplicateCheck);
155 if(!isset($record[$fieldName])) {
156 return false;
157
158 }
159 $SQL_fieldValue = $record[$fieldName];
160 $existingRecord = DataObject::get_one($this->objectClass, "\"$SQL_fieldName\" = '{$SQL_fieldValue}'");
161 if($existingRecord) return $existingRecord;
162 } elseif(is_array($duplicateCheck) && isset($duplicateCheck['callback'])) {
163 if($this->hasMethod($duplicateCheck['callback'])) {
164 $existingRecord = $this->{$duplicateCheck['callback']}($record[$fieldName], $record);
165 } elseif($SNG_objectClass->hasMethod($duplicateCheck['callback'])) {
166 $existingRecord = $SNG_objectClass->{$duplicateCheck['callback']}($record[$fieldName], $record);
167 } else {
168 user_error("CsvBulkLoader::processRecord(): {$duplicateCheck['callback']} not found on importer or object class.", E_USER_ERROR);
169 }
170
171 if($existingRecord) return $existingRecord;
172 } else {
173 user_error('CsvBulkLoader::processRecord(): Wrong format for $duplicateChecks', E_USER_ERROR);
174 }
175 }
176
177 return false;
178 }
179
180
181 182 183 184 185 186
187 public function () {
188 return ($this->hasHeaderRow || isset($this->columnMap));
189 }
190
191 }
192 ?>
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-