Rafalsky/HomeFinance

View on GitHub
common/base/MultiModel.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/*
 * This file is part of the HomeFinanceV2 project.
 *
 * (c) Rafalsky.com <http://github.com/Rafalsky/>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace common\base;

use yii\base\Model;
use yii\helpers\ArrayHelper;

/**
 * @author Eugene Terentev <eugene@terentev.net>
 * @var array $models
 * Example:
 * $model = new MultiModel([
 *      'models' => [
 *          'account' => $accountModel,
 *          'profile' => $profileModel
 *      ]
 * ])
 * $model->load($_POST);
 * $model->save();
 *
 * In view:
 * $form->field($model->getModel('account'), 'username')->textInput();
 */
class MultiModel extends Model
{
    /**
     * @var string
     */
    public $db = 'db';
    /**
     * @var array
     */
    protected $models = [];

    /**
     * @param $key
     * @param Model $model
     * @return Model
     */
    public function setModel($key, Model $model)
    {
        return $this->models[$key] = $model;
    }

    /**
     * @param array $models
     */
    public function setModels(array $models)
    {
        foreach ($models as $key => $model) {
            $this->setModel($key, $model);
        }
    }

    /**
     * @param $key
     * @return Model|null
     * @throws \yii\base\InvalidParamException
     */
    public function getModel($key)
    {
        return ArrayHelper::getValue($this->models, $key, false);
    }

    /**
     * @return array
     */
    public function getModels()
    {
        return $this->models;
    }

    /**
     * @param array $data
     * @param string $formName
     * @return bool
     */
    public function load($data, $formName = '')
    {
        foreach ($this->models as $k => &$model) {
            $success = $model->load($data);
            if (!$success) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param null $attributeNames
     * @param bool $clearErrors
     * @return bool
     * @throws \yii\base\InvalidParamException
     */
    public function validate($attributeNames = null, $clearErrors = true)
    {
        $this->trigger(Model::EVENT_BEFORE_VALIDATE);
        $success = true;
        foreach ($this->models as $key => $model) {
            /* @var $model Model */
            if (!$model->validate()) {
                $success = false;
                $this->addErrors([$key => $model->getErrors()]);
            }
        }
        $this->trigger(Model::EVENT_AFTER_VALIDATE);
        return $success;
    }

    /**
     * @param bool $runValidation
     * @return bool
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\base\InvalidParamException
     * @throws \yii\db\Exception
     */
    public function save($runValidation = true)
    {
        if ($runValidation && !$this->validate()) {
            return false;
        }
        $success = true;
        $transaction = $this->getDb()->beginTransaction();
        foreach ($this->models as $model) {
            $success = $model->save(false);
            if (!$success) {
                $transaction->rollBack();
                return false;
            }
        }
        $transaction->commit();
        return $success;
    }

    /**
     * @return \yii\db\Connection
     * @throws \yii\base\InvalidConfigException
     */
    public function getDb()
    {
        return \Yii::$app->get($this->db);
    }
}