<?php

namespace admin\action;

class exportAction  extends \action
{
   
    /**导出 grid
     * @param $url
     * @param $query
     * @param $fields
     * @param $keyField 主键名
     * @param $keys 选择的 keys
     * @param $colModel
     * @param $searchoptions
     * @param $pwcode 权限模块
     * @param $page 默认 1
     * @param $pagesize 默认 int 无负数最大值 21亿
     */
    public function exportForGrid($url,$query,$fields,$keyField,$keys,$searchoptions,$pwcode='',$page=1,$pagesize=2147483647,$callback=null)
    {
		ini_set('memory_limit', \mvc::$cfg['export_memory_limit']);
		set_time_limit(\mvc::$cfg['export_time_limit']);
		$bigDataPageSize = 65535;
		$excelType = 'binary'; //binary | xml ,默认 binary
		
		$dir = str_replace('\\','/',__DIR__);
		preg_match('/(\w+)\/action/i',str_replace('\\','/',__DIR__),$m);
		$path_info = stripos($url, $m[1].'/') !== false? '/'. explode($m[1].'/',$url)[1]: $url;
		
        $fields = html_entity_decode($fields);
        $arr1 = explode(',',$fields);
        $fields = [];
        foreach($arr1 as $k=>$v){
            $arr2 = explode('=>',$v);
            $fields[$arr2[0]] = $arr2[1];
        }
        parse_str(html_entity_decode($query), $post);
        
        if(!\p::isAdmin() && !in_array($url,\mvc::$cfg['export_record_max_urls'])){
			if ($pwcode != '') {
				if ($pwcode == 'ALL') {

				} else {
					$pagesize = \p::fieldval($pwcode, 'export_limit');
				}
            } else {
				$pagesize = \mvc::$cfg['export_record_limit'];
			}
        }
        if(empty($pagesize)) $pagesize = \mvc::$cfg['export_record_limit'];
        $post['page'] = 1;
        $post['rows'] = $pagesize;
        list($class,$method,$uri_params,$req,$reqUriValues) = \mvc::parseurl($path_info);
		if($req){
		    foreach ($req as $k=>$v){
		        $post[$k] = $v;
		    }
		}
		\mvc::$req = [];
		if(strpos($url,'?')){
		    parse_str(html_entity_decode(explode('?',$url)[1]), \mvc::$req);
		}
		$_hasJsonFields = [];
        if(!empty($post['_hasJsonFields'])){
    		$_hasJsonFields = explode(',',$post['_hasJsonFields']);
        }
	    foreach ($post as $k=>$v){
	        if(in_array($k,$_hasJsonFields)) $v = json_decode(urldecode(base64_decode($v)), true);
	        \mvc::$req[$k] = $v;
	    }
		$action = new $class();
		if (false == method_exists ($class, $method)) {
			throw new \Exception ($class.'->'.$method.'()'.lg('方法不存在') );
		}
		$params = [];
		$paramsWithKey = []; //用于前置与后置方法传参
		$reflector = new \ReflectionMethod($action,$method);
		$reflectorParameters = $reflector->getParameters();
		if($reqUriValues){
			foreach($reflectorParameters as $k => $v){
				if(array_key_exists($k,$reqUriValues)){
					$post[$v->name] = $reqUriValues[$k];
				}
			}
		}
		foreach($reflectorParameters as $k => $v){
			if(array_key_exists($v->name, $post)){
				$params[$k] = $post[$v->name];
				$paramsWithKey[$v->name] = $params[$k];
			}elseif($v->isDefaultValueAvailable()){
				$params[$k] = $v->getDefaultValue();
				$paramsWithKey[$v->name] = $params[$k];
			}else{
				throw new \Exception ($class . '::'. $method . ' ' .  lg('参数') .' $'.$v->name . ' ' .lg('没有传值') );
			}
		}
	    foreach ($post as $k=>$v){
	        \mvc::$req[$k] = $v;
	    }
	    
	    \mvc::$isExportOutput = true;
	    
	    if($pagesize > $bigDataPageSize){
	        $pagesize = $bigDataPageSize;
	        \mvc::$req['page'] = 1;
	        \mvc::$req['rows'] = rand(2, 100);
    		call_user_func_array ( array ( $action , $method ), $params );
    		$data = \mvc::$ExportOutputData[0];
    		$records = \mvc::$ExportOutputData[3];
    		$total = ceil($records / $pagesize);
    		if($pagesize<$records){
		        $excelType = 'xml';
    		}
    		if(empty($data)) exit(lg('无数据'));
	    }else{
	        \mvc::$req['page'] = 1;
	        \mvc::$req['rows'] = rand(2, 100);
    		call_user_func_array ( array ( $action , $method ), $params );
    		$data = \mvc::$ExportOutputData[0];
    		$records = \mvc::$ExportOutputData[3];
	        $excelType = 'binary';
    		$total = 1;
    		if(empty($data)) exit(lg('无数据'));
	    }
		
        \mvc::$req['rows'] = $pagesize;
		$lgtag = (cateName()=='en_name') ? 'en' : 'cn';
		$filename = str_replace('Action','',end(explode('\\',$class))).'_'.$method.'_'.$_SESSION['user']['au_name'].'_'.ucfirst(getOpuser()).'_'.date('Y-m-d_His').'.xlsx';
		
		//当前选择
		if($keys && is_string($keys)) $keys = explode(',',$keys);
		//格式化状态列文本
		if($searchoptions!=''){
		    parse_str(html_entity_decode($searchoptions), $searchoptions);
		    foreach($searchoptions as $k=>$v){
		        $texts = [];
		        $t = explode(';',$v);
		        foreach($t as $tk=>$tv){
		            $t2 = explode(':',$tv);
		            $texts[$t2[0]] = $t2[1];
		        }
		        $searchoptions[$k] = $texts;
		    }
		}

        (new \model\user)->toLog('导出','导出'.$filename.', 共 '. $records . '条. '. json_encode([
                'query'=>$query,
                'params'=>$params,
                'keys'=>$keys,
            ]),$records);
		if($callback==null){
            ob_end_clean();
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelInterface.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excel.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelBase.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelXlsx.php');
            $excel = new \lib\excel\excel('xlsx');
            $excel->setConstMemory(false);
            $dir = \mvc::$cfg['dir']['cache'].'/'.date('Y-m');
    	    mkdirs($dir);
            $excel->setDirFile($dir.'/'.$filename);
            $excel->header();
            $excel->bookBegin();
            $excel->sheetBegin(lg('基本资料'),$fields);
    		for($i=1;$i<=$total;$i++){
        		$data = $this->getPageData($fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $i, $pagesize);
        		foreach($data as $row){
        		    $item = [];
                    foreach($fields as $field=>$label){
                        $item[] = isset($row[$field]) ? $row[$field] : '';
                    }
                     $excel->append($item);
        		}
    		}
            $excel->sheetEnd();
            $excel->bookEnd();
            exit();
		}else{
		    $callback($total, $fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $i, $pagesize);
		}
        /*
        if(1){
            header('Content-Description: File Transfer');
            header("Content-type:application/vnd.ms-excel");
            header('Content-Disposition: attachment; filename='.basename($filename));
            error_reporting(0);
        }
        $excelType == 'isConstMemory';
        if($excelType === 'binary'){
    		$data = $this->getPageData($fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, 1, $pagesize);
            $this->outxlsxByPHPExcel($data,$fields,$filename);
        }elseif($excelType === 'xml'){
            echo '<?xml version="1.0"?>';
            echo '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">';
            echo '<ss:Worksheet ss:Name="Sheet1">';
            echo '<ss:Table>';
            echo '<ss:Row>';
            foreach($fields as $field=>$label){
                echo '<ss:Cell><ss:Data ss:Type="String">'.$label.'</ss:Data></ss:Cell>';
            }
    	    echo "</ss:Row>";
    		for($i=1;$i<=$total;$i++){
        		$data = $this->getPageData($fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $i, $pagesize);
        		foreach($data as &$row){
                    echo '<ss:Row>';
                    foreach($fields as $field=>$label){
                        $value = isset($row[$field]) ? $row[$field] : '';
        	            echo '<ss:Cell><ss:Data ss:Type="String">'.htmlspecialchars($value).'</ss:Data></ss:Cell>';
        		    }
            	    echo "</ss:Row>";
                    flush();
                    ob_flush();
        		}
    		}
            echo "</ss:Table>";
            echo "</ss:Worksheet>";
            echo "</ss:Workbook>";
        }elseif($excelType === 'isConstMemory'){
            dd(\mvc::$cfg);
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelInterface.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excel.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelBase.php');
            include(\mvc::$cfg['mvcDir'].'/lib/excel/excelXlsx.php');
        }
        exit();
		*/
    }
    
    //
    public function getPageData($fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $page, $pagesize){
        \mvc::$req['page'] = $page;
		call_user_func_array ( array ( $action , $method ), $params );
		$data = \mvc::$ExportOutputData[0];
		foreach($data as $k=>&$row){
		    if($keys && in_array($row[$keyField],$keys)===false){
		        unset($data[$k]);
		        continue;
		    }
		    if($searchoptions){
		        foreach($searchoptions as $field=>$texts){
					if(!is_array($row[$field]) && isset($texts[$row[$field]]))
						$row[$field] = $texts[$row[$field]];
		        }
		    }
		    if(isset($row['captions'])){
		        foreach($row['captions'] as $field=>$value){
		            $row[$field] = $value;
		        }
		    }
		    if(isset($row['langs'])){
		        foreach($row['langs'] as $field=>$value){
		            $row[$field] = $value[$lgtag];
		        }
		    }
		    //去html标签
	        foreach($row as $field=>$value){
	            if(is_string($value)){
	                $row[$field] = strip_tags($value);
	            }
	        }
		} 
		return $data;
    }
    
	//输出二进制格式xlsx
	public function outxlsxByPHPExcel($data,$fields,$filename){
	    $dir = \mvc::$cfg['dir']['cache'].'/'.date('Y-m');
	    mkdirs($dir);
	    $excel  = new \Vtiful\Kernel\Excel(['path' => $dir]);
	    $header = [];
        foreach($fields as $field=>$label){
            $header[] = $label;
        }
        $xlsfile = $excel->fileName($filename)->header($header);
        
        //头样式
        $fileHandle = $xlsfile->getHandle();
        $format    = new \Vtiful\Kernel\Format($fileHandle);
        $boldStyle = $format->bold()
                    ->background(0x002F5F)
                    ->fontColor(0xFFFFFF)
                    ->toResource();
        $xlsfile->setRow('A0', 16, $boldStyle);
        
        //列宽
        $r = 0;
		$c=0;
        $maxColLabel = 'A';
        foreach($fields as $field=>$label){
            $maxColLabel = int2Excel($c);
            $xlsfile->setColumn($maxColLabel.$r.':'.$maxColLabel.$r,20);
            $c++;
        }
        
        //自动筛选
        $excel->autoFilter('A0:'.$maxColLabel.'0');
        
        //数据
        foreach($data as $row){
            $r++;
            $c=0;
            foreach($fields as $field => $label){
                $xlsfile->insertText($r, $c, $row[$field]);
                $c++;
            }
        }
	    $xlsfile->output();
	    $excel->close();
	    readfile($dir.'/'.$filename);
        ob_end_flush();
        unlink($dir.'/'.$filename);
	}
    
	//输出xml格式xlsx
	public function outxlsxByXml($data,$fields){
        echo '<?xml version="1.0"?>';
        echo '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">';
        echo '<ss:Worksheet ss:Name="Sheet1">';
        echo '<ss:Table>';
        echo '<ss:Row>';
        foreach($fields as $field=>$label){
            echo '<ss:Cell><ss:Data ss:Type="String">'.$label.'</ss:Data></ss:Cell>';
        }
	    echo "</ss:Row>";
		foreach($data as &$row){
            echo '<ss:Row>';
            foreach($fields as $field=>$label){
                $value = isset($row[$field]) ? $row[$field] : '';
	            echo '<ss:Cell><ss:Data ss:Type="String">'.htmlspecialchars($value).'</ss:Data></ss:Cell>';
		    }
    	    echo "</ss:Row>";
            flush();
            ob_flush();
		}
        echo "</ss:Table>";
        echo "</ss:Worksheet>";
        echo "</ss:Workbook>";
	}
    
	//输出html格式xlsx
	public function outxlsxByHtml($data,$fields){
        echo '<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">';
        echo "  <head>";
        echo '    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
        echo "  <head>";
        echo "  <body>";
        echo '      <table border="1">';
	    echo "            <tr>";
        foreach($fields as $field=>$label){
            echo "<th>".$label."</th>";
        }
	    echo "            </tr>";
		foreach($data as &$row){
		    echo "<tr>";
            foreach($fields as $field=>$label){
                $value = isset($row[$field]) ? $row[$field] : '';
	            echo "<td>".htmlspecialchars($value)."</td>";
		    }
		    echo "</tr>";
            flush();
            ob_flush();
		}
        echo "      </table>";
        echo "  </body>";
        echo "</html>";
	}
    
	public function samplePhoto($url,$query,$fields,$keyField,$keys,$searchoptions,$pwcode='',$page=1,$pagesize=2147483647){
		ini_set('memory_limit', \mvc::$cfg['export_memory_limit']);
		set_time_limit(\mvc::$cfg['export_time_limit']);
	    $this->exportForGrid($url,$query,$fields,$keyField,$keys,$searchoptions,$pwcode='',$page=1,$pagesize=2147483647,
	        function($total, $fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $i, $pagesize){
                $zipfile = \mvc::$cfg['dir']['cache'].'/sample_'.getOpuser().'.zip';   
                if(file_exists($zipfile)) unlink($zipfile);
                $zip = new \ZipArchive(); //linux需开启zlib,windows需php_zip.dll
                if ($zip->open ($zipfile, \ZIPARCHIVE::CREATE ) !== true) {
                   throw new \Exception ('生成压缩文件失败,请检查相关目录权限');
                }
        		for($i=1;$i<=$total;$i++){
            		$data = $this->getPageData($fields, $keyField, $keys, $searchoptions, $lgtag, $action, $method, $params, $i, $pagesize);
            		foreach($data as $row){
            		    $innum = $row['s_innum'] ? $row['s_innum'] : $row['s_plmseq'];
            		    $photos = ($row['s_photos']) ? json_decode($row['s_photos'],true) :[];
            		    $imgRegI=0;
            		    foreach($photos as $item){
            		        $putfile = \mvc::$cfg['dir']['files'].'/'.ltrim($item['filename'],'/');
            		        $filename = ($imgRegI>0) ? $innum.'_'.$imgRegI : $innum;
            		        $filename = $filename.'.'.extname($putfile);
            		        if(file_exists($putfile)){
                    		    $zip->addfile($putfile,$filename);
            		        }
            		        $imgRegI++;
            		    }
            		}
            		}
                $zip->close();
                ob_end_clean();
                header('Content-Description: File Transfer');
                header('Content-Type: application/zip');
                header('Content-Disposition: attachment; filename='.basename($zipfile));
                header('Content-Length: '.filesize($zipfile));
                error_reporting(0);
                readfile($zipfile);
                flush();
                ob_flush();
                unlink($zipfile);
	        }
	    );
        exit();       
	}


	public function exportByOrgData()
	{
		ini_set('memory_limit', \mvc::$cfg['export_memory_limit']);
		$req = \mvc::$req;
		$filename = $req['title'].'-'.date('YmdHis').'.xls';
		$header = json_decode($req['header'], true);
		$dataArr = json_decode($req['data'], true);
		ob_end_clean();
		include(\mvc::$cfg['mvcDir'].'/lib/excel/excelInterface.php');
		include(\mvc::$cfg['mvcDir'].'/lib/excel/excel.php');
		include(\mvc::$cfg['mvcDir'].'/lib/excel/excelBase.php');
		include(\mvc::$cfg['mvcDir'].'/lib/excel/excelXlsx.php');
		$excel = new \lib\excel\excel('xlsx');
		$excel->setConstMemory(false);
		$dir = \mvc::$cfg['dir']['cache'].'/'.date('Y-m');
		mkdirs($dir);
		$excel->setDirFile($dir.'/'.$filename);
		$excel->header();
		$excel->bookBegin();
		$excel->sheetBegin(lg('基本资料'), $header);
		foreach($dataArr as $row){
			$excel->append($row);
		}
		$excel->sheetEnd();
		$excel->bookEnd();
		exit();
	}
}