mirror of
https://github.com/RaspbianFrance/raspisms.git
synced 2025-04-20 16:37:48 +02:00
add import/Export contacts system
This commit is contained in:
parent
6503eb62ec
commit
cfde77a0c1
10 changed files with 509 additions and 12 deletions
|
@ -109,4 +109,229 @@ namespace controllers\internals;
|
|||
|
||||
return $this->get_model()->update_for_user($id_user, $id, $contact);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import a list of contacts as csv
|
||||
* @param resource $file_handler : File handler to import contacts from
|
||||
* @param int $id_user : User id
|
||||
* @return mixed : False on error, number of inserted contacts else
|
||||
*/
|
||||
public function import_csv (int $id_user, $file_handler)
|
||||
{
|
||||
if (!is_resource($file_handler))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$nb_insert = 0;
|
||||
|
||||
$head = null;
|
||||
while ($line = fgetcsv($file_handler))
|
||||
{
|
||||
if ($head === null)
|
||||
{
|
||||
$head = $line;
|
||||
continue;
|
||||
}
|
||||
|
||||
$line = array_combine($head, $line);
|
||||
if ($line === false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($line['name'], $line['number']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$datas = [];
|
||||
foreach ($line as $key => $value)
|
||||
{
|
||||
if ($key == 'name' || $key == 'number')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value === '')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = mb_ereg_replace('[\W]', '', $key);
|
||||
$datas[$key] = $value;
|
||||
}
|
||||
$datas = json_encode($datas);
|
||||
|
||||
$success = $this->create($id_user, $line['number'], $line['name'], $datas);
|
||||
if ($success)
|
||||
{
|
||||
$nb_insert ++;
|
||||
}
|
||||
}
|
||||
|
||||
return $nb_insert;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import a list of contacts as json
|
||||
* @param resource $file_handler : File handler to import contacts from
|
||||
* @param int $id_user : User id
|
||||
* @return mixed : False on error, number of inserted contacts else
|
||||
*/
|
||||
public function import_json (int $id_user, $file_handler)
|
||||
{
|
||||
if (!is_resource($file_handler))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$file_content = '';
|
||||
while ($line = fgets($file_handler))
|
||||
{
|
||||
$file_content .= $line;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$contacts = json_decode($file_content, true);
|
||||
|
||||
if (!is_array($contacts))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$nb_insert = 0;
|
||||
foreach ($contacts as $contact)
|
||||
{
|
||||
if (!is_array($contact))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($contact['name'], $contact['number']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$datas = $contact['datas'] ?? [];
|
||||
$datas = json_encode($datas);
|
||||
|
||||
$success = $this->create($id_user, $contact['number'], $contact['name'], $datas);
|
||||
if ($success)
|
||||
{
|
||||
$nb_insert ++;
|
||||
}
|
||||
}
|
||||
|
||||
return $nb_insert;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export the contacts of a user as csv
|
||||
* @param int $id_user : User id
|
||||
* @return array : ['headers' => array of headers to return, 'content' => the generated file]
|
||||
*/
|
||||
public function export_csv (int $id_user) : array
|
||||
{
|
||||
$contacts = $this->get_model()->gets_for_user($id_user);
|
||||
|
||||
$columns = [
|
||||
'name',
|
||||
'number',
|
||||
];
|
||||
|
||||
foreach ($contacts as $contact)
|
||||
{
|
||||
$datas = json_decode($contact['datas'], true);
|
||||
foreach ($datas as $key => $value)
|
||||
{
|
||||
$columns[] = $key;
|
||||
}
|
||||
}
|
||||
$columns = array_unique($columns);
|
||||
|
||||
$lines = [];
|
||||
foreach ($contacts as $contact)
|
||||
{
|
||||
$datas = json_decode($contact['datas'], true);
|
||||
|
||||
$line = [];
|
||||
foreach ($columns as $column)
|
||||
{
|
||||
if (isset($contact[$column]))
|
||||
{
|
||||
$line[] = $contact[$column];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($datas[$column]))
|
||||
{
|
||||
$line[] = $datas[$column];
|
||||
continue;
|
||||
}
|
||||
|
||||
$line[] = null;
|
||||
}
|
||||
$lines[] = $line;
|
||||
}
|
||||
|
||||
//Php only support csv formatting to file. To get it in string we need to create a tmp in memory file, write in it, and then read the file into a var
|
||||
// output up to 5MB is kept in memory, if it becomes bigger it will automatically be written to a temporary file
|
||||
$csv_tmp_file = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
|
||||
fputcsv($csv_tmp_file, $columns);
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
fputcsv($csv_tmp_file, $line);
|
||||
}
|
||||
rewind($csv_tmp_file);
|
||||
|
||||
$csv_string = stream_get_contents($csv_tmp_file);
|
||||
|
||||
return [
|
||||
'headers' => [
|
||||
'Content-Disposition: attachment; filename=contacts.csv',
|
||||
'Content-Type: text/csv',
|
||||
'Content-Length: ' . strlen($csv_string),
|
||||
],
|
||||
'content' => $csv_string,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export the contacts of a user as json
|
||||
* @param int $id_user : User id
|
||||
* @return array : ['headers' => array of headers to return, 'content' => the generated file]
|
||||
*/
|
||||
public function export_json (int $id_user) : array
|
||||
{
|
||||
$contacts = $this->get_model()->gets_for_user($id_user);
|
||||
|
||||
foreach ($contacts as &$contact)
|
||||
{
|
||||
unset($contact['id']);
|
||||
unset($contact['id_user']);
|
||||
$contact['datas'] = json_decode($contact['datas']);
|
||||
}
|
||||
$content = json_encode($contacts);
|
||||
|
||||
return [
|
||||
'headers' => [
|
||||
'Content-Disposition: attachment; filename=contacts.json',
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($content),
|
||||
],
|
||||
'content' => $content,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,13 +26,24 @@ namespace controllers\internals;
|
|||
*/
|
||||
public static function parse_phone($number)
|
||||
{
|
||||
$number = preg_replace('#[^-0-9+]#', '', $number);
|
||||
if (preg_match('#^(0|\+[1-9]{1,3}|\+1\-[0-9]{3})[1-9][0-9]{8,10}$#', $number))
|
||||
try
|
||||
{
|
||||
return $number;
|
||||
}
|
||||
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
|
||||
$phone_number_o = $phone_number_util->parse($number, null);
|
||||
|
||||
return false;
|
||||
$valid = $phone_number_util->isValidNumber($phone_number_o);
|
||||
|
||||
if (!$valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::E164);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,10 +55,17 @@ namespace controllers\internals;
|
|||
*/
|
||||
public static function phone_format($number)
|
||||
{
|
||||
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
|
||||
$phone_number_o = $phone_number_util->parse($number, null);
|
||||
try
|
||||
{
|
||||
$phone_number_util = \libphonenumber\PhoneNumberUtil::getInstance();
|
||||
$phone_number_o = $phone_number_util->parse($number, null);
|
||||
|
||||
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::INTERNATIONAL);
|
||||
return $phone_number_util->format($phone_number_o, \libphonenumber\PhoneNumberFormat::INTERNATIONAL);
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
return $number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,4 +223,69 @@ namespace controllers\internals;
|
|||
|
||||
return mail($to, $settings['subject'], $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to read an uploaded file
|
||||
* @param array $file : The array extracted from $_FILES['file']
|
||||
* @return array : ['success' => bool, 'content' => file handler | error message, 'error_code' => $file['error']]
|
||||
*/
|
||||
public static function read_uploaded_file(array $file)
|
||||
{
|
||||
$result = [
|
||||
'success' => false,
|
||||
'content' => 'Une erreur inconnue est survenue.',
|
||||
'error_code' => $file['error'] ?? 99,
|
||||
'mime_type' => false,
|
||||
];
|
||||
|
||||
if ($file['error'] !== UPLOAD_ERR_OK)
|
||||
{
|
||||
switch ($file['error'])
|
||||
{
|
||||
case UPLOAD_ERR_INI_SIZE :
|
||||
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_FORM_SIZE :
|
||||
$result['content'] = 'Le fichier dépasse la limite de taille.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_PARTIAL :
|
||||
$result['content'] = 'L\'envoi du fichier a été interrompu.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_NO_FILE :
|
||||
$result['content'] = 'Aucun fichier n\'a été envoyé.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_NO_TMP_DIR :
|
||||
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_CANT_WRITE :
|
||||
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
|
||||
break;
|
||||
|
||||
case UPLOAD_ERR_EXTENSION :
|
||||
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$tmp_filename = $file['tmp_name'] ?? false;
|
||||
if (!$tmp_filename || !is_readable($tmp_filename))
|
||||
{
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result['mime_type'] = mime_content_type($tmp_filename) == 'text/plain' ? $file['type'] : mime_content_type($tmp_filename);
|
||||
|
||||
$file_handler = fopen($tmp_filename, 'r');
|
||||
$result['success'] = true;
|
||||
$result['content'] = $file_handler;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,6 +243,120 @@ namespace controllers\publics;
|
|||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow to import a contacts list
|
||||
* @param string $csrf : Csrf token
|
||||
* @param $_FILES['contacts_list_file'] : A csv file of the contacts to import
|
||||
*/
|
||||
public function import (string $csrf)
|
||||
{
|
||||
if (!$this->verify_csrf($csrf))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
$id_user = $_SESSION['user']['id'];
|
||||
|
||||
$upload_array = $_FILES['contacts_list_file'] ?? false;
|
||||
if (!$upload_array)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Vous devez fournir un fichier de contacts à importer.');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
$read_file = \controllers\internals\Tool::read_uploaded_file($upload_array);
|
||||
if (!$read_file['success'])
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', $read_file['content']);
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
//Try to import file
|
||||
$invalid_type = false;
|
||||
switch ($read_file['mime_type'])
|
||||
{
|
||||
case 'text/csv' :
|
||||
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
|
||||
break;
|
||||
|
||||
case 'application/json' :
|
||||
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
|
||||
break;
|
||||
|
||||
default :
|
||||
$invalid_type = true;
|
||||
}
|
||||
|
||||
if ($invalid_type)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Le type de fichier n\'est pas valide.');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Le fichier contient des erreurs. Impossible d\'importer les contacts.');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
$msg = $result . ' nouveau contact a été inséré.';
|
||||
if ($result > 1)
|
||||
{
|
||||
$msg = $result . ' nouveaux contacts ont été insérés.';
|
||||
}
|
||||
|
||||
\FlashMessage\FlashMessage::push('success', $msg);
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow to export a contacts list
|
||||
* @param $format : Format to export contacts to
|
||||
*/
|
||||
public function export (string $format)
|
||||
{
|
||||
$id_user = $_SESSION['user']['id'];
|
||||
|
||||
//Try to export contacts
|
||||
$invalid_type = false;
|
||||
switch ($format)
|
||||
{
|
||||
case 'csv' :
|
||||
$result = $this->internal_contact->export_csv($id_user);
|
||||
break;
|
||||
|
||||
case 'json' :
|
||||
$result = $this->internal_contact->export_json($id_user);
|
||||
break;
|
||||
|
||||
default :
|
||||
$invalid_type = true;
|
||||
}
|
||||
|
||||
if ($invalid_type)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Le format demandé n\'est pas supporté.');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Nous ne sommes par parveu à exporté les contacts.');
|
||||
return $this->redirect(\descartes\Router::url('Contact', 'list'));
|
||||
}
|
||||
|
||||
$result['headers'] = $result['headers'] ?? [];
|
||||
foreach ($result['headers'] as $header)
|
||||
{
|
||||
header($header);
|
||||
}
|
||||
|
||||
echo $result['content'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Cette fonction retourne la liste des contacts sous forme JSON.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue