mirror of
https://gitee.com/ShopeX/OMS
synced 2026-04-03 06:05:46 +08:00
221 lines
6.3 KiB
PHP
221 lines
6.3 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
|
||
|
||
class desktop_system_mysqldumper {
|
||
public $_isDroptables;
|
||
public $tableid; //数据表ID
|
||
public $startid;
|
||
|
||
/**
|
||
* __construct
|
||
* @return mixed 返回值
|
||
*/
|
||
public function __construct() {
|
||
$this->_db = kernel::database();
|
||
}
|
||
|
||
|
||
/*
|
||
* @params $app 所属app
|
||
* @params $bakdir 备份临时文件夹
|
||
*/
|
||
|
||
public function multi_dump_sdf( $app,$bakdir ) {
|
||
$dirname = $bakdir .'/sdf';
|
||
$dbschema_dirname = $bakdir .'/dbschema';
|
||
is_dir($dirname) or mkdir( $dirname,0755,true );
|
||
is_dir($dbschema_dirname) or mkdir( $dbschema_dirname,0755,true );
|
||
|
||
$sql = 'SELECT app_id FROM sdb_base_apps WHERE status=\'active\'';
|
||
$tables = $this->_db->select($sql);
|
||
|
||
if($app) {
|
||
foreach($tables as $key => $name) {
|
||
if($app==$name['app_id']) {
|
||
$tables = array_slice($tables, $key);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
$i=0;
|
||
foreach($tables as $key => $tbl) {
|
||
$app = $tbl['app_id'];
|
||
$service = false;
|
||
foreach ( kernel::servicelist('desktop_backup.'. $app) as $object ) {
|
||
$service = true;
|
||
$m = substr( get_class($object), ( strpos(get_class($object), $app) + strlen($app) + strlen('_mdl_') ) );
|
||
$this->dump_data( $dirname, $app, $m );
|
||
}
|
||
if( !$service) {
|
||
if(!is_dir(APP_DIR . '/' . $app .'/dbschema')){
|
||
if( count($tables)==1 ) {
|
||
return false;
|
||
} else {
|
||
$arr = $tables[$key+1];
|
||
return $arr['app_id'];
|
||
}
|
||
break;
|
||
};
|
||
if ($handle = opendir(APP_DIR . '/' . $app .'/dbschema')) {
|
||
chdir(APP_DIR . '/' . $app .'/dbschema');
|
||
while (false !== ($file = readdir($handle))) {
|
||
if($file[0]!='.') {
|
||
if( strtolower(substr( $file, -strpos(strrev($file),'.') ))!='php' ) {
|
||
if( count($tables)==1 ) {
|
||
return false;
|
||
} else {
|
||
$arr = $tables[$key+1];
|
||
return $arr['app_id'];
|
||
}
|
||
break;
|
||
};
|
||
require($file);
|
||
}
|
||
}
|
||
|
||
closedir($handle);
|
||
}
|
||
if(!is_array($db)) {
|
||
if( count($tables)==1 ) {
|
||
return false;
|
||
} else {
|
||
$arr = $tables[$key+1];
|
||
return $arr['app_id'];
|
||
}
|
||
break;
|
||
};
|
||
|
||
foreach($db as $m => $row) {
|
||
if($row['unbackup']) {
|
||
if( count($tables)==1 ) {
|
||
return false;
|
||
} else {
|
||
$arr = $tables[$key+1];
|
||
return $arr['app_id'];
|
||
}
|
||
break;
|
||
};
|
||
$this->dump_data( $dirname, $app, $m );
|
||
|
||
}
|
||
}
|
||
utils::cp( APP_DIR .'/'. $app .'/dbschema',$dbschema_dirname.'/'.$app );
|
||
if( count($tables)==1 ) {
|
||
return false;
|
||
} else {
|
||
$arr = $tables[$key+1];
|
||
return $arr['app_id'];
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
|
||
private function dump_data( $dirname, $app, $model ) {
|
||
$len = 10;
|
||
$cols = $startid = $filesize = 0;
|
||
while(true) {
|
||
|
||
$bakfile = $this->get_bak_file( $app,$model,$cols );
|
||
|
||
$tname = "sdb_{$app}_{$model}";
|
||
$limit = sprintf( 'LIMIT %s,%s', $startid, $len );
|
||
if( strtolower($app)=='base' && strtolower($model)=='kvstore' )
|
||
$where = ' WHERE prefix NOT LIKE "cache/%"';
|
||
|
||
$sql = "SELECT * FROM $tname $where $limit";
|
||
$aData = $this->_db->select( $sql );
|
||
require APP_DIR . "/{$app}/dbschema/{$model}.php";
|
||
|
||
if(empty($aData)) { $startid=0; break; }
|
||
|
||
foreach($aData as $row) {
|
||
foreach( $row as $key => &$val ) {
|
||
if( $db[$model]['columns'][$key]['type']=='serialize' ) $val = unserialize($val);
|
||
}
|
||
|
||
$i_str = serialize($row);
|
||
$filesize += strlen($i_str);
|
||
|
||
$this->write( $dirname,$bakfile,$i_str."\r\n" );
|
||
if( $filesize>1024*800 ) {
|
||
$cols++;
|
||
$bakfile = $this->get_bak_file( $app,$model,$cols );
|
||
$filesize = 0;
|
||
}
|
||
$startid++;
|
||
}
|
||
|
||
if( count($aData)<$len ) { $startid=0; break; }
|
||
}
|
||
}
|
||
|
||
|
||
private function write( $dirname, $bakfile, $str ) {
|
||
$fp = fopen($dirname.'/'.$bakfile, 'a+');
|
||
fwrite( $fp, $str );
|
||
fclose($fp);
|
||
}
|
||
|
||
private function get_bak_file( $app,$model,$cols ) {
|
||
$ext = 'sdf';
|
||
if( empty($cols) ) {
|
||
return "{$app}.{$model}.{$ext}";
|
||
} else {
|
||
return "{$app}.{$model}.{$cols}.{$ext}";
|
||
}
|
||
}
|
||
|
||
|
||
//截最后一个是否是半个UTF-8中文
|
||
/**
|
||
* utftrim
|
||
* @param mixed $str str
|
||
* @return mixed 返回值
|
||
*/
|
||
public function utftrim($str)
|
||
{
|
||
$found = false;
|
||
for($i=0;$i<4&&$i<strlen($str);$i++)
|
||
{
|
||
$ord = ord(substr($str,strlen($str)-$i-1,1));
|
||
//UTF-8中文分{四/三/二字节码},第一位分别为11110xxx(>192),1110xxxx(>192),110xxxxx(>192);接下去的位数都是10xxxxxx(<192)
|
||
//其他ASCII码都是0xxxxxxx
|
||
if($ord> 192)
|
||
{
|
||
$found = true;
|
||
break;
|
||
}
|
||
if ($i==0 && $ord < 128){
|
||
break;
|
||
}
|
||
}
|
||
|
||
if($found)
|
||
{
|
||
if($ord>240)
|
||
{
|
||
if($i==3) return $str;
|
||
else return substr($str,0,strlen($str)-$i-1);
|
||
}
|
||
elseif($ord>224)
|
||
{
|
||
if($i>=2) return $str;
|
||
else return substr($str,0,strlen($str)-$i-1);
|
||
}
|
||
else
|
||
{
|
||
if($i>=1) return $str;
|
||
else return substr($str,0,strlen($str)-$i-1);
|
||
}
|
||
}
|
||
else return $str;
|
||
}
|
||
|
||
}
|