<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

namespace think;

class Config
{
   // 配置参数
   private static $config = [];// 这里的 static 设置的 比较出神入化
   // 参数作用域
   private static $range = '_sys_';// 同上

   // 设定配置参数的作用域
   public static function range($range)
   {
       self::$range = $range;// 初始化, 范围
       if (!isset(self::$config[$range])) {// 如果不存在,就 初始化为空
           self::$config[$range] = [];// 默认设置 初始化 为空
       }
   }

   /**
    * 解析配置文件或内容
    * @param string    $config 配置文件路径或内容
    * @param string    $type 配置解析类型
    * @param string    $name 配置名(如设置即表示二级配置)
    * @param string    $range  作用域
    * @return mixed
    */
   public static function parse($config, $type = '', $name = '', $range = '')
   {// 解析 配置文件
       $range = $range ?: self::$range;// 默认 文件 配置 选项
       if (empty($type)) {// 如果为空
           $type = pathinfo($config, PATHINFO_EXTENSION);// 解析 配置 文件
       }
       $class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type);
       // 获取 解析 类文件 分别对应为 ini \ json \ xml 类文件 方式 解析 文件
       return self::set((new $class())->parse($config), $name, $range);// 解析配置文件
   }

   /**
    * 加载配置文件(PHP格式)
    * @param string    $file 配置文件名
    * @param string    $name 配置名(如设置即表示二级配置)
    * @param string    $range  作用域
    * @return mixed
    */
   public static function load($file, $name = '', $range = '')
   {// 加载 配置 文件
       $range = $range ?: self::$range;// 配置文件类型 初始化
       if (!isset(self::$config[$range])) {// 没有设置过,直接初始化
           self::$config[$range] = [];
       }
       if (is_file($file)) {// 如果是文件,
           $type = pathinfo($file, PATHINFO_EXTENSION);// 文件类型
           if ('php' != $type) {
               return self::parse($file, $type, $name, $range);// 解析 默认的 文件 ini xml json
           } else {
               return self::set(include $file, $name, $range);// 获取文件
           }
       } else {
           return self::$config[$range];// 直接返回数据
       }
   }

   /**
    * 检测配置是否存在
    * @param string    $name 配置参数名(支持二级配置 .号分割)
    * @param string    $range  作用域
    * @return bool
    */
   public static function has($name, $range = '')
   {
       $range = $range ?: self::$range;// 文件 类型

       if (!strpos($name, '.')) {
           return isset(self::$config[$range][strtolower($name)]);
       } else {
           // 二维数组设置和获取支持
           $name = explode('.', $name);
           return isset(self::$config[$range][strtolower($name[0])][$name[1]]);
       }
   }// 检测 是否 有这个 配置 选项

   /**
    * 获取配置参数 为空则获取所有配置
    * @param string    $name 配置参数名(支持二级配置 .号分割)
    * @param string    $range  作用域
    * @return mixed
    */
   public static function get($name = null, $range = '')
   {// 获取 配置 参数 为空 则获取所有的配置
       $range = $range ?: self::$range;// 配置 类型
       // 无参数时获取所有
       if (empty($name) && isset(self::$config[$range])) {
           return self::$config[$range];
       }// 如果为空,直接返回

       if (!strpos($name, '.')) {// 如果 没有 这个
           $name = strtolower($name);// 返回数据
           return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null;
       } else {
           // 二维数组设置和获取支持
           $name = explode('.', $name);
           $name[0] = strtolower($name[0]);
           return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null;
       }// 返回二维 数组
   }

   /**
    * 设置配置参数 name为数组则为批量设置
    * @param string|array  $name 配置参数名(支持二级配置 .号分割)
    * @param mixed         $value 配置值
    * @param string        $range  作用域
    * @return mixed
    */
   public static function set($name, $value = null, $range = '')
   {
       $range = $range ?: self::$range;// 进行 设置 范围圈定,默认的是 _sys_ 系统配置项目
       if (!isset(self::$config[$range])) {// 如果设置了 self::$config 没有设置这个,
           self::$config[$range] = [];// 默认的  初始化 为空
       }
       if (is_string($name)) {// 如果是字符串 默认就是key
           if (!strpos($name, '.')) {// 如果没有.
               self::$config[$range][strtolower($name)] = $value;// self::
           } else {
               // 二维数组设置和获取支持
               // 最大支持到二维数组
               $name                                                 = explode('.', $name);
               self::$config[$range][strtolower($name[0])][$name[1]] = $value;
           }
           return;
       } elseif (is_array($name)) {
           // 批量设置
           if (!empty($value)) {// 如果 value 有数值 此处的 value 变成了 key
               self::$config[$range][$value] = isset(self::$config[$range][$value]) ?
               array_merge(self::$config[$range][$value], $name) :
               self::$config[$range][$value] = $name;
               return self::$config[$range][$value];// 并且 返回 他,这个应该是个非常不科学的决定
           } else {
               return self::$config[$range] = array_merge(self::$config[$range], array_change_key_case($name));
               // 返回合并的数据 如果不调用,没有任何意义
           }
       } else {
           // 为空直接返回 已有配置
           return self::$config[$range];// 很喜欢 这个风格 跟调调,哈哈
       }
   }

   /**
    * 重置配置参数
    */
   public static function reset($range = '')
   {// 这个是 个重量级的 函数啊,
       $range = $range ?: self::$range;// 查看是否存在范围
       if (true === $range) {// 如果 传入了 真 清空一切
           self::$config = [];
       } else {
           self::$config[$range] = [];// 否则  清空 指定对象
       }
   }
}