You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
8.3 KiB
PHTML
284 lines
8.3 KiB
PHTML
5 years ago
|
<?php
|
||
|
|
||
|
namespace OT;
|
||
|
class DataDictionary{
|
||
|
|
||
|
public function __construct($table){
|
||
|
$this->headers = $table['header'];
|
||
|
$this->rows = $table['rows'];
|
||
|
$this->crossingChar = '+';
|
||
|
$this->horizontalBorderChar = '-';
|
||
|
$this->verticalBorderChar = '|';
|
||
|
$this->borderFormat = '%s';
|
||
|
$this->cellHeaderFormat = '%s';
|
||
|
$this->cellRowFormat = '%s';
|
||
|
$this->paddingChar = ' ';
|
||
|
$this->padType = STR_PAD_RIGHT;
|
||
|
}
|
||
|
/**
|
||
|
* Renders table to output.
|
||
|
*
|
||
|
* Example:
|
||
|
* +---------------+-----------------------+------------------+
|
||
|
* | ISBN | Title | Author |
|
||
|
* +---------------+-----------------------+------------------+
|
||
|
* | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
|
||
|
* | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||
|
* | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
|
||
|
* +---------------+-----------------------+------------------+
|
||
|
*
|
||
|
*/
|
||
|
public function render($out = true){
|
||
|
if(!$this->rows)
|
||
|
exit('invalid table content');
|
||
|
//获得表头行首 +---------------+-----------------------+------------------+
|
||
|
$output = $this->renderRowSeparator();
|
||
|
//获取头部输出| ISBN | Title | Author |
|
||
|
$output .= $this->renderRow($this->headers, $this->cellHeaderFormat);
|
||
|
//header存在的话再输出行分割符
|
||
|
if ($this->headers) {
|
||
|
$output .= $this->renderRowSeparator();
|
||
|
}
|
||
|
//渲染每一行
|
||
|
foreach ($this->rows as $row) {
|
||
|
$output .= $this->renderRow($row, $this->cellRowFormat);
|
||
|
}
|
||
|
if ($this->rows) {
|
||
|
$output .= $this->renderRowSeparator();
|
||
|
}
|
||
|
if($out){
|
||
|
exit($output);
|
||
|
}else{
|
||
|
$this->cleanup();
|
||
|
return $output;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function renderWitoutHeadTail($out = true){
|
||
|
if(!$this->rows)
|
||
|
exit('invalid table content');
|
||
|
//获取头部输出| ISBN | Title | Author |
|
||
|
$output .= $this->renderRow($this->headers, $this->cellHeaderFormat);
|
||
|
//header存在的话再输出行分割符
|
||
|
if ($this->headers) {
|
||
|
$output .= $this->renderRowSeparator();
|
||
|
}
|
||
|
//渲染每一行
|
||
|
foreach ($this->rows as $row) {
|
||
|
$output .= $this->renderRow($row, $this->cellRowFormat);
|
||
|
}
|
||
|
if($out){
|
||
|
print($output);
|
||
|
}else{
|
||
|
$this->cleanup();
|
||
|
return $output;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//渲染表格行起始分割行
|
||
|
private function renderRowSeparator(){
|
||
|
if (0 === $count = $this->getNumberOfColumns()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$markup = $this->crossingChar;
|
||
|
for ($column = 0; $column < $count; $column++) {
|
||
|
$markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column))
|
||
|
.$this->crossingChar
|
||
|
;
|
||
|
}
|
||
|
|
||
|
return sprintf($this->borderFormat, $markup).PHP_EOL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 渲染表格行.
|
||
|
*
|
||
|
* Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
|
||
|
*
|
||
|
* @param array $row
|
||
|
* @param string $cellFormat
|
||
|
*/
|
||
|
private function renderRow(array $row, $cellFormat){
|
||
|
if (empty($row)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$output = $this->renderColumnSeparator();
|
||
|
for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
|
||
|
$output .= $this->renderCell($row, $column, $cellFormat);
|
||
|
$output .= $this->renderColumnSeparator();
|
||
|
}
|
||
|
$output .= $this->writeln('');
|
||
|
return $output;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 带边距的渲染单元格.
|
||
|
*
|
||
|
* @param array $row
|
||
|
* @param integer $column
|
||
|
* @param string $cellFormat
|
||
|
*/
|
||
|
private function renderCell(array $row, $column, $cellFormat){
|
||
|
$cell = isset($row[$column]) ? $row[$column] : '';
|
||
|
return sprintf(
|
||
|
$cellFormat,
|
||
|
$this->str_pad(
|
||
|
$this->paddingChar.$cell.$this->paddingChar,
|
||
|
$this->getColumnWidth($column),
|
||
|
$this->paddingChar,
|
||
|
$this->padType
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 渲染水平列分隔符.
|
||
|
*/
|
||
|
private function renderColumnSeparator(){
|
||
|
return(sprintf($this->borderFormat, $this->verticalBorderChar));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取表格的列数.
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
private function getNumberOfColumns() {
|
||
|
if (null !== $this->numberOfColumns) {
|
||
|
return $this->numberOfColumns;
|
||
|
}
|
||
|
|
||
|
$columns = array(0);
|
||
|
$columns[] = count($this->headers);
|
||
|
foreach ($this->rows as $row) {
|
||
|
$columns[] = count($row);
|
||
|
}
|
||
|
|
||
|
return $this->numberOfColumns = max($columns);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取列宽.
|
||
|
*
|
||
|
* @param integer $column
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
private function getColumnWidth($column) {
|
||
|
if (isset($this->columnWidths[$column])) {
|
||
|
return $this->columnWidths[$column];
|
||
|
}
|
||
|
|
||
|
$lengths = array(0);
|
||
|
$lengths[] = $this->getCellWidth($this->headers, $column);
|
||
|
foreach ($this->rows as $row) {
|
||
|
$lengths[] = $this->getCellWidth($row, $column);
|
||
|
}
|
||
|
|
||
|
return $this->columnWidths[$column] = max($lengths) + 2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取单元格宽度.
|
||
|
*
|
||
|
* @param array $row
|
||
|
* @param integer $column
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
private function getCellWidth(array $row, $column) {
|
||
|
if ($column < 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (isset($row[$column])) {
|
||
|
return $this->strlen($row[$column]);
|
||
|
}
|
||
|
|
||
|
return $this->getCellWidth($row, $column - 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the length of a string, using mb_strlen if it is available.
|
||
|
*
|
||
|
* @param string $string The string to check its length
|
||
|
*
|
||
|
* @return integer The length of the string
|
||
|
*/
|
||
|
protected function strlen($string) {
|
||
|
// if (!function_exists('mb_strlen')) {
|
||
|
return (strlen($string) + mb_strlen($string,'UTF8')) / 2;
|
||
|
// }
|
||
|
|
||
|
// if (false === $encoding = mb_detect_encoding($string)) {
|
||
|
// return strlen($string);
|
||
|
// }
|
||
|
|
||
|
// return mb_strlen($string, $encoding);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called after rendering to cleanup cache data.
|
||
|
*/
|
||
|
private function cleanup(){
|
||
|
$this->columnWidths = array();
|
||
|
$this->numberOfColumns = null;
|
||
|
}
|
||
|
|
||
|
public function writeln($line=''){
|
||
|
return $line.PHP_EOL;
|
||
|
}
|
||
|
|
||
|
public function str_pad($input , $pad_length ,$pad_string , $pad_type){
|
||
|
$strlen = $this->strlen($input);
|
||
|
if($strlen < $pad_length){
|
||
|
$difference = $pad_length - $strlen;
|
||
|
switch ($pad_type) {
|
||
|
case STR_PAD_RIGHT:
|
||
|
return $input . str_repeat($pad_string, $difference);
|
||
|
break;
|
||
|
case STR_PAD_LEFT:
|
||
|
return str_repeat($pad_string, $difference) . $input;
|
||
|
break;
|
||
|
default:
|
||
|
$left = $difference / 2;
|
||
|
$right = $difference - $left;
|
||
|
return str_repeat($pad_string, $left) . $input . str_repeat($pad_string, $right);
|
||
|
break;
|
||
|
}
|
||
|
}else{
|
||
|
return $input;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//生成当前数据库指定表的数据字典(字符串)
|
||
|
public function generate($tableName=''){
|
||
|
$this->crossingChar = '|';
|
||
|
$out_array = array();
|
||
|
$output = '';
|
||
|
if($tableName){
|
||
|
echo substr($tableName, strlen(C('DB_PREFIX'))).PHP_EOL;
|
||
|
$rows = array();
|
||
|
$array = M()->query('SHOW FULL COLUMNS FROM '.$tableName);
|
||
|
foreach ($array as $key => $value) {
|
||
|
$rows[] = array($value['Field'], $value['Type'], $value['Comment']);
|
||
|
}
|
||
|
|
||
|
$this->headers = array('字段','类型','注释');
|
||
|
$this->rows = $rows;
|
||
|
$this->renderWitoutHeadTail();
|
||
|
}
|
||
|
echo PHP_EOL;
|
||
|
}
|
||
|
|
||
|
public function generateAll(){
|
||
|
$tables = M()->query('SHOW TABLE STATUS;');
|
||
|
$tables = array_column($tables,'Name');
|
||
|
foreach ($tables as $value) {
|
||
|
$this->generate($value);
|
||
|
$this->cleanup();
|
||
|
}
|
||
|
}
|
||
|
}
|