Location: PHPKode > scripts > Txt Xtrator > TxtXtrator.class.php
<?php
/*
 * TxtXtrator é uma classe PHP que oferece ferramentas para extração, tratamento
 * e conversão de arquivos texto com dados no formato de colunas com largura fixa,
 * CSV (texto separados por vírgula ou ponto-e-vírgula) ou relatórios em modo texto.
 *
 * @author Everton da Rosa
 * @e-mail hide@address.com
 * @version 1.0
 */
class TxtXtrator {

    //config properties
    protected $outputType;//Tipo da saída de dados: array|json|csv|sql|html
    protected $firstRow;//Número da primeira linha a ser processada por xtract()
    protected $countRow;//Número de linhas a serem processadas por xtract()
    protected $rowLen;//Tamanho exigido da linha para que ela seja processada por xtract()
    protected $fileType;//Tipo do arquivo a ser processado: fixed|csv
    protected $csvSeparator;//Caractere que separa os campos em cada linha da saída CSV
    protected $lineBreak;//Caractere de quebra de linha
    protected $lineBreakType;//Tipo do caractere de quebra de linha: linux|windows|html
    protected $sqlTable;//Nome da tabela SQL para o método outputToSql()

    //staff properties
    protected $result;//Resultado de xtract()
    protected $output;//Saída de dados resultante de output()
    protected $error;//Erros relatados
    protected $source;//Conteúdo do arquivo texto recebido de loadFile()
    protected $cm;//Modelo de colunas do template, definido por loadTpl()
    protected $export;//Dados para serem exportados para arquivo via download() ou file(), export()

    //constructor
    public function  __construct($config = false) {
        if($config){
            if($config['outputType']){
                $this->setOutputType($config['outputType']);
            }
            if($config['fistRow']){
                $this->setFirstRow($config['firstRow']);
            }
            if($config['countRow']){
                $this->setCountRow($config['countRow']);
            }
            if($config['rowLen']){
                $this->setRowLen($config['rowLen']);
            }
            if($config['fileType']){
                $this->setFileType($config['fileType']);
            }
            if($config['csvSeparator']){
                $this->setCsvSeparator($config['csvSeparator']);
            }
            if($config['lineBreakType']){
                $this->setLineBreakType($config['lineBreakType']);
            }
            if($config['sqlTable']){
                $this->setSqlTable($config['sqlTable']);
            }
        }
    }

    public function loadFile($filename){
        /*
         * Lê o arquivo texto $filename e armazena seu conteúdo em $this->source
         */

        if(!is_string($filename)){
            $this->error('$filename em loadFile() não é uma string', 'error');
            return false;
        }

        $content = @file($filename, FILE_IGNORE_NEW_LINES);

        if(!$content){
            $this->error('file_get_contents() não leu o arquivo', 'error');
            return false;
        }else{
            $this->source = $content;
            return true;
        }
    }//END loadFile()

    public function loadTpl($tpl){
        /*
         * Carrega em $this->$tpl o template passado em $tpl
         * Template armazena as definições de layout do arquivo texto fonte dos
         * dados, além de conter parâmetros para interpretação dos dados.
         */
        if(!is_string($tpl)){
            $this->error('$tpl em loadTpl() não é uma string', 'error');
            return false;
        }

        $json = @file_get_contents($tpl);
        
        if(!$json){
            $this->error('Não foi possível ler $tpl em loadTpl()', 'error');
            return false;
        }else{
            $template = json_decode($json, true);
            $this->fileType = $template['fileType'];
            $this->firstRow = $template['firstRow'];
            $this->rowLen = $template['rowLen'];
            $this->countRow = $template['countRow'];
            $this->cm = $template['cm'];
            $this->sqlTable = $template['sqlTable'];
            $this->csvSeparator = $template['csvSeparator'];
            return true;
        }
    }//END loadTpl()

    public function xtract(){
        /*
         * Processa $this->source de acordo com $this->tpl e demais parâmetros
         * de configuração e salva em $this->result
         */
        switch($this->fileType){
            case 'fixed':
                $result = $this->fromFixed();
                return $result;
                break;
            case 'csv':
                $result = $this->fromCsv();
                return $result;
                break;
            default:
                $this->error('$this->fileType não tem valor válido em xtract()', 'error');
                return false;
                break;
        }
    }//END xtract()

    public function output(){
        /*
         * Processa $this->result e transforma em saída formatada conforme
         * $this->outputType
         */
        if(!is_array($this->result)){
            $this->error('$this->result não é um array em output()', 'error');
            return false;
        }

        if(count($this->result) == 0){
            $this->error('$this->result não tem linhas em output()', 'error');
            return false;
        }
        
        switch ($this->outputType){
            case 'array':
                $this->output = $this->result;
                return true;
                break;
            case 'json':
                $this->output = json_encode($this->result);
                return true;
                break;
            case 'csv':
                return $this->outputToCsv();
                break;
            case 'sql':
                return $this->outputToSql();
                break;
            case 'html':
                return $this->outputToHtml();
                break;
            default:
                $this->error('$this->outputType não tem valor válido em output()', 'error');
                return false;
                break;
        }
    }//END output()

    protected function error($error, $type){
        /*
         * Salva em $this->error os erros recebidos por $error
         */
        $this->error[][$type] = $error;
        return true;
    }//END error()

    public function getLastError(){
        /*
         * Retorna o últiom erro armazenado em $this->error por error()
         */

        if(is_array($this->error)){
            $num_errors = count($this->error)-1;
            return $this->error[$num_errors];
        }else{
            return false;
        }
    }//END getLastError()

    public function getErrors(){
        /*
         * Retorna o log de erros de $this->error
         */
        return $this->error;
    }//END getErrors()
    
    protected function fromFixed(){
        /*
         * Extrai dados do tipo coluna com largura fixa
         */

        if(!$this->rowLen){
            $this->error('$this->rowLen não está definida para fromFixed()', 'error');
            return false;
        }

        if(!$this->firstRow){
            $this->firstRow = 0;
        }

        if(!$this->countRow){
            $this->countRow = count($this->source);
        }

        $num_row = 0;
        for($i = $this->firstRow; $i <= $this->countRow; $i++){
            $row = $this->source[$i];
            if(strlen($row) != $this->rowLen){
                $this->error('O tamanho da linha '.$i.' é '.strlen($row), 'alert');
            }else{
                reset($this->cm);
                foreach ($this->cm as $prop){
                    $value = substr($row, $prop['start'], $prop['len']);
                    if($prop['fn']){
                        $fn = $prop['fn'];
                        $value = $fn($value);
                    }
                    $this->result[$num_row][$prop['ref']] = $value;
                }
                $num_row++;
            }
        }
        return true;
    }//END fromFixed()

    protected function fromCsv(){
        /*
         * Extrai dados do tipo CSV
         */

        if(!$this->firstRow){
            $this->firstRow = 0;
        }

        if(!$this->countRow){
            $this->countRow = count($this->source);
        }

        $num_row = 0;
        for($i = $this->firstRow; $i <= $this->countRow; $i++){
            $row = $this->source[$i];
            $data = str_getcsv($row, $this->csvSeparator);
            $fld = $this->getFieldNames();
            if(count($data) == count($fld)){
                $rows[$num_row] = array_combine($fld, $data);
            }
            $num_row++;
        }
        $this->result = $rows;
        return true;
    }//END fromCsv()

    protected function outputToCsv(){
        /*
         * Formata $this->result como uma string CSV
         */
        if(!$this->csvSeparator){
            $this->error('$this->csvSeparator não definido em outputToCsv()', 'error');
            return false;
        }

        reset($this->result);
        foreach($this->result as $row){
            $csv[] = implode($this->csvSeparator, $row);
        }

        $this->output = $csv;
        return true;
    }//END outputToCsv()

    protected function outputToSql(){
        /*
         * Formata $this->result como uma string SQL do tipo INSERT
         */

        if(!$this->sqlTable){
            $this->error('$this->sqlTable não definido em outputToSql()', 'error');
            return false;
        }

        $fld_names = $this->getSqlFieldNames();
        if($fld_names === false){
            return false;
        }else{
            $fld_names = implode(',', $fld_names);
        }

        $str = 'INSERT INTO `'.$this->sqlTable.'` ('.$fld_names.') VALUES ';

        foreach($this->result as $row){
            foreach($row as $value){
                $values[] = "'$value'";
            }
            $values = implode(',', $values);
            $sql[] = $str.'('.$values.');';
            unset($values);
        }

        $this->output = $sql;
        return true;
    }//END outputToSql()

    protected function outputToHtml(){
        /*
         * Formata $this->result como uma tabela HTML
         */
        $fld_names = $this->getFieldNames();
        if($fld_names === false){
            return false;
        }else{
            foreach($fld_names as $name){
                $header .= "<th>$name</th>";
            }
            $header = "<thead><tr>$header</tr></thead>";
        }

        $num_cols = count($fld_names)-1;
        $num_rows = count($this->result);
        $footer = "<tfoot><tr><td colspan='$num_cols'>Total de registros:</td><td>$num_rows</td></tr></tfoot>";

        foreach($this->result as $row){
            $rows .= "<tr>";
            foreach($row as $value){
                $rows .= "<td>$value</td>";
            }
            $rows .= '<tr>';
        }
        $tbody = "<tbody>$rows</tbody>";

        $html = "<table border='1'>".$thead.$tbody.$tfoot."</table>";
        $this->output = $html;
        return true;
    }//END outputToHtml()

    protected function getSqlFieldNames(){
        /*
         * Retorna os nomes dos campos SQL (colunas) existentes em $this->cm
         */
        if(!$this->cm){
            $this->error('$this->cm não definido em getfieldNames()', 'error');
            return false;
        }

        reset($this->cm);
        foreach($this->cm as $field){
            if($field['sqlName']){
                $fields[] = $field['sqlName'].'`';
            }else{
                $fields[] = '`'.$field['ref'].'`';
            }
        }

        return $fields;
    }//END getSqlFieldNames()

    protected function getFieldNames(){
        /*
         * Retorna os nomes dos campos (colunas) existentes em $this->cm
         */
        if(!$this->cm){
            $this->error('$this->cm não definido em getfieldNames()', 'error');
            return false;
        }

        reset($this->cm);
        foreach($this->cm as $field){
            $fields[] = $field['ref'];
        }

        return $fields;
    }//END getFieldNames()

    public function get(){
        /*
         * Retorna o conteúdo de $this->output
         */
        if(!$this->output){
            $this->error('$this->output não definido em get()', 'error');
            return false;
        }else{
            return $this->output;
        }
    }//END get()

    public function show(){
        /*
         * Escreve o conteúdo de $this->output
         */
        if(!$this->output){
            $this->error('$this->output não definido em show()', 'error');
            return false;
        }else{
            if(is_array($this->output)){
                $show = implode('<br />', $this->output);
                echo $show;
                return true;
            }elseif(is_string($this->output)){
                echo $this->output;
                return true;
            }else{
                $this->error('$this->output não é um array ou string em show()', 'error');
                return false;
            }
        }
    }//END show()

    public function download(){
        /*
         * Oferece download de $this->export conforme $this->outputType
         */
        $this->export();
        switch ($this->outputType){
            case 'json':
                $type = 'application/x-javascript';
                break;
            case 'csv':
                $type = 'text/plain';
                break;
            case 'sql';
                $type = 'text/plain';
                break;
            case 'html';
                $type = 'text/html';
                break;
            default:
                $this->error('$this->outputType não definido em download()', 'error');
                return false;
                break;
        }

        if(count($this->export) == 0){
            $this->error('$this->export não tem conteúdo válido em download()', 'error');
            return false;
        }

        header('Content-type: '.$type);
        header('Content-Disposition: attachment; filename="output.'.$this->outputType.'"');
        foreach($this->export as $row){
            echo $row;
        }
        return true;
    }//END download()

    public function file($filename){
        /*
         * Grava o conteúdo de $this->export em um arquivo texto
         */
        $this->export();
        switch ($this->outputType){
            case 'array':
                $this->error('$this->outputType tem valor inválido em file()', 'error');
                return false;
                break;
            case 'html':
                $this->error('$this->outputType tem valor inválido em file()', 'error');
                return false;
                break;
        }

        if(count($this->export) == 0){
            $this->error('$this->export não tem conteúdo válido em file()', 'error');
            return false;
        }
        
        if(!is_string($filename)){
            $this->error('$filename em file() não foi definido', 'error');
            return false;
        }else{
            if(!is_array($this->export)){
                $this->error('$this->export não é um array em file()', 'error');
                return false;
            }else{
                if($this->lineBreakType == 'html'){
                    $this->error('$this->lineBreakType não tem valor válido em file()', 'error');
                    return false;
                }else{
                    if(file_exists($filename)){
                        unlink($filename);
                    }
                    file_put_contents($filename, $this->export, FILE_APPEND);
                }
                return true;
            }
        }
    }//END file()

    protected function export(){
        /*
         * Transforma $this->output para $this->export possibilitando exportação por download() ou file()
         */

        switch ($this->outputType){
            case 'array':
                $this->error('$this->outputType tem valor inválido em export()', 'error');
                return false;
                break;
            case 'html':
                $this->error('$this->outputType tem valor inválido em export()', 'error');
                return false;
                break;
        }

        if(!is_array($this->output)){
            $this->error('$this->output não é um array em export()', 'error');
            return false;
        }else{
            if($this->lineBreakType == 'html'){
                $this->error('$this->lineBreakType não tem valor válido em export()', 'error');
                return false;
            }else{
                foreach ($this->output as $row){
                    switch ($this->lineBreakType){
                        case 'linux':
                            $this->export[] = $row."\n";
                            break;
                        case 'windows':
                            $this->export[] = $row."\r\n";
                            break;
                    }

                }
            }
            return true;
        }
    }//END export()
    
    public function setOutputType($str){
        /*
         * Define o valor de $this->outputType
         */
        if(!is_string($str)){
            $this->error('$str em setOutputType() não é uma string', 'error');
            return false;
        }else{
            switch ($str){
                case 'array':
                    break;
                case 'json':
                    break;
                case 'csv':
                    break;
                case 'sql':
                    break;
                case 'html':
                    break;
                default:
                    $this->error('$str não tem valor válido em setOutputType()', 'error');
                    return false;
            }
            $this->outputType = $str;
            return true;
        }
    }//END setOutputType()

    public function getOutputType(){
        /*
         * Retorna o valor de $this->outputType
         */
        return $this->outputType;
    }//END getOutputType()

    public function setFirstRow($int){
        /*
         * Define o valor de $this->firstRow
         */
        if(!is_int($int)){
            $this->error('$int não é um inteiro em setFirstRow()', 'error');
            return false;
        }else{
            $this->firstRow = $int;
            return true;
        }
    }//END setFirstRow()

    public function getFirstRow(){
        /*
         * Retorna o valor de $this->firstRow
         */
        return $this->firstRow;
    }//END getFirstRow()

    public function setCountRow($int){
        /*
         * Define o valor de $this->countRow
         */
        if(!is_int($int)){
            $this->error('$int não é um inteiro em setCountRow()', 'error');
            return false;
        }else{
            $this->countRow = $int;
            return true;
        }
    }//END setCountRow()

    public function getCountRow(){
        /*
         * Retorna o valor de $this->countRow
         */
        return $this->countRow;
    }//END getCountRow()

    public function setRowLen($int){
        /*
         * Define o valor de $this->rowLen
         */
        if(!is_int($int)){
            $this->error('$int não é um inteiro em setRowLen()', 'error');
            return false;
        }else{
            $this->rowLen = $int;
            return true;
        }
    }//END setRowLen()

    public function getRowLen(){
        /*
         * Retorna o valor de $this->rowLen
         */
        return $this->rowLen;
    }//END getRowLen()

    public function setFileType($str){
        /*
         * Define o valor de $this->fileType
         */
        if(!is_string($str)){
            $this->error('$str em setfileType() não é uma string', 'error');
            return false;
        }else{
            switch ($str){
                case 'fixed':
                    break;
                case 'csv':
                    break;
                default:
                    $this->error('$str não tem valor válido em setFileType()', 'error');
                    return false;
            }
            $this->fileType = $str;
            return true;
        }
    }//END setFileType()

    public function getFileType(){
        /*
         * Retorna o valor de $this->fileType
         */
        return $this->fileType;
    }//END getFileType()

    public function setCsvSeparator($str){
        /*
         * Define o valor de $this->csvSeparator
         */
        if(!is_string($str)){
            $this->error('$str não é uma string em setCsvSeparator()', 'error');
            return false;
        }else{
            $this->csvSeparator = $str;
            return true;
        }
    }//END setCsvSeparator()

    public function getCsvSeparator(){
        /*
         * Retorna o valor de $this->csvSeparator
         */
        return $this->csvSeparator;
    }//END getCsvSeparator()
    
    public function setLineBreakType($str){
        /*
         * Define o valor de $this->LineBreakType e $this->lineBreak
         */
        if(!is_string($str)){
            $this->error('$str em setLineBreakType() não é uma string', 'error');
            return false;
        }else{
            switch ($str){
                case 'html':
                    $this->lineBreakType = $str;
                    $this->lineBreak = '<br />';
                    return true;
                    break;
                case 'linux':
                    $this->lineBreakType = $str;
                    $this->lineBreak = '\n';
                    return true;
                    break;
                case 'windows':
                    $this->lineBreakType = $str;
                    $this->lineBreak = '\r\n';
                    return true;
                    break;
                default:
                    $this->error('$str não tem valor válido em setLineBreakType()', 'error');
                    return false;
            }
        }
    }//END setLineBreakType()

    public function getLineBreakType(){
        /*
         * Retorna o valor de $this->LineBreakType
         */
        return $this->lineBreakType;
    }//END getLineBreakType()

    public function setSqlTable($str){
        /*
         * Define o valor de $this->sqlTable
         */
        if(!is_string($str)){
            $this->error('$str não é uma string em setSqlTable()', 'error');
            return false;
        }else{
            $this->sqlTable = $str;
            return true;
        }
    }//END setSqlTable()

    public function getSqlTable(){
        /*
         * Retorna o valor de $this->sqlTable
         */
        return $this->sqlTable;
    }//END getSqlTable()

}//END TxtXtrator
?>
Return current item: Txt Xtrator