1 <?php
2
3 4 5 6 7
8 class RecipientImportField extends FormField {
9
10 protected $memberGroup;
11 protected $memberClass;
12 protected $tableColumns;
13 protected $table;
14 protected $clientFileName;
15 protected $typeID;
16
17 static $column_types = array(
18 'Salutation' => array( 'title', 'salutation' ),
19 'FirstName' => array( 'firstname', 'christianname', 'givenname' ),
20 'Surname' => array( 'lastname','surname', 'familyname' ),
21 'Email' => array( 'email', 'emailaddress' ),
22 'Address' => array( 'address' ),
23 'PhoneNumber' => array('phone','phonenumber'),
24 'JobTitle' => array( 'jobtitle' ),
25 'Organisation' => array( 'organisation', 'organization' ),
26 'EmailType' => array( 'htmlorplaintext', 'emailtype' )
27 );
28
29 static $custom_set_fields = array();
30
31 public static function setCustomField( $getMapCode, $fieldName ) {
32 self::$custom_set_fields[] = array(
33 'Code' => $getMapCode,
34 'Field' => $fieldName
35 );
36 }
37
38 function __construct( $name, $title, $memberGroup, $memberClass = 'Member', $form = null ) {
39 $this->memberGroup = $memberGroup;
40 $this->memberClass = $memberClass;
41 parent::__construct( $name, $title, null, $form );
42 }
43
44 function Field() {
45 $frameURL = Director::absoluteBaseURL() . 'admin/newsletter/displayfilefield/' . $this->typeID;
46
47 return "<iframe name=\"{$this->Name}\" frameborder=\"0\" class=\"RecipientImportField\" src=\"$frameURL\"></iframe>";
48 }
49
50 function setTypeID( $id ) {
51 $this->typeID = $id;
52 }
53
54 function CustomSetFields() {
55 $fields = new FieldSet();
56
57
58
59 foreach( self::$custom_set_fields as $customField ) {
60 eval( '$map = ' . $customField['Code'] .';' );
61
62 $noneMap = array( 0 => '(Not set)' );
63
64 $map = $noneMap + $map;
65
66 $fields->push( new DropdownField( 'Set['.$customField['Field'].']', $customField['Field'], $map ) );
67 }
68
69 return $fields;
70 }
71
72 73 74
75 static function fileupload() {
76
77 }
78
79 80 81 82
83 function displaytable() {
84
85
86 $tempFile = fopen( $_FILES['ImportFile']['tmp_name'], 'r' );
87
88
89 if(!$tempFile) {
90 return 'The selected file did not arrive at the server';
91 }
92
93 $this->clientFileName = $_FILES['ImportFile']['name'];
94
95 while( ( $row = fgetcsv( $tempFile ) ) !== false ) {
96
97 if( !$this->tableColumns ) {
98 $this->parseTableHeader( $row );
99 } else {
100 $newRow = array();
101 $newSessionTableRow = array();
102
103 foreach( $row as $cell ) {
104 $newRow[] = $this->parseCSVCell( $cell );
105 $newSessionTableRow[] = $cell;
106 }
107
108 $cells = new DataObjectSet( $newRow );
109 $table[] = $cells->customise( array( 'Cells' => $cells ) );
110
111 $sessionTable[] = $newSessionTableRow;
112 }
113 }
114
115 fclose( $tempFile );
116
117 $this->table = new DataObjectSet( $table );
118
119 Session::set("ImportFile.{$_REQUEST['ID']}", $sessionTable);
120
121 return $this->renderWith( 'Newsletter_RecipientImportField_Table' );
122 }
123
124 125 126
127 function ( $columns ) {
128
129 $columnSource = array_combine(
130 array_keys( self::$column_types ),
131 array_keys( self::$column_types )
132 );
133
134 $columnSource = array_merge( array( 'Unknown' => 'Unknown' ), $columnSource );
135 $colCount = 0;
136 foreach( $columns as $cell ) {
137 $columnType = $this->getColumnType( $this->parseCSVCell( $cell )->Value() );
138 $this->tableColumns[] = new DropdownField( 'ImportFileColumns[' . (string)( $colCount++ ) . ']', '', $columnSource, $columnType );
139 }
140 }
141
142 function parseCSVCell( $cell ) {
143 return new RecipientImportField_Cell( $cell );
144 }
145
146 function getColumnType( $cell ) {
147 $cell = strtolower( $cell );
148 $escapedValue = preg_replace( '/[^a-z]/', '', $cell );
149
150 foreach( self::$column_types as $type => $aliases ) {
151 if( in_array( $escapedValue, $aliases ) )
152 return $type;
153 }
154
155 return 'Unknown';
156 }
157
158 function setController( $controller ) {
159 $this->controller = $controller;
160 }
161
162 163 164
165 function ColumnHeaders() {
166 return new DataObjectSet( $this->tableColumns );
167 }
168
169 function Rows() {
170 return $this->table;
171 }
172
173 function FileName() {
174 return $this->clientFileName;
175 }
176
177 function TypeID() {
178 return $this->typeID;
179 }
180 }
181
182 183 184 185 186
187 class RecipientImportField_Cell extends ViewableData {
188 protected $value;
189
190 function __construct( $value ) {
191 $this->value = $value;
192 parent::__construct();
193 }
194
195 function Value() {
196 return $this->value;
197 }
198 }
199
200 201 202 203 204
205 class RecipientImportField_UploadForm extends Form {
206 function import( $data, $form ) {
207 $id = $data['ID'];
208 $mailType = DataObject::get_one("NewsletterType", "ID = $id");
209 if($mailType->GroupID)
210 $group = DataObject::get_one("Group", "ID = $mailType->GroupID");
211
212 $recipientField = new RecipientImportField("ImportFile","Import from file", $group );
213 $recipientField->setTypeID( $id );
214
215
216 if( empty( $_FILES ) || empty( $_FILES['ImportFile'] ) || $_FILES['ImportFile']['size'] == 0 )
217 return $this->customise( array( 'ID' => $id, "UploadForm" => $this->controller->UploadForm( $id ), 'ErrorMessage' => 'Please choose a CSV file to import' ) )->renderWith('Newsletter_RecipientImportField');
218 elseif( !$this->isValidCSV( $_FILES['ImportFile'] ) ) {
219 220
221 return $this->customise( array( 'ID' => $id, "UploadForm" => $this->controller->UploadForm( $id ), 'ErrorMessage' => 'The selected file was not a CSV file' ) )->renderWith('Newsletter_RecipientImportField');
222 } else
223 return $recipientField->displaytable();
224 }
225
226 function isValidCSV( $file ) {
227 return preg_match( '/.*\.csv$/i', $file['name'] ) > 0;
228 }
229
230 function confirm( $data, $form ) {
231 $id = $data['ID'];
232 $mailType = DataObject::get_one("NewsletterType", "ID = $id");
233 if($mailType->GroupID)
234 $group = DataObject::get_one("Group", "ID = $mailType->GroupID");
235
236 return $this->importMembers( $id, $group, $data['ImportFileColumns'], (isset($data['Set']) ? $data['Set'] : array()));
237 }
238
239 function cancel( $data, $form ) {
240 $newForm = $this->controller->UploadForm( $data['ID'] );
241 return $newForm->forTemplate();
242 }
243
244 function action_import( $data, $form ) {
245 return $this->import( $data, $form );
246 }
247
248 function action_confirm( $data, $form ) {
249 return $this->confirm( $data, $form );
250 }
251
252 function action_cancel( $data, $form ) {
253 return $this->cancel( $data, $form );
254 }
255
256 257 258
259 protected function importMembers( $id, $group, $cols, $setFields, $primaryColType = 'Email' ) {
260
261 $startTime = time();
262
263 $importData = Session::get("ImportFile.{$id}");
264
265 $validColumns = array_keys( RecipientImportField::$column_types );
266
267 $columnMap = array_flip( $cols );
268
269
270
271
272 $primaryColumn = $columnMap[$primaryColType];
273
274
275 $changedFields = array();
276
277
278 $importColumns = array_intersect( $validColumns, $cols );
279
280
281 $newMembers = 0;
282 $changedMembers = 0;
283 $skippedMembers = 0;
284
285
286 $newMemberClass = Object::getCustomClass( 'Member' );
287
288
289 foreach( $importData as $newMemberRow ) {
290
291
292 if( empty( $newMemberRow[$primaryColumn] ) ) {
293 $skippedMembers++;
294 continue;
295 }
296
297
298 $trackChanges = true;
299
300
301 $member = $this->findMember( $newMemberRow[$primaryColumn] );
302
303 if( !$member ) {
304 $newMembers++;
305 $trackChanges = false;
306 $member = Object::create("Member");
307 } else {
308
309 if( $member->Unsubscribed ) {
310 $skippedMembers++;
311 continue;
312 }
313
314 if( $member->class != $newMemberClass )
315 $member->setClassName( $newMemberClass );
316
317 $changedMembers++;
318 }
319
320
321 foreach( $importColumns as $datum ) {
322
323
324 $newValue = trim( $newMemberRow[$columnMap[$datum]] );
325 $oldValue = trim( $member->$datum );
326
327
328
329
330 if( $trackChanges && $newValue != $oldValue && $datum != $primaryColumn ) {
331 $changedFields[] = array(
332 $newMemberRow[$primaryColumn],
333 "$datum:\n$oldValue",
334 "$datum:\n$newValue"
335 );
336
337 $numChangedFields++;
338 }
339
340 $member->$datum = $newValue;
341 }
342
343
344 if( $setFields )
345 foreach( $setFields as $fieldName => $fieldValue )
346 $member->$fieldName = $fieldValue;
347
348
349 $member->write();
350 $member->Groups()->add( $group->ID );
351 }
352
353 $numChangedFields = count( $changedFields );
354 $this->notifyChanges( $changedFields );
355
356
357 $customData = array(
358 'ID' => $id,
359 "UploadForm" => $this->controller->UploadForm( $id ),
360 'ImportMessage' => 'Imported new members',
361 'NewMembers' => (string)$newMembers,
362 'ChangedMembers' => (string)$changedMembers,
363 'ChangedFields' => (string)$numChangedFields,
364 'SkippedRecords' => (string)$skippedMembers,
365 'Time' => time() - $startTime
366 );
367 return $this->customise( $customData )->renderWith('Newsletter_RecipientImportField');
368 }
369
370 function findMember( $email ) {
371 $email = addslashes( $email );
372 if(defined('DB::USE_ANSI_SQL')) {
373 return DataObject::get_one( 'Member', "\"Email\"='$email'" );
374 } else {
375 return DataObject::get_one( 'Member', "`Email`='$email'" );
376 }
377 }
378
379 function notifyChanges( $changes ) {
380 $email = new Email( Email::getAdminEmail(), Email::getAdminEmail(), 'Changed Fields' );
381
382 $body = "";
383
384 foreach( $changes as $change ) {
385 $body .= "-------------------------------\n";
386 $body .= implode( ' ', $change ) . "\n";
387 }
388
389 $email->setBody( $body );
390 $email->send();
391 }
392 }
393 ?>
[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.
-