数据自动完成
@access protected
@param array $auto 要自动更新的字段列表
@return void
3539
protected function autoCompleteData($auto = [])
    {
        foreach ($auto as $field => $value) {
            if (is_integer($field)) {
                $field = $value;
                $value = null;
            }

            if (!isset($this->data[$field])) {
                $default = null;
            } else {
                $default = $this->data[$field];
            }

            $this->setAttr($field, !is_null($value) ? $value : $default);
        }
    }
621495
public function backup($table, $start)
    {
        $db = self::connect();
        // 备份表结构
        if (0 == $start) {
            $result = $db->query("SHOW CREATE TABLE `{$table}`");
            $sql = "\n";
            $sql .= "-- -----------------------------\n";
            $sql .= "-- Table structure for `{$table}`\n";
            $sql .= "-- -----------------------------\n";
            $sql .= "DROP TABLE IF EXISTS `{$table}`;\n";
            $sql .= trim($result[0]['Create Table']) . ";\n\n";
            if (false === $this->write($sql)) {
                return false;
            }
        }
        //数据总数
        $result = $db->query("SELECT COUNT(*) AS count FROM `{$table}`");
        $count = $result['0']['count'];
        //备份表数据
        if ($count) {
            //写入数据注释
            if (0 == $start) {
                $sql = "-- -----------------------------\n";
                $sql .= "-- Records of `{$table}`\n";
                $sql .= "-- -----------------------------\n";
                $this->write($sql);
            }
            //备份数据记录
            $result = $db->query("SELECT * FROM `{$table}` LIMIT {$start}, 1000");
            foreach ($result as $row) {
                $row = array_map('addslashes', $row);
                $sql = "INSERT INTO `{$table}` VALUES ('" . str_replace(array("\r", "\n"), array('\\r', '\\n'), implode("', '", $row)) . "');\n";
                if (false === $this->write($sql)) {
                    return false;
                }
            }
            //还有更多数据
            if ($count > $start + 1000) {
                //return array($start + 1000, $count);
                return $this->backup($table, $start + 1000);
            }
        }
        //备份下一表
        return 0;
    }
1311737
public function copyFromArray(array &$array)
    {
        parent::copyFromArray($array);

        // action
        $this->setAction(
            TokenIssueAction::valueOf(
                LanguageUtility::getFromArray('action', $array)));

        // responseContent
        $this->setResponseContent(
            LanguageUtility::getFromArray('responseContent', $array));

        // accessToken
        $this->setAccessToken(
            LanguageUtility::getFromArray('accessToken', $array));

        // accessTokenExpiresAt
        $this->setAccessTokenExpiresAt(
            LanguageUtility::getFromArray('accessTokenExpiresAt', $array));

        // accessTokenDuration
        $this->setAccessTokenDuration(
            LanguageUtility::getFromArray('accessTokenDuration', $array));

        // refreshToken
        $this->setRefreshToken(
            LanguageUtility::getFromArray('refreshToken', $array));

        // refreshTokenExpiresAt
        $this->setRefreshTokenExpiresAt(
            LanguageUtility::getFromArray('refreshTokenExpiresAt', $array));

        // refreshTokenDuration
        $this->setRefreshTokenDuration(
            LanguageUtility::getFromArray('refreshTokenDuration', $array));

        // clientId
        $this->setClientId(
            LanguageUtility::getFromArray('clientId', $array));

        // clientIdAlias
        $this->setClientIdAlias(
            LanguageUtility::getFromArray('clientIdAlias', $array));

        // subject
        $this->setSubject(
            LanguageUtility::getFromArray('subject', $array));

        // scopes
        $this->setScopes(
            LanguageUtility::getFromArray('scopes', $array));

        // properties
        $properties = LanguageUtility::getFromArray('properties', $array);
        $this->setProperties(
            LanguageUtility::convertArrayToArrayOfArrayCopyable(
                $properties, __NAMESPACE__ . '\Property'));
    }
692262
public function autoload_on_admin()
	{
		$this->on_admin();
		// Addons
		for ( $i = count( $this->addons ) - 1; $i >= 0; --$i ) {
			$this->addons[$i]->on_admin();
		}
	}
560271
public static function begin(): void
  {
    $ret = self::$mysqli->autocommit(false);
    if (!$ret) self::mySqlError('mysqli::autocommit');
  }
427322
public function start( $autoCommit = 1 )
	{
		$this->openTransactions ++;
		if( $this->openTransactions == 1 )
		{
			if( $autoCommit )
			{
				$query = "SET AUTOCOMMIT=0";
			}
			$this->Execute( $query );
			$query = "START TRANSACTION";
			$this->Execute ($query);
		}
	}
429831
public function init()
    {
        /**
         * 设置默认时区
         */
        if ($this->timezone)
        {
            date_default_timezone_set($this->timezone);
        }

        /**
         * 设置地区信息（地域信息）
         */
        if ($this->locale)
        {
            setlocale(LC_ALL, $this->locale);
        }

        if ($this->charset && function_exists('mb_internal_encoding'))
        {
            mb_internal_encoding($this->charset);
        }

        /**
         * 当输入字符的编码是无效的，或者字符代码不存在于输出的字符编码中时，可以为其指定一个替代字符。
         *
         * @link http://www.php.net/manual/function.mb-substitute-character.php
         */
        mb_substitute_character('none');

        // 确保输入的数据安全
        $_GET = Security::sanitize($_GET);
        $_POST = Security::sanitize($_POST);
        $_COOKIE = Security::sanitize($_COOKIE);

        self::cleanComponents();
    }
1081110
public function update($data = null, $all = false)
    {
        if (is_null($data)) $data = $this->_data;
        if (!$data && !isset($this->options['increment'])) return NULL;

        $this->updatedAt && $data['updated_at'] = $this->_getTime();

        if($data)
            $columns = '`' . implode('` = ?, `', array_keys($data)). '` = ?,';
        else
            $columns = '';

        $increment = '';
        if(isset($this->options['increment']) && $this->options['increment']) {
            foreach ($this->options['increment'] as $field => $value)
                $increment .= "`{$field}` = `$field` + {$value},";
            $increment = rtrim($increment, ',');
        }else{
            $columns = rtrim($columns, ',');
        }

        $sql = 'UPDATE ' . $this->getTableName() . ' SET ' . $columns . $increment . ' WHERE ';

        $params = array();
        // 如果有设置主键
        if (isset($data[$this->key])) {
            $where = $this->key . ' = ?';
            $params = array($data[$this->key]);
        } elseif (isset($this->options['where']['0'])) { // 或者有设置where
            $where = $this->options['where']['0'];
            if (isset($this->options['where']['1'])) $params = $this->options['where']['1'];
        } elseif ($all) { // 更新所有数据，慎用！
            $where = '1 = 1';
        } else {
            return NULL;
        }

        if ($statement = $this->execute($sql . $where, $data ? array_merge(array_values($data), $params) : $params))
            return $statement->rowCount();
        else
            return NULL;
    }
1333012
public function auto()
    {
        if (strtoupper($this->encoding) === self::ENCODING) {
            return $this->string;
        }
        $errorHandler = new ErrorHandler();
        set_error_handler([$errorHandler, 'callback'], E_NOTICE | E_WARNING);
        foreach ([
                     'intl',
                     'iconv',
                     'xml',
                     'mbstring',
                 ] as $extension) {
            $last = $errorHandler->getLast();
            if (extension_loaded($extension) &&
                ($result = call_user_func([$this, $extension])) !== false &&
                $last === $errorHandler->getLast()
            ) {
                restore_error_handler();
                return $result;
            }
        }
        restore_error_handler();
        return false;
    }
625347
public function save(): void
    {
        $keys = [];

        $primaryKey = $this->primaryKey;

        //每个行对象进行保存
        foreach ($this as $record) {
            /*
             * @var SRecord
             */
            $record->save();

            //取行对象的主键值
            $keys[] = $record->{$primaryKey};
        }

        //要删除的记录的主键值
        $deletedKeys = array_diff($this->oldPrimaryKeys, $keys);

        //一对多时,在关联表中进行删除
        if ($this->type === 'hasMany') {
            /**
             * @var $tableClass Table
             */
            $tableClass = $this->tableClass;
            $tableClass::instance()->delete([$this->primaryKey => $deletedKeys]);
        } elseif ($this->type === 'belongsToMany') {
            //多对多关联时,删除 中间表
            $config = $this->relation;

            //配置信息
            $middleClass = $config['middle'];  //中间表
            $selfForeignKey = $config['selfForeignKey'];//中间表中与本表关联的键
            $targetForeignKey = $config['targetForeignKey'];//中间表中与对方 表关联的键
            $selfPrimaryValue = $config['selfPrimaryValue']; //主表主键值

            //在中间表中进行删除
            $middleClass::instance()->delete([$selfForeignKey => $selfPrimaryValue, $targetForeignKey => $deletedKeys]);
        }
    }
750526
public function init(array $config = [])
    {
        $config = $config ?: $this->config;

        $isDoStart = false;
        if (isset($config['use_trans_sid'])) {
            ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
        }

        // 启动session
        if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) {
            ini_set('session.auto_start', 0);
            $isDoStart = true;
        }

        if (isset($config['prefix'])) {
            $this->prefix = $config['prefix'];
        }

        if (isset($config['use_lock'])) {
            $this->lock = $config['use_lock'];
        }

        if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) {
            session_id($_REQUEST[$config['var_session_id']]);
        } elseif (isset($config['id']) && !empty($config['id'])) {
            session_id($config['id']);
        } else {
            session_id(WorkerHttp::sessionId());
        }

        if (isset($config['name'])) {
            WorkerHttp::sessionName($config['name']);
        }

        if (isset($config['path'])) {
            WorkerHttp::sessionSavePath($config['path']);
        }

        if (isset($config['domain'])) {
            ini_set('session.cookie_domain', $config['domain']);
        }

        if (isset($config['expire'])) {
            ini_set('session.gc_maxlifetime', $config['expire']);
            ini_set('session.cookie_lifetime', $config['expire']);
        }

        if (isset($config['secure'])) {
            ini_set('session.cookie_secure', $config['secure']);
        }

        if (isset($config['httponly'])) {
            ini_set('session.cookie_httponly', $config['httponly']);
        }

        if (isset($config['use_cookies'])) {
            ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0);
        }

        if (isset($config['cache_limiter'])) {
            session_cache_limiter($config['cache_limiter']);
        }

        if (isset($config['cache_expire'])) {
            session_cache_expire($config['cache_expire']);
        }

        if (!empty($config['type'])) {
            // 读取session驱动
            $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);

            // 检查驱动类
            if (!class_exists($class) || !session_set_save_handler(new $class($config))) {
                throw new ClassNotFoundException('error session handler:' . $class, $class);
            }
        }

        if ($isDoStart) {
            $this->start();
        } else {
            $this->init = false;
        }

        return $this;
    }
419440
protected function getCacheKey(string $name, bool $auto = false): string
    {
        $name = hash($this->options['hash_type'], $name);

        if ($this->options['cache_subdir']) {
            // 使用子目录
            $name = substr($name, 0, 2) . DIRECTORY_SEPARATOR . substr($name, 2);
        }

        if ($this->options['prefix']) {
            $name = $this->options['prefix'] . DIRECTORY_SEPARATOR . $name;
        }

        $filename = $this->options['path'] . $name . '.php';
        $dir      = dirname($filename);

        if ($auto && !is_dir($dir)) {
            try {
                mkdir($dir, 0755, true);
            } catch (\Exception $e) {
                // 创建失败
            }
        }

        return $filename;
    }
1066173
public function createRow(array $row): array
    {
        // 更新时必须指定要更新的数据
        if (!$row) {
            throw new MysqlException('更新时必须指定数据', MysqlException::MISS_DATA_IN_MODIFY);
        }

        // 要更新的数据必须以对象或数组的方式提供
        if (!is_array($row)) {
            trigger_error('更新时数据类型错误:' . json($row), E_USER_ERROR);
        }

        $fields = $values = [];
        foreach ($row as $name => $value) {
            // 更新的数据中,列名必须是字符串
            if (!is_string($name) or is_numeric($name)) {
                trigger_error('更新时字段名必须是字符串:' . json($name), E_USER_ERROR);
            }

            // 如果值为空,则存储空字符串
            if (is_null($value) or (is_bool($value) and !$value)) {
                $value = '';
            }

            // 值只能是字符串或数值
            if (!is_string($value) and !is_numeric($value)) {
                trigger_error('更新时字段的值必须是字符串或数值:' . json($value), E_USER_ERROR);
            }

            // 名加上定界符,值不加(可能是表达式)
            $fields[] = $this->markField($name);
            $values[] = $value;
        }

        // 没有有效的更新数据
        if (!count($fields)) {
            throw new MysqlException('更新时没有有效的数据:' . json($row), MysqlException::INVALID_MODIFY);
        }

        return [$fields, $values];
    }
359927
final public function update($data = [], $autoSave = true)
    {
        foreach ($data as $key => $value) {
            if ($value === null) {
                continue;
            } else if (property_exists($this, $key) && method_exists($this, $key)) {
                $this->$key($value);
            }
        }
        if ($autoSave) {
            $this->save();
        }
        return $this;
    }
856265
public function bootstrap($app)
    {
        /** @var Module $module */
        /** @var \yii\db\ActiveRecord $modelName */
        if ($app->hasModule('oauth2') && ($module = $app->getModule('oauth2')) instanceof Module) {
            if ($app instanceof \yii\console\Application) {
                $app->controllerMap[$module->id] = [
                    'class' => Oauth2Controller::className(),
                ];
            }
            /**
             * 注册语言包
             */
            if (!isset($app->get('i18n')->translations['oauth2*'])) {
                $app->get('i18n')->translations['oauth2*'] = [
                    'class' => PhpMessageSource::className(),
                    'sourceLanguage' => 'en-US',
                    'basePath' => __DIR__ . '/messages',
                ];
            }
        }
    }
658195
public function run()
    {
        // add default menus.
        Menu::truncate();
        Menu::insert([
            [
                'parent_id' => 0,
                'order' => 1,
                'title' => '系统管理',
                'icon' => 'fa-tasks',
                'uri' => '/',
            ],

            [
                'parent_id' => 1,
                'order' => 1,
                'title' => 'Index',
                'icon' => 'fa-bar-chart',
                'uri' => '/',
            ],

            [
                'parent_id' => 1,
                'order' => 2,
                'title' => 'Admin',
                'icon' => 'fa-tasks',
                'uri' => '',
            ],
            [
                'parent_id' => 3,
                'order' => 3,
                'title' => 'Users',
                'icon' => 'fa-users',
                'uri' => 'auth/users',
            ],
            [
                'parent_id' => 3,
                'order' => 4,
                'title' => 'Roles',
                'icon' => 'fa-user',
                'uri' => 'auth/roles',
            ],
            [
                'parent_id' => 3,
                'order' => 5,
                'title' => 'Permission',
                'icon' => 'fa-ban',
                'uri' => 'auth/permissions',
            ],
            [
                'parent_id' => 3,
                'order' => 6,
                'title' => 'Menu',
                'icon' => 'fa-bars',
                'uri' => 'auth/menu',
            ],
            [
                'parent_id' => 3,
                'order' => 7,
                'title' => 'Operation log',
                'icon' => 'fa-history',
                'uri' => 'auth/logs',
            ],
        ]);

        // add role to menu.
        Menu::find(2)->roles()->save(Role::first());
    }
1032295
public function copyFromArray(array &$array)
    {
        parent::copyFromArray($array);

        // action
        $this->setAction(
            TokenAction::valueOf(
                LanguageUtility::getFromArray('action', $array)));

        // responseContent
        $this->setResponseContent(
            LanguageUtility::getFromArray('responseContent', $array));

        // username
        $this->setUsername(
            LanguageUtility::getFromArray('username', $array));

        // password
        $this->setPassword(
            LanguageUtility::getFromArray('password', $array));

        // ticket
        $this->setTicket(
            LanguageUtility::getFromArray('ticket', $array));

        // accessToken
        $this->setAccessToken(
            LanguageUtility::getFromArray('accessToken', $array));

        // accessTokenExpiresAt
        $this->setAccessTokenExpiresAt(
            LanguageUtility::getFromArray('accessTokenExpiresAt', $array));

        // accessTokenDuration
        $this->setAccessTokenDuration(
            LanguageUtility::getFromArray('accessTokenDuration', $array));

        // refreshToken
        $this->setRefreshToken(
            LanguageUtility::getFromArray('refreshToken', $array));

        // refreshTokenExpiresAt
        $this->setRefreshTokenExpiresAt(
            LanguageUtility::getFromArray('refreshTokenExpiresAt', $array));

        // refreshTokenDuration
        $this->setRefreshTokenDuration(
            LanguageUtility::getFromArray('refreshTokenDuration', $array));

        // idToken
        $this->setIdToken(
            LanguageUtility::getFromArray('idToken', $array));

        // grantType
        $this->setGrantType(
            GrantType::valueOf(
                LanguageUtility::getFromArray('grantType', $array)));

        // clientId
        $this->setClientId(
            LanguageUtility::getFromArray('clientId', $array));

        // clientIdAlias
        $this->setClientIdAlias(
            LanguageUtility::getFromArray('clientIdAlias', $array));

        // clientIdAliasUsed
        $this->setClientIdAliasUsed(
            LanguageUtility::getFromArrayAsBoolean('clientIdAlias', $array));

        // subject
        $this->setSubject(
            LanguageUtility::getFromArray('subject', $array));

        // scopes
        $this->setScopes(
            LanguageUtility::getFromArray('scopes', $array));

        // properties
        $properties = LanguageUtility::getFromArray('properties', $array);
        $this->setProperties(
            LanguageUtility::convertArrayToArrayOfArrayCopyable(
                $properties, __NAMESPACE__ . '\Property'));
    }