mirror of
https://github.com/silverstripe/silverstripe-reports
synced 2024-10-22 11:05:53 +02:00
d9ac1a1f85
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/cms/trunk@47798 467b73ca-7a2a-4603-9d3b-597d59a354a9
391 lines
10 KiB
PHP
Executable File
391 lines
10 KiB
PHP
Executable File
<?php
|
|
|
|
/**
|
|
* @package cms
|
|
* @subpackage newsletter
|
|
*/
|
|
|
|
/**
|
|
* Displays a field for importing recipients.
|
|
* @package cms
|
|
* @subpackage newsletter
|
|
*/
|
|
class RecipientImportField extends FormField {
|
|
|
|
protected $memberGroup;
|
|
protected $memberClass;
|
|
protected $tableColumns;
|
|
protected $table;
|
|
protected $clientFileName;
|
|
protected $typeID;
|
|
|
|
static $column_types = array(
|
|
'Salutation' => array( 'title', 'salutation' ),
|
|
'FirstName' => array( 'firstname', 'christianname', 'givenname' ),
|
|
'Surname' => array( 'lastname','surname', 'familyname' ),
|
|
'Email' => array( 'email', 'emailaddress' ),
|
|
'Address' => array( 'address' ),
|
|
'PhoneNumber' => array('phone','phonenumber'),
|
|
'JobTitle' => array( 'jobtitle' ),
|
|
'Organisation' => array( 'organisation', 'organization' ),
|
|
'EmailType' => array( 'htmlorplaintext', 'emailtype' )
|
|
);
|
|
|
|
static $custom_set_fields = array();
|
|
|
|
public static function setCustomField( $getMapCode, $fieldName ) {
|
|
self::$custom_set_fields[] = array(
|
|
'Code' => $getMapCode,
|
|
'Field' => $fieldName
|
|
);
|
|
}
|
|
|
|
function __construct( $name, $title, $memberGroup, $memberClass = 'Member', $form = null ) {
|
|
$this->memberGroup = $memberGroup;
|
|
$this->memberClass = $memberClass;
|
|
parent::__construct( $name, $title, null, $form );
|
|
}
|
|
|
|
function Field() {
|
|
$frameURL = Director::absoluteBaseURL() . 'admin/newsletter/displayfilefield/' . $this->typeID;
|
|
|
|
return "<iframe name=\"{$this->Name}\" frameborder=\"0\" class=\"RecipientImportField\" src=\"$frameURL\"></iframe>";
|
|
}
|
|
|
|
function setTypeID( $id ) {
|
|
$this->typeID = $id;
|
|
}
|
|
|
|
function CustomSetFields() {
|
|
$fields = new FieldSet();
|
|
|
|
|
|
|
|
foreach( self::$custom_set_fields as $customField ) {
|
|
eval( '$map = ' . $customField['Code'] .';' );
|
|
|
|
$noneMap = array( 0 => '(Not set)' );
|
|
|
|
$map = $noneMap + $map;
|
|
|
|
$fields->push( new DropdownField( 'Set['.$customField['Field'].']', $customField['Field'], $map ) );
|
|
}
|
|
|
|
return $fields;
|
|
}
|
|
|
|
/**
|
|
* Returns HTML to be displayed inside the IFrame
|
|
*/
|
|
static function fileupload() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Returns the table of results to be displayed in the table of
|
|
* details loaded from the file
|
|
*/
|
|
function displaytable() {
|
|
|
|
// Check that a file was uploaded
|
|
|
|
$tempFile = fopen( $_FILES['ImportFile']['tmp_name'], 'r' );
|
|
|
|
// display some error if the file cannot be opened
|
|
|
|
$this->clientFileName = $_FILES['ImportFile']['name'];
|
|
|
|
while( ( $row = fgetcsv( $tempFile ) ) !== false ) {
|
|
|
|
if( !$this->tableColumns ) {
|
|
$this->parseTableHeader( $row );
|
|
} else {
|
|
$newRow = array();
|
|
$newSessionTableRow = array();
|
|
|
|
foreach( $row as $cell ) {
|
|
$newRow[] = $this->parseCSVCell( $cell );
|
|
$newSessionTableRow[] = $cell;
|
|
}
|
|
|
|
$cells = new DataObjectSet( $newRow );
|
|
$table[] = $cells->customise( array( 'Cells' => $cells ) );
|
|
|
|
$sessionTable[] = $newSessionTableRow;
|
|
}
|
|
}
|
|
|
|
fclose( $tempFile );
|
|
|
|
$this->table = new DataObjectSet( $table );
|
|
|
|
Session::set("ImportFile.{$_REQUEST['ID']}", $sessionTable);
|
|
|
|
return $this->renderWith( 'Newsletter_RecipientImportField_Table' );
|
|
}
|
|
|
|
/**
|
|
* Determines what type each column is
|
|
*/
|
|
function parseTableHeader( $columns ) {
|
|
|
|
$columnSource = array_combine(
|
|
array_keys( self::$column_types ),
|
|
array_keys( self::$column_types )
|
|
);
|
|
|
|
$columnSource = array_merge( array( 'Unknown' => 'Unknown' ), $columnSource );
|
|
$colCount = 0;
|
|
foreach( $columns as $cell ) {
|
|
$columnType = $this->getColumnType( $this->parseCSVCell( $cell )->Value() );
|
|
$this->tableColumns[] = new DropdownField( 'ImportFileColumns[' . (string)( $colCount++ ) . ']', '', $columnSource, $columnType );
|
|
}
|
|
}
|
|
|
|
function parseCSVCell( $cell ) {
|
|
return new RecipientImportField_Cell( $cell );
|
|
}
|
|
|
|
function getColumnType( $cell ) {
|
|
$cell = strtolower( $cell );
|
|
$escapedValue = preg_replace( '/[^a-z]/', '', $cell );
|
|
|
|
foreach( self::$column_types as $type => $aliases ) {
|
|
if( in_array( $escapedValue, $aliases ) )
|
|
return $type;
|
|
}
|
|
|
|
return 'Unknown';
|
|
}
|
|
|
|
function setController( $controller ) {
|
|
$this->controller = $controller;
|
|
}
|
|
|
|
/**
|
|
* Set of table column headers
|
|
*/
|
|
function ColumnHeaders() {
|
|
return new DataObjectSet( $this->tableColumns );
|
|
}
|
|
|
|
function Rows() {
|
|
return $this->table;
|
|
}
|
|
|
|
function FileName() {
|
|
return $this->clientFileName;
|
|
}
|
|
|
|
function TypeID() {
|
|
return $this->typeID;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Single cell of the recipient import field
|
|
* @package cms
|
|
* @subpackage newsletter
|
|
*/
|
|
class RecipientImportField_Cell extends ViewableData {
|
|
protected $value;
|
|
|
|
function __construct( $value ) {
|
|
$this->value = $value;
|
|
}
|
|
|
|
function Value() {
|
|
return $this->value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upload form that appears in the iframe
|
|
* @package cms
|
|
* @subpackage newsletter
|
|
*/
|
|
class RecipientImportField_UploadForm extends Form {
|
|
function import( $data, $form ) {
|
|
$id = $data['ID'];
|
|
$mailType = DataObject::get_one("NewsletterType", "ID = $id");
|
|
if($mailType->GroupID)
|
|
$group = DataObject::get_one("Group", "ID = $mailType->GroupID");
|
|
|
|
$recipientField = new RecipientImportField("ImportFile","Import from file", $group );
|
|
$recipientField->setTypeID( $id );
|
|
|
|
// if the file is not valid, then return an error
|
|
if( empty( $_FILES ) || empty( $_FILES['ImportFile'] ) || $_FILES['ImportFile']['size'] == 0 )
|
|
return $this->customise( array( 'ID' => $id, "UploadForm" => $this->controller->UploadForm( $id ), 'ErrorMessage' => 'Please choose a CSV file to import' ) )->renderWith('Newsletter_RecipientImportField');
|
|
elseif( !$this->isValidCSV( $_FILES['ImportFile'] ) ) {
|
|
/*if( file_exists( $_FILES['ImportFile']['tmp_name'] ) ) unlink( $_FILES['ImportFile']['tmp_name'] );
|
|
unset( $_FILES['ImportFile'] );*/
|
|
return $this->customise( array( 'ID' => $id, "UploadForm" => $this->controller->UploadForm( $id ), 'ErrorMessage' => 'The selected file was not a CSV file' ) )->renderWith('Newsletter_RecipientImportField');
|
|
} else
|
|
return $recipientField->displaytable();
|
|
}
|
|
|
|
function isValidCSV( $file ) {
|
|
return preg_match( '/.*\.csv$/i', $file['name'] ) > 0;
|
|
}
|
|
|
|
function confirm( $data, $form ) {
|
|
$id = $data['ID'];
|
|
$mailType = DataObject::get_one("NewsletterType", "ID = $id");
|
|
if($mailType->GroupID)
|
|
$group = DataObject::get_one("Group", "ID = $mailType->GroupID");
|
|
// @TODO Look into seeing if $data['Set'] should be removed since it seems to be undefined
|
|
return $this->importMembers( $id, $group, $data['ImportFileColumns'], $data['Set'] );
|
|
}
|
|
|
|
function cancel( $data, $form ) {
|
|
$newForm = $this->controller->UploadForm( $data['ID'] );
|
|
return $newForm->forTemplate();
|
|
}
|
|
|
|
function action_import( $data, $form ) {
|
|
return $this->import( $data, $form );
|
|
}
|
|
|
|
function action_confirm( $data, $form ) {
|
|
return $this->confirm( $data, $form );
|
|
}
|
|
|
|
function action_cancel( $data, $form ) {
|
|
return $this->cancel( $data, $form );
|
|
}
|
|
|
|
/**
|
|
* Import members from the uploaded file
|
|
*/
|
|
protected function importMembers( $id, $group, $cols, $setFields, $primaryColType = 'Email' ) {
|
|
|
|
$startTime = time();
|
|
|
|
$importData = Session::get("ImportFile.{$id}");
|
|
|
|
$validColumns = array_keys( RecipientImportField::$column_types );
|
|
|
|
$columnMap = array_flip( $cols );
|
|
|
|
// Debug::show($columnMap);
|
|
|
|
// locate the primary column's index
|
|
$primaryColumn = /*array_search( $primaryColType, $validColumns );*/ $columnMap[$primaryColType];
|
|
|
|
// changed fields
|
|
$changedFields = array();
|
|
|
|
// intersect the list of valid columns with the column map to find the columns we need
|
|
$importColumns = array_intersect( $validColumns, $cols );
|
|
|
|
// statistics
|
|
$newMembers = 0;
|
|
$changedMembers = 0;
|
|
$skippedMembers = 0;
|
|
|
|
// the class that the imported members will become
|
|
$newMemberClass = Object::getCustomClass( 'Member' );
|
|
|
|
// for each row, add a new member or overwrite an existing member
|
|
foreach( $importData as $newMemberRow ) {
|
|
|
|
// skip rows with an empty value for the primary column
|
|
if( empty( $newMemberRow[$primaryColumn] ) ) {
|
|
$skippedMembers++;
|
|
continue;
|
|
}
|
|
|
|
// remember to check if the user has unsubscribed
|
|
$trackChanges = true;
|
|
|
|
// TODO: Write DataObject::update
|
|
$member = $this->findMember( $newMemberRow[$primaryColumn] );
|
|
|
|
if( !$member ) {
|
|
$newMembers++;
|
|
$trackChanges = false;
|
|
$member = Object::create("Member");
|
|
} else {
|
|
// skip this member if the are unsubscribed
|
|
if( $member->Unsubscribed ) {
|
|
$skippedMembers++;
|
|
continue;
|
|
}
|
|
|
|
if( $member->class != $newMemberClass )
|
|
$member->setClassName( $newMemberClass );
|
|
|
|
$changedMembers++;
|
|
}
|
|
|
|
// add each of the valid columns
|
|
foreach( $importColumns as $datum ) {
|
|
|
|
// perform any required conversions
|
|
$newValue = trim( $newMemberRow[$columnMap[$datum]] );
|
|
$oldValue = trim( $member->$datum );
|
|
|
|
// Debug::message( "$datum@{$columnMap[$datum]}" );
|
|
|
|
// track the modifications to the member data
|
|
if( $trackChanges && $newValue != $oldValue && $datum != $primaryColumn ) {
|
|
$changedFields[] = array(
|
|
$newMemberRow[$primaryColumn],
|
|
"$datum:\n$oldValue",
|
|
"$datum:\n$newValue"
|
|
);
|
|
|
|
$numChangedFields++;
|
|
}
|
|
|
|
$member->$datum = $newValue;
|
|
}
|
|
|
|
// set any set fields
|
|
if( $setFields )
|
|
foreach( $setFields as $fieldName => $fieldValue )
|
|
$member->$fieldName = $fieldValue;
|
|
|
|
// add member to group
|
|
$member->write();
|
|
$member->Groups()->add( $group->ID );
|
|
}
|
|
|
|
$numChangedFields = count( $changedFields );
|
|
$this->notifyChanges( $changedFields );
|
|
|
|
// TODO Refresh window
|
|
$customData = array(
|
|
'ID' => $id,
|
|
"UploadForm" => $this->controller->UploadForm( $id ),
|
|
'ImportMessage' => 'Imported new members',
|
|
'NewMembers' => (string)$newMembers,
|
|
'ChangedMembers' => (string)$changedMembers,
|
|
'ChangedFields' => (string)$numChangedFields,
|
|
'SkippedRecords' => (string)$skippedMembers,
|
|
'Time' => time() - $startTime
|
|
);
|
|
return $this->customise( $customData )->renderWith('Newsletter_RecipientImportField');
|
|
}
|
|
|
|
function findMember( $email ) {
|
|
$email = addslashes( $email );
|
|
return DataObject::get_one( 'Member', "`Email`='$email'" );
|
|
}
|
|
|
|
function notifyChanges( $changes ) {
|
|
$email = new Email( Email::getAdminEmail(), Email::getAdminEmail(), 'Changed Fields' );
|
|
|
|
$body = "";
|
|
|
|
foreach( $changes as $change ) {
|
|
$body .= "-------------------------------\n";
|
|
$body .= implode( ' ', $change ) . "\n";
|
|
}
|
|
|
|
$email->setBody( $body );
|
|
$email->send();
|
|
}
|
|
}
|
|
?>
|