mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
193 lines
4.1 KiB
PHP
193 lines
4.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* CSVParser
|
|
* CSV interpreter helper, optionaly tries to guess column mapping and the separator, check the consistency
|
|
*
|
|
* @package iTopORM
|
|
* @author Romain Quetiez <romainquetiez@yahoo.fr>
|
|
* @author Denis Flaven <denisflave@free.fr>
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
* @link www.itop.com
|
|
* @since 1.0
|
|
* @version 1.1.1.1 $
|
|
*/
|
|
|
|
class CSVParserException extends CoreException
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* CSVParser
|
|
*
|
|
* @package iTopORM
|
|
* @author Romain Quetiez <romainquetiez@yahoo.fr>
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
* @link www.itop.com
|
|
* @since 1.0
|
|
* @version $itopversion$
|
|
*/
|
|
class CSVParser
|
|
{
|
|
private $m_sCSVData;
|
|
private $m_sSep;
|
|
private $m_iSkip;
|
|
|
|
public function __construct($sTxt)
|
|
{
|
|
$this->m_sCSVData = $sTxt;
|
|
}
|
|
|
|
public function SetSeparator($sSep)
|
|
{
|
|
$this->m_sSep = $sSep;
|
|
}
|
|
public function GetSeparator()
|
|
{
|
|
return $this->m_sSep;
|
|
}
|
|
|
|
public function SetSkipLines($iSkip)
|
|
{
|
|
$this->m_iSkip = $iSkip;
|
|
}
|
|
public function GetSkipLines()
|
|
{
|
|
return $this->m_iSkip;
|
|
}
|
|
|
|
public function GuessSeparator()
|
|
{
|
|
// Note: skip the first line anyway
|
|
|
|
$aKnownSeps = array(';', ',', "\t"); // Use double quote for special chars!!!
|
|
$aStatsBySeparator = array();
|
|
foreach ($aKnownSeps as $sSep)
|
|
{
|
|
$aStatsBySeparator[$sSep] = array();
|
|
}
|
|
|
|
foreach(split("\n", $this->m_sCSVData) as $sLine)
|
|
{
|
|
$sLine = trim($sLine);
|
|
if (substr($sLine, 0, 1) == '#') continue;
|
|
if (empty($sLine)) continue;
|
|
|
|
$aLineCharsCount = count_chars($sLine, 0);
|
|
foreach ($aKnownSeps as $sSep)
|
|
{
|
|
$aStatsBySeparator[$sSep][] = $aLineCharsCount[ord($sSep)];
|
|
}
|
|
}
|
|
|
|
// Default to ','
|
|
$this->SetSeparator(",");
|
|
|
|
foreach ($aKnownSeps as $sSep)
|
|
{
|
|
// Note: this function is NOT available :-(
|
|
// stats_variance($aStatsBySeparator[$sSep]);
|
|
$iMin = min($aStatsBySeparator[$sSep]);
|
|
$iMax = max($aStatsBySeparator[$sSep]);
|
|
if (($iMin == $iMax) && ($iMax > 0))
|
|
{
|
|
$this->SetSeparator($sSep);
|
|
break;
|
|
}
|
|
}
|
|
return $this->GetSeparator();
|
|
}
|
|
|
|
public function GuessSkipLines()
|
|
{
|
|
// Take the FIRST -valuable- LINE ONLY
|
|
// If there is a number, then for sure this is not a header line
|
|
// Otherwise, we may consider that there is one line to skip
|
|
foreach(split("\n", $this->m_sCSVData) as $sLine)
|
|
{
|
|
$sLine = trim($sLine);
|
|
if (substr($sLine, 0, 1) == '#') continue;
|
|
if (empty($sLine)) continue;
|
|
|
|
foreach (split($this->m_sSep, $sLine) as $value)
|
|
{
|
|
if (is_numeric($value))
|
|
{
|
|
$this->SetSkipLines(0);
|
|
return 0;
|
|
}
|
|
}
|
|
$this->SetSkipLines(1);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
function ToArray($aFieldMap = null, $iMax = 0)
|
|
{
|
|
// $aFieldMap is an array of col_index=>col_name
|
|
// $iMax is to limit the count of rows computed
|
|
$aRes = array();
|
|
|
|
$iCount = 0;
|
|
$iSkipped = 0;
|
|
foreach(split("\n", $this->m_sCSVData) as $sLine)
|
|
{
|
|
$sLine = trim($sLine);
|
|
if (substr($sLine, 0, 1) == '#') continue;
|
|
if (empty($sLine)) continue;
|
|
|
|
if ($iSkipped < $this->m_iSkip)
|
|
{
|
|
$iSkipped++;
|
|
continue;
|
|
}
|
|
|
|
foreach (split($this->m_sSep, $sLine) as $iCol=>$sValue)
|
|
{
|
|
if (is_array($aFieldMap)) $sColRef = $aFieldMap[$iCol];
|
|
else $sColRef = $iCol;
|
|
$aRes[$iCount][$sColRef] = $sValue;
|
|
}
|
|
|
|
$iCount++;
|
|
if (($iMax > 0) && ($iCount >= $iMax)) break;
|
|
}
|
|
return $aRes;
|
|
}
|
|
|
|
public function ListFields()
|
|
{
|
|
// Take the first valuable line
|
|
foreach(explode("\n", $this->m_sCSVData) as $sLine)
|
|
{
|
|
$sLine = trim($sLine);
|
|
if (substr($sLine, 0, 1) == '#') continue;
|
|
if (empty($sLine)) continue;
|
|
// We've got the first valuable line, that's it!
|
|
break;
|
|
}
|
|
|
|
$aRet = array();
|
|
foreach (explode($this->m_sSep, $sLine) as $iCol=>$value)
|
|
{
|
|
if ($this->m_iSkip == 0)
|
|
{
|
|
// No header to help us
|
|
$sLabel = "field $iCol";
|
|
}
|
|
else
|
|
{
|
|
$sLabel = "$value";
|
|
}
|
|
$aRet[] = $sLabel;
|
|
}
|
|
return $aRet;
|
|
}
|
|
}
|
|
|
|
|
|
?>
|