2024-07-03 12:02:11 +00:00
< ? php
/*
2024-07-06 16:56:09 +00:00
SPDX - License - Identifier : AGPL - 3.0 - only
2024-07-03 12:02:11 +00:00
SPDX - FileCopyrightText : © 2024 Millions Missing FRANCE < info @ millionsmissing . fr >
*/
2024-07-06 16:50:42 +00:00
namespace MillionsMissingFrance\FreescoutRestrictedCustomers\Http\Controllers ;
2024-07-03 12:02:11 +00:00
use App\Conversation ;
use App\Email ;
use Modules\Crm\Entities\CustomerField ;
use Modules\Crm\Entities\CustomerCustomerField ;
use Validator ;
use Illuminate\Http\Request ;
use Illuminate\Http\Response ;
use Illuminate\Routing\Controller ;
use Modules\Crm\Http\Controllers\CrmController as BaseCrmController ;
2024-07-06 16:50:42 +00:00
use MillionsMissingFrance\FreescoutRestrictedCustomers\Customer ;
2024-07-03 12:02:11 +00:00
class CrmController extends BaseCrmController {
public function createCustomer ( Request $request ) {
$customer = new Customer ();
2024-07-05 12:18:54 +00:00
// Get the list of Mailboxes the current User has access to.
$user = auth () -> user ();
$mailboxes = $user -> mailboxesCanView ();
return view ( 'freescout-restricted-customers::create_customer' , [
'customer' => $customer ,
'mailboxes' => $mailboxes ,
'emails' => [ '' ],
2024-07-03 12:02:11 +00:00
]);
}
public function createCustomerSave ( Request $request ) {
// TODO: Find a way to call parent::createCustomerSave while only overriding the Customer class,
// instead of overriding the whole method here.
$validator = Validator :: make ( $request -> all (), [
'first_name' => 'nullable|string|max:255|required_without:emails.0' ,
'last_name' => 'nullable|string|max:255' ,
'city' => 'nullable|string|max:255' ,
'state' => 'nullable|string|max:255' ,
'zip' => 'nullable|string|max:12' ,
'country' => 'nullable|string|max:2' ,
//'emails' => 'array|required_without:first_name',
//'emails.1' => 'nullable|email|required_without:first_name',
'emails.*' => 'nullable|email|distinct|required_without:first_name' ,
]);
$validator -> setAttributeNames ([
//'emails.1' => __('Email'),
'emails.*' => __ ( 'Email' ),
]);
// Check email uniqueness.
$fail = false ;
foreach ( $request -> emails as $i => $email ) {
$sanitized_email = Email :: sanitizeEmail ( $email );
if ( $sanitized_email ) {
$email_exists = Email :: where ( 'email' , $sanitized_email ) -> first ();
if ( $email_exists ) {
$validator -> getMessageBag () -> add ( 'emails.' . $i , __ ( 'A customer with this email already exists.' ));
$fail = true ;
}
}
}
if ( $fail || $validator -> fails ()) {
2024-07-05 12:18:54 +00:00
return redirect () -> route ( 'freescout-restricted-customers.create_customer' )
2024-07-03 12:02:11 +00:00
-> withErrors ( $validator )
-> withInput ();
}
$customer = new Customer ();
$customer -> setData ( $request -> all ());
$customer -> save ();
$customer -> syncEmails ( $request -> emails );
\Eventy :: action ( 'customer.created' , $customer );
\Session :: flash ( 'flash_success_unescaped' , __ ( 'Customer saved successfully.' ));
\Session :: flash ( 'customer.updated' , 1 );
// Create customer.
if ( $customer -> id ) {
return redirect () -> route ( 'customers.update' , [ 'id' => $customer -> id ]);
} else {
// Something went wrong.
return $this -> createCustomer ( $request );
}
}
/**
* Ajax controller .
*/
public function ajax ( Request $request ) {
// TODO: Find a way to call parent::ajax while only overriding the Customer class,
// instead of overriding the whole method here.
$response = [
'status' => 'error' ,
'msg' => '' , // this is error message
];
switch ( $request -> action ) {
// Delete customer.
case 'delete_customer' :
$has_conversations = Conversation :: where ( 'customer_id' , $request -> customer_id ) -> first ();
if ( $has_conversations ) {
$response [ 'msg' ] = __ ( " This customer has conversations. In order to delete the customer you need to completely delete all customer's conversations first. " );
}
if ( ! $response [ 'msg' ]) {
$customer = Customer :: find ( $request -> customer_id );
if ( $customer ) {
$customer -> deleteCustomer ();
$response [ 'msg_success' ] = __ ( 'Customer deleted' );
$response [ 'status' ] = 'success' ;
} else {
$response [ 'msg' ] = __ ( 'Customer not found' );
}
}
break ;
case 'delete_without_conv' :
// Delete customers by bunches.
do {
$customers = $this -> getCustomersWithoutConvQuery ()
-> limit ( 100 )
-> get ();
foreach ( $customers as $customer ) {
$customer -> deleteCustomer ();
}
} while ( count ( $customers ));
$response [ 'msg_success' ] = __ ( 'Customers deleted' );
$response [ 'status' ] = 'success' ;
break ;
default :
$response [ 'msg' ] = 'Unknown action' ;
break ;
}
if ( $response [ 'status' ] == 'error' && empty ( $response [ 'msg' ])) {
$response [ 'msg' ] = 'Unknown error occured' ;
}
return \Response :: json ( $response );
}
/**
* Ajax controller .
*/
public function ajaxAdmin ( Request $request ) {
// TODO: Find a way to call parent::ajaxAdmin while only overriding the Customer class,
// instead of overriding the whole method here.
$response = [
'status' => 'error' ,
'msg' => '' , // this is error message
];
switch ( $request -> action ) {
// Create/update saved reply
case 'customer_field_create' :
case 'customer_field_update' :
// if (!$user->isAdmin()) {
// $response['msg'] = __('Not enough permissions');
// }
if ( ! $response [ 'msg' ]) {
$name = $request -> name ;
if ( ! $name ) {
$response [ 'msg' ] = __ ( 'Name is required' );
}
}
// Check unique name.
if ( ! $response [ 'msg' ]) {
$name_exists = CustomerField :: where ( 'name' , $name );
if ( $request -> action == 'customer_field_update' ) {
$name_exists -> where ( 'id' , '!=' , $request -> customer_field_id );
}
$name_exists = $name_exists -> first ();
if ( $name_exists ) {
$response [ 'msg' ] = __ ( 'A Customer Field with this name already exists.' );
}
}
if ( ! $response [ 'msg' ]) {
if ( $request -> action == 'customer_field_update' ) {
$customer_field = CustomerField :: find ( $request -> customer_field_id );
if ( ! $customer_field ) {
$response [ 'msg' ] = __ ( 'Customer Field not found' );
}
} else {
$customer_field = new CustomerField ();
$customer_field -> setSortOrderLast ();
}
if ( ! $response [ 'msg' ]) {
//$customer_field->mailbox_id = $mailbox->id;
$customer_field -> name = $name ;
if ( $request -> action != 'customer_field_update' ) {
$customer_field -> type = $request -> type ;
}
if ( $customer_field -> type == CustomerField :: TYPE_DROPDOWN ) {
if ( $request -> action == 'customer_field_create' ) {
$options = [];
$options_tmp = preg_split ( '/\r\n|[\r\n]/' , $request -> options ? ? '' );
// Remove empty
$option_index = 1 ;
foreach ( $options_tmp as $i => $value ) {
$value = trim ( $value );
if ( $value ) {
$options [ $option_index ] = $value ;
$option_index ++ ;
}
}
if ( empty ( $options )) {
$options = [ 1 => '' ];
}
} else {
$options = $request -> options ;
}
$customer_field -> options = $options ;
// Remove values.
if ( $customer_field -> id ) {
CustomerCustomerField :: where ( 'customer_field_id' , $customer_field -> id )
-> whereNotIn ( 'value' , array_keys ( $request -> options ))
-> delete ();
}
} elseif ( isset ( $request -> options )) {
$customer_field -> options = $request -> options ;
} else {
$customer_field -> options = '' ;
}
$customer_field -> required = $request -> filled ( 'required' );
$customer_field -> display = $request -> filled ( 'display' );
$customer_field -> conv_list = $request -> filled ( 'conv_list' );
$customer_field -> customer_can_view = $request -> filled ( 'customer_can_view' );
$customer_field -> customer_can_edit = $request -> filled ( 'customer_can_edit' );
$customer_field -> save ();
$response [ 'id' ] = $customer_field -> id ;
$response [ 'name' ] = $customer_field -> name ;
$response [ 'required' ] = ( int ) $customer_field -> required ;
$response [ 'display' ] = ( int ) $customer_field -> display ;
$response [ 'conv_list' ] = ( int ) $customer_field -> conv_list ;
$response [ 'customer_can_view' ] = ( int ) $customer_field -> customer_can_view ;
$response [ 'customer_can_edit' ] = ( int ) $customer_field -> customer_can_edit ;
$response [ 'status' ] = 'success' ;
if ( $request -> action == 'customer_field_update' ) {
$response [ 'msg_success' ] = __ ( 'Customer field updated' );
} else {
// Flash
\Session :: flash ( 'flash_success_floating' , __ ( 'Customer field created' ));
}
}
}
break ;
// Delete
case 'customer_field_delete' :
// if (!$user->isAdmin()) {
// $response['msg'] = __('Not enough permissions');
// }
if ( ! $response [ 'msg' ]) {
$customer_field = CustomerField :: find ( $request -> customer_field_id );
if ( ! $customer_field ) {
$response [ 'msg' ] = __ ( 'Customer Field not found' );
}
}
if ( ! $response [ 'msg' ]) {
\Eventy :: action ( 'customer_field.before_delete' , $customer_field );
$customer_field -> delete ();
// Delete links to customers;
CustomerCustomerField :: where ( 'customer_field_id' , $request -> customer_field_id ) -> delete ();
$response [ 'status' ] = 'success' ;
$response [ 'msg_success' ] = __ ( 'Customer Field deleted' );
\Eventy :: action ( 'customer_field.after_delete' , $request -> customer_field_id );
}
break ;
// Update saved reply
case 'customer_field_update_sort_order' :
// if (!$user->isAdmin()) {
// $response['msg'] = __('Not enough permissions');
// }
if ( ! $response [ 'msg' ]) {
$customer_fields = CustomerField :: whereIn ( 'id' , $request -> customer_fields ) -> select ( 'id' , 'sort_order' ) -> get ();
if ( count ( $customer_fields )) {
foreach ( $request -> customer_fields as $i => $request_customer_field_id ) {
foreach ( $customer_fields as $customer_field ) {
if ( $customer_field -> id != $request_customer_field_id ) {
continue ;
}
$customer_field -> sort_order = $i + 1 ;
$customer_field -> save ();
}
}
$response [ 'status' ] = 'success' ;
}
}
break ;
// Parse CSV before importing.
case 'import_parse' :
if ( ! $request -> hasFile ( 'file' ) || ! $request -> file ( 'file' ) -> isValid () || ! $request -> file ) {
$response [ 'msg' ] = __ ( 'Error occurred uploading file' );
}
if ( ! $response [ 'msg' ]) {
try {
$csv = $this -> readCsv ( $request -> file ( 'file' ) -> getPathName (), $request -> separator , $request -> enclosure , $request -> encoding );
} catch ( \Exception $e ) {
$response [ 'msg' ] = __ ( 'Error occurred' ) . ': ' . $e -> getMessage ();
}
if ( ! $response [ 'msg' ] && $csv && is_array ( $csv )) {
$response [ 'cols' ] = [];
foreach ( $csv as $r => $row ) {
if ( $request -> skip_header && $r == 0 ) {
continue ;
}
foreach ( $row as $c => $value ) {
if ( ! empty ( $response [ 'cols' ][ $c ])
&& $response [ 'cols' ][ $c ] != __ ( 'Column :number' , [ 'number' => $c + 1 ])
) {
continue ;
}
if ( $request -> skip_header ) {
if ( $r == 0 ) {
if ( isset ( $csv [ 1 ][ $c ]) && $csv [ 1 ][ $c ] != '' ) {
$response [ 'cols' ][ $c ] = $value . ' (' . $csv [ 1 ][ $c ] . ')' ;
} elseif ( $value != '' ) {
$response [ 'cols' ][ $c ] = $value ;
} else {
$response [ 'cols' ][ $c ] = __ ( 'Column :number' , [ 'number' => $c + 1 ]);
}
} elseif ( isset ( $csv [ 0 ][ $c ]) && $value ) {
$response [ 'cols' ][ $c ] = $csv [ 0 ][ $c ] . ' (' . $value . ')' ;
} elseif ( $value != '' ) {
$response [ 'cols' ][ $c ] = $value ;
} else {
$response [ 'cols' ][ $c ] = __ ( 'Column :number' , [ 'number' => $c + 1 ]);
}
} elseif ( $value != '' ) {
$response [ 'cols' ][ $c ] = $value ;
} else {
$response [ 'cols' ][ $c ] = __ ( 'Column :number' , [ 'number' => $c + 1 ]);
}
}
}
}
if ( ! $response [ 'msg' ]) {
if ( ! empty ( $response [ 'cols' ])) {
$response [ 'status' ] = 'success' ;
} else {
$response [ 'msg' ] = __ ( 'Could not parse CSV file.' );
}
}
}
break ;
// Import.
case 'import_import' :
if ( ! $request -> hasFile ( 'file' ) || ! $request -> file ( 'file' ) -> isValid () || ! $request -> file ) {
$response [ 'msg' ] = __ ( 'Error occurred uploading file' );
}
if ( ! $response [ 'msg' ]) {
try {
$csv = $this -> readCsv ( $request -> file ( 'file' ) -> getPathName (), $request -> separator , $request -> enclosure , $request -> encoding );
$imported = 0 ;
$errors = [];
$email_conflicts = [];
if ( $csv && is_array ( $csv )) {
foreach ( $csv as $r => $row ) {
if ( $request -> skip_header && $r == 0 ) {
continue ;
}
$data = $this -> importParseRow ( $row , json_decode ( $request -> mapping , true ));
try {
if ( ! empty ( $data [ 'emails' ])) {
// Try to find customers with emails.
// If found one - update.
// If found more than one customer - it's a conflict.
$customers_count = 0 ;
$customer_email = '' ;
$customer_customer = null ;
foreach ( $data [ 'emails' ] as $email ) {
$customer = Customer :: getByEmail ( $email );
if ( $customer ) {
$customer_email = $email ;
$customer_customer = $customer ;
$customers_count ++ ;
}
}
if ( $customers_count > 1 ) {
$email_conflicts [] = ( int )( $r + 1 );
} elseif ( $customers_count == 1 && $customer_customer ) {
// Update existing customer.
$imported ++ ;
$customer_customer -> setData ( $this -> prepareEmails ( $data ), true , true );
} else {
$customer_customer = Customer :: create ( $data [ 'emails' ][ 0 ], $this -> prepareEmails ( $data ));
if ( $customer_customer ) {
$imported ++ ;
}
}
} else {
// Create without email.
if ( ! empty ( $data [ 'first_name' ])) {
$customer_customer = Customer :: createWithoutEmail ( $this -> prepareEmails ( $data ));
if ( $customer_customer ) {
$imported ++ ;
}
} else {
$errors [] = '#' . ( $r + 1 );
}
}
// Set photo.
if ( ! empty ( $data [ 'photo_url' ]) && $customer_customer ) {
try {
$customer_customer -> setPhotoFromRemoteFile ( $data [ 'photo_url' ]);
$customer_customer -> save ();
} catch ( \Exception $e ) {
}
}
} catch ( \Exception $e ) {
$errors [] = '#' . ( $r + 1 );
}
}
}
// if ($imported) {
// $flash_type = 'flash_success_floating';
// } else {
// $flash_type = 'flash_error_floating';
// }
$response [ 'result_html' ] = __ ( 'Imported or updated: :imported customers.' , [ 'imported' => $imported ]);
if ( count ( $errors )) {
$response [ 'result_html' ] .= '<br/>' . __ ( 'Could not import the following CSV rows as they contain not enough data: :errors.' , [ 'errors' => implode ( ', ' , $errors )]);
}
if ( count ( $email_conflicts )) {
$response [ 'result_html' ] .= '<br/>' . __ ( 'Could not import the following CSV rows as emails specified in those rows belong to different existing customers: :email_conflicts.' , [ 'email_conflicts' => implode ( ', ' , $email_conflicts )]);
}
// \Session::flash($flash_type, __(':imported customer(s) imported, :errors error(s) occurred', ['imported' => $imported, 'errors' => $errors]));
// \Session::reflash();
} catch ( \Exception $e ) {
$response [ 'msg' ] = __ ( 'Error occurred' ) . ': ' . $e -> getMessage ();
}
if ( ! $response [ 'msg' ] && $csv ) {
$response [ 'status' ] = 'success' ;
}
}
break ;
default :
$response [ 'msg' ] = 'Unknown action' ;
break ;
}
if ( $response [ 'status' ] == 'error' && empty ( $response [ 'msg' ])) {
$response [ 'msg' ] = 'Unknown error occured' ;
}
return \Response :: json ( $response );
}
public function importParseRow ( $row , $mapping ) {
// TODO: Find a way to call parent::importParseRow while only overriding the Customer class,
// instead of overriding the whole method here.
$data = [];
foreach ( $mapping as $field_name => $field_row_i ) {
if ( ! isset ( $row [ $field_row_i ])) {
continue ;
}
$data [ $field_name ] = $row [ $field_row_i ];
$data_value = $data [ $field_name ];
switch ( $field_name ) {
case 'emails' :
case 'phones' :
case 'websites' :
case 'social_profiles' :
$data [ $field_name ] = explode ( ',' , $data [ $field_name ]);
if ( is_array ( $data [ $field_name ])
&& count ( $data [ $field_name ]) == 1
&& isset ( $data [ $field_name ][ 0 ])
&& empty ( $data [ $field_name ][ 0 ])
) {
unset ( $data [ $field_name ][ 0 ]);
}
break ;
}
if ( $field_name == 'social_profiles' && is_array ( $data [ $field_name ])) {
// Social profiles.
foreach ( $data [ $field_name ] as $i => $value ) {
preg_match ( " /^([^:]+):(.*)/ " , $value , $m );
if ( ! empty ( $m [ 1 ]) && ! empty ( $m [ 2 ])) {
$social_name = $m [ 1 ];
if ( array_search ( $social_name , Customer :: $social_type_names )) {
$data [ $field_name ][ $i ] = [
'value' => $m [ 2 ],
'type' => array_search ( $social_name , Customer :: $social_type_names ),
];
}
}
}
} elseif ( $field_name == 'country' ) {
// Country.
if ( array_search ( $data [ $field_name ], Customer :: $countries )) {
$data [ $field_name ] = array_search ( $data [ $field_name ], Customer :: $countries );
}
$data [ $field_name ] = strtoupper ( mb_substr ( $data [ $field_name ], 0 , 2 ));
} elseif ( \Str :: startsWith ( $field_name , CustomerField :: NAME_PREFIX )) {
// Custom field.
$value = $data [ $field_name ];
$field_id = preg_replace ( " /^ " . CustomerField :: NAME_PREFIX . " / " , '' , $field_name );
$field = CustomerField :: find ( $field_id );
if ( $field ) {
$data [ $field_name ] = CustomerField :: sanitizeValue ( $value , $field );
}
}
}
return $data ;
}
public function getCustomersWithoutConvQuery () {
// TODO: Find a way to call parent::getCustomersWithoutConvQuery while only overriding the Customer class,
// instead of overriding the whole method here.
return Customer :: select ( 'customers.*' )
-> leftJoin ( 'conversations' , function ( $join ) {
$join -> on ( 'conversations.customer_id' , '=' , 'customers.id' );
})
-> leftJoin ( 'threads' , function ( $join ) {
$join -> on ( 'threads.created_by_customer_id' , '=' , 'customers.id' );
})
-> where ( 'conversations.customer_id' , null )
-> where ( 'threads.created_by_customer_id' , null );
}
/**
* Export .
*/
public function export ( Request $request ) {
// TODO: Find a way to call parent::export while only overriding the Customer class,
// instead of overriding the whole method here.
$fields = $request -> fields ? ? [];
$export_emails = false ;
$exportable_fields = \Crm :: getExportableFields ();
$fields_regular = [];
foreach ( $fields as $i => $field_name ) {
if ( array_key_exists ( $field_name , $exportable_fields )) {
if ( ! preg_match ( " /^ " . CustomerField :: NAME_PREFIX . " / " , $field_name )) {
$fields_regular [] = $field_name ;
}
} else {
unset ( $fields [ $i ]);
}
if ( $field_name == 'emails' ) {
$export_emails = true ;
if ( \Helper :: isMySql ()) {
$fields_regular [ count ( $fields_regular ) - 1 ] = \DB :: raw ( " GROUP_CONCAT(emails.email SEPARATOR ', ') as emails " );
} else {
$fields_regular [ count ( $fields_regular ) - 1 ] = \DB :: raw ( " string_agg(emails.email, ', ') as emails " );
}
}
}
$results = [];
if ( count ( $fields_regular )) {
if ( ! in_array ( 'customers.id' , $fields_regular )) {
$fields_regular [] = 'customers.id' ;
}
if ( $export_emails ) {
$query = Customer :: select ( $fields_regular )
-> leftJoin ( 'emails' , function ( $join ) {
$join -> on ( 'emails.customer_id' , '=' , 'customers.id' );
})
-> groupby ( 'customers.id' );
} else {
$query = Customer :: select ( $fields_regular );
}
$results = $query -> get () -> toArray ();
}
// Add customer fields.
$fields_cf = [];
foreach ( $fields as $field_name ) {
if ( preg_match ( " /^ " . CustomerField :: NAME_PREFIX . " / " , $field_name )) {
$fields_cf [] = str_replace ( CustomerField :: NAME_PREFIX , '' , $field_name );
}
}
if ( count ( $fields_cf )) {
$customer_fields = CustomerCustomerField :: whereIn ( 'customer_field_id' , $fields_cf )
-> get ();
foreach ( $results as $i => $row ) {
foreach ( $fields_cf as $cf_id ) {
$results [ $i ][ CustomerField :: NAME_PREFIX . $cf_id ] = '' ;
foreach ( $customer_fields as $cf_row ) {
if ( $cf_row -> customer_id == $row [ 'id' ] && $cf_row -> customer_field_id == $cf_id ) {
$results [ $i ][ CustomerField :: NAME_PREFIX . $cf_id ] = $cf_row -> value ;
break ;
}
}
}
}
}
foreach ( $results as $i => $row ) {
if ( ! in_array ( 'customers.id' , $fields ) && isset ( $row [ 'id' ])) {
unset ( $results [ $i ][ 'id' ]);
}
if ( ! empty ( $row [ 'photo_url' ])) {
$results [ $i ][ 'photo_url' ] = Customer :: getPhotoUrlByFileName ( $row [ 'photo_url' ]);
}
if ( ! empty ( $row [ 'phones' ])) {
$phones = json_decode ( $row [ 'phones' ], true );
$row [ 'phones' ] = '' ;
$phones_list = [];
if ( is_array ( $phones ) && ! empty ( $phones )) {
foreach ( $phones as $phone ) {
$phones_list [] = $phone [ 'value' ];
}
$results [ $i ][ 'phones' ] = implode ( ', ' , $phones_list );
}
}
if ( ! empty ( $row [ 'websites' ])) {
$websites = json_decode ( $row [ 'websites' ], true );
$results [ $i ][ 'websites' ] = '' ;
if ( is_array ( $websites ) && ! empty ( $websites )) {
$results [ $i ][ 'websites' ] = implode ( ', ' , $websites );
}
}
if ( ! empty ( $row [ 'social_profiles' ])) {
$social_profiles = json_decode ( $row [ 'social_profiles' ], true );
$row [ 'social_profiles' ] = '' ;
$social_profiles_list = [];
if ( is_array ( $social_profiles ) && ! empty ( $social_profiles )) {
foreach ( $social_profiles as $social_profile ) {
$sp_formatted = Customer :: formatSocialProfile ( $social_profile );
$social_profiles_list [] = $sp_formatted [ 'type_name' ] . ':' . $social_profile [ 'value' ];
}
$results [ $i ][ 'social_profiles' ] = implode ( ', ' , $social_profiles_list );
}
}
}
$filename = 'customers_' . date ( 'Y-m-d' ) . '.csv' ;
$encoding = $request -> encoding ;
$separator = $request -> separator ;
if ( $separator == 'TAB' ) {
$separator = " \t " ;
}
// Rename some fields.
foreach ( $fields as $i => $field_name ) {
// if (strstr($field_name, 'as emails')) {
// $field_name = 'emails';
// }
if ( ! empty ( $exportable_fields [ $field_name ])) {
$fields [ $i ] = $exportable_fields [ $field_name ];
}
}
$schema_insert = '"' . implode ( '"' . $separator . '"' , $fields ) . '"' ;
$out = $schema_insert . " \n " ;
foreach ( $results as $row ) {
$schema_insert = '' ;
foreach ( $row as $row_value ) {
$value_prepared = str_replace ( '"' , '""' , $row_value ? ? '' );
$value_prepared = str_replace ( " \t " , '' , $value_prepared );
$schema_insert .= '"' . $value_prepared . '"' . $separator ;
}
$out .= $schema_insert . " \n " ;
}
if ( ob_get_contents ()) {
ob_clean ();
}
if ( $encoding != 'UTF-8' ) {
try {
$out = iconv ( " UTF-8 " , $encoding , $out );
} catch ( \Exception $e ) {
// https://github.com/freescout-helpdesk/freescout/issues/2825
$out = iconv ( " UTF-8 " , $encoding . '//IGNORE' , $out );
}
if ( $encoding == 'UCS-2LE' ) {
$out = " \xFF \xFE " . $out ;
}
} else {
// BOM: https://github.com/freescout-helpdesk/freescout/issues/3993
$out = " \xEF \xBB \xBF " . $out ;
}
header ( " Cache-Control: must-revalidate, no-cache, no-store, private " );
header ( " Content-Length: " . strlen ( $out ));
header ( " Content-type: application/csv; charset=UCS-2LE " );
header ( " Content-Disposition: attachment; filename= $filename " );
echo $out ;
exit ;
}
}