list 合并
@param mixed $data
@throws Exception
175865
public function mergeWith($data)
    {
        if (is_array($data) || ($data instanceof \Traversable)) {
            if ($data instanceof CList) {
                $data = $data->_data;
            }
            foreach ($data as $item) {
                $this->push($item);
            }
        } elseif ($data !== null) {
            throw new Exception('列表合并参数必须是数组或可遍历的对象', 100100502);
        }
    }
1160645
public function fromDbTableRow(DoplioDbTable $data) {

        $data = $data->toArray();

        if (!is_array($data)) {
            throw new \Exception('Object must be either an array or a DoplioDbTable');
        }

        return $this->fromArray($data);
    }
1123272
public function delete($data = null)
    {
        // 分析查询表达式
        $options = $this->parseExpress();
        $pk      = $this->getPk();
        if (!is_null($data) && true !== $data) {
            if (!is_array($data)) {
                // 缓存标识
                $key = 'mongo:' . $options['table'] . '|' . $data;
            }
            // AR模式分析主键条件
            $this->parsePkWhere($data, $options);
        } elseif (!isset($key) && is_string($pk) && isset($options['where']['$and'][$pk])) {
            $key = $this->getCacheKey($options['where']['$and'][$pk], $options);
        }

        if (true !== $data && empty($options['where'])) {
            // 如果不是强制删除且条件为空 不进行删除操作
            throw new Exception('delete without condition');
        }

        // 生成bulkWrite对象
        $bulk         = $this->builder->delete($options);
        $writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : null;
        // 执行操作
        $writeResult = $this->execute($options['table'], $bulk, $writeConcern);

        $result = $writeResult->getDeletedCount();
        if ($result) {
            if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, '|')) {
                list($a, $val) = explode('|', $key);
                unset($a);
                $item[$pk]     = $val;
                $data          = $item;
            }
            $options['data'] = $data;
            $this->trigger('after_delete', $options);
        }
        return $result;
    }
1081906
public function addIndex(array $data)
    {
        if (!is_array($data)) {
            throw new \Exception('你的索引参数不是一个数组');
        }
        if (isset($data[0]) && is_array($data[0])) {
            // 多维数组
            foreach ($data as $v) {
                $this->getIndex()->add(new \XSDocument($v));
            }
        } else {
            // 一维数组
            $this->getIndex()->add(new \XSDocument($data));
        }
        //索引是否立即生效
        if ($this->flush_index) {
            $this->getIndex()->flushIndex();
        }
        return $this->getIndex();
    }
708668
public function unserialize($data)
    {
        //argument 1 must be a string
        Argument::i()->test(1, 'string');
        
        $this->list = json_decode($data, true);
        return $this;
    }
1175100
public function add($key, $value)
    {
        if ($this->getReadOnly()) {
            throw new Exception('只读map，不允许执行添加操作', 100100603);
        }
        if (null === $key) {
            $this->_data[] = $value;
        } else {
            $this->_data[$key] = $value;
        }
    }
1341657
public function insert($data)
    {
        if(empty($data))
            throw new Exception("Can't insert an empty row");

        return $this->_connection->execute(sprintf(
            'INSERT INTO %s SET %s',
            $this->_name->quoted(),
            $this->_buildSet($data)
            ), array_values($data)
        );
    }
889188
public function updateBy($data, $whArr)
    {
        $this->mustBeDataModel();

        $where = \wf\db\QueryBuilder::whereArr($whArr);

        if (empty($where)) {
            throw new Exception('The $whereArr param format error!');
        }

        // 不允许修改主键值
        foreach ((array)($this->getPk()) as $pk) {
            unset($data[$pk]);
        }

        $arg = [$this->table, $this->fieldSet($data), $where];
        $exe = $this->getDb()->exec("UPDATE %t SET %x WHERE %x", $arg);

        if (false === $exe) {
            throw new \wf\model\Exception($this->getDb()->getLastErr());
        }

        return $exe;
    }
664668
public function insert($data, $action = 'insert') {
        #移除非法字段
        $data = $this->connection->filterTableField($data);
        if (empty($data)) {
            throw new Exception('没有数据用于插入,请检查字段名');
        }
        foreach ($data as $k => $v) {
            $this->build()->bindExpression('field', "`$k`");
            $this->build()->bindExpression('values', '?');
            $this->build()->bindParams('values', $v);
        }
        return $this->connection->execute($this->build()->$action(), $this->build()->getInsertParams());
    }
966934
public function callback($data = null)
    {
        $data = $data ?: $_POST;
        if ($data['ReturnCode'] != 1) {
            throw new \Exception("交易查询失败：" . $data['ReturnMsg']);
        }
        Datasheet::set($data);
        if (isset($data['Hash']) && $data['Hash'] != Helper::signature(Helper::SIGN_CALLBACK)) {
            throw new \Exception("回调签名验证失败");
        }

        if ($data['PayResult'] != 3) {
            throw new \Exception("交易不成功：" . $data['ReturnMsg']);
        }
        return $data;
    }
1212550
public static function addGraph($data)
    {
        self::registerView();
        
        if (is_scalar($data)) {
            throw new Exception("Data must be either an array or an object of type luya\web\jsonld\BaseThing.");
        }
        
        Yii::$app->view->params['@context'] = 'https://schema.org';
        Yii::$app->view->params['@graph'][] = $data;
        
        return $data;
    }
1173535
public function search(array $data = [])
    {
        if (is_null($this->schema)) {
            throw SystemException::forNoSchema();
        }

        $sum = null;
        $filter = [];
        $like = [];
        $in = [];
        $json = [];
        $span  = [];
        $range = 50;
        $start = 0;
        $order = [];
        $count = 0;

        if (isset($data['filter']) && is_array($data['filter'])) {
            $filter = $data['filter'];
        }

        //Legacy TODO: remove
        if (isset($data['like_filter']) && is_array($data['like_filter'])) {
            $like = $data['like_filter'];
        }

        if (isset($data['like']) && is_array($data['like'])) {
            $like = $data['like'];
        }

        //Legacy TODO: remove
        if (isset($data['in_filter']) && is_array($data['in_filter'])) {
            $in = $data['in_filter'];
        }

        if (isset($data['in']) && is_array($data['in'])) {
            $in = $data['in'];
        }

        //Legacy TODO: remove
        if (isset($data['json_filter']) && is_array($data['json_filter'])) {
            $json = $data['json_filter'];
        }

        if (isset($data['span']) && is_array($data['span'])) {
            $span = $data['span'];
        }

        if (isset($data['range']) && is_numeric($data['range'])) {
            $range = $data['range'];
        }

        if (isset($data['start']) && is_numeric($data['start'])) {
            $start = $data['start'];
        }

        if (isset($data['order']) && is_array($data['order'])) {
            $order = $data['order'];
        }

        if (isset($data['sum']) && !empty($data['sum'])) {
            $sum = sprintf('sum(%s) as total', $data['sum']);
        }

        $active = $this->schema->getActiveFieldName();
        if ($active && !isset($filter[$active])) {
            $filter[$active] = 1;
        }

        $table = $this->schema->getName();
        $search = $this->resource
            ->search($table)
            ->setStart($start);

        if ($range) {
            $search->setRange($range);
        }

        // collect searchable
        $searchable = $this->schema->getSearchableFieldNames();

        // collect json fields
        $fields = $this->schema->getJsonFieldNames();

        //consider forward relations
        $relations = $this->schema->getRelations();
        foreach ($relations as $joinTable => $relation) {
            //deal with post_post at a later time
            if ($table === $relation['name']) {
                continue;
            }

            //1:1
            if ($relation['many'] == 1) {
                $search
                    ->innerJoinUsing(
                        $joinTable,
                        $relation['primary1']
                    )
                    ->innerJoinUsing(
                        $relation['name'],
                        $relation['primary2']
                    );

                //add to searchable
                $searchable = array_merge($searchable, $relation['searchable']);
            //needs to have a filter to add the other kinds of joins
            } else if (!isset($filter[$relation['primary2']])
                && !isset($in[$relation['primary2']])
            ) {
                continue;
            //1:0, 1:N, N:N
            } else {
                $search
                    ->innerJoinUsing(
                        $joinTable,
                        $relation['primary1']
                    )
                    ->innerJoinUsing(
                        $relation['name'],
                        $relation['primary2']
                    );
            }

            $relatedJson = Schema::i($relation['name'])->getJsonFieldNames();
            $fields = array_merge($fields, $relatedJson);
        }

        //consider reverse relations
        $relations = $this->schema->getReverseRelations();
        foreach ($relations as $joinTable => $relation) {
            //deal with post_post at a later time
            if ($relation['source']['name'] === $relation['name']) {
                continue;
            }

            //if filter primary is not set
            if (!isset($filter[$relation['primary1']])
                && !isset($in[$relation['primary1']])
            ) {
                continue;
            }

            $search
                ->innerJoinUsing(
                    $joinTable,
                    $relation['primary2']
                )
                ->innerJoinUsing(
                    $relation['source']['name'],
                    $relation['primary1']
                );

            $relatedJson = Schema::i($relation['source']['name'])->getJsonFieldNames();
            $fields = array_merge($fields, $relatedJson);
        }

        //now deal with post_post
        $circular = $this->schema->getRelations($this->schema->getName());
        //if there is a post_post and they are trying to filter by it
        if (!empty($circular) && isset($filter[$circular['primary']])) {
            //they mean to filter by the parent
            $filter[$circular['primary1']] = $filter[$circular['primary']];

            //remove the old
            unset($filter[$circular['primary']]);

            //now add the join
            $search->innerJoinOn(
                $circular['table'],
                sprintf(
                    '%s = %s',
                    $circular['primary'],
                    $circular['primary2']
                )
            );
        }

        //add filters
        foreach ($filter as $column => $value) {
            if (preg_match('/^[a-zA-Z0-9-_]+$/', $column)) {
                $search->addFilter($column . ' = %s', $value);
                continue;
            }

            //by chance is it a json filter?
            if (preg_match('/^[a-zA-Z0-9-_\.]+$/', $column)) {
                $name = substr($column, 0, strpos($column, '.'));
                $path = substr($column, strpos($column, '.'));
                $path = preg_replace('/\.*([0-9]+)/', '[$1]', $path);

                //it should be a json column type
                if (!in_array($name, $this->schema->getJsonFieldNames())) {
                    continue;
                }

                $column = sprintf('JSON_EXTRACT(%s, "$%s")', $name, $path);

                $search->addFilter($column . ' = %s', $value);
                continue;
            }
        }

        //add like filters
        foreach ($like as $column => $value) {
            if (preg_match('/^[a-zA-Z0-9-_]+$/', $column)) {
                $search->addFilter($column . ' LIKE %s', '%' . $value . '%');
                continue;
            }

            //by chance is it a json filter?
            if (preg_match('/^[a-zA-Z0-9-_\.]+$/', $column)) {
                $name = substr($column, 0, strpos($column, '.'));
                $path = substr($column, strpos($column, '.'));
                $path = preg_replace('/\.*([0-9]+)/', '[$1]', $path);

                 //it should be a json column type
                if (!in_array($name, $this->schema->getJsonFieldNames())) {
                    continue;
                }

                $column = sprintf('JSON_EXTRACT(%s, "$%s")', $name, $path);
                $search->addFilter($column . ' = %s', $value);
                continue;
            }
        }

        // add in filters
        foreach ($in as $column => $values) {
            // values should be array
            if (!is_array($values)) {
                $values = [$values];
            }

            //if it's a json column type
            if (in_array($column, $this->schema->getJsonFieldNames())) {
                $or = [];
                $where = [];
                foreach ($values as $value) {
                    $where[] = "JSON_SEARCH(LOWER($column), 'one', %s) IS NOT NULL";
                    $or[] = '%' . strtolower($value) . '%';
                }

                array_unshift($or, '(' . implode(' OR ', $where) . ')');
                call_user_func([$search, 'addFilter'], ...$or);

                continue;
            }

            if (preg_match('/^[a-zA-Z0-9-_]+$/', $column)) {
                $search->addFilter($column . ' IN ("' . implode('", "', $values) . '")');
            }
        }

        //Legacy TODO: remove
        // add json filters
        foreach ($json as $column => $values) {
            //it should be a json column type
            if (!in_array($column, $this->schema->getJsonFieldNames())) {
                continue;
            }

            // values should be array
            if (!is_array($values)) {
                $values = [$values];
            }

            $or = [];
            $where = [];
            foreach ($values as $value) {
                $where[] = "JSON_SEARCH(LOWER($column), 'one', %s) IS NOT NULL";
                $or[] = '%' . strtolower($value) . '%';
            }

            array_unshift($or, '(' . implode(' OR ', $where) . ')');
            call_user_func([$search, 'addFilter'], ...$or);
        }

        //add spans
        foreach ($span as $column => $value) {
            if (!empty($value)) {
                if (!preg_match('/^[a-zA-Z0-9-_]+$/', $column)) {
                    continue;
                }

                // minimum?
                if (isset($value[0]) && !empty($value[0])) {
                    $search
                        ->addFilter($column . ' >= %s', $value[0]);
                }

                // maximum?
                if (isset($value[1]) && !empty($value[1])) {
                    $search
                        ->addFilter($column . ' <= %s', $value[1]);
                }
            }
        }

        //keyword?
        if (!empty($searchable)) {
            $keywords = [];

            if (isset($data['q'])) {
                $keywords = $data['q'];

                if (!is_array($keywords)) {
                    $keywords = [$keywords];
                }
            }

            foreach ($keywords as $keyword) {
                $or = [];
                $where = [];
                foreach ($searchable as $name) {
                    $where[] = 'LOWER(' . $name . ') LIKE %s';
                    $or[] = '%' . strtolower($keyword) . '%';
                }

                array_unshift($or, '(' . implode(' OR ', $where) . ')');
                call_user_func([$search, 'addFilter'], ...$or);
            }
        }

        //add sorting
        foreach ($order as $sort => $direction) {
            if (preg_match('/^[a-zA-Z0-9-_]+$/', $sort)) {
                $search->addSort($sort, $direction);
                continue;
            }

            //by chance is it a json filter?
            if (preg_match('/^[a-zA-Z0-9-_\.]+$/', $sort)) {
                $name = substr($sort, 0, strpos($sort, '.'));
                $path = substr($sort, strpos($sort, '.'));
                $path = preg_replace('/\.*([0-9]+)/', '[$1]', $path);

                //it should be a json column type
                if (!in_array($name, $this->schema->getJsonFieldNames())) {
                    continue;
                }

                $column = sprintf('JSON_EXTRACT(%s, "$%s")', $name, $path);
                $search->addSort($column, $direction);
                continue;
            }
        }

        $rows = $search->getRows();

        foreach ($rows as $i => $results) {
            foreach ($fields as $field) {
                if (isset($results[$field]) && $results[$field]) {
                    $rows[$i][$field] = json_decode($results[$field], true);
                } else {
                    $rows[$i][$field] = [];
                }
            }

            //custom formats & formulas
            foreach($this->schema->getFields() as $field) {
                if($field['detail']['format'] === 'formula') {
                    $helper = cradle('global')
                        ->handlebars()
                        ->getHelper('formula');

                    $rows[$i][$field['name']] = $helper(
                        $field['detail']['parameters'],
                        $results,
                        false
                    );

                    continue;
                }

                if($field['detail']['format'] === 'custom') {
                    $helper = cradle('global')
                        ->handlebars()
                        ->getHelper('compile');

                    $rows[$i][$field['name']] = $helper(
                        $field['detail']['parameters'],
                        $results
                    );

                    continue;
                }
            }
        }

        //return response format
        $response =  [
            'rows' => $rows,
            'total' => $search->getTotal()
        ];

        if ($sum) {
            $total = $search
                ->setColumns($sum)
                ->getRow();

            $response['sum_field'] = $total['total'] ? $total['total'] : 0;
        }

        return $response;
    }
633983
public function send($data)
    {
        $token = $this->grantToken();
        $newData = $data;
        foreach($token as $k=>$v) {
            $newData[$k] = $v;
        }

        //必填 消息发送类型,其值为unicast,listcast,broadcast,groupcast或customizedcast
        if(!isset($data['type'])) {
            throw new Exception('need param: type');
        }

        // 可选 当type=customizedcast时,开发者填写自己的alias,友盟根据alias进行反查找,得到对应的device_token。多个alias时用英文逗号分,不能超过50个。
        if(isset($data['alias']) && !empty($data['alias'])) {
            if(is_array($data['alias'])) {
                $newData['alias'] = implode(',', $data['alias']);
            } else {
                $newData['alias'] = $data['alias'];
            }
        }

        // 必填 消息类型，值为notification或者message
        if(!isset($data['payload']['display_type'])) {
            $newData['payload']['display_type'] = 'notification';
        }

        // 必填 通知栏提示文字。但实际没有用，todo确认
        if(!isset($data['payload']['body']['ticker'])) {
            $newData['payload']['body']['ticker'] = $data['payload']['body']['title'];
        }

        //可选 消息描述。用于友盟推送web管理后台，便于查看。
        if(!isset($data['description'])) {
            $newData['description'] = $data['payload']['body']['title'];
        }
        
        $defaultTrueParams = array(
            // 通知到达设备后的提醒方式
            'play_vibrate', // 可选 收到通知是否震动,默认为"true".注意，"true/false"为字符串
            'play_lights',  // 可选 收到通知是否闪灯,默认为"true"
            'play_sound',   // 可选 收到通知是否发出声音,默认为"true"
        );

        foreach($defaultTrueParams as $one) {
            if(isset($data['payload']['body'][$one]) && ($data['payload']['body'][$one] == false || $data['payload']['body'][$one] == 'false')) {
                $newData['payload']['body'][$one] = 'false';
            }
        }

        $http = new \HTTPRequest($this->conf['api_uri_prefix'] . 'api/send', HTTP_METH_POST);
        $http->setBody(json_encode($newData));
        $http->send();
        $body = $http->getResponseBody();
        if($http->getResponseCode() != 200) {
            throw new Exception($body);
        }
        $tmp = json_decode($body, true);

        if(!isset($tmp['ret']) || $tmp['ret'] != 'SUCCESS') {
            throw new Exception($body);
        }
        return true;
    }
417725
public function saveCategory($data = [])
    {
        if (!empty($data)) {
            $this->data($data);
        }
        $validate = new \gmars\rbac\validate\PermissionCategory();
        if (!$validate->check($this)) {
            throw new Exception($validate->getError());
        }
        $data = $this->getData();
        if (isset($data['id']) && !empty($data['id'])) {
            $this->isUpdate(true);
        }
        $this->save();
        return $this;
    }
954116
protected function UFCreate(array $data)
    {
        $return = [];
        global $USER_FIELD_MANAGER;
        if (empty($data['FIELD_NAME'])) {
            throw new Exception('You must set group FIELD_NAME');
        }
        if (empty($data['ENTITY_ID'])) {
            throw new Exception('You must set group ENTITY_ID');
        }
        if ($this->UFGetIdByCode($data['ENTITY_ID'], $data['FIELD_NAME'])) {
            throw new Exception('UF with code ' . $data['FIELD_NAME'] . ' already exists');
        }
        $ib = new CUserTypeEntity();
        $id = $ib->Add(array_merge(['USER_TYPE_ID' => 'string'], $data));
        if ($id) {
            $return[] = "Add {$data['FIELD_NAME']} user field";
            if (
                !empty($data['LIST'])
                && ($arType = $USER_FIELD_MANAGER->GetUserType($data['USER_TYPE_ID']))
                && $arType['BASE_TYPE'] == 'enum'
            ) {
                $obEnum = new CUserFieldEnum();
                $res = $obEnum->SetEnumValues($id, $data['LIST']);
                $return[] = "Add {$data['FIELD_NAME']} user field list";
            }
        } else {
            throw new Exception("Can't create {$data['FIELD_NAME']} user field");
        }

        return $return;
    }
959204
public function appendData($data)
    {
        if (!is_array($data)) {
            throw new \InvalidArgumentException('Cannot append view data. Expected array argument.');
        }
        $this->data = array_merge($this->data, $data);
    }
257947
public function merge($data) : Collection
    {
        return static::create(array_merge($this->data, $this->convertToArray($data)));
    }