<?php

/* ========================================================================
 * $Id: build.vue.php 10594 2020-06-26 23:21:11Z onez $
 * 
 * Email: www@onez.cn
 * QQ: 6200103
 * HomePage: http://www.onez.cn
 * ========================================================================
 * Copyright 2016-2017 佳蓝科技.
 * 
 * ======================================================================== */

!defined('IN_ONEZ') && exit('Access Denied');
class _vue_parse extends onezphp{
  var $path='';
  var $token='';
  var $name='';
  var $vars=array();
  var $files=array();
  var $iconfonts=array();
  function __construct($path,$name=''){
    $this->path=$path;
    $this->token=basename($path);
    $this->file=$path.'/'.$this->token.'.php';
    !$name && $name=$this->token;
    $this->name=$name;
  }
  function files(){
    global $G;
    !$G['_vue_parse_files'] && $G['_vue_parse_files']=array();
    #防止重复
    if(in_array($this->file,$G['_vue_parse_files'])){
      return array();
    }
    $G['_vue_parse_files'][]=$this->file;
    $name=$this->name;
    #php
    $file=$this->file;
    if(file_exists($file)){
      include($file);
      $this->files[$file]=onez()->read($file);
    }else{
      $this->files[$file]=<<<ONEZ
<?php
!defined('IN_ONEZ') && exit('Access Denied');
# $name
#请求数据
if(\$MODE=='\$post'){
  \$action=onez()->gp('action');
  if(\$action=='data'){
    \$items=array();
    \$A['items']=\$items;
  }
  return;
}
/*
\$this->add(array(
  'type'=>'products',
  'name'=>'全局组件',
));
\$this->add(array(
  'type'=>'./products',
  'name'=>'页面内组件',
));
*/

ONEZ;
    }
    $data=$this->getVars();
    #js
    $file=substr($this->file,0,-4).'.js';
    if(file_exists($file)){
      $this->files[$file]=onez()->read($file);
    }else{
      $this->files[$file]="//$name js
export default{
  data(){
    return $data;
  },
  mounted(){
    //onez.data(this,['items']);
  }
}
";
    }
    #data
    /*
    $file=substr($this->file,0,-4).'.data';
    #$data=str_replace("",'',$data);
    $this->files[$file]="data(){
  return {
    data:$data
  };
}";
    */
    #less
    $file=substr($this->file,0,-4).'.less';
    if(file_exists($file)){
      $this->files[$file]=onez()->read($file);
    }else{
      $this->files[$file]="/*$name less*/\n";
    }
    return $this->files;
  }
  function replaces($code){
    global $G;
    if(!$this->_url){
      $url=dirname($this->file);
      if(strpos($url,ONEZ_CACHE_PATH)!==false){
        $url=str_replace(ONEZ_CACHE_PATH,ONEZ_CACHE_URL,$url);
      }else{
        $url=str_replace(ONEZ_ROOT,onez()->homepage(),$url);
      }
      $this->_url=$url;
    }
    $code=str_replace('${myurl}',$this->_url,$code);
    $code=str_replace('${siteurl}',$G['this']->url,$code);
    return $code;
  }
  function vue($token=false,&$js=false,&$css=false){
    global $G;
    if(!file_exists($this->file)){
      return;
    }
    $this->mode='vue';
    if($token){
      ob_clean();
      $token=preg_replace('/[^0-9a-zA-Z\-\_]/i','-',$token);
      $token=str_replace(array('pages-','components-'),'',$token);
      $classname=$token;
      $tagname='div';
      include($this->file);
      $template='<'.$tagname.' class="'.$classname.'"'.$tagAttrs.'>';
      $code=ob_get_contents();
      $code=$this->replaces($code);
      if(strpos($code,"onez('bs').emit(")!==false){
        onez('vue')->components_info['onez.plugins']['bs.live']++;
      }
      $code=preg_replace_callback('/\s(\:|)href="([^"]+)"([^\>]*)\>/is',function($mat){
        if(strpos($mat[3],' islink ')!==false){
          return $mat[0];
        }
        if($mat[1]==':'){
          return " @click.prevent=\"link\" :href=\"\'#\'+$mat[2]\"$mat[3]>";
        }elseif($mat[2]=='#'){
          return $mat[0];
        }elseif(strpos($mat[2],'javascript:')!==false){
          return $mat[0];
        }elseif(strpos($mat[2],'#')===0){
          return " @click.prevent=\"link\" href=\"$mat[2]\" $mat[3]>";
        }
        return $mat[0];
      },$code);
      $phpVars=array();
      $code=preg_replace_callback('/\$([a-zA-Z0-9_]+)/i',function($mat)use(&$phpVars){
        if(!in_array($mat[1],$phpVars)){
          $phpVars[]=$mat[1];
        }
        return $mat[1];
      },$code);
      
      $template.=$code;
      $template.='</'.$tagname.'>';
      ob_clean();
      $file=substr($this->file,0,-4).'.js';
      if(!file_exists($file)){//没有主文件
        return;
      }
      $_js=trim(onez()->read($file));
      if(strpos($_js,'onez.$on(')!==false||strpos($_js,'onez.$off(')!==false||strpos($_js,'onez.$emit(')!==false){
        onez('vue')->components_info['onez.plugins']['bs.live']++;
      }
      list(,$_js)=explode('export default',$_js);
      $cId='c'.uniqid();
      $mounted='';
      if(strpos($token,'page-')!==false){
        $mounted.="this.\$root.path=this.path;\n";
      }
      if($phpVars){
        foreach($phpVars as $k=>$v){
          if(strpos($v,"onez.data(this,['$v']);")!==false||strpos($v,"onez.data(this,['@$v']);")!==false){
            unset($phpVars[$k]);
          }
        }
      }
      $data='';
      if($phpVars){
        $mounted.="          onez.data(this,".json_encode(array_values($phpVars)).");\n";
        foreach($phpVars as $v){
          $data.="            $v:null,\n";
        }
      }
      $path=substr($this->file,strlen(ONEZ_ROOT));
      if(strpos($this->file,ONEZ_CACHE_PATH)!==false){
        $path='@'.substr($this->file,strlen(ONEZ_CACHE_PATH));
      }
      $_js=substr($_js,0,-1).',extends:{
        data(){
          return {
'.$data.'
            cId:"'.$cId.'",
            path:"'.$path.'"
          }
        },
        methods:ONEZ_VUE_METHODS,
        mounted(){
          if(this.file){
            if(this.file==\'self\'){
              this.path=this.$parent.path;
            }else{
              this.path=this.file;
            }
          }
          this.update();
          this.$root.$on("update",this.update);
'.$mounted.'
        },
        destroyed(){
          this.$root.$off("update",this.update);
        },
        props:["data","file","urlAdd"],
        template:`'.$template.'`
      }}';
      $js[]="Vue.component('onez-$token',$_js);";
      $file=substr($this->file,0,-4).'.less';
      if(file_exists($file)){
        $myCSS=onez()->read($file);
        $myCSS=$this->replaces($myCSS);
        if($classname){
          $css[]=onez('less')->tocss(".{$classname}".'{'.$myCSS.'}');
        }else{
          $css[]=onez('less')->tocss($myCSS);
        }
      }
      $file=substr($this->file,0,-4).'.mobile.less';
      if(file_exists($file)){
        $myCSS=onez()->read($file);
        if($classname){
          $myCSS=".{$classname}".'{'.$myCSS.'}';
        }
        $myCSS="@media screen and (max-width: 750px) {\n$myCSS\n}";
        $myCSS=$this->replaces($myCSS);
        $css[]=onez('less')->tocss($myCSS);
      }
      #云事件相关
      $tmpPath=dirname($this->file);
      $glob=glob($tmpPath.'/on.*.php');
      if($glob){
        foreach($glob as $v){
          onez('vue')->components_info['onez.events'][]=array(
            'page'=>substr($this->file,strlen(ONEZ_ROOT)),
            'file'=>$v,
            'event'=>substr(basename($v),3,-4),
          );
        }
      }
      #云字体
      if($this->iconfonts){
        foreach($this->iconfonts as $v){
          onez('vue')->cloudres['iconfonts'][]=$v;
        }
      }
      return;
    }
    $html=array();
    $html[]='<template>';
    $html[]='<div>';
    ob_clean();
    include($this->file);
    $html[]=ob_get_contents();
    ob_clean();
    $html[]='</div>';
    $html[]='</template>';
    $html[]='<script>';
    $file=substr($this->file,0,-4).'.js';
    $html[]=onez()->read($file);
    $html[]='</script>';
    $html[]='<style scoped>';
    $file=substr($this->file,0,-4).'.less';
    $html[]=onez('less')->tocss($file);
    $html[]='</style>';
    return implode("\n",$html);
  }
  function getVars(){
    $vars=array();
    foreach($this->vars as $k=>$v){
      $vars[]='      '.$k.':{}';
    }
    return "{\n".implode(",\n",$vars)."\n    }";
  }
  function add($opt,$output=true){
    global $G;
    if(is_string($opt)){
      return $this->add(array(
        'type'=>$opt,
      ),false);
    }
    if($this->mode=='vue'){
      if(strpos($opt['type'],'./')===0){
        $token=substr($opt['type'],2);
        $tag=$this->token.'-'.$token;
      }else{
        $token=$opt['type'];
        $tag=$token;
      }
      if($tag[0]==='@'){
        $dataKey=$opt['data']?$opt['data']:'data';
        $tag=substr($tag,1);
        !onez('vue')->cloudres['components'] && onez('vue')->cloudres['components']=array();
        if(empty(onez('vue')->cloudres['components'][$tag])){
          onez('vue')->cloudres['components'][$tag]=0;
        }
      }else{
        $dataKey=$opt['data']?$opt['data']:$token;
      }
      if(!$output){
        return;
      }
      $tag=preg_replace('/[^0-9a-zA-Z\-\_]/i','-',$tag);
      $Add='';
      $slot='';
      foreach($opt as $k=>$v){
        if(in_array($k,array('type','data','name'))){
          continue;
        }
        if($k=='slot'){
          $slot=$v;
          continue;
        }
        $Add.=' '.$k.'="'.$v.'"';
      }
      #echo"<onez-{$tag} :data=\"onez.get(\$data,'{$dataKey}')\"/>\n";
      if($slot){
        echo"<onez-{$tag} :data=\"{$dataKey}\"$Add>$slot</onez-{$tag}>\n";
      }else{
        echo"<onez-{$tag} :data=\"{$dataKey}\"$Add/>\n";
      }
      return;
    }
    if(strpos($opt['type'],'./')===0){
      $token=substr($opt['type'],2);
      $path=$this->path.'/components/'.$token;
    }else{
      $token=$opt['type'];
      $path='@/components/'.$token;
    }
    $this->vars[$token]='{}';
    $r=new _vue_parse($path,$opt['name']);
    $this->files=array_merge($this->files,$r->files());
  }
  #字体图标
  function iconfont($svg,$name=''){
    onez('vue')->components_info['iconfont']++;
    if($name){
      $name=onez('pinyin')->pinyin($name);
    }else{
      
    }
    $name && $svg.='|'.$name;
    if(!in_array($svg,$this->iconfonts)){
      $this->iconfonts[]=$svg;
    }
    if($name){
      return 'onez-iconfont-'.$name;
    }else{
      return 'onez-iconfont-'.md5($svg);
    }
  }
}
class _vue_build extends onezphp{
  var $path='';
  var $type='';
  var $token='';
  function __construct($path,$type){
    $this->path=$path;
    $this->token=basename($path);
    $this->type=$type;
  }
  function vue($token=false,&$js=false,&$css=false){
    $p=$this->parse($this->path);
    return $p->vue($token,$js,$css);
  }
  function parse($file){
    return (new _vue_parse($file));
  }
  function files($offset=0){
    $path=$this->path;
    $files=array();
    $p=$this->parse($this->path);
    $files=$p->files();
    $path=substr($path,$offset);
    $_files=array();
    foreach($files as $k=>$v){
      $k=str_replace('@/',dirname(dirname($this->path)).'/',$k);
      $_files[substr($k,$offset)]=$v;
    }
    return $_files;
  }
  
}