Settings::save()   A
last analyzed

Complexity

Conditions 4
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 2
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace andmemasin\myabstract;
4
5
use yii;
6
7
class Settings extends yii\base\Model
8
{
9
    /** @var Setting[] */
10
    public $settings;
11
12
    /** @var string */
13
    public $itemClass;
14
15
    /** @var string */
16
    public $typeRelationName;
17
18
    /** @var string Value field name in itemClass*/
19
    public $valueField = 'value';
20
21
    /** @var boolean whether we skip checking attribute existence */
22
    public $doCheck = true;
23
24
    /** @var string a class name implementing TypeInterface  */
25
    public $typeClass;
26
27
    /** @var string[] $alwaysSkipCheckAttributes */
28
    private static $alwaysSkipCheckAttributes = ['typeClass', 'settings', 'itemClass', 'typeRelationName', 'valueField', 'doCheck', 'skipCheckAttributes'];
29
30
31
    /** @var string[] $skipCheckAttributes extended attributed that we skip in checking */
32
    public $skipCheckAttributes = [];
33
34
    /** {@inheritdoc} */
35
    public function init()
36
    {
37
        parent::init();
38
39
        if (!$this->itemClass) {
40
            throw new yii\base\InvalidArgumentException('ItemClass must be defined');
41
        }
42
        $this->checkSettings();
43
44
        $this->setSettings();
45
        if (!is_null($this->typeClass)) {
0 ignored issues
show
introduced by
The condition is_null($this->typeClass) is always false.
Loading history...
46
           $this->loadStrings();
47
        }
48
    }
49
50
    /**
51
     * Check if all defined attributes exist in settings[] and throw an error if its missing
52
     */
53
    protected function checkSettings() {
54
        if ($this->doCheck) {
55
            $skipAttributes = array_merge($this->skipCheckAttributes, self::$alwaysSkipCheckAttributes);
56
            $checkAttributes = array_diff(array_keys($this->attributes), $skipAttributes);
57
58
            if (!empty($checkAttributes)) {
59
                foreach ($checkAttributes as $checkAttribute) {
60
                    /** @var Setting $setting */
61
                    $setting = new $this->itemClass;
62
63
                    if (! $setting->findOneByKey($checkAttribute)) {
64
                        throw new yii\base\InvalidConfigException('Key "' . $checkAttribute . '" is missing in ' . $this->itemClass);
65
                    }
66
                }
67
            }
68
        }
69
70
    }
71
72
    /** {@inheritdoc} */
73
    public function beforeValidate() {
74
        foreach ($this->attributes as $key => $value) {
75
            if ($value === "") {
76
                $this->$key = NULL;
77
            }
78
        }
79
80
        return parent::beforeValidate();
81
    }
82
83
    /** {@inheritdoc} */
84
    public function loadStrings() {
85
        if (!empty($this->settings)) {
86
            foreach ($this->settings as $key => $setting) {
87
                // only accept keys that are described in the model
88
                /** @var TypeInterface $typeClass */
89
                $typeClass = $this->typeClass;
90
                $type = $typeClass::getByKey($key);
91
                if ($type) {
92
                    $this->{$key} = $setting->{$this->valueField};
93
                }
94
            }
95
        }
96
    }
97
98
99
    /** {@inheritdoc} */
100
    public function setSettings() {
101
        // get existing settings
102
103
        /** @var Setting $settingClass */
104
        $settingClass = $this->itemClass;
105
        $query = $settingClass::find();
106
        $settings = $query->all();
107
        if (!empty($settings)) {
108
            foreach ($settings as $setting) {
109
                if (in_array($setting->{$setting->keyColumn}, array_keys($this->attributes))) {
0 ignored issues
show
Bug introduced by
Accessing keyColumn on the interface yii\db\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
110
                    $this->settings[$setting->{$setting->keyColumn}] = $setting;
111
                    $this->{$setting->{$setting->keyColumn}} = $setting->value;
0 ignored issues
show
Bug introduced by
Accessing value on the interface yii\db\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
112
                }
113
            }
114
        }
115
    }
116
117
    /** {@inheritdoc} */
118
    public function load($data, $formName = null)
119
    {
120
        parent::load($data, $formName = null);
121
        if (!empty($this->settings)) {
122
            foreach ($this->settings as $setting) {
123
                if (in_array($setting->key, array_keys($this->attributes))) {
124
                    $setting->value = $this->{$setting->key};
125
                }
126
            }
127
        }
128
    }
129
130
    /** {@inheritdoc} */
131
    public function save() {
132
        if (!empty($this->settings)) {
133
            foreach ($this->settings as $key=> $setting) {
134
                if (in_array($setting->key, array_keys($this->attributes))) {
135
                    $setting->save();
136
                    $this->settings[$key] = $setting;
137
                    $this->addErrors($setting->errors);
138
                }
139
            }
140
        }
141
        return empty($this->errors);
142
    }
143
144
}