实时同步脚本

前一阵由于公司的项目需要,需要将一个服务网站上的文件库实时同步过来,包括其目录架构和内容,于是我写了一个脚本去在Linux上执行。
现在贴一下我写的脚本代码。

 

// exit;

set_time_limit(0);

$conn=new PDO("mysql:host=xxx;dbname=xxx;","root","xxx");
$conn->exec("SET NAMES 'utf8';");

function writeLog($msg){//记录日志
    if(!$msg) return false;
    $dir = '/data/www/default/temp/';
    $log = 'updatelog';

    $filesize = filesize($dir.'/'.$log);
    if($filesize>3145728){//设置log文件大小为3mb
        rename($dir.'/'.$log,$dir.'/'.$log."".date('YmdH',time()));
    }
    $result = file_put_contents($dir.'/'.$log,(date('Y-m-d h:i:s',time())).'   '.$msg."\r\n",FILE_APPEND);
    return $result;
}
function get_transid(){//取目录id关联表数据
    global $conn;
    $result = $conn->query("select * from transid");
    $row = $result->fetchAll(PDO::FETCH_ASSOC);
    $row_n = array();
    foreach ($row as $key => $value) {
        $row_n[$value['oldid']] = $value['id'];
    }
    $row_n[''] = 0;
    return $row_n;
}
function addnavigation($pid,$arr){//更新category表中的navigation字段
    global $conn;
    if($pid!=0){
        $result = $conn->query("select * from category where cid=".$pid);
        $row = $result->fetch(PDO::FETCH_ASSOC);
        $arr[] = array('cid'=>$row['cid'],'name'=>$row['name']);
        $parentarr = addnavigation($row['pid'],$arr);
        return $parentarr;
    }else{
        return $arr;
    }
}
function writedata($dataArr,$flag=0,$table){//导入对比目录表
    global $conn;
    if(!in_array($table,array('tempdir2','file_compare'))){
        return "tablename is wrong!";
    }
    if($flag==0){//先做清空
        $res = $conn->exec("truncate table ".$table);
        $arr = $conn->query("select count(1) as flag from ".$table);
        $row = $arr->fetch(PDO::FETCH_ASSOC);
        $flag = $row['flag']==0?1:0;
        writedata($dataArr,$flag,$table);
    }else{
        //然后写入
        if($table=='tempdir2'){
            $stmt = $conn->prepare("insert into tempdir2 (id,catalogName,parentId,catalogRoutingNumber) values (:id,:name,:pid,:cnum)");
            foreach ($dataArr as $key => $value) {
                $arr = array(
                    ':name' => $value['catalogName'],
                    ':cnum' => $value['catalogRoutingNumber'],
                    ':id' => $value['id'],
                    ':pid' => $value['parentId']
                );
                $result = $stmt->execute($arr);
            }
        }elseif($table=='file_compare'){
            $stmt = $conn->prepare("insert into file_compare (oldid,CatalogId,title,uploadUserName,uploadDate,newUptime,summary,isvisiableForuser,isdeleted,url) values (:oldid,:pid,:title,:uploadUserName,:uploadDate,:newUptime,:summary,:isvisiable,:isdeleted,:url)");
            $id_arr = get_transid();//取目录id关联表
            foreach ($dataArr as $key => $value) {
                $time = strtotime(substr($value['uploadDate'],0,strlen($value['uploadDate'])-2));
                $newUptime = strtotime(substr($value['newVersionUploaddate'],0,strlen($value['newVersionUploaddate'])-2));
                if(in_array($value['knowledgeCatalogId'],array_keys($id_arr))){
                    $pid = intval($id_arr[$value['knowledgeCatalogId']]);
                }else{
                    $pid = 0;
                }
                $arr = array(
                    ':oldid' => $value['id'],
                    ':pid' => $pid,
                    ':title' => $value['title'],
                    ':uploadUserName' => $value['uploadUserName'],
                    ':uploadDate' => $time,
                    ':newUptime' => $newUptime,
                    ':summary' => $value['summary'],
                    ':isvisiable' => intval($value['isvisiableForuser']),
                    ':isdeleted' => intval($value['isdeleted']),
                    ':yxturl' => $value['knowledgeUrl']
                );
                $result = $stmt->execute($arr);
            }
        }
        return 1;
    }
}

echo date("Y-m-d H:i:s")."运行开始 ———————————————— ";
writeLog("【*****************检查更新开始********************】");

//**********************************************************************************
//获取接口数据
//
// CURL
function curl_post($url,$arr){
    $ch=curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json; charset=utf-8"));//important
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($arr));
    $data=curl_exec($ch);
    curl_close($ch);
    return json_decode($data,true);
}
function curl_post_del($url,$arr){
    $ch=curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $arr);
    $data=curl_exec($ch);
    curl_close($ch);
    return json_decode($data,true);
}
function salt(){
    $salt=rand(10000,99999);
    return $salt;
}
$apikey="xxxxxxx";
$secretkey="xxxxxxx";
$salt1=salt();
$salt2=salt();
$signature1=hash('sha256',$secretkey.$salt1);
$signature2=hash('sha256',$secretkey.$salt2);

//获取文件数据
$url1='http://url';
$data1=array(
    'apikey' => $apikey,
    'salt' => $salt1,
    'signature' => $signature1,
    'kngCatalogId' => '',
    'updateDate' => '',
    'knowledgeTypes'=>''
);
$result1=curl_post($url1,$data1);
$new_filedata=$result1['data'];

// 获取目录数据
$url2='http://url';
$data2=array(
    'apikey' => $apikey,
    'salt' => $salt2,
    'signature' => $signature2
);
$result2=curl_post($url2,$data2);
$new_dirdata=$result2['data'];


//**********************************************************************************
//对比本地进行同步

// 写入目录对比表
writedata($new_dirdata,0,'tempdir2');

//对比新旧目录
$compare_sql = "SELECT t2.* from tempdir2 t2 LEFT JOIN tempdir t1 ON t1.id=t2.id && t1.catalogName=t2.catalogName && t1.parentId=t2.parentId && t1.catalogRoutingNumber=t2.catalogRoutingNumber WHERE t1.sid is null";
$compareArr = $conn->query($compare_sql);
$compareRow = $compareArr->fetchAll(PDO::FETCH_ASSOC);

$category_add_arr = array();
$category_update_arr = array();
$navigation_row = array();
if(count($compareRow)>0){
    writeLog("【目录存在差异数据".count($compareRow)."条】");
    //先对关联表进行全部更新
    foreach ($compareRow as $key => $value) {
        $id = $value['id'];
        $catalogName = $value['catalogName'];
        $parentId = $value['parentId'];
        $catalogRoutingNumber = $value['catalogRoutingNumber'];
        $result = $conn->query("select 1 from tempdir where id='".$id."'");
        $row = $result->fetch(PDO::FETCH_ASSOC); 
        if(empty($row)){
            $result_add = $conn->exec("insert into tempdir (id,catalogName,parentId,catalogRoutingNumber) values ('".$id."','".$catalogName."','".$parentId."','".$catalogRoutingNumber."')");//插入对比表
            $result_add2 = $conn->exec("insert into transid (oldid) values ('".$id."')");//插入ID关联表  该表ID就是分类表cid

            if($result_add>0 && $result_add2>0){
                $value["newid"] = $conn->lastInsertId();
                $category_add_arr[] = $value;
            }else{
                writeLog("【关联表或对比表插入失败】");
            }
        }else{
            $result_update = $conn->exec("update tempdir set catalogName='".$catalogName."',parentId='".$parentId."',catalogRoutingNumber='".$catalogRoutingNumber."' where id='".$id."'");//修改对比表
            if($result_update>0){
                $category_update_arr[] = $value;
            }else{
                writeLog("【对比表更新失败】");
            }
        }
    }
    //取关联表数据
    $dirid_arr = get_transid();
    //再更新使用表
    if(!empty($category_add_arr)){//插入目录树表
        writeLog("【新条目".count($category_add_arr)."条】");
        foreach ($category_add_arr as $key => $value) {
            $pid = $dirid_arr[$value['parentId']];
            $cid = $value['newid'];
            $displayorder = $value['catalogRoutingNumber'];
            $displayorder = substr($displayorder,strlen($displayorder)-3,strlen($displayorder));
            $navigation_row[] = array('cid'=>$cid,'pid'=>$pid,'name'=>$catalogName,);
            $result_add_c = $conn->exec("insert into category (cid,pid,name,displayorder,image,navigation,description) values ('".$cid."','".$pid."','".$catalogName."','".$displayorder."','','','')");
            // echo "【插入结果:".$result_add_c."】\r\n";
        }
    }
    if(!empty($category_update_arr)){//修改目录树表
        writeLog("【变动条目".count($category_update_arr)."条】");
        foreach ($category_update_arr as $key => $value) {
            $pid = $dirid_arr[$value['parentId']];
            $id = $dirid_arr[$value['id']];
            $displayorder = $value['catalogRoutingNumber'];
            $displayorder = substr($displayorder,strlen($displayorder)-3,strlen($displayorder));
            $result_update_c = $conn->exec("update category set pid='".$pid."',name='".$value['catalogName']."',displayorder='".$displayorder."' where cid='".$id."'");
            // echo "【修改结果:".$result_update_c."】\r\n";
        }
    }
    foreach ($navigation_row as $key => $value) {//更改navigation字段
        $arr = array();
        if($value['pid']!=0){
            $arr = addnavigation($value['cid'],$arr);
        }else{
            $arr[] = array('cid'=>$value['cid'],'name'=>$value['name']);
        }
        $navigation = addslashes(serialize($arr));
        $conn->exec("update category set navigation='".$navigation."' WHERE cid=".$value['cid']);
    }
}else{
    writeLog("【目录没有新变动】");
}

//**********************************************************************************
//对比是否有删除

//再次对比新旧目录
$delcompare_sql = "SELECT t1.* from tempdir t1 LEFT JOIN tempdir2 t2 ON t1.id=t2.id WHERE t2.sid is null";
$delcompareArr = $conn->query($delcompare_sql);
$delcompareRow = $delcompareArr->fetchAll(PDO::FETCH_ASSOC);
if(count($delcompareRow)>0){
    writeLog("【存在被删除项".count($delcompareRow)."条】");
    foreach ($delcompareRow as $key => $value) {
        $result_del_1 = $conn->exec("delete from tempdir where id='".$value['id']."'");
        $result_delid = $conn->query("select * from transid where oldid='".$value['id']."'");//查询预删除数据在目录树表中对应的id
        $row_delid = $result_delid->fetch(PDO::FETCH_ASSOC);
        if(!empty($row_delid)){
            $result_del_2 = $conn->exec("delete from transid where oldid='".$value['id']."'");
            $result_del_3 = $conn->exec("delete from category where cid=".$row_delid['id']);
        }
    }
}
//至此 目录树 同步完毕


//**********************************************************************************
//文件对比

//先写入临时对照表
writedata($new_filedata,0,'file_compare');

//对比新旧文件表
$compare_sql = "SELECT t2.*,t1.lastedit as lastedit  from file_compare t2 LEFT JOIN wiki_doc t1 ON t1.oldid=t2.oldid && t2.knowledgeCatalogId=t1.cid && t2.isdeleted=t1.isdeleted && t2.isvisiableForuser=t1.visible && t1.title=t2.title WHERE t1.did is null";
$compareArr = $conn->query($compare_sql);
$compareRow = $compareArr->fetchAll(PDO::FETCH_ASSOC);

if(count($compareRow)>0){
    writeLog("【文件表存在差异数据".count($compareRow)."条】");

    //********************************************************************************************************
    //查询被删除的文件,给领一关联网站发送通知
    $delid_arr = array();
    foreach ($compareRow as $key => $value) {
        if($value['isdeleted']==1){
            $delid_arr[] = "'".$value['oldid']."'";
        }
    }
    if(!empty($delid_arr)){
        $id_str = implode(",",$delid_arr);
        $sel_del_sql = "SELECT oldid from doc WHERE isdeleted=0 and oldid in (".$id_str.")";//对比找出此次被删除的文件
        $del_Arr = $conn->query($sel_del_sql);
        $del_Row = $del_Arr->fetchAll(PDO::FETCH_ASSOC);
        if(!empty($del_Row)){
            $report_del_str = '';//已被删除的ID字符串
            foreach ($del_Row as $key => $value) {
                $report_del_str .= $value['oldid'].",";
            }
            $report_del_str = substr($report_del_str,0,strlen($report_del_str)-1);
            $del_data=array('id' => $report_del_str);
            $url_repdel = "url";
            $post_del = curl_post_del($url_repdel,$del_data);//发送通知
            writeLog("【通知xxx已被删除文件ID,共".count($del_Row)."个,id=".$report_del_str.",".$post_del['reMsg']."】");
        }
    }
    //********************************************************************************************************

    //先对关联表进行全部更新
    $stmt_add = $conn->prepare("insert into doc (cid,title,summary,author,time,lastedit,lasteditor,visible,isdeleted,oldid) values (:cid,:title,:summary,:author,:time,:lastedit,:lasteditor,:visible,:isdeleted,:oldid)");//插入doc表
    $stmt_update = $conn->prepare("update doc set cid=:cid,title=:title,summary=:summary,lastedit=:lastedit,lasteditor=:lasteditor,visible=:visible,isdeleted=:isdeleted where oldid=:oldid");//更新doc表
    $stmt_down_url = $conn->prepare("insert into temp_downurl (oid,did,cid,time,filename) values (:oid,:did,:cid,:time,:filename)");

    foreach ($compareRow as $key => $value) {
        //判断插入还是更新
        $result = $conn->query("select did from doc where oldid='".$value['oldid']."'");
        $row = $result->fetch(PDO::FETCH_ASSOC);
        if(empty($row)){
            $arr = array(
                ':oldid' => $value['oldid'],
                ':cid' => intval($value['knowledgeCatalogId']),
                ':title' => $value['title'],
                ':summary' => $value['summary'],
                ':time' => intval($value['uploadDate']),
                ':lastedit' => intval($value['uploadDate']),
                ':author' => $value['uploadUserName'],
                ':lasteditor' => $value['uploadUserName'],
                ':isdeleted' => intval($value['isdeleted']),
                ':visible' => intval($value['isvisiableForuser'])
            );
            $result_add = $stmt_add->execute($arr);
            if($result_add>0){
                writeLog("【wiki_doc表成功插入oldid=".$value['oldid']."】");
            }else{
                writeLog("【wiki_doc表插入失败oldid=".$value['oldid']."】");
            }
            $did = $conn->lastInsertId();
            //向预下载表中添加数据
            $arr_url = array(
                ':oid' => $value['oldid'],
                ':did' => intval($did),
                ':cid' => intval($value['knowledgeCatalogId']),
                ':time' => intval($value['uploadDate']),
                ':filename' => $value['title']
            );
            $result_url = $stmt_down_url->execute($arr_url);
            if($result_url>0){
                writeLog("【预下载表写入成功did=".$did."】");
            }else{
                writeLog("【预下载表写入失败did=".$did."】");
            }
        }else{
            $arr = array(
                ':oldid' => $value['oldid'],
                ':cid' => intval($value['knowledgeCatalogId']),
                ':title' => $value['title'],
                ':summary' => $value['summary'],
                ':lastedit' => intval($value['newUptime']),
                ':lasteditor' => $value['uploadUserName'],
                ':isdeleted' => intval($value['isdeleted']),
                ':visible' => intval($value['isvisiableForuser'])
            );
            $result_update = $stmt_update->execute($arr);
            if($result_update>0){
                writeLog("【wiki_doc表修改成功oldid=".$value['oldid']."】");
            }else{
                writeLog("【wiki_doc表修改失败oldid=".$value['oldid']."】");
            }

            if($value['lastedit']!==$value['newUptime']){//确定文件重新被上传过
                //向预下载表中添加数据
                $arr_url = array(
                    ':oid' => $value['oldid'],
                    ':did' => intval($row['did']),
                    ':cid' => intval($value['knowledgeCatalogId']),
                    ':time' => intval($value['newUptime']),
                    ':filename' => $value['title']
                );
                $result_url = $stmt_down_url->execute($arr_url);
                if($result_url>0){
                    writeLog("【预下载表写入成功did=".$row['did']."】");
                }else{
                    writeLog("【预下载表写入失败did=".$row['did']."】");
                }
            }
        }
    }
}else{
    writeLog("【文件没有新变动】");
}

//查看link表是否正确对应doc表
$compare_sql_link = "SELECT t2.did,t2.cid from doc t2 LEFT JOIN categorylink t1 ON t1.did=t2.did && t2.cid=t1.cid WHERE t1.did is null";
$compareArr_link = $conn->query($compare_sql_link);
$compareRow_link= $compareArr_link->fetchAll(PDO::FETCH_ASSOC);

if(count($compareRow_link)>0){
    $stmt_add_link = $conn->prepare("insert into categorylink (did,cid) values (:did,:cid)");//插入link表
    $stmt_update_link = $conn->prepare("update categorylink set cid=:cid where did=:did");//插入link表
    foreach ($compareRow_link as $key => $value) {
        $result = $conn->query("select 1 from categorylink where did='".$value['did']."'");
        $row = $result->fetch(PDO::FETCH_ASSOC);
        if(empty($row)){
            $arr_link = array(
                ':did' => intval($value['did']),
                ':cid' => intval($value['cid'])
            );
            $result_add_link = $stmt_add_link->execute($arr_link);
            if($result_add_link>0){
                writeLog("【插入link表成功did=".$value['did']."】");
            }else{
                writeLog("【插入link表失败did=".$value['did']."】");
            }
        }else{
            $arr_link = array(
                ':did' => intval($value['did']),
                ':cid' => intval($value['cid'])
            );
            $result_update_link = $stmt_update_link->execute($arr_link);
            if($result_update_link>0){
                writeLog("【修改link表成功did=".$value['did']."】");
            }else{
                writeLog("【修改link表失败did=".$value['did']."】");
            }
        }
    }
}

writeLog("【**********************检查更新结束*************************】");
echo date("Y-m-d H:i:s")."运行结束\r\n";





















?>

你可能感兴趣的:(PHP)