mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
232 lines
6.8 KiB
PHP
232 lines
6.8 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2012-2026 ShopeX (https://www.shopex.cn)
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
}
|