Initial commit

This commit is contained in:
易焱
2021-04-18 18:51:51 +08:00
commit ec705f2fa8
3240 changed files with 623103 additions and 0 deletions
@@ -0,0 +1,284 @@
<?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();
}
}
}
+215
View File
@@ -0,0 +1,215 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
namespace OT;
use Think\Db;
//数据导出模型
class Database{
/**
* 文件指针
* @var resource
*/
private $fp;
/**
* 备份文件信息 part - 卷号,name - 文件名
* @var array
*/
private $file;
/**
* 当前打开文件大小
* @var integer
*/
private $size = 0;
/**
* 备份配置
* @var integer
*/
private $config;
/**
* 数据库备份构造方法
* @param array $file 备份或还原的文件信息
* @param array $config 备份配置信息
* @param string $type 执行类型,export - 备份数据, import - 还原数据
*/
public function __construct($file, $config, $type = 'export'){
$this->file = $file;
$this->config = $config;
}
/**
* 打开一个卷,用于写入数据
* @param integer $size 写入数据的大小
*/
private function open($size){
if($this->fp){
$this->size += $size;
if($this->size > $this->config['part']){
$this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
$this->fp = null;
$this->file['part']++;
session('backup_file', $this->file);
$this->create();
}
} else {
$backuppath = $this->config['path'];
$filename = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql";
if($this->config['compress']){
$filename = "{$filename}.gz";
$this->fp = @gzopen($filename, "a{$this->config['level']}");
} else {
$this->fp = @fopen($filename, 'a');
}
$this->size = filesize($filename) + $size;
}
}
/**
* 写入初始数据
* @return boolean true - 写入成功,false - 写入失败
*/
public function create(){
$sql = "-- -----------------------------\n";
$sql .= "-- Think MySQL Data Transfer \n";
$sql .= "-- \n";
$sql .= "-- Host : " . C('DB_HOST') . "\n";
$sql .= "-- Port : " . C('DB_PORT') . "\n";
$sql .= "-- Database : " . C('DB_NAME') . "\n";
$sql .= "-- \n";
$sql .= "-- Part : #{$this->file['part']}\n";
$sql .= "-- Date : " . date("Y-m-d H:i:s") . "\n";
$sql .= "-- -----------------------------\n\n";
$sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n";
return $this->write($sql);
}
/**
* 写入SQL语句
* @param string $sql 要写入的SQL语句
* @return boolean true - 写入成功,false - 写入失败!
*/
private function write($sql){
$size = strlen($sql);
//由于压缩原因,无法计算出压缩后的长度,这里假设压缩率为50%,
//一般情况压缩率都会高于50%
$size = $this->config['compress'] ? $size / 2 : $size;
$this->open($size);
return $this->config['compress'] ? @gzwrite($this->fp, $sql) : @fwrite($this->fp, $sql);
}
/**
* 备份表结构
* @param string $table 表名
* @param integer $start 起始行数
* @return boolean false - 备份失败
*/
public function backup($table, $start){
//创建DB对象
$db = Db::getInstance();
//备份表结构
if(0 == $start){
$result = $db->query("SHOW CREATE TABLE `{$table}`");
$result=array_values($result[0]);//重新排列数据,避免因在大小写导致数组下标不统一
$sql = "\n";
$sql .= "-- -----------------------------\n";
$sql .= "-- Table structure for `{$table}`\n";
$sql .= "-- -----------------------------\n";
$sql .= "DROP TABLE IF EXISTS `{$table}`;\n";
$sql .= trim($result[1]) . ";\n\n";
if(false === $this->write($sql)){
return false;
}
}
//数据总数
$result = $db->query("SELECT COUNT(*) AS count FROM `{$table}`");
$count = $result['0']['count'];
//备份表数据
if($count){
//写入数据注释
if(0 == $start){
$sql = "-- -----------------------------\n";
$sql .= "-- Records of `{$table}`\n";
$sql .= "-- -----------------------------\n";
$this->write($sql);
}
//备份数据记录
$result = $db->query("SELECT * FROM `{$table}` LIMIT {$start}, 1000");
foreach ($result as $row) {
$row = array_map('addslashes', $row);
$row = array_map('nl2huanhang', $row);//把记录集的换行换成特定字符,防止出错
$sql = "INSERT INTO `{$table}` VALUES ('" . implode("', '", $row) . "');\n";
if(false === $this->write($sql)){
return false;
}
}
//还有更多数据
if($count > $start + 1000){
return array($start + 1000, $count);
}
}
//备份下一表
return 0;
}
public function import($start){
//还原数据
$db = Db::getInstance();
if($this->config['compress']){
$gz = gzopen($this->file[1], 'r');
$size = 0;
} else {
$size = filesize($this->file[1]);
$gz = fopen($this->file[1], 'r');
}
$sql = '';
if($start){
$this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start);
}
for($i = 0; $i < 1000; $i++){
$sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz);
if(preg_match('/.*;$/', trim($sql))){
$sql=huanhang2nl($sql);//将备份时 把换行符转成其它字符的内容再转回来
if(false !== $db->execute($sql)){
$start += strlen($sql);
} else {
return false;
}
$sql = '';
} elseif ($this->config['compress'] ? gzeof($gz) : feof($gz)) {
return 0;
}
}
return array($start, $size);
}
/**
* 析构方法,用于关闭文件资源
*/
public function __destruct(){
$this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
}
}