<?php
class Menu extends kcate {
  public $AUTH;
  public $authDest = array();

  function __construct( $cate_table="" ){
    parent::__construct($cate_table);
    $this->DB->tableExists(TB_menu_auth_page);

    $this->set_cate_area();
    $this->AUTH = new Auth();
  }

  public function getMenuList($usage="Y"){
    $where = new DB_where("and");
    $where->add("cate.cate_area = ?", $this->cate_area);
    if( $usage ){
      $where->add("cate_use = ?", "Y");
    }

    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    $sql = "select * from {$this->cate_table} where cate_area = '{$this->cate_area}' and cate_use != 'Y'";
    $notuse_row = $this->DB->query($sql);
    $use_fld = array();
    foreach( (array)$notuse_row as $nrow ){
      $use_fld[] = " cate.cate_code like '{$nrow['cate_code']}%' ";
    }
    if( count($use_fld) ){
      $add_fld = implode(" or ", $use_fld);
    }else{
      $add_fld = " 1!=1 ";
    }

    $sql = "select
              cate.cate_area,
              cate.cate_id,
              cate.cate_code,
              cate.cate_name,
              case when ({$add_fld}) then 'N' else 'Y' end as cate_use
            from {$this->cate_table} as cate
            left join (select * from {$this->cate_table} where cate_area = '{$this->cate_area}') pa_cate
            on substring(cate.cate_code, 1, len(cate.cate_code)-{$this->dmax}) = pa_cate.cate_code
            where {$whereqry} order by cate.cate_code asc";

    $rst = $this->DB->qry($sql, $whererow);
    if( $rst ){
      $rows = array();
      while( $row = $this->DB->fetch_array($rst) ){
        $row['level'] = $this->level_cate($row['cate_code']);
        $rows[] = Array(
          "id" => $row['cate_id'],
          "text" => $row['cate_name'],
          "parent" => $row['parent'],
          "icon" => "",
          "data" => $row,
        );
      }
      return $rows;
    }else{
      return 0;
    }
  }

  public function getMenuAuthList($usage="Y"){
    $where = new DB_where("and");
    $where->add("cate.cate_area = ?", $this->cate_area);
    if( $usage ){
      $where->add("cate_use = ?", "Y");
    }
    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    /*
    $sql = "select
              cate.cate_id as id,
              cate.cate_code as data,
              ifnull(pa_cate.cate_id, '#') as parent,
              cate.cate_name as text,
              case cate.cate_auth when 'Y' then '' else '' end as icon
            from {$this->cate_table} as cate
            left join pa_cate
            on substring(cate.cate_code, 1, LENGTH(cate_code)-{$this->dmax}) = pa_cate.cate_code where {$whereqry} order by cate.cate_code asc";*/

    /* 쿼리 2번 실행 */
    $sql = "select cate_area, cate_id, auth_area, auth_target, auth from ".TB_auth_manage." where cate_area = '{$this->cate_area}'";
    $rows = $this->DB->query($sql);

    $auths = array();
    foreach( (array)$rows as $auth ){
      if( !isset($auths[$auth['cate_id']]) ) $auths[$auth['cate_id']] = array();
      if( !isset($auths[$auth['cate_id']][$auth['auth_area']]) ) $auths[$auth['cate_id']][$auth['auth_area']] = array();

      $auths[$auth['cate_id']][$auth['auth_area']][$auth['auth_target']] = $auth['auth'];
    }

    $sql = "select
              cate.cate_area,
              cate.cate_id,
              cate.cate_code,
              cate.cate_name,
              cate.cate_data,
              cate.cate_exp,
              cate.cate_class,
              cate.cate_auth,
              cate.cate_use,
              isnull(pa_cate.cate_id, '#') as parent,
              pages.cate_filepath
            from {$this->cate_table} as cate
            left join (select cate_area, cate_id, stuff(( select char(13)+ tagg.filepath from ".TB_menu_auth_page." as tagg where tagg.cate_area = tmap.cate_area for xml path(''), type).value('.','varchar(max)'),1,1,'') as cate_filepath from ".TB_menu_auth_page." as tmap group by cate_area, cate_id) as pages
              on cate.cate_area = pages.cate_area and cate.cate_id = pages.cate_id
            left join (select cate_id, cate_code from {$this->cate_table} where cate_area = '{$this->cate_area}') pa_cate
              on substring(cate.cate_code, 1, len(cate.cate_code)-{$this->dmax}) = pa_cate.cate_code
            where {$whereqry} order by cate.cate_code asc";

    //string_agg 대체
    //stuff(( select char(13)+ tagg.filepath from ".TB_menu_auth_page." as tagg where tagg.cate_area = tmap.cate_area for xml path(''), type).value('.','varchar(max)'),1,1,'') as cate_filepath
    //cate_filepath=stuff(( select char(13)+ tagg.filepath from ".TB_menu_auth_page." as tagg where tagg.cate_area = tmap.cate_area for xml path(''), type).value('.','varchar(max)'),1,1,'')
    //
    //string_agg(filepath,CHAR(13)) as cate_filepath

    /* 서브쿼리 이용
    $sql = "select
              cate.cate_area,
              cate.cate_id,
              cate.cate_code,
              cate.cate_name,
              cate.cate_data,
              cate.cate_exp,
              cate.cate_class,
              cate.cate_auth,
              isnull(pa_cate.cate_id, '#') as parent
            from {$this->cate_table} as cate
            left join (select * from {$this->cate_table} where cate_area = '{$this->cate_area}') as pa_cate
            on substring(cate.cate_code, 1, len(cate.cate_code)-{$this->dmax}) = pa_cate.cate_code
            left join (select cate_area, cate_id, auth_area, string_agg(concat(auth_target,':',auth),',') as auths from ".TB_auth_manage." group by cate_area, cate_id, auth_area ) as auth
            on cate.cate_area = auth.cate_area and cate.cate_id = auth.cate_id
            where cate.cate_area = '{$this->cate_area}' group by cate.cate_area, cate.cate_id, auth_area order by cate.cate_code asc";*/


    $rst = $this->DB->qry($sql, $whererow);
    if( $rst ){
      $rows = array();
      while( $row = $this->DB->fetch_array($rst) ){
//        foreach( $GLOBALS['_varsAuthArea'] as $auth_area => $name ){
//          $row['cate_auth_read'][$auth_area] = $authObj->getHasAuthRow($auths[$row['cate_id']][$auth_area], "READ");
//          $row['cate_auth_write'][$auth_area] = $authObj->getHasAuthRow($auths[$row['cate_id']][$auth_area], "WRITE");
//          $row['cate_auth_delete'][$auth_area] = $authObj->getHasAuthRow($auths[$row['cate_id']][$auth_area], "DELETE");
//        }

        $row['auth'] = $auths[$row['cate_id']];
        $rows[] = Array(
          "id" => $row['cate_id'],
          "text" => $row['cate_name'],
          "parent" => $row['parent'],
          "icon" => "",
          "data" => $row,
        );
      }
      return $rows;
    }else{
      return 0;
    }
  }

  public function getTreeList($cate_code="", $direct=false){
    $temp_ren = strlen($cate_code) + $this->dmax;

    $where = $this->getAreaQry();
    $where = $this->getShowQry($where);
    $where->add("cate_code like ?", "{$cate_code}%");
    $where->add("cate_code != ?", $cate_code);
    $where->add("len(cate_code) = ?", $temp_ren);
    $where->add("cate.cate_use = ?", "Y");
    $subwhere = $where->sub_where("or");
    $subwhere->add("auth.auth_read = ?", 1);

    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    $tb_auth = "select 
        cate_id,
        cast(sum(auth & 4) as bit) as auth_delete,
        cast(sum(auth & 2) as bit) as auth_write,
        cast(sum(auth & 1) as bit) as auth_read
      from ".TB_auth_manage."
      where (auth_area = 'G' and auth_target = '".$GLOBALS['_Umem']['member_auth']."') or (auth_area = 'M' and auth_target = '".$GLOBALS['_Umem']['member_id']."')
      group by cate_id";

    $sql = "select cate.cate_id, cate_code, cate_name, cate_data, cate_exp, cate_class from {$this->cate_table} as cate
            left join ({$tb_auth}) as auth on cate.cate_id = auth.cate_id
            where {$whereqry} order by cate_code";
    $rst = $this->DB->qry($sql, $whererow);
    $i = 0;
    $rows = Array();
    while( $row = $this->DB->fetch_array($rst) ){
      if( !$direct ){
        $row['child'] = $this->getTreeList($row['cate_code']);
      }
      $rows[] = $row;
    }
    return $rows;
  }

  public function getTreeListForTreeView($cate_code="", $now_code=""){
    $temp_ren = strlen($cate_code) + $this->dmax;

    $where = $this->getAreaQry();
    $where = $this->getShowQry($where);
    $where->add("cate.cate_code like ?", "{$cate_code}%");
    $where->add("cate.cate_code != ?", $cate_code);
    $where->add("len(cate.cate_code) = ?", $temp_ren);
    $where->add("cate.cate_use = ?", "Y");
    $subwhere = $where->sub_where("or");
    $subwhere->add("auth.auth_read = ?", 1);
    $subwhere->add("'SA' = ?", $GLOBALS['_Umem']['member_auth']);

    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    $tb_auth = "select 
        cate_id,
        cast(sum(auth & 4) as bit) as auth_delete,
        cast(sum(auth & 2) as bit) as auth_write,
        cast(sum(auth & 1) as bit) as auth_read
      from ".TB_auth_manage."
      where (auth_area = 'G' and auth_target = '".$GLOBALS['_Umem']['member_auth']."') or (auth_area = 'M' and auth_target = '".$GLOBALS['_Umem']['member_id']."')
      group by cate_id";

    $sql = "select
              cate.cate_id,
              cate.cate_code,
              cate.cate_name,
              cate.cate_data,
              cate.cate_exp,
              cate.cate_class
            from {$this->cate_table} as cate
            left join ({$tb_auth}) as auth
            on cate.cate_id = auth.cate_id
            where {$whereqry} order by cate.cate_code";
    $rst = $this->DB->qry($sql, $whererow);
    $i = 0;
    $rows = Array();
    while( $row = $this->DB->fetch_array($rst) ){
      $children = $this->getTreeListForTreeView($row['cate_code'], $now_code);
      $temp = array(
        "id"   => $row['cate_id'],
        "key"  => $row['cate_id'],//
        "text" => $row['cate_name'],
        "title" => $row['cate_name'],//
        "href" => $row['cate_data'],
        "icon" => $row['cate_class'],
        "selectable" => 0,
        "state" => array("expanded"=>false),
        "tags" => [''],
        "nodes" => $children?:"",
        "children" => $children?:"",//
        "folder" => $children?true:false,//
      );
      if( preg_match( "/^{$row['cate_code']}/", $now_code ) ){
        $temp['state']['expanded'] = true;
        $temp['expanded'] = true;//
      }
      if( $row['cate_code'] == $now_code ){
        $temp['state']['selected'] = true;
        $temp['active'] = true;//
      }
      $rows[] = $temp;
    }
    return $rows;
  }

  public function putMenu($sqldata, $auth_area){
    /* 권한 추가 */
    foreach( (array)$this->authDest as $grpcode => $grpname ){
      $readAuth = in_array($grpcode, (array)$sqldata['cate_auth_read']);
      $writeAuth = in_array($grpcode, (array)$sqldata['cate_auth_write']);
      $deleteAuth = in_array($grpcode, (array)$sqldata['cate_auth_delete']);

      $this->AUTH->putAuth(
        $this->cate_area,
        $sqldata['cate_id'],
        $auth_area,
        $grpcode,
        $this->AUTH->getAuthToNum($readAuth, $writeAuth, $deleteAuth)
      );
    }

    /* 메뉴 등록 */
    $sql_row = Array(
      "cate_area"  => $this->cate_area,
      "cate_id"    => $sqldata['cate_id']?:"",
      "cate_name"  => $sqldata['cate_name']?:"",
      "cate_data"  => $sqldata['cate_data']?:"",
      "cate_exp"   => $sqldata['cate_exp']?:"",
      "cate_class" => $sqldata['cate_class']?:"",
      "cate_auth"  => $sqldata['cate_auth']?:"",
      "cate_use"   => $sqldata['cate_use']?:"",
    );

    $pa_row = $this->cate_info_id($sqldata['parent_id']);
    $cate_code = $this->new_cate($pa_row['cate_code']);
    $sql_row['cate_code'] = $cate_code;

    $rst = $this->DB->insert($this->cate_table, $sql_row);
    if( $rst ){
      $auth_filepath = explode("\n",preg_replace("\r\n","\n",$sqldata['cate_filepath']));
      foreach( (array)$auth_filepath as $path ){
        if( trim($path) ){
          $sql_row = Array(
            "cate_area"  => $this->cate_area,
            "cate_id"    => $sqldata['cate_id']?:"",
            "filepath"   => $path,
          );
          $this->DB->insert(TB_menu_auth_page, $sql_row);
        }
      }
    }
    return $rst;
  }

  public function setMenu($sqldata, $auth_area){
    /* 권한 수정 */
    foreach( (array)$this->authDest as $grpcode => $grpname ){
      $readAuth = in_array($grpcode, (array)$sqldata['cate_auth_read']);
      $writeAuth = in_array($grpcode, (array)$sqldata['cate_auth_write']);
      $deleteAuth = in_array($grpcode, (array)$sqldata['cate_auth_delete']);

      $this->AUTH->setAuth(
        $this->cate_area,
        $sqldata['cate_id'],
        $auth_area,
        $grpcode,
        $this->AUTH->getAuthToNum($readAuth, $writeAuth, $deleteAuth),
        $sqldata['parent_id']
      );
    }


    /* 메뉴 수정 */
    $sql_row = Array(
      "cate_area"  => $this->cate_area,
      "cate_id"    => $sqldata['cate_id']?:"",
      "cate_name"  => $sqldata['cate_name']?:"",
      "cate_data"  => $sqldata['cate_data']?:"",
      "cate_exp"   => $sqldata['cate_exp']?:"",
      "cate_class" => $sqldata['cate_class']?:"",
      "cate_auth"  => $sqldata['cate_auth']?:"",
      "cate_use"   => $sqldata['cate_use']?:"",
    );

    $where = $this->getAreaQry();
    $where->add("cate_id = ?",$sqldata['parent_id']);

    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    $rst = $this->DB->update($this->cate_table, $sql_row, $whereqry, $whererow);
    if( $rst ){
      $where = new DB_where("and");
      $where->add("cate_area = ?", $this->cate_area);
      $where->add("cate_id = ?", $sqldata['cate_id']?:"");

      $wqry = $where->get_where();
      $whereqry = $wqry['qry'];
      $whererow = $wqry['val'];
      $this->DB->delete(TB_menu_auth_page, $whereqry, $whererow);

      $auth_filepath = explode("\n",preg_replace("/\r\n/ims","\n",$sqldata['cate_filepath']));
      foreach( (array)$auth_filepath as $path ){
        if( trim($path) ){
          $sql_row = Array(
            "cate_area"  => $this->cate_area,
            "cate_id"    => $sqldata['cate_id']?:"",
            "filepath"   => $path,
          );
          $this->DB->insert(TB_menu_auth_page, $sql_row);
        }
      }
    }
    return $rst;
  }

  public function delMenu($cate_id, $auth_area="", $auth_target=""){
    $caterow = $this->cate_info_id($cate_id);
    $rst = $this->drop_cate($caterow['cate_code']);
    if( $rst ){
      $rst = $rst && $this->AUTH->delAuth($this->cate_area, $cate_id, $auth_area, $auth_target);
    }
    return $rst;
  }

  public function getMenuIdFromUrl($url){
    $where = new DB_where("and");
    $where->add("cate_area = ?", $this->cate_area);
    //$where->add("filepath like ?", "%{$url}%");
    $where->add("CHARINDEX(filepath, ?) <> 0", $url);

    $wqry = $where->get_where();
    $whereqry = $wqry['qry'];
    $whererow = $wqry['val'];

    $sql = "select cate_id from ".TB_menu_auth_page." where {$whereqry}";
    return $this->DB->queryFirstField($sql,$whererow);
  }

  public function hasMenuAuth($auth, $cate_id=""){
    if( !$cate_id ){
      if( $GLOBALS['_Auth_']['cate_id'] ){
        $cate_id = $GLOBALS['_Auth_']['cate_id'];
      }else{
        $cate_id = $this->getMenuIdFromUrl($_SERVER['SCRIPT_URI']);
      }
    }
    return $this->AUTH->hasAuth($auth, $this->cate_area, $cate_id);
  }

  public function getMenuBrdcom($cate_id){
    $menu_info = $this->cate_info_id($cate_id);
    return $this->history_cate($menu_info['cate_code']);
  }

  public function set_cate_area($cate_area=""){
    $this->cate_area = $cate_area?:"service";
    $this->authDest = $this->gsetAuthTarget("all");
  }

  public function gsetAuthTarget( $type="", $include_sa="" ){
    switch( $this->cate_area ){
      case "admin":
        $authTarget = $GLOBALS['_varsAuthAdmin'];
       break;

      case "service":
        if( $type == "all" ){
          $authTarget = array_merge($GLOBALS['_varsAuthAdmin'], $GLOBALS['_varsAuthMember']);
        }else{
          $authTarget = $GLOBALS['_varsAuthMember'];
        }
      break;
    }
    if( !$include_sa ){
      unset($authTarget['SA']); //슈퍼관리자 제외
    }
    return $authTarget;
  }
}