<?php
namespace model\import;
use \model;
use ZipArchive;

class uploadPackMaterialZip extends model
{
    public function uploadCheck($filecount,$reqfilename,$reqfilesize,$uploadID,$extname,$category,$item,$params)
    {
        if(strtolower($extname) !== 'zip') return lg('仅支持'). ' zip';
        return true;
    }

    public function uploadGet($fileid,$zipFilename,$dir,$filebase,$extname,$category,$item,$params)
    {
        ini_set('memory_limit', \mvc::$cfg['upload']['memory_limit']);
        set_time_limit(0);
        ignore_user_abort(true);

        $resultFiles = [];
        $invalidCodes = [];
        $zip = new ZipArchive();
        if($zip->open($zipFilename) === true){
            $globalIncode = isset($params['incode']) ? trim($params['incode']) : '';
            $mode = isset($params['mode']) ? strtolower($params['mode']) : 'add';
            $clearedIncodes = [];
            $tmpBase = sys_get_temp_dir();
            $tmpDir = $tmpBase.'/packmaterial_zip_'.uniqid();
            @mkdir($tmpDir,0777,true);
            $materialModel = make(\model\pack\material::class);
            for($i=0; $i<$zip->numFiles; $i++){
                $entry = $zip->getNameIndex($i);
                if(!$entry) continue;
                $entryPath = str_replace('\\','/',$entry);
                $lower = strtolower($entryPath);
                // 这里保证了只有图片文件才会被处理
                if(preg_match('/\.(jpg|jpeg|png|gif)$/i',$lower) !== 1) continue;
                $entryPath = ltrim($entryPath,'/');
                $pathParts = explode('/',$entryPath);
                $incode = $globalIncode;
                if($incode === ''){
                    if(count($pathParts) < 2) continue;
                    $cand = '';
                    if(count($pathParts) >= 3){
                        $cand = strtoupper(trim($pathParts[count($pathParts)-2]));
                    }else{
                        $cand= strtoupper(trim($pathParts[0]));
                    }
                    if($cand==='') continue;
                    if(!$materialModel->checkExistByIncode($cand)){
                        $invalidCodes[$cand] = true;
                        continue;
                    }           
                    $incode = $cand;
                }else{
                    $incode = strtoupper($incode);
                    if(!$materialModel->checkExistByIncode($incode)){
                        $invalidCodes[$incode] = true;
                        continue;
                    }
                }
                if($mode === 'cover' && !isset($clearedIncodes[$incode])){
                    $targetRelDirOld = call_user_func(\mvc::$cfg['upload']['category']['packmaterial']['path'], '', 'img', '', ['incode'=>$incode], '');
                    $oldFileIds = $this->db->select('files','fileid',['filepath'=>$targetRelDirOld]);
                    if($oldFileIds){
                        make(\model\files::class)->delete($oldFileIds);
                    }
                    $clearedIncodes[$incode] = true;
                }
                $baseName = basename($entryPath);
                $to = $tmpDir.'/'.$entryPath;
                if(!$zip->extractTo($tmpDir,$entryPath)) continue;
                $targetRelDir = call_user_func(\mvc::$cfg['upload']['category']['packmaterial']['path'], '', 'img', '', ['incode'=>$incode], $baseName);
                $targetAbsDir = \mvc::$cfg['dir']['files'].'/'.$targetRelDir;
                @mkdir($targetAbsDir,0777,true);
                $ext = strtolower(pathinfo($to, PATHINFO_EXTENSION));
                $nameNoExt = pathinfo($to, PATHINFO_FILENAME);
                $safeBase = preg_replace('/[^a-zA-Z0-9_\-]/','_', $nameNoExt);
                if($safeBase==='') $safeBase = strtolower(str_replace('.','',uniqid('',true)));
                $uploadID = guid();
                $filebase = call_user_func(\mvc::$cfg['upload']['category']['packmaterial']['filebase'], $uploadID, 'img', $ext, ['incode'=>$incode], $baseName);
                $targetAbsFile = $targetAbsDir.'/'.$filebase.'.'.$ext;
                if(!@copy($to,$targetAbsFile)) continue;
                $filesModel = make(\model\files::class);
                $fileParams = $params;
                $fileParams['incode'] = $incode;
                $fid = $filesModel->add($baseName, $targetAbsFile, $targetRelDir, $filebase, $ext, 'packmaterial', 'img', $fileParams);
                if($fid){
                    $filename = $filesModel->getFilename($fid);
                    $resultFiles[] = [
                        'fileid'=>$fid,
                        'filename'=>$filename,
                        'orgname'=>$baseName,
                        'incode'=>$incode,
                        'mode'=>isset($fileParams['mode']) ? $fileParams['mode'] : 'add',
                    ];
                }
            }
            $zip->close();
            $this->removeDir($tmpDir);
        }
        make(\model\files::class)->delete($fileid);
        $invalidList = array_keys($invalidCodes);
        return ['files'=>$resultFiles, 'orgname'=>basename($zipFilename), 'invalid_codes'=>$invalidList];
    }

    private function removeDir($dir)
    {
        if(!is_dir($dir)) return;
        $items = scandir($dir);
        foreach($items as $it){
            if($it==='.' || $it==='..') continue;
            $path = $dir.'/'.$it;
            if(is_dir($path)){
                $this->removeDir($path);
            }else{
                @unlink($path);
            }
        }
        @rmdir($dir);
    }
}
