Retrieves grid columns configuration using the modelClass.
@param Model $model
@param array $fields
@return array grid columns
329425
public static function getGridColumns($model, $fields)
    {
        if (!$model instanceof ActiveRecord) {
            return $model->attributes();
        }

        /** @var ActiveRecord $model */
        list($behaviorAttributes, $blameableAttributes) = self::getModelBehaviorAttributes($model);
        /** @var LabelsBehavior $labelsBehavior */
        $labelsBehavior = $model->getBehavior('labels');
        $versionAttribute = $model->optimisticLock();
        $formats = $model->attributeFormats();
        $keys    = self::getModelKeys($model);

        $columns = [];
        foreach ($fields as $key => $field) {
            // for arrays and callables, don't generate the column, use the one provided
            if (is_array($field)) {
                $columns[$key] = $field;
                continue;
            } elseif (!is_string($field) && is_callable($field)) {
                $columns[$key] = call_user_func($field, $model);
                continue;
            }
            // if the field is from a relation (eg. client.firstname) treat it as an attribute
            $format = isset($formats[$field]) ? $formats[$field] : $model->getAttributeFormat($field);
            if ($format === 'paragraphs') {
                $format = 'shortText';
            }
            if ($format !== null) {
                if ((in_array($field, $keys)
                        && ($labelsBehavior === null || !in_array($field, $labelsBehavior->attributes)))
                    || in_array($field, $behaviorAttributes)
                    || $field === $versionAttribute
                ) {
                    continue;
                }
                if (in_array($field, $labelsBehavior->attributes)) {
                    $columns[] = static::getLinkedColumn($model, $field);
                    continue;
                }
                $columns[] = static::getAttributeColumn($model, $field, $format);
                continue;
            }

            $relation = $model->getRelation($field);
            foreach ($relation->link as $left => $right) {
                if (in_array($right, $blameableAttributes)) {
                    continue 2;
                }
            }

            if (!Yii::$app->user->can($relation->modelClass . '.read')) {
                continue;
            }
            $columns[] = static::getRelationColumn($model, $field, $relation);
        }

        return $columns;
    }
1003968
public function children( $model )
	{
		$query = $this->model->newQuery();

		$query->where( $this->model->getQualifiedParentColumnName(), '=', $model->getKey() );

		// We must also add the scoped column values to the query to compute valid
		// left and right indexes.
		foreach ( $this->scopedAttributes( $model ) as $fld => $value )
			$query->where( $this->qualify( $fld ), '=', $value );

		$query->orderBy( $this->model->getQualifiedLeftColumnName() );
		$query->orderBy( $this->model->getQualifiedRightColumnName() );
		$query->orderBy( $this->model->getQualifiedKeyName() );

		return $query->get();
	}
52687
protected function saveColumns(Model $model)
    {
        /** @var \T4\Orm\Model $class */
        $class = get_class($model);
        $columns = $class::getColumns();
        $relations = $class::getRelations();
        $cols = [];
        $prep = [];
        $sets = [];
        $data = [];

        foreach ($columns as $column => $def) {
            if (isset($model->{$column}) && null === $model->{$column} && isset($def['default'])) {
                $cols[] = $this->quoteName($column);
                $prep[] = ':' . $column;
                $sets[] = '' . $this->quoteName($column) . '=:' . $column;
                $data[':' . $column] = $def['default'];
            } else {
                $cols[] = $this->quoteName($column);
                $prep[] = ':' . $column;
                $sets[] = '' . $this->quoteName($column) . '=:' . $column;
                switch ($def['type']) {
                    case 'boolean':
                        $data[':' . $column] = (int)$model->{$column};
                        break;
                    default:
                        $data[':' . $column] = $model->{$column};
                        break;
                }
            }
        }

        foreach ($relations as $rel => $def) {
            switch ($def['type']) {
                case $class::BELONGS_TO:
                    $column = $class::getRelationLinkName($def);
                    if (!in_array($column, $cols)) {
                        // @todo: test this!
                        // if (isset($model->{$column}) && !is_null($model->{$column})) {
                        if (isset($model->{$column})) {
                            $cols[] = $this->quoteName($column);
                            $prep[] = ':' . $column;
                            $sets[] = '' . $this->quoteName($column) . '=:' . $column;
                            $data[':' . $column] = $model->{$column};
                        } elseif (isset($model->{$rel}) && $model->{$rel} instanceof Model) {
                            $cols[] = $this->quoteName($column);
                            $prep[] = ':' . $column;
                            $sets[] = '' . $this->quoteName($column) . '=:' . $column;
                            $data[':' . $column] = $model->{$rel}->getPk();
                        }
                    }
                    break;
            }
        }

        $connection = $class::getDbConnection();
        if ($model->isNew()) {
            $sql = '
                INSERT INTO ' . $this->quoteName($class::getTableName()) . '
                (' . implode(', ', array_unique($cols)) . ')
                VALUES
                (' . implode(', ', array_unique($prep)) . ')
                RETURNING ' . $class::PK . '
            ';
            $res = $connection->query($sql, $data);
            $model->{$class::PK} = $res->fetch()[$class::PK];
        } else {
            $sql = '
                UPDATE ' . $this->quoteName($class::getTableName()) . '
                SET ' . implode(', ', array_unique($sets)) . '
                WHERE "' . $class::PK . '"=\'' . $model->{$class::PK} . '\'
            ';
            $connection->execute($sql, $data);
        }

        return $model;

    }
196385
protected function getSelectedColumns(array $fields, $fieldSourceAlias)
    {
        $columns = [];

        foreach ($fields as $fieldName => $field) {
            if ($field instanceof ILocalizableField && $field->getIsLocalized()) {
                $currentLocaleId = $this->getCurrentLocale();
                $defaultLocaleId = $this->getDefaultLocale();

                if ($this->withLocalization) {
                    foreach ($field->getLocalizations() as $localeId => $localeInfo) {
                        $columnName = $fieldSourceAlias . self::FIELD_SEPARATOR . $localeInfo['columnName'];
                        $alias = $fieldSourceAlias . self::ALIAS_SEPARATOR . $fieldName
                            . ILocalizedProperty::LOCALE_SEPARATOR . $localeId;
                        $columns[] = [$columnName, $alias];
                    }
                } else {
                    $columnName = $fieldSourceAlias . self::FIELD_SEPARATOR
                        . $field->getLocaleColumnName($currentLocaleId);
                    $alias = $fieldSourceAlias . self::ALIAS_SEPARATOR . $fieldName
                        . ILocalizedProperty::LOCALE_SEPARATOR . $currentLocaleId;
                    $columns[] = [$columnName, $alias];

                    if ($currentLocaleId !== $defaultLocaleId) {
                        $columnName = $fieldSourceAlias . self::FIELD_SEPARATOR
                            . $field->getLocaleColumnName($defaultLocaleId);
                        $alias = $fieldSourceAlias . self::ALIAS_SEPARATOR . $fieldName
                            . ILocalizedProperty::LOCALE_SEPARATOR . $defaultLocaleId;
                        $columns[] = [$columnName, $alias];
                    }
                }

            } else {
                $columnName = $fieldSourceAlias . self::FIELD_SEPARATOR . $field->getColumnName();
                $alias = $fieldSourceAlias . self::ALIAS_SEPARATOR . $fieldName;
                $columns[] = [$columnName, $alias];
            }
        }

        return $columns;
    }
875475
public function serialize(ModelInterface $model, $fields)
    {
        $result = array();

        foreach ($fields as $field) {
            $value = $field->getValue($model);
            if (is_string($value)) {
                $value = utf8_encode($value);
            }

            $result[$field->getName()] = $value;
        }

        return $result;
    }
49245
public function validate($model, $fields = [])
    {
        $context = $this->_context;

        $context->messages = [];

        if (!$rules = $model->rules()) {
            return;
        }

        $context->model = $model;

        if (is_string($fields)) {
            $fields = (array)preg_split('#[\s,]+#', $fields, -1, PREG_SPLIT_NO_EMPTY);
        }

        $templates = null;
        foreach ($fields ?: $model->getChangedFields() as $field) {
            if (!isset($rules[$field])) {
                continue;
            }
            $context->field = $field;

            foreach ((array)$rules[$field] as $k => $v) {
                if (is_int($k)) {
                    $name = $v;
                    $parameters = null;
                } else {
                    $name = $k;
                    $parameters = $v;
                }

                $value = $this->_validate($model->$field, $name, $parameters);
                if ($value === null) {
                    $templates = $this->_templates ?: $this->_loadTemplates();
                    $template = isset($templates[$name]) ? $templates[$name] : $templates['default'];
                    $this->appendMessage(new Message($template, $context->model, $context->field, $parameters));
                } else {
                    $model->$field = $value;
                }
            }
        }

        if ($context->messages) {
            throw new ValidateFailedException('validate failed: ' . json_encode($context->messages));
        }
    }
1277881
public function getFields($model, $context = null)
    {
        if (is_array($this->fields)) {
            return $this->fields;
        } elseif (is_callable($this->fields)) {
            return call_user_func($this->fields, $this, $context, $model);
        }
        return static::getDefaultFields($model);
    }
792340
protected function getPrintColumnsForGridField(GridField $gridField)
    {
        if ($this->printColumns) {
            return $this->printColumns;
        }

        /** @var GridFieldDataColumns $dataCols */
        $dataCols = $gridField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
        if ($dataCols) {
            return $dataCols->getDisplayFields($gridField);
        }

        return DataObject::singleton($gridField->getModelClass())->summaryFields();
    }
204852
public function importFields($model, $fields = null)
    {
        $this->model = $model;
        $this->form = $this->owner;

        if ($fields === false) {
            return;
        }

        if (!$fields) {
            $fields = 'editable';
        }
        if (!is_array($fields)) {
            // note: $fields parameter is only useful if model is SQL_Model
            $fields = $model->getActualFields($fields);
        }

        // import fields one by one
        foreach ($fields as $field) {
            $this->importField($field);
        }

        // set update hook
        if (!$this->_hook_set) {
            $this->owner->addHook('update', array($this, 'update'));
            $model->addHook('afterLoad', array($this, 'setFields'));
            $this->_hook_set = true;
        }

        return $this;
    }
1374578
public static function buildTemplates($models)
    {
        $result = [];
        foreach($models as $model) {
            $result[] = self::buildTemplate($model);
        }

        return $result;
    }
617970
protected function getExportColumnsForGridField(GridField $gridField)
    {
        if ($this->exportColumns) {
            return $this->exportColumns;
        }

        /** @var GridFieldDataColumns $dataCols */
        $dataCols = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
        if ($dataCols) {
            return $dataCols->getDisplayFields($gridField);
        }

        return DataObject::singleton($gridField->getModelClass())->summaryFields();
    }
690726
protected function getModelFields(\atk4\data\Model $model)
    {
        $fields = [];
        foreach ($model->elements as $f) {
            if (!$f instanceof \atk4\data\Field) {
                continue;
            }

            if ($f->isEditable() || $f->isVisible()) {
                $fields[] = $f->short_name;
            }
        }

        return $fields;
    }
198493
public static function getRelationGridColumns($model, $fields, $relationName, $relation)
    {
        $columns = parent::getRelationGridColumns($model, $fields, $relationName, $relation);
        $controller = Yii::$app->crudModelsMap[$model::className()];
        $actionColumn = new \yii\grid\ActionColumn();

        if (!isset($columns[0]) || !isset($columns[0]['class']) || $columns[0]['class'] !== 'yii\grid\ActionColumn') {
            array_unshift($columns, [
                'class'         => 'yii\grid\ActionColumn',
                'headerOptions' => ['class' => 'column-action'],
                'controller'    => $controller,
                'template'      => '',
                'buttons'       => [],
            ]);
        }

        $columns[0]['template'] = '{update} {unlink}';
        $columns[0]['urlCreator'] = function ($action, $model, $key, $index) use ($controller, $relation) {
            $params = is_array($key) ? $key : ['id' => (string)$key];
            if ($action === 'update') {
                $params['hide'] = implode(',', array_keys($relation->link));
            }
            $params[0] = $controller . '/' . $action;

            return Url::toRoute($params);
        };
        $columns[0]['buttons']['update'] = function ($url, $model, $key) use ($actionColumn, $relationName) {
            /** @var \netis\crud\db\ActiveRecord $model */
            if (!Yii::$app->user->can($model::className() . '.update', ['model' => $model])) {
                return null;
            }

            $options = array_merge([
                'title'         => Yii::t('app', 'Update'),
                'aria-label'    => Yii::t('app', 'Update'),
                'data-pjax'     => '0',
                // required for editing in a modal
                'data-toggle'   => 'modal',
                'data-target'   => '#relationModal',
                'data-relation' => $relationName,
                'data-title'    => $model->getCrudLabel('update'),
                'data-pjax-url' => $url,
                'class'         => 'btn btn-default btn-xs',
            ], $actionColumn->buttonOptions);
            return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, $options);
        };

        /** @var \yii\db\ActiveQuery $relation */
        $remove = false;
        $modelClass = $relation->modelClass;
        foreach (array_keys($relation->link) as $foreignKey) {
            $remove = $remove || !$modelClass::getTableSchema()->getColumn($foreignKey)->allowNull;
        }

        $columns[0]['buttons']['unlink'] = function ($url, $model, $key) use ($actionColumn, $remove) {
            /** @var \netis\crud\db\ActiveRecord $model */
            if (!Yii::$app->user->can($model::className() . ($remove ? '.delete' : '.update'), ['model' => $model])) {
                return null;
            }

            $options = array_merge([
                'title'      => Yii::t('app', 'Unlink'),
                'aria-label' => Yii::t('app', 'Unlink'),
                //'data-confirm' => Yii::t('app', 'Are you sure you want to unlink this item?'),
                'data-pjax'  => '0',
                'class'      => 'remove btn btn-default btn-xs',
            ], $actionColumn->buttonOptions);
            return Html::a('<span class="glyphicon glyphicon-remove"></span>', $url, $options);
        };
        return $columns;
    }
667027
protected function getFormFieldValuesFromModel(Model $model, array $keys)
    {
        $values = [];

        foreach ($keys as $key) {

            $field    = $this->getModelFormFieldDataForKey($key);
            $instance = $this->getFormFieldStoreStrategyInstanceForField($field);

            $instance->setFormFieldData($field);
            $instance->setParameters(
                $this->getFormFieldStoreStrategyParametersForField($field)
            );

            // If we're creating a new model, pre-select the form field for the active list parent
            if ( ! $model->exists && $this->isFieldValueBeDerivableFromListParent($field->key)) {

                try {
                    $values[ $key ] = $instance->valueForListParentKey($this->getListParentRecordKey());

                    // @codeCoverageIgnoreStart
                } catch (Exception $e) {
                    $message = "Failed retrieving value for form field '{$key}' (using " . get_class($instance)
                             . " (valueForListParentKey)): \n{$e->getMessage()}";

                    throw new StrategyRetrievalException($message, $e->getCode(), $e);
                    // @codeCoverageIgnoreEnd
                }

                continue;
            }

            try {
                $values[ $key ] = $instance->retrieve($model, $field->source ?: $field->key);

                // @codeCoverageIgnoreStart
            } catch (Exception $e) {
                $message = "Failed retrieving value for form field '{$key}' (using " . get_class($instance)
                         . "): \n{$e->getMessage()}";

                throw new StrategyRetrievalException($message, $e->getCode(), $e);
                // @codeCoverageIgnoreEnd
            }
        }

        return $values;
    }
700442
protected function setColumns($model)
    {
        $schema = $model->getConnection()->getDoctrineSchemaManager();
        $platform = $schema->getDatabasePlatform();

        // Prevents a DBALException if the table contains an enum.
        $platform->registerDoctrineTypeMapping('enum', 'string');

        list($table, $database) = $this->getTableAndDatabase($model);

        $this->columns = $model->getConnection()->getDoctrineConnection()->fetchAll(
            $platform->getListTableColumnsSQL($table, $database)
        );

        $this->rejectVirtualColumns();

        $columns = $this->columns;
        $this->columns = call_user_func(\Closure::bind(function () use ($table, $database, $columns) {
            return $this->_getPortableTableColumnList($table, $database, $columns);
        }, $schema, $schema));

        return $this->unquoteColumnNames($platform->getIdentifierQuoteCharacter());
    }
171822
public function getInstanceValueForFields(Model $modelInstance, $fields)
    {
        $values = [];
        /** @var $field Field */
        foreach ($fields as $field) {
            $val = $modelInstance->{$field->getAttrName()};
            if (!$val) {
                continue;
            }
            $values[] = $val;
        }

        return $values;
    }
1270620
public function getModels($columns = ['*'])
    {
        $models = [];

        $documents = $this->query->get($columns);
        foreach ($documents as $doc) {
            $models[] = $this->model->newInstance($doc, true);
        }

        return $models;
    }