예제 #1
0
 /**
  * Renders the sorter.
  * @return string the rendering result
  */
 public function renderSorter()
 {
     $sort = $this->dataProvider->getSort();
     if ($sort === false || empty($sort->attributes) || $this->dataProvider->getCount() <= 0) {
         return '';
     }
     /* @var $class LinkSorter */
     $sorter = $this->sorter;
     $class = ArrayHelper::remove($sorter, 'class', LinkSorter::className());
     $sorter['sort'] = $sort;
     $sorter['view'] = $this->getView();
     return $class::widget($sorter);
 }
예제 #2
0
 /**
  * Serializes a set of models.
  * @param array $models
  * @return array the array representation of the models
  */
 protected function serializeModels(array $models)
 {
     list($fields, $expand) = $this->getRequestedFields();
     foreach ($models as $i => $model) {
         if ($model instanceof Arrayable) {
             $models[$i] = $model->toArray($fields, $expand);
         } elseif (is_array($model)) {
             $models[$i] = ArrayHelper::toArray($model);
         }
     }
     return $models;
 }
예제 #3
0
 /**
  * Normalizes the attribute specifications.
  * @throws InvalidConfigException
  */
 protected function normalizeAttributes()
 {
     if ($this->attributes === null) {
         if ($this->model instanceof Model) {
             $this->attributes = $this->model->attributes();
         } elseif (is_object($this->model)) {
             $this->attributes = $this->model instanceof Arrayable ? $this->model->toArray() : array_keys(get_object_vars($this->model));
         } elseif (is_array($this->model)) {
             $this->attributes = array_keys($this->model);
         } else {
             throw new InvalidConfigException('The "model" property must be either an array or an object.');
         }
         sort($this->attributes);
     }
     foreach ($this->attributes as $i => $attribute) {
         if (is_string($attribute)) {
             if (!preg_match('/^([\\w\\.]+)(:(\\w*))?(:(.*))?$/', $attribute, $matches)) {
                 throw new InvalidConfigException('The attribute must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
             }
             $attribute = ['attribute' => $matches[1], 'format' => isset($matches[3]) ? $matches[3] : 'text', 'label' => isset($matches[5]) ? $matches[5] : null];
         }
         if (!is_array($attribute)) {
             throw new InvalidConfigException('The attribute configuration must be an array.');
         }
         if (isset($attribute['visible']) && !$attribute['visible']) {
             unset($this->attributes[$i]);
             continue;
         }
         if (!isset($attribute['format'])) {
             $attribute['format'] = 'text';
         }
         if (isset($attribute['attribute'])) {
             $attributeName = $attribute['attribute'];
             if (!isset($attribute['label'])) {
                 $attribute['label'] = $this->model instanceof Model ? $this->model->getAttributeLabel($attributeName) : Inflector::camel2words($attributeName, true);
             }
             if (!array_key_exists('value', $attribute)) {
                 $attribute['value'] = ArrayHelper::getValue($this->model, $attributeName);
             }
         } elseif (!isset($attribute['label']) || !array_key_exists('value', $attribute)) {
             throw new InvalidConfigException('The attribute configuration requires the "attribute" element to determine the value and display label.');
         }
         $this->attributes[$i] = $attribute;
     }
 }
예제 #4
0
 /**
  * @inheritdoc
  */
 protected function getMigrationHistory($limit)
 {
     if ($this->db->schema->getTableSchema($this->migrationTable, true) === null) {
         $this->createMigrationHistoryTable();
     }
     $query = new Query();
     $rows = $query->select(['version', 'apply_time'])->from($this->migrationTable)->orderBy('apply_time DESC, version DESC')->limit($limit)->createCommand($this->db)->queryAll();
     $history = ArrayHelper::map($rows, 'version', 'apply_time');
     unset($history[self::BASE_MIGRATION]);
     return $history;
 }
예제 #5
0
 /**
  * Renders the content of a menu item.
  * Note that the container and the sub-menus are not rendered here.
  * @param array $item the menu item to be rendered. Please refer to [[items]] to see what data might be in the item.
  * @return string the rendering result
  */
 protected function renderItem($item)
 {
     if (isset($item['url'])) {
         $template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
         return strtr($template, ['{url}' => Html::encode(Url::to($item['url'])), '{label}' => $item['label']]);
     } else {
         $template = ArrayHelper::getValue($item, 'template', $this->labelTemplate);
         return strtr($template, ['{label}' => $item['label']]);
     }
 }
예제 #6
0
 /**
  * Finds ActiveRecord instance(s) by the given condition.
  * This method is internally called by [[findOne()]] and [[findAll()]].
  * @param mixed $condition please refer to [[findOne()]] for the explanation of this parameter
  * @return ActiveQueryInterface the newly created [[ActiveQueryInterface|ActiveQuery]] instance.
  * @throws InvalidConfigException if there is no primary key defined
  * @internal
  */
 protected static function findByCondition($condition)
 {
     $query = static::find();
     if (!ArrayHelper::isAssociative($condition)) {
         // query by primary key
         $primaryKey = static::primaryKey();
         if (isset($primaryKey[0])) {
             $pk = $primaryKey[0];
             if (!empty($query->join) || !empty($query->joinWith)) {
                 $pk = static::tableName() . '.' . $pk;
             }
             $condition = [$pk => $condition];
         } else {
             throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
         }
     }
     return $query->andWhere($condition);
 }
예제 #7
0
 /**
  * Renders a single data model.
  * @param mixed $model the data model to be rendered
  * @param mixed $key the key value associated with the data model
  * @param integer $index the zero-based index of the data model in the model array returned by [[dataProvider]].
  * @return string the rendering result
  */
 public function renderItem($model, $key, $index)
 {
     if ($this->itemView === null) {
         $content = $key;
     } elseif (is_string($this->itemView)) {
         $content = $this->getView()->render($this->itemView, array_merge(['model' => $model, 'key' => $key, 'index' => $index, 'widget' => $this], $this->viewParams));
     } else {
         $content = call_user_func($this->itemView, $model, $key, $index, $this);
     }
     $options = $this->itemOptions;
     $tag = ArrayHelper::remove($options, 'tag', 'div');
     if ($tag !== false) {
         $options['data-key'] = is_array($key) ? json_encode($key, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : (string) $key;
         return Html::tag($tag, $content, $options);
     } else {
         return $content;
     }
 }
예제 #8
0
 /**
  * Returns the data cell value.
  * @param mixed $model the data model
  * @param mixed $key the key associated with the data model
  * @param integer $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
  * @return string the data cell value
  */
 public function getDataCellValue($model, $key, $index)
 {
     if ($this->value !== null) {
         if (is_string($this->value)) {
             return ArrayHelper::getValue($model, $this->value);
         } else {
             return call_user_func($this->value, $model, $key, $index, $this);
         }
     } elseif ($this->attribute !== null) {
         return ArrayHelper::getValue($model, $this->attribute);
     }
     return null;
 }
예제 #9
0
 /**
  * Registers a JS file.
  * @param string $url the JS file to be registered.
  * @param array $options the HTML attributes for the script tag. The following options are specially handled
  * and are not treated as HTML attributes:
  *
  * - `depends`: array, specifies the names of the asset bundles that this JS file depends on.
  * - `position`: specifies where the JS script tag should be inserted in a page. The possible values are:
  *     * [[POS_HEAD]]: in the head section
  *     * [[POS_BEGIN]]: at the beginning of the body section
  *     * [[POS_END]]: at the end of the body section. This is the default value.
  *
  * Please refer to [[Html::jsFile()]] for other supported options.
  *
  * @param string $key the key that identifies the JS script file. If null, it will use
  * $url as the key. If two JS files are registered with the same key, the latter
  * will overwrite the former.
  */
 public function registerJsFile($url, $options = [], $key = null)
 {
     $url = Leaps::getAlias($url);
     $key = $key ?: $url;
     $depends = ArrayHelper::remove($options, 'depends', []);
     if (empty($depends)) {
         $position = ArrayHelper::remove($options, 'position', self::POS_END);
         $this->jsFiles[$position][$key] = Html::jsFile($url, $options);
     } else {
         $this->getAssetManager()->bundles[$key] = new AssetBundle(['baseUrl' => '', 'js' => [strncmp($url, '//', 2) === 0 ? $url : ltrim($url, '/')], 'jsOptions' => $options, 'depends' => (array) $depends]);
         $this->registerAssetBundle($key);
     }
 }
예제 #10
0
 /**
  * Loads the messages from database.
  * You may override this method to customize the message storage in the database.
  * @param string $category the message category.
  * @param string $language the target language.
  * @return array the messages loaded from database.
  */
 protected function loadMessagesFromDb($category, $language)
 {
     $mainQuery = new Query();
     $mainQuery->select(['t1.message message', 't2.translation translation'])->from(["{$this->sourceMessageTable} t1", "{$this->messageTable} t2"])->where('t1.id = t2.id AND t1.category = :category AND t2.language = :language')->params([':category' => $category, ':language' => $language]);
     $fallbackLanguage = substr($language, 0, 2);
     if ($fallbackLanguage != $language) {
         $fallbackQuery = new Query();
         $fallbackQuery->select(['t1.message message', 't2.translation translation'])->from(["{$this->sourceMessageTable} t1", "{$this->messageTable} t2"])->where('t1.id = t2.id AND t1.category = :category AND t2.language = :fallbackLanguage')->andWhere("t2.id NOT IN (SELECT id FROM {$this->messageTable} WHERE language = :language)")->params([':category' => $category, ':language' => $language, ':fallbackLanguage' => $fallbackLanguage]);
         $mainQuery->union($fallbackQuery, true);
     }
     $messages = $mainQuery->createCommand($this->db)->queryAll();
     return ArrayHelper::map($messages, 'message', 'translation');
 }
예제 #11
0
 /**
  * Renders the opening tag of the field container.
  * @return string the rendering result.
  */
 public function begin()
 {
     if ($this->form->enableClientScript) {
         $clientOptions = $this->getClientOptions();
         if (!empty($clientOptions)) {
             $this->form->attributes[] = $clientOptions;
         }
     }
     $inputID = Html::getInputId($this->model, $this->attribute);
     $attribute = Html::getAttributeName($this->attribute);
     $options = $this->options;
     $class = isset($options['class']) ? [$options['class']] : [];
     $class[] = "field-{$inputID}";
     if ($this->model->isAttributeRequired($attribute)) {
         $class[] = $this->form->requiredCssClass;
     }
     if ($this->model->hasErrors($attribute)) {
         $class[] = $this->form->errorCssClass;
     }
     $options['class'] = implode(' ', $class);
     $tag = ArrayHelper::remove($options, 'tag', 'div');
     return Html::beginTag($tag, $options);
 }
예제 #12
0
 /**
  * Generates a form field.
  * A form field is associated with a model and an attribute. It contains a label, an input and an error message
  * and use them to interact with end users to collect their inputs for the attribute.
  * @param Model $model the data model
  * @param string $attribute the attribute name or expression. See [[Html::getAttributeName()]] for the format
  * about attribute expression.
  * @param array $options the additional configurations for the field object. These are properties of [[ActiveField]]
  * or a subclass, depending on the value of [[fieldClass]].
  * @return ActiveField the created ActiveField object
  * @see fieldConfig
  */
 public function field($model, $attribute, $options = [])
 {
     $config = $this->fieldConfig;
     if ($config instanceof \Closure) {
         $config = call_user_func($config, $model, $attribute);
     }
     if (!isset($config['className'])) {
         $config['className'] = $this->fieldClass;
     }
     return Leaps::createObject(ArrayHelper::merge($config, $options, ['model' => $model, 'attribute' => $attribute, 'form' => $this]));
 }
예제 #13
0
 /**
  * Renders a single breadcrumb item.
  * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
  * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link.
  * @return string the rendering result
  * @throws InvalidConfigException if `$link` does not have "label" element.
  */
 protected function renderItem($link, $template)
 {
     $encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels);
     if (array_key_exists('label', $link)) {
         $label = $encodeLabel ? Html::encode($link['label']) : $link['label'];
     } else {
         throw new InvalidConfigException('The "label" element is required for each link.');
     }
     if (isset($link['template'])) {
         $template = $link['template'];
     }
     if (isset($link['url'])) {
         $options = $link;
         unset($options['template'], $options['label'], $options['url']);
         $link = Html::a($label, $link['url'], $options);
     } else {
         $link = $label;
     }
     return strtr($template, ['{link}' => $link]);
 }
예제 #14
0
 /**
  * 将模型转换为一个数组.
  *
  * This method will first identify which fields to be included in the resulting array by calling [[resolveFields()]].
  * It will then turn the model into an array with these fields. If `$recursive` is true,
  * any embedded objects will also be converted into arrays.
  *
  * If the model implements the [[Linkable]] interface, the resulting array will also have a `_link` element
  * which refers to a list of links as specified by the interface.
  *
  * @param array $fields the fields being requested. If empty, all fields as specified by [[fields()]] will be returned.
  * @param array $expand the additional fields being requested for exporting. Only fields declared in [[extraFields()]]
  *        will be considered.
  * @param boolean $recursive whether to recursively return array representation of embedded objects.
  * @return array the array representation of the object
  */
 public function toArray(array $fields = [], array $expand = [], $recursive = true)
 {
     $data = [];
     foreach ($this->resolveFields($fields, $expand) as $field => $definition) {
         $data[$field] = is_string($definition) ? $this->{$definition} : call_user_func($definition, $this, $field);
     }
     if ($this instanceof Linkable) {
         $data['_links'] = Link::serialize($this->getLinks());
     }
     return $recursive ? ArrayHelper::toArray($data) : $data;
 }
예제 #15
0
 /**
  * Sorts the data models according to the given sort definition
  * 
  * @param array $models the models to be sorted
  * @param Sort $sort the sort definition
  * @return array the sorted data models
  */
 protected function sortModels($models, $sort)
 {
     $orders = $sort->getOrders();
     if (!empty($orders)) {
         ArrayHelper::multisort($models, array_keys($orders), array_values($orders));
     }
     return $models;
 }