createModel(); $controller=$this->createController(); $view=$this->createView(); Db::commit(); }catch (\Exception $e){ $error=$e->getMessage(); $this->rollback(); } if($error){ throw new \Exception($error); } $r=compact('model','controller','view'); return $r; } public function volidate() { if($this->type=='file'){ $filelist=$this->buildFile(); foreach ($filelist as $key=>$file){ if($key=='view'){ foreach ($file as $f){ if(file_exists($f)){ throw new \Exception(__('%s文件已存在',['s'=>'view'])); } } }else if(file_exists($file)){ throw new \Exception(__('%s文件已存在',['s'=>$key])); } } } if($this->isTree && !$this->treeTitle){ throw new \Exception(__('树形结构标题未定义')); } if(!key_exists('index',$this->actionList)){ throw new \Exception(__('%s方法未定义',['s'=>'index'])); } } public function clear() { $filelist=$this->buildFile(); foreach ($filelist as $key=>$file){ if($key=='view'){ foreach ($file as $f){ if(file_exists($f)){ $time=filectime($f); if(time()-$time>3600){ throw new \Exception(__('%s已创建超过一个小时,禁止删除',['s'=>'view'])); } unlink($f); } } }else if(file_exists($file)){ $time=filectime($file); if(time()-$time>3600){ throw new \Exception(__('%s已创建超过一个小时,禁止删除',['s'=>$key])); } unlink($file); } } } protected function init() { $config = Db::getConfig(); $default=$config['default']; self::$prefix=$config['connections'][$default]['prefix']; $recyclebinField=[]; $relations=[]; foreach ($this->fields as $key=>$value){ $title=trim($value['title']); $this->fields[$key]['title']=$title?:$value['field']; if($this->actions['table'] && $value['visible']==='relation'){ if(!$value['relation']){ throw new \Exception(__('%s字段关联关系未定义',['s'=>$value['title']])); } $relation=json_decode($value['relation'],true); if($value['field']==$relation['table']){ throw new \Exception(__('字段名与关联表名重名,禁止关联,建议修改字段名为%s',['s'=>$relation['table'].'_id'])); } $relations[$value['field']]=$relation; } if(!empty($value['recyclebin'])){ $type=$value['formatter']; if(!in_array($type,['text','image','images','date','datetime','tag','tags'])){ $type='text'; } $recyclebinField[]=[ 'field'=>$value['field'], 'type'=>$type, 'title'=>$value['title'] ]; } } if(key_exists('recyclebin',$this->actionList) && empty($recyclebinField)){ throw new \Exception(__('回收站的显示字段未定义')); } $this->relations=$relations; $this->recyclebinField=$recyclebinField; } public function getIndexUrl() { $pack=str_replace('\\','/',substr($this->controller,strpos($this->controller,'controller\\')+11)); $pack=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $pack)); return request()->domain().build_url($pack.'/index','admin'); } private function rollback() { Db::rollback(); if($this->type=='file'){ $filelist=$this->buildFile(); foreach ($filelist as $key=>$file){ if($key=='view'){ foreach ($file as $f){ if(file_exists($f)){ unlink($f); } } }else if(file_exists($file)){ unlink($file); } } } } private function buildFile(mixed $key=false) { $rootPath = root_path(); $controller=$rootPath.str_replace('\\',DS,$this->controller).'.php'; $model=$rootPath.str_replace('\\',DS,$this->model).'.php'; $temp=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $this->controller)); $view=[ 'index'=>$rootPath.str_replace(['\\','controller'],[DS,'view'],$temp).DS.'index.html', ]; if(key_exists('add',$this->actionList)){ $view['add']=$rootPath.str_replace(['\\','controller'],[DS,'view'],$temp).DS.'add.html'; } if(key_exists('edit',$this->actionList)){ $view['edit']=$rootPath.str_replace(['\\','controller'],[DS,'view'],$temp).DS.'edit.html'; } $js=$rootPath.'public'.DS.'assets'.DS.'js'.DS.str_replace(['app\\','controller\\','\\'],['','',DS],$temp).'.js'; $arr=compact('controller','model','view','js'); if($key){ return $arr[$key]; } return $arr; } private function createView() { $keys=array_keys($this->actionList); $reduced=$this->reduced; $table=$this->actions['table']; $form=$this->actions['form']; $isTree=$this->isTree; $treeTitle=$this->treeTitle; $viewContent=[]; foreach ($keys as $key){ if(in_array($key,['del','multi','import','download','recyclebin'])){ continue; } $action=$key; $title=$this->actionList[$key]; $search=[]; $commonSearch=false; $pagination=$this->pagination; $tabs=$this->tabs; $toolbar=['refresh']; if($key=='index'){ foreach ($this->actionList as $xkey=>$value){ if(in_array($xkey,['add','edit','del'])){ $toolbar[]=$xkey; } } $slot=''; $weigh=0; foreach ($this->fields as $value){ if(!empty($value['search'])){ $search[]=$value['field']; } if(trim($value['operate'])){ $commonSearch=true; } if($value['field']=='weigh' && $value['type']=='int'){ $weigh=1; } if($value['field']=='status' && $value['type']=='varchar'){ $toolbar[]='more'; } $slot.=getTableslot($value); } $slot=rtrim($slot); foreach ($this->actionList as $fkey=>$value){ if(in_array($fkey,['import','download','recyclebin'])){ $toolbar[]=$fkey; } } $search=empty($search)?'':implode(',',$search); $toolbarStr=implode(',',$toolbar); $controller=str_replace('\\','\\\\',$this->controller); $summary=$this->summary; $expand=$this->expand; $js=$this->getJsContent('js-index'); $replace=compact('title','reduced','table','slot','expand','weigh','search','summary','controller','toolbar','toolbarStr','commonSearch','pagination','tabs','isTree','js'); $content=$this->getContent('view-index',$replace); }else if($key=='add'){ $slot=''; foreach ($this->fields as $value){ $slot.=getFormslot($value,$isTree,$treeTitle); } $slot=rtrim($slot); $js=$this->getJsContent('js-add'); $replace=compact('title','reduced','slot','form','js'); $content=$this->getContent('view-add',$replace); }else if($key=='edit'){ $temp=''; if($key=='edit'){ $temp=str_replace('\\','/',substr($this->controller,strpos($this->controller,'controller\\')+11)); $temp=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $temp)).'/add'; } $js=$this->getJsContent('js'); $replace=compact('title','reduced','form','temp','js'); $content=$this->getContent('view-edit',$replace); }else{ $js=$this->getJsContent('js'); $replace=compact('title','js'); $content=$this->getContent('view-method',$replace); } if($this->type=='file'){ $file=$this->buildFile('view')[$key]; create_file($file,$content); } $viewContent[$key]=$content; } return $viewContent; } private function getJsContent(string $jsfile) { $reduced=$this->reduced; $table=$this->actions['table']; $form=$this->actions['form']; $expand=$this->expand; $actions=array_keys($this->actionList); $pack=str_replace('\\','/',substr($this->controller,strpos($this->controller,'controller\\')+11)); $pack=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $pack)); $sort=''; $fields=''; $isTree=$this->isTree; $treeTitle=$this->treeTitle; foreach ($this->fields as $value){ $istable=($jsfile=='js-index'); $isform=($jsfile=='js-add'); $fields.=getFields($value,$istable,$isform,$isTree,$treeTitle); if($value['field']=='weigh' && $value['type']=='int'){ $sort=true; } } $fields=rtrim($fields); $isTree=$this->isTree; $replace=compact('pack','reduced','table','form','actions','expand','sort','isTree','fields'); $content=$this->getContent($jsfile,$replace); return $content; } private function createController() { $reduced=$this->reduced; $controllerName=substr($this->controller,strrpos($this->controller,'\\')+1); $namespace=substr($this->controller,0,strrpos($this->controller,'\\')); $model=$this->model; $modelName=substr($this->model,strrpos($this->model,'\\')+1); $recyclebinField=rtrim(getRecyclebinField($this->recyclebinField)); $recyclebinType=rtrim(getRecyclebinType($this->recyclebinField)); $table=$this->actions['table']; $form=$this->actions['form']; $group=str_replace('\\','/',substr($this->controller,strpos($this->controller,'controller\\')+11)); $group=strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $group)); $methods=''; foreach ($this->actionList as $key=>$value){ if($table && in_array($key,['index','del','multi','import','download','recyclebin'])){ continue; } if($form && in_array($key,['add','edit'])){ continue; } $methods.=getAction($key,$value); } $methods=rtrim($methods); $relation=$this->getRelation(); $actionList=$this->actionList; $isTree=$this->isTree; $summary=$this->summary; $treeTitle=$this->treeTitle; $replace=compact( 'namespace','controllerName','model','modelName', 'group','table','summary','form', 'relation', 'methods','actionList','isTree','treeTitle', 'recyclebinField','recyclebinType' ); if($reduced){ $content=$this->getContent('controller-reduced',$replace); }else{ $content=$this->getContent('controller-normal',$replace); } if($this->type=='file'){ $file=$this->buildFile('controller'); create_file($file,$content); } return $content; } private function getRelation() { if(!$this->actions['table']){ return ''; } $relation=[]; foreach ($this->relations as $value){ $relation[]=str_replace(self::$prefix,'',$value['table']); } $relation=count($relation)>0?json_encode($relation):''; return $relation; } private function createModel() { //用户自定义模型名 $modelName=substr($this->model,strrpos($this->model,'\\')+1); $namespace=substr($this->model,0,strrpos($this->model,'\\')); //根据表名生成模型名 $table=str_replace(self::$prefix,'',$this->table); $tableModelName=str_replace(' ','',ucwords(str_replace('_',' ',$table))); $name=''; if($tableModelName!=$modelName) { $name = $table; } $createtime=false; $updatetime=false; $deletetime=false; $weigh=false; foreach ($this->fields as $value){ if($value['field']=='createtime'){ $createtime=true; } if($value['field']=='updatetime'){ $updatetime=true; } if($value['field']=='deletetime'){ $deletetime=true; } if($value['field']=='weigh'){ $weigh=true; } } $methods=''; foreach($this->relations as $field=>$value){ $methods.=getRelationMethods($field,$value); } $methods=rtrim($methods); if($createtime && $updatetime && $deletetime) { $content=$this->getContent('model-extend-base',compact('namespace','modelName','name','weigh','methods')); }else{ $content=$this->getContent('model-normal',compact('namespace','modelName','name','createtime','updatetime','deletetime','weigh','methods')); } if($this->type=='file'){ $file=$this->buildFile('model'); create_file($file,$content); } return $content; } private function getContent(string $file,array $replace=[]):string { $filepath=__DIR__.DS.$file.'.txt'; $myfile = fopen($filepath, "r"); $content=''; $if=[]; $lastline=''; while(!feof($myfile)) { $line_str = fgets($myfile); if($line_str){ $ix=false; if($lastline==='' && trim($line_str)===''){ $ix=true; } //条件判断 if(strpos($line_str,'<#if')!==false){ $continue=false; $if_str=substr($line_str,strpos($line_str,'<#if')+4); $if_str=substr($if_str,0,strpos($if_str,'#>')); $keys=array_keys($replace); $values=array_map(function ($res){ return '$replace[\''.$res.'\']'; },$keys); $if_str=str_replace(array_keys($replace),$values,$if_str); $phpstr="if(!({$if_str})){\$continue=true;}"; eval($phpstr); $if[]=$continue; $ix=true; } if(strpos($line_str,'<#endif#>')!==false){ array_pop($if); $ix=true; } foreach ($if as $value) { if ($value) { $ix = true; break; } } if($ix){ continue; } //替换内容 foreach ($replace as $key=>$value){ if(is_string($value)){ $line_str=str_replace('<#'.$key.'#>',$value,$line_str); } } $content.=$line_str; $lastline=trim($line_str); } } fclose($myfile); return $content; } }