138 lines
3.8 KiB
PHP
138 lines
3.8 KiB
PHP
|
<?php
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* SPIP, Systeme de publication pour l'internet *
|
||
|
* *
|
||
|
* Copyright (c) 2001-2019 *
|
||
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
|
||
|
* *
|
||
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
|
||
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
|
||
|
\***************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* Analyse de fichiers CSV
|
||
|
*
|
||
|
* @package SPIP\Core\CSV
|
||
|
*/
|
||
|
|
||
|
if (!defined('_ECRIRE_INC_VERSION')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retourne les données d'un texte au format CSV
|
||
|
*
|
||
|
* @param string $t
|
||
|
* Contenu du CSV
|
||
|
* @return array
|
||
|
* Tableau des données en 3 index :
|
||
|
* - Liste des noms des colonnes
|
||
|
* - Liste des valeurs de chaque ligne et chaque colonne
|
||
|
* - Titre du tableau (si une seule colonne)
|
||
|
**/
|
||
|
function analyse_csv($t) {
|
||
|
|
||
|
// Quel est le séparateur ?
|
||
|
$virg = substr_count($t, ',');
|
||
|
$pvirg = substr_count($t, ';');
|
||
|
$tab = substr_count($t, "\t");
|
||
|
if ($virg > $pvirg) {
|
||
|
$sep = ',';
|
||
|
$hs = ',';
|
||
|
} else {
|
||
|
$sep = ';';
|
||
|
$hs = ';';
|
||
|
$virg = $pvirg;
|
||
|
}
|
||
|
// un certain nombre de tab => le séparateur est tab
|
||
|
if ($tab > $virg / 10) {
|
||
|
$sep = "\t";
|
||
|
$hs = "\t";
|
||
|
}
|
||
|
|
||
|
// un separateur suivi de 3 guillemets attention !
|
||
|
// attention au ; ou , suceptible d'etre confondu avec un separateur
|
||
|
// on substitue un # et on remplacera a la fin
|
||
|
$t = preg_replace("/([\n$sep])\"\"\"/", '\\1""#', $t);
|
||
|
$t = str_replace('""', '"#', $t);
|
||
|
preg_match_all('/"[^"]*"/', $t, $r);
|
||
|
foreach ($r[0] as $cell) {
|
||
|
$t = str_replace($cell,
|
||
|
str_replace($sep, $hs,
|
||
|
str_replace("\n", "``**``", // échapper les saut de lignes, on les remettra après.
|
||
|
substr($cell, 1, -1))),
|
||
|
$t);
|
||
|
}
|
||
|
|
||
|
$t = preg_replace('/\r?\n/', "\n",
|
||
|
preg_replace('/[\r\n]+/', "\n", $t));
|
||
|
|
||
|
list($entete, $corps) = explode("\n", $t, 2);
|
||
|
$caption = '';
|
||
|
// sauter la ligne de tete formee seulement de separateurs
|
||
|
if (substr_count($entete, $sep) == strlen($entete)) {
|
||
|
list($entete, $corps) = explode("\n", $corps, 2);
|
||
|
}
|
||
|
// si une seule colonne, en faire le titre
|
||
|
if (preg_match("/^([^$sep]+)$sep+\$/", $entete, $l)) {
|
||
|
$caption = "\n||" . $l[1] . "|";
|
||
|
list($entete, $corps) = explode("\n", $corps, 2);
|
||
|
}
|
||
|
// si premiere colonne vide, le raccourci doit quand meme produire <th...
|
||
|
if ($entete[0] == $sep) {
|
||
|
$entete = ' ' . $entete;
|
||
|
}
|
||
|
|
||
|
$lignes = explode("\n", $corps);
|
||
|
|
||
|
// retrait des lignes vides finales
|
||
|
while (count($lignes) > 0
|
||
|
and preg_match("/^$sep*$/", $lignes[count($lignes) - 1])) {
|
||
|
unset($lignes[count($lignes) - 1]);
|
||
|
}
|
||
|
// calcul du nombre de colonne a chaque ligne
|
||
|
$nbcols = array();
|
||
|
$max = $mil = substr_count($entete, $sep);
|
||
|
foreach ($lignes as $k => $v) {
|
||
|
if ($max <> ($nbcols[$k] = substr_count($v, $sep))) {
|
||
|
if ($max > $nbcols[$k]) {
|
||
|
$mil = $nbcols[$k];
|
||
|
} else {
|
||
|
$mil = $max;
|
||
|
$max = $nbcols[$k];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Si pas le meme nombre, cadrer au nombre max
|
||
|
if ($mil <> $max) {
|
||
|
foreach ($nbcols as $k => $v) {
|
||
|
if ($v < $max) {
|
||
|
$lignes[$k] .= str_repeat($sep, $max - $v);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// et retirer les colonnes integralement vides
|
||
|
while (true) {
|
||
|
$nbcols = ($entete[strlen($entete) - 1] === $sep);
|
||
|
foreach ($lignes as $v) {
|
||
|
$nbcols &= ($v[strlen($v) - 1] === $sep);
|
||
|
}
|
||
|
if (!$nbcols) {
|
||
|
break;
|
||
|
}
|
||
|
$entete = substr($entete, 0, -1);
|
||
|
foreach ($lignes as $k => $v) {
|
||
|
$lignes[$k] = substr($v, 0, -1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach ($lignes as &$l) {
|
||
|
$l = str_replace('"#','"',$l);
|
||
|
$l = str_replace('``**``',"\n",$l);
|
||
|
$l = explode($sep, $l);
|
||
|
}
|
||
|
|
||
|
return array(explode($sep, $entete), $lignes, $caption);
|
||
|
}
|