合并配置
@param array $cfgs
328056
public function merge(array $cfgs) 
    {
        if ($this->env != 'product') {
            $this->checkKey($cfgs);
        }
        
        $this->configs = array_replace_recursive($this->configs, $cfgs);
        
        return $this;
    }
611012
protected function mergeConfigs(array $configs) {
		$result = new stdClass();
		
		$result->parameters   = new stdClass();
		$result->services     = new stdClass();
		$result->initializers = new stdClass();
		
		foreach ($configs as $config) {
			$this->mergeConfigsPart($config->getParameters(), $result->parameters);
			$this->mergeConfigsPart($config->getServices(), $result->services);
			$this->mergeConfigsPart($config->getInitializers(), $result->initializers);
		}
		
		return $result;
	}
414392
private function _connect_ssh(array $cfg): bool
  {
    if ( isset($cfg['host']) ){
      $param = [];
      if ( isset($cfg['public'], $cfg['private']) ){
        $param['hostkey'] = 'ssh-rsa';
      }
      $this->cn = @ssh2_connect($cfg['host'], $cfg['port'] ?? 22, $param, [
        'debug' => function($message, $language, $always_display){
          bbn\x::log([$message, $language, $always_display]);
        },
        'disconnect' => function($reason, $message, $language){
          bbn\x::log([$reason, $message, $language]);
        }
      ]);
      if ( !$this->cn ){
        $this->error = _("Could not connect through SSH.");
      }
      else if ( isset($cfg['user'], $cfg['public'], $cfg['private']) ){
        /*
        $fingerprint = ssh2_fingerprint($this->cn, SSH2_FINGERPRINT_MD5 | SSH2_FINGERPRINT_HEX);
        if ( strcmp($this->ssh_server_fp, $fingerprint) !== 0 ){
          $this->error = _('Unable to verify server identity!');
        }
        */
        if ( !ssh2_auth_pubkey_file($this->cn, $cfg['user'], $cfg['public'], $cfg['private'], $cfg['pass'] ?? null) ){
          $this->error = _('Authentication rejected by server');
        }
        else if ( $this->stream = @ssh2_sftp($this->cn) ){
          $this->current = ssh2_sftp_realpath($this->stream, '.');
          return true;
        }
        else{
          $this->error = _("Could not connect through SFTP.");
        }
      }
      else if ( isset($cfg['user'], $cfg['pass']) && @ssh2_auth_password($this->cn, $cfg['user'], $cfg['pass']) ){
        //die(_("Could not authenticate with username and password."));
        $this->stream = @ssh2_sftp($this->cn);
        if ( $this->stream ){
          $this->current = ssh2_sftp_realpath($this->stream, '.');
          return true;
        }
        $this->error = _("Could not initialize SFTP subsystem.");
      }
      else{
        $this->error = _("Could not authenticate with username and password.");
      }
    }
    return false;
  }
784721
public function execute($configs) {

        $this->setConfigs($configs);

        //请求初始化
        $this->requestInit();

        //检查当前模块下是否有监听器，如果有则加载监听器
        $lisennerClassName = APP_NAME."\\".$this->httpRequest->getModule()."\\ModuleListener";
        try {
            $reflect = new \ReflectionClass($lisennerClassName);
            $this->listeners[] = $reflect->newInstance();
        } catch (\Exception $exception) {
            //__print($exception);die();
        }
        //如果是单元测试，则直接返回
		if(defined("PHP_UNIT") && PHP_UNIT == true) return;

        //invoker 方法调用
        try {
            $this->actionInvoke();
        } catch(HeroException $e) {
            //记录日志
            Log::error($e->toString());
            if ( APP_DEBUG ) { //如果是调试模式就抛出异常
                throw $e;
            } else {
                die("Hacker Attempt!");
            }
        }

        //发送响应
        $this->sendResponse();

    }
697170
public function get_limit(array $cfg): string
  {
    $res = '';
    if ( !empty($cfg['limit']) && bbn\str::is_integer($cfg['limit']) ){
      $res .= 'LIMIT '.(!empty($cfg['start']) && bbn\str::is_integer($cfg['start']) ? (string)$cfg['start'] : '0').', '.$cfg['limit'];
    }
    return $res;
  }
1156300
public function registerPrefixes(array $classes)
    {
        foreach ($classes as $prefix => $locations) {
            $this->prefixes[$prefix] = (array) $locations;
        }
    }
977421
public function registerAll(array $loggers)
    {
        foreach($loggers as $key => $logger){
            $this->loggers[$key] = $logger;
            $logger->writeHeader();
        }
    }
251753
public function merge(array $newConfig, array &$config)
    {
        foreach ($newConfig as $routeName => $routeInfo) {
            if (!isset($config[$routeName])) {
                $config[$routeName] = $this->newRoute($routeName, $routeInfo);
            }

            if (isset($routeInfo['child_routes'])) {
                if (!isset($config[$routeName]['child_routes'])) {
                    $config[$routeName]['child_routes'] = array();
                }

                $this->merge($routeInfo['child_routes'], $config[$routeName]['child_routes']);
            }
        }
    }
685198
public static function init(bbn\db $db, array $cfg = []): void
  {
    /** @var string $hash Unique hash for this DB connection (so we don't init twice a same connection) */
    $hash = $db->get_hash();
    if ( !\in_array($hash, self::$dbs, true) && $db->check() ){
      // Adding the connection to the list of connections
      self::$dbs[] = $hash;
      /** @var bbn\db db */
      self::$db = $db;
      $vars = get_class_vars(__CLASS__);
      foreach ( $cfg as $cf_name => $cf_value ){
        if ( array_key_exists($cf_name, $vars) ){
          self::$$cf_name = $cf_value;
        }
      }
      if ( !self::$admin_db ){
        self::$admin_db = self::$db->current;
      }
      self::$table = self::$admin_db.'.'.self::$prefix.'history';
      self::$table_uids = self::$admin_db.'.'.self::$prefix.'history_uids';
      self::$ok = true;
      self::$is_used = true;
      self::$links = self::$db->get_foreign_keys('bbn_uid', self::$prefix.'history_uids', self::$admin_db);
      self::$db->set_trigger('\\bbn\\appui\\history::trigger');
    }
  }
1028202
function (cfg) {
    this._cfg = merge({
      delay: 400
    }, cfg)

    // 事件订阅数组
    this._subs = {
      on: [],
      after: []
    }

    // 当前信息
    this.info = this.getInfo()

    // 绑定事件回调上下文
    this._onWinOrientationChange = bind(this._onWinOrientationChange, this)

    // 绑定窗口切换事件
    window.addEventListener(EVT_ORIENTATION_CHANGE, this._onWinOrientationChange, false)
  }
339422
public function reply($msg)
    {
        // 获取消息类型
        $msg_type = '';
        if (gettype($msg)=='string') {
            $msg_type = 'text_simple';
        } elseif (gettype($msg)=='array') {
            $msg_type = $msg['type'];
        }

        switch ($msg_type) {
            /**
             * 1.1 回复文本消息(简洁输入)
             *
             * Examples:
             * ```
             * $wechat->reply('hello world!');
             * ```
             */
            case 'text_simple':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[text]]></MsgType>'.
                        '<Content><![CDATA[%s]]></Content>'.
                        '</xml>',
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(), 
                        $msg);
                break;

            /**
             * 1.2 回复文本消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
             *    'type' => 'text',
             *    'content' => '嘿嘿，呵呵~~'
             * ));
             * ```
             */
            case 'text':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[text]]></MsgType>'.
                        '<Content><![CDATA[%s]]></Content>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(), 
                        $msg['content']);
                break;

            /**
             * 2 回复图片消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
              *     'type' => 'image',
              *    'media_id' => 'Uq7OczuEGEyUu--dYjg7seTm-EJTa0Zj7UDP9zUGNkVpjcEHhl7tU2Mv8mFRiLKC'
             * ));
             * ```
             */
            case 'image':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[image]]></MsgType>'.
                        '<Image><MediaId><![CDATA[%s]]></MediaId></Image>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(), 
                        $msg['media_id']);
                break;

            /**
             * 3 回复语音消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
              *     'type' => 'voice',
              *    'media_id' => 'rVT43tfDwjh4p1BV2gJ5D7Zl2BswChO5L_llmlphLaTPytcGcguBAEJ1qK4cg4r_'
             * ));
             * ```
             */            
            case 'voice':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[voice]]></MsgType>'.
                        '<Voice><MediaId><![CDATA[%s]]></MediaId></Voice>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(), 
                        $msg['media_id']);
                break;

            /**
             * 4 回复视频消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
              *    'type' => 'video',
              *    'media_id' => 'yV0l71NL0wtpRA8OMX0-dBRQsMVyt3fspPUzurIS3psi6eWOrb_WlEeO39jasoZ8',
              *    'title' => '视频消息的标题',            //可选
              *    'description' => '视频消息的描述'        //可选
             * ));
             * ```
             */
            case 'video':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[video]]></MsgType>'.
                        '<Video>'.
                        '<MediaId><![CDATA[%s]]></MediaId>'.
                        '<Title><![CDATA[%s]]></Title>'.
                        '<Description><![CDATA[%s]]></Description>'.
                        '</Video>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(), 
                        $msg['media_id'], 
                        isset($msg['title']) ? $msg['title'] : '',
                        isset($msg['description']) ? $msg['description'] : '');
                break;

            /**
             * 5 回复音乐消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
              *    'type' => 'music',
              *    'title' => '音乐标题',                        //可选
              *    'description' => '音乐描述',                //可选
              *    'music_url' => 'http://me.diary8.com/data/music/2.mp3',        //可选
              *    'hqmusic_url' => 'http://me.diary8.com/data/music/2.mp3',    //可选
              *    'thumb_media_id' => 'O39wW0ZsXCb5VhFoCgibQs5PupFb6VZ2jH5A8gHUJCJz2Qmkrb7objoTue7bGTGQ',
             * ));
             * ```
             */
            case 'music':
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[music]]></MsgType>'.
                        '<Music>'.
                        '<Title><![CDATA[%s]]></Title>'.
                        '<Description><![CDATA[%s]]></Description>'.
                        '<MusicUrl><![CDATA[%s]]></MusicUrl>'.
                        '<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>'.
                        '<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>'.
                        '</Music>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(),
                        isset($msg['title']) ? $msg['title'] : '',
                        isset($msg['description']) ? $msg['description'] : '',
                        isset($msg['music_url']) ? $msg['music_url'] : '',
                        isset($msg['hqmusic_url']) ? $msg['hqmusic_url'] : '',
                        $msg['thumb_media_id']);
                break;

            /**
             * 6 回复图文消息
             *
             * Examples:
             * ```
             * $wechat->reply(array(
             *    'type' => 'news',
             *    'articles' => array(
             *        array(
             *            'title' => '图文消息标题1',                                 //可选
             *            'description' => '图文消息描述1',                           //可选
             *            'picurl' => 'http://me.diary8.com/data/img/demo1.jpg',      //可选
             *            'url' => 'http://www.example.com/'                          //可选
             *        ),
             *        array(
             *            'title' => '图文消息标题2',
             *            'description' => '图文消息描述2',
             *            'picurl' => 'http://me.diary8.com/data/img/demo2.jpg',
             *            'url' => 'http://www.example.com/'
             *        ),
             *        array(
             *            'title' => '图文消息标题3',
             *            'description' => '图文消息描述3',
             *            'picurl' => 'http://me.diary8.com/data/img/demo3.jpg',
             *            'url' => 'http://www.example.com/'
             *        )
             *     )
             * ));
             * ```
             */
            case 'news':
                $articles = '';
                foreach ($msg['articles'] as $article) {
                    $articles .= sprintf('<item>'.
                                    '<Title><![CDATA[%s]]></Title>'.
                                    '<Description><![CDATA[%s]]></Description>'.
                                    '<PicUrl><![CDATA[%s]]></PicUrl>'.
                                    '<Url><![CDATA[%s]]></Url>'.
                                '</item>', 
                                $article['title'],
                                $article['description'],
                                $article['picurl'],
                                $article['url']);
                }
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[news]]></MsgType>'.
                        '<ArticleCount>%s</ArticleCount>'.
                        '<Articles>%s</Articles>'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(),
                        count($msg['articles']),
                        $articles);
                break;
            
            /**
             * 0 转发到多客服接口
             *
             * Examples:
             * ```
             * $wechat->reply(array(
             *    'type' => 'transfer_customer_service',
             *    'kf_account' => 'test1@test'                // 可选
             * ));
             * ```
             */
            case 'transfer_customer_service':
                $xml_transinfo = '';
                if (isset($msg['kf_account']) && !empty($msg['kf_account'])) {
                    $xml_transinfo = sprintf('<TransInfo>'.
                            '<KfAccount><![CDATA[%s]]></KfAccount>'.
                            '</TransInfo>',
                            $msg['kf_account']);
                }
                $xml = sprintf('<xml>'.
                        '<ToUserName><![CDATA[%s]]></ToUserName>'.
                        '<FromUserName><![CDATA[%s]]></FromUserName>'.
                        '<CreateTime>%s</CreateTime>'.
                        '<MsgType><![CDATA[transfer_customer_service]]></MsgType>%s'.
                        '</xml>', 
                        $this->message->FromUserName,
                        $this->message->ToUserName,
                        time(),
                        $xml_transinfo);
                break;

            /**
             * 0 异常消息处理
             *
             */ 
            default:
                @error_log("$msg_type is not a message type that can be used.", 0);
                exit();                
                break;
        }
        
        // 对消息加解密方式 兼容模式\安全模式 - 加密消息
        if ($this->encrypt_type == 'aes' && $xml != '') {

            // 异常处理: 未配置encodingAESKey
            if ($this->encodingAESKey === false) {
                @error_log('EncodingAESKey Not Defined.', 0);
                exit();
            }

            $reply_timestamp = time();

            // 消息加密
            $pc = new Prpcrypt($this->encodingAESKey);            
            $reply_encrypt = $pc->encrypt($xml, $this->appId);
            // 消息加密: 异常处理
            if ($reply_encrypt === false) {
                @error_log('Encrypt Message Error.', 0);
                exit();
            }

            // 生成安全签名
            $reply_signature = SHA1::getSHA1($this->token, $reply_timestamp, $this->nonce, $reply_encrypt);
            // 生成安全签名: 异常处理
            if ($reply_signature===false) {
                @error_log('Get Message Signature Error.', 0);
                exit();
            }

            // 生成发送的xml
            $xml = sprintf('<xml>'.
                        '<Encrypt><![CDATA[%s]]></Encrypt>'.
                        '<MsgSignature><![CDATA[%s]]></MsgSignature>'.
                        '<TimeStamp>%s</TimeStamp>'.
                        '<Nonce><![CDATA[%s]]></Nonce>'.
                        '</xml>', 
                        $reply_encrypt,
                        $reply_signature,
                        $reply_timestamp,
                        $this->nonce);
        }
error_log($xml);
        echo $xml;
    }
577135
protected function setParsedConfig(array $config)
    {
        foreach ($config as $key => $value) {
            $setter = 'set'.ucfirst($key);
            $this->$setter($value);
        }
    }
730029
public function setMerged(array $files)
    {
        if (!empty($files)) {
            foreach ($files as $_file) {
                $this->addMerged($_file);
            }
        }
        return $this;
    }
1228151
public function initialize(array $config = [])
    {
        $this->setConfig($config);
        $this->_registry->getController()->viewBuilder()->setHelpers(['Recaptcha.Recaptcha' => $this->_config]);
    }
1179793
private function _connect_ftp(array $cfg): bool
  {
    if ( isset($cfg['host'], $cfg['user'], $cfg['pass']) ){
      $args = [$cfg['host'], $cfg['port'] ?? 21, $cfg['timeout'] ?? 3];
      try {
        $this->stream = ftp_ssl_connect(...$args);
      }
      catch ( \Exception $e ){
        $this->error = _('Impossible to connect to the FTP host');
        $this->error .= PHP_EOL.$e->getMessage();
      }
      if ( $this->stream ){
        if ( !@ftp_login($this->stream, $cfg['user'], $cfg['pass']) ){
          try {
            $this->stream = ftp_connect(...$args);
          }
          catch ( \Exception $e ){
            $this->error = _('Impossible to connect to the FTP host');
            $this->error .= PHP_EOL.$e->getMessage();
          }
          if ( !@ftp_login($this->stream, $cfg['user'], $cfg['pass']) ){
            $this->error = _('Impossible to login to the FTP host');
            $this->error .= PHP_EOL.error_get_last()['message'];
          }
        }
        if ( !$this->error ){
          $this->current = ftp_pwd($this->stream);
          if (
            !empty($cfg['passive']) ||
            (defined('BBN_SERVER_NAME') && !@fsockopen(BBN_SERVER_NAME, $args[1]))
          ){
            ftp_pasv($this->stream, true);
          }
          return true;
        }
      }
    }
    return false;
  }
70593
public function configure(ConfigProviderInterface $cfg)
  {
    if($this->_configured)
    {
      return $this;
    }

    try
    {
      $config = $cfg->getSection('console');
      $commands = $config->getItem('commands', []);
      $patterns = $config->getItem('patterns', []);
    }
    catch(\Throwable $e)
    {
      $commands = $patterns = [];
    }

    $this->_searchPatterns = array_merge($this->_searchPatterns, $patterns);

    foreach($commands as $name => $class)
    {
      $command = $this->getCommandByString($class);
      if($command !== null)
      {
        if(!is_int($name))
        {
          $command->setName($name);
        }
        $this->add($command);
      }
    }

    $this->_configured = true;
    return $this;
  }
786985
public function initialize(array $config)
    {
        $config = Hash::merge($this->_defaultConfig, $config);
        $this->setConfig($config);
    }