Files
OMS/app/desktop/lib/system/mysqldumper.php
2025-12-28 23:13:25 +08:00

221 lines
6.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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;
}
}