2007-07-19 12:40:05 +02:00
< ? php
/**
* Displays a file upload field .
*/
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 );
2007-09-15 23:57:33 +02:00
$colCount = 0 ;
2007-07-19 12:40:05 +02:00
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 ;
}
}
class RecipientImportField_Cell extends ViewableData {
protected $value ;
function __construct ( $value ) {
$this -> value = $value ;
}
function Value () {
return $this -> value ;
}
}
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$/' , $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 " );
2007-09-16 00:02:06 +02:00
// @TODO Look into seeing if $data['Set'] should be removed since it seems to be undefined
2007-07-19 12:40:05 +02:00
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 ();
2007-09-16 00:02:06 +02:00
$importData = Session :: get ( " ImportFile. { $id } " );
2007-07-19 12:40:05 +02:00
$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 ();
}
}
?>