<?php /** * Arquivo da classe Php4Console * @author Everton da Rosa everton3x@gmail.com * @version 1.1 * @license gpl-3.0.txt GPL v3.0 * @filesource * @package Text4Shell * @since 1.0 * @example teste.php */ /** * Classe para exibição de texto em ambiente Console (modo texto) * A classe Php4Console possibilita ao desenvolvedor uma maneira fácil e elegante de exibir conteúdo em modo texto. * Se você utiliza o PHP CLI (PHP Command Line Interface), Php4Console é a solução ideal para exibir conteúdo. * @package Php4Console * @since 1.0 */ class Php4Console { /** Número de colunas do Console * @var int $cols Número de colunas do Console * @since 1.0 */ protected $cols; /** Tamanho da última string usada nos métodos de carregamento * @var int $strlen tamanho da última string utilizada nos métodos de carregamento. * @since 1.1 */ protected $strlen; /** InÃcio da linha de etapas do método openLoadStepLine * @var string $stepindicator InÃcio da linha de etapas do método openLoadStepLine * @since 1.1 */ protected $stepindicator = ' ->'; /** Número de etapas da última barra de progresso iniciada * @var ind $steps Número de etapas da última barra de progrsso inicada * @since 1.1 */ protected $steps; /** Número da última etapa iniciada na barra de progresso * @var int $laststep Número da última etapa iniciada na barra de progresso * @since 1.1 */ protected $laststep; /** * Construtor da classe * @method __construct(int $cols) Construtor da classe * @param int $cols Número de colunas do Console. O valor informado aqui ficará armazenado em Php4Console::cols. * @return object Retorna um objeto que representa a classe * @since 1.0 */ public function __construct($cols) { $this->setCols($cols); return $this; } /** * Setter do número de colunas * @method setCols(int $cols) Define o número de colunas que a classe utilizará para criação das telas * @param int $cols Número de colunas * @return boolean Retorna TRUE em caso de sucesso ou FALSE em caso de falha. * @since 1.0 */ public function setCols($cols){ if(!is_int($cols) || $cols <= 0){ trigger_error("Número de colunas inválido!\n", E_USER_ERROR); return false; }else{ $this->cols = $cols; return true; } } /** * Getter do número de colunas * @method getCols() Retorna o número de colunas armazenado em Php4Console::cols * @return int Retorna o número de colunas. * @since 1.0 */ public function getCols(){ return $this->cols; } /** * Prepara o texto para a exibição * @method paragraph(string $text, int $cols) Quebra o texto em linhas com o tamanho máximo do número de colunas especificado em $cols. * @param string $text O texto a ser exibido * @param int $cols Número de colunas de quada linha * @param string $align Alinhamento do text. Aceita LEFT (padrão), RIGHT ou CENTER (mÃnuscula/maiúscula). * @return boolean|array Retorna FALSE em caso de falha ou um array contendo as linhas do texto. * @since 1.0 */ protected function paragraph($text, $cols = 0, $align = 'left'){ if($cols == 0){ $cols = $this->getCols(); } if(!is_string($text)){ trigger_error("Texto inválido!\n", E_USER_ERROR); return false; }else{ $arr = str_split($text, $cols); } $output = array(); foreach($arr as $line){ $output[] = str_pad($line, $cols, ' ', $this->getAlign($align)); } return $output; } /** * Quebra um texto em linhas. * @method write(string $text, string $align) Quebra um texto em linhas de acordo com o número de colunas em Php4Console::cols. * @param string $text O texto a ser escrito. * @param string $align [Opcional] O alinhamento do texto. O padrão é LEFT, porém aceita RIGHT e CENTER (maipusculas ou minúsculas). * @return string Texto quebrado em linhas. * @since 1.0 */ public function write($text, $align = ''){ $str = ''; if(strlen($align) == 0){ $align = 'left'; } foreach($this->paragraph($text, 0, $align) as $lines){ $str .= "$lines".PHP_EOL; } return $str; } /** * Quebra um texto em linhas e coloca dentro de um Box. * @method box(string $box, string $title, string $align) Quebra um texto em linhas de acordo com o número de colunas em Php4Console::cols e coloca dentro de um Box. * @param string $text O texto a ser exibido * @param string $title [Opcional] Se definido, exibe um tÃtulo para a caixa. * @param string $align [Opcional] O alinhamento do texto do box. O padrão é LEFT, porém aceita RIGHT e CENTER (maipusculas ou minúsculas). * @return string O Box com o texto quebrado em linhas; * @since 1.0 */ public function box($text, $title = '', $align = ''){ $box = ''; $cols = $this->getCols() - 4; if(strlen($align) == 0){ $align = 'left'; } if(strlen($title) > 0){ $box .= $this->hline(); $title = str_pad($title, $cols, ' ', STR_PAD_BOTH ); $box .= "| $title |".PHP_EOL; } $box .= $this->hline(); $lines = $this->paragraph($text, $cols, $align); foreach($lines as $ln){ if(strlen($ln) < $cols){ $ln = str_pad($ln, $cols, ' '); } $box .= "| $ln |".PHP_EOL; } $box .= $this->hline(); return $box; } /** * Cria uma linha divisória horizontal. * @method hline() Método auxiliar que cria uma linha divisória horizontal. * @return string Retorna a linha criada. */ protected function hline(){ $line = ''; $pad_length = $this->getCols() - 2; $line .= '+'; $line .= str_pad('-', $pad_length, '-'); $line .= '+'.PHP_EOL; return $line; } /** * Cria uma linha divisória horizontal para tabelas. * @method tblline() Método auxiliar que cria uma linha divisória horizontal para tabela. * @param array $colmodel O modelo de coluna da tabela. * @return string Retorna a linha criada. * @since 1.0 */ protected function tblline($colmodel){ $line = ''; foreach($colmodel as $col){ $len = $col['len']; if($len <= 0){ trigger_error('Falha no modelo de coluna', E_USER_ERROR); return false; }else{ $pad_length = $len; $line .= str_pad('+', $pad_length, '-'); } } $minus = $this->getCols() - 1; $line = substr($line, 0, $minus); $line .= '+'.PHP_EOL; return $line; } /** * Cria uma tabela com os dados recebidos. * @method table(array $data, array $colmodel, string $title) Cria uma tabela os dados contidos em $data. $data precisa estar no formato: * $data = array( * 0 => array('coluna1' => 'valor1', 'coluna2' => 'valor2') * ,1 => array('coluna1' => 'valor1', 'coluna2' => 'valor2') * ,2 => array('coluna1' => 'valor1', 'coluna2' => 'valor2') * ); * @param array $data Um array multidimensional com os dados de linhas e colunas par exibir. * @param array $colmodel Um array especificando os rótulos das colunas, a largura de cada coluna e o alinhamento de cada coluna. Observe que a soma das larguras das colunas deve ser igual ao valor de Php4Console::cols. Se um rótulo não for especificado, o id da coluna será utilizado. Os alinhamentos válidos são LEFT, RIGHT e CENTER (em maiúsculas ou minúsculas). Se nenhum for especificado, LEFT é adotado. O array segue a estrutura: array( 'campo1' => array('label' => 'Rótulo', 'len' => 10, 'align' => 'LEFT'), 'campo2' => array([...]), [...]) * @param string $title [Opcional] Se definido, mostra o texto com tÃtulo da tabela. * @return string Retorna a tabela criada. * @since 1.0 */ public function table($data, $colmodel, $title = ''){ if(count($data) == 0){ trigger_error('Dados para tabela inválidos!\n', E_USER_ERROR); return false; } if(count($colmodel) == 0){ trigger_error('Modelo de coluna da tabela inválido!\n', E_USER_ERROR); return false; } //configurando colmodel foreach($data[0] as $k => $v){ if(!isset($colmodel[$k]['label'])){ $colmodel[$k]['label'] = $k; } if(!isset($colmodel[$k]['align'])){ $colmodel[$k]['align'] = 'left'; } } unset($k, $v); $table = ''; //tÃtulo if(strlen($title) >0){ $cols = $this->getCols() - 4; if(strlen($title) > 0){ $table .= $this->hline(); $title = str_pad($title, $cols, ' ', STR_PAD_BOTH ); $table .= "| $title |".PHP_EOL; } } //cabeçalho $table .= $this->tblline($colmodel); foreach($colmodel as $cmk => $cm){ $len = $cm['len'] - 2; $id = $cmk; $labels[$id] = $this->paragraph($cm['label'], $len); } unset($cm, $len, $id); $maxsize = 0; foreach($labels as $label){ $size = count($label); if($maxsize < $size){ $maxsize = $size; } } unset($label); $last = count($labels) - 1; $j = 0; $rows = array(); for($i = 0; $i < $maxsize; $i++){ @$rows[$i] .= "|"; } foreach($labels as $id => $arr){ if(count($arr) <= $maxsize){ $arr = array_pad($arr, $maxsize, ' '); } if($j == $last){ $len = $colmodel[$id]['len'] -2; }else{ $len = $colmodel[$id]['len'] -1; } $j++; for($i = 0; $i < $maxsize; $i++){ if(!isset($colmodel[$id]['align'])){ $align = 'center'; }else{ $align = $colmodel[$id]['align']; } $align = $this->getAlign($align); $label = str_pad($arr[$i], $len, ' ', $align); $rows[$i] .= "$label|"; } } foreach($rows as $line){ $table .= "$line\n"; } $table .= $this->tblline($colmodel); //corpo com os dados $lens = array(); foreach($colmodel as $k => $v){ $lens[$k] = $v['len'] - 2; } $tmp = array(); foreach($data as $id => $line){ foreach($line as $fldname => $fldvalue){ $tmp[$id][$fldname] = $this->paragraph($fldvalue, $lens[$fldname]); } } $data = $tmp; unset($tmp); foreach($data as $line){ $maxsize = 0; foreach($line as $row){ if($maxsize < count($row)){ $maxsize = count($row); } } unset($row); $last = count($line) - 1; $j = 0; $rows = array(); for($i = 0; $i < $maxsize; $i++){ @$rows[$i] .= "|"; } foreach($line as $id => $arr){ if(count($arr) <= $maxsize){ $arr = array_pad($arr, $maxsize, ' '); } if($j == $last){ $len = $colmodel[$id]['len'] -2; }else{ $len = $colmodel[$id]['len'] -1; } $j++; for($i = 0; $i < $maxsize; $i++){ if(!isset($colmodel[$id]['align'])){ $align = 'center'; }else{ $align = $colmodel[$id]['align']; } $align = $this->getAlign($align); $label = str_pad($arr[$i], $len, ' ', $align); $rows[$i] .= "$label|"; } } foreach($rows as $line){ $table .= "$line\n"; } $table .= $this->tblline($colmodel); } return $table; } /** * Retorna a constante para alinhamento. * @method int getAlign(string $align) Retorna o valor da constante de alinhamento para ser utilizada com str_pad(). * @param string $align Alinhamento desejado. Admite RIGHT LEFT e CENTER (mÃnusculas ou maiúsculas). * @return int Retorna o valor da constante STR_PAD_RIGHT, STR_PAD_LEFT OU STR_PAD_BOTH, para $align RIGHT, LEFT ou CENTER, respectivamente. * @since 1.0 */ protected function getAlign($align){ $align = strtolower($align); switch($align){ case 'center': return STR_PAD_BOTH; break; case 'right': return STR_PAD_LEFT; break; case 'left': return STR_PAD_RIGHT; break; default: trigger_error("Alinhamento desconhecido\n", E_USER_ERROR); return false; } } /** Inicia a exibição de uma linha de log de carregamento * @method void openLoadLine(string $str) inicia a exibição de uma linha de carregamento * @param string $str A mensagem de carregamento * @return void Nada é retornado * @since 1.1 */ public function openLoadLine($str){ if(strlen($str) == 0) { trigger_error('Nenhuma mensagem de carregamento definida.', E_USER_ERROR); return; }else{ $maxlen = $this->getCols() - 8; $str = substr($str, 0, $maxlen); $strlen = strlen($str); $this->strlen = $strlen; echo $str; return; } } /** Termina uma linha de carregamento * @method void closeLoadLine(bool $success) Fecha a última linha de carregamento aberta por openLoadLine() * @param bool $success [Opcional] Se TRUE (padrão), a linha termina com [OK], senão, termina com[FAIL] * @return void Nada é retornado * @since 1.1 */ public function closeLoadLine($success = true){ $pad = $this->getCols() - $this->strlen; if($success){ echo str_pad('[OK]', $pad, '.', STR_PAD_LEFT); }else{ echo str_pad('[FAIL]', $pad, '.', STR_PAD_LEFT); } echo PHP_EOL; return; } /** Inicia um grupo de linhas de carregamento * @method void openLoadGroupLine(string $str) Inicia um grupo de linhas de carregamento * @param string $str Uma mensagem da linha de inÃcio do grupo * @return void Nenhum retorno * @since 1.1 */ public function openLoadGroupLine($str){ if(strlen($str) == 0) { trigger_error('Nenhuma mensagem de carregamento definida.', E_USER_ERROR); return; }else{ $maxlen = $this->getCols(); $str = substr($str, 0, $maxlen); $str = str_pad($str, $maxlen, '.', STR_PAD_RIGHT); echo $str.PHP_EOL; return; } } /** Inicia uma linha de um grupo de linhas de carregamento * @method void openLoadStepLine(string $str) Inicia uma linha de um grupo de linhas de carregamento * @param string $str O texto para ser exibido na linha * @return void Nada é retornado * @since 1.1 */ public function openLoadStepLine($str){ if(strlen($str) == 0) { trigger_error('Nenhuma mensagem de carregamento definida.', E_USER_ERROR); return; }else{ $maxlen = $this->getCols() - 8; $str = $this->stepindicator.$str; $str = substr($str, 0, $maxlen); $strlen = strlen($str); $this->strlen = $strlen; echo $str; return; } } /** Termina uma linha de um grupo de linhas de carregamento * @method void closeLoadStepLine(bool $success) Fecha a última linha de um grupo de carregamento aberta por openLoadStepLine() * @param bool $success [Opcional] Se TRUE (padrão), a linha termina com [OK], senão, termina com[FAIL] * @return void Nada é retornado * @since 1.1 */ public function closeLoadStepLine($success = true){ $pad = $this->getCols() - $this->strlen - 4; if($success){ echo str_pad('[OK]', $pad, '.', STR_PAD_LEFT); }else{ echo str_pad('[FAIL]', $pad, '.', STR_PAD_LEFT); } echo PHP_EOL; return; } /** Termina um grupo de linhas de carregamento * @method void closeLoadGroupLine(string $str, bool $success) Fecha um grupo linhas de carregamento aberto por openLoadGroupLine() * @param string $str Uma mensagem para ser exibida ao final * @param bool $success [Opcional] Se TRUE (padrão), a linha termina com [OK], senão, termina com[FAIL] * @return void Nada é retornado * @since 1.1 */ public function closeLoadGroupLine($str, $success = true){ if(strlen($str) == 0) { trigger_error('Nenhuma mensagem de carregamento definida.', E_USER_ERROR); return; }else{ echo $str; $pad = $this->getCols() - strlen($str); if($success){ echo str_pad('[OK]', $pad, '.', STR_PAD_LEFT); }else{ echo str_pad('[FAIL]', $pad, '.', STR_PAD_LEFT); } echo PHP_EOL; return; } } /** inicia uma barra de progresso * @method void initProgressBar(int $steps) inicia uma barra de progresso e carrega a primeira etapa dela * @param int $steps Número total de etapas da barra de progresso * @return void Nenhum retorno * @since 1.1 */ public function initProgressBar($steps){ if($steps == 0){ trigger_error('Etapas da barra de progresso são inválidas.', E_USER_ERROR); return; } $this->steps = $steps; $this->runProgressBar(); return; } /** Executa uma etapa da última barra de progresso * @method void runProgressBar() Executa uma etapa da última barra de progresso * @return void Nada é retornado * @since 1.1 */ public function runProgressBar(){ $percent = floor($this->getCols() / $this->steps); $module = $this->getCols() % $this->steps; if($this->laststep < ($this->steps - 1)){ echo str_pad('', $percent, '|'); $this->laststep++; return; }elseif($this->laststep < $this->steps){ $percent = $percent + $module; echo str_pad('', $percent, '|'); $this->laststep = 0; $this->steps = 0; echo PHP_EOL; return; } } /** Emula um prompt de comando retornando o resultado digitado pelo usuário. * @method string prompt(string $prompt) Emula um prompt de comando retornando o resultado digitado pelo usuário. * @param string $prompt [Opcional] Texto do prompt. O padrão é [diretório atual> ]. * @return string Retorna uma string contendo o que foi digitado pelo usuário. * @since 1.1 */ public function prompt($prompt = ''){ if(strlen($prompt) == 0){ $prompt = getcwd().'>'; } echo "$prompt "; $stdin = fgets(STDIN); return rtrim($stdin, PHP_EOL); } } ?>