QuestionForm::getPrefixProps()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
c 0
b 0
f 0
rs 10
cc 3
nc 1
nop 1
1
<?php
2
namespace site\models;
3
4
use Yii;
5
use yii\base\Model;
6
use yii\db\Expression;
7
use \common\interfaces\UserInterface;
8
use \common\interfaces\QuestionInterface;
9
10
/**
11
 * Question form
12
 */
13
class QuestionForm extends Model
14
{
15
  public $user_behavior_id1;
16
  public $user_behavior_id2;
17
  public $user_behavior_id3;
18
  public $user_behavior_id4;
19
  public $user_behavior_id5;
20
  public $user_behavior_id6;
21
  public $user_behavior_id7;
22
23
  public $answer_1a;
24
  public $answer_1b;
25
  public $answer_1c;
26
27
  public $answer_2a;
28
  public $answer_2b;
29
  public $answer_2c;
30
31
  public $answer_3a;
32
  public $answer_3b;
33
  public $answer_3c;
34
35
  public $answer_4a;
36
  public $answer_4b;
37
  public $answer_4c;
38
39
  public $answer_5a;
40
  public $answer_5b;
41
  public $answer_5c;
42
43
  public $answer_6a;
44
  public $answer_6b;
45
  public $answer_6c;
46
47
  public $answer_7a;
48
  public $answer_7b;
49
  public $answer_7c;
50
51
  private $question;
52
53
  public function __construct(QuestionInterface $question,
54
                              $config = []) {
55
    $this->question    = $question;
56
    parent::__construct($config);
57
  }
58
59
  /**
60
   * @inheritdoc
61
   */
62
  public function rules()
63
  {
64
    return [
65
      [['user_behavior_id1', 'user_behavior_id2', 'user_behavior_id3', 'user_behavior_id4', 'user_behavior_id5', 'user_behavior_id6', 'user_behavior_id7'], 'integer'],
66
67
      [['user_behavior_id1', 'user_behavior_id2', 'user_behavior_id3', 'user_behavior_id4', 'user_behavior_id5', 'user_behavior_id6', 'user_behavior_id7'],
68
        'required',
69
        'when' => $this->getBhvrValidator(),
70
        'whenClient' => "function(attribute, value) { return false; }", // lame, but acceptable
71
        "message" => "You must select a behavior your responses apply to."],
72
73
      [['answer_1a','answer_1b','answer_1c','answer_2a','answer_2b','answer_2c','answer_3a','answer_3b','answer_3c','answer_4a','answer_4b','answer_4c','answer_5a', 'answer_5b','answer_5c','answer_6a', 'answer_6b','answer_6c','answer_7a','answer_7b','answer_7c'], 'safe']
74
    ];
75
  }
76
77
  public function attributeLabels() {
78
    return [
79
      'user_behavior_id1' => 'Restoration',
80
      'user_behavior_id2' => 'Forgetting Priorities',
81
      'user_behavior_id3' => 'Anxiety',
82
      'user_behavior_id4' => 'Speeding Up',
83
      'user_behavior_id5' => 'Ticked Off',
84
      'user_behavior_id6' => 'Exhausted',
85
      'user_behavior_id7' => 'Relapsed/Moral Failure'
86
    ];
87
  }
88
89
  public function getBhvrValidator() {
90
    return function($model, $attr) {
91
      $attrNum = $attr[strlen($attr)-1];
92
      foreach(['a', 'b', 'c'] as $l) {
93
        $attr = "answer_{$attrNum}{$l}";
94
        if($model->$attr) return true;
95
      }
96
      return false;
97
    };
98
  }
99
100
  public function deleteToday($user_id) {
101
    $time = Yii::$container->get(\common\interfaces\TimeInterface::class);
102
    $date = $time->getLocalDate();
103
    list($start, $end) = $time->getUTCBookends($date);
104
    $this->question->deleteAll("user_id=:user_id 
0 ignored issues
show
Bug introduced by
'user_id=:user_id ... AND date < :end_date' of type string is incompatible with the type array expected by parameter $condition of yii\db\ActiveRecordInterface::deleteAll(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
    $this->question->deleteAll(/** @scrutinizer ignore-type */ "user_id=:user_id 
Loading history...
105
      AND date > :start_date 
106
      AND date < :end_date", 
107
      [
0 ignored issues
show
Unused Code introduced by
The call to yii\db\ActiveRecordInterface::deleteAll() has too many arguments starting with array(':user_id' => $use...t, ':end_date' => $end). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
    $this->question->/** @scrutinizer ignore-call */ 
108
                     deleteAll("user_id=:user_id 

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
108
        ":user_id" => $user_id,
109
        ':start_date' => $start, 
110
        ":end_date" => $end
111
      ]
112
    );
113
  }
114
115
  public function behaviorToAnswers($bhvr_number) {
116
    $prop_names   = array_keys($this->getPrefixProps("answer_$bhvr_number"));
117
    $prop_letters = array_map(function($n) { return substr($n, -1, 1); }, $prop_names);
118
    $answers = array_map(function($n) { return $this->$n; }, $prop_names);
119
 
120
    return array_combine($prop_letters, $answers);
121
  }
122
123
  public function getPrefixProps($prefix) {
124
    return array_filter(get_object_vars($this), function($v, $k) use($prefix) {
125
      if(strpos($k, $prefix) === 0 && strlen($v)) {
126
        return true;
127
      }
128
    }, ARRAY_FILTER_USE_BOTH);
129
  }
130
131
  public function getUserBehaviorProps() {
132
    return array_keys($this->getPrefixProps('user_behavior_id'));
133
  }
134
135
  public function getUserBehaviorIds() {
136
    // for security reasons, make double-sure we're giving back an array of integers
137
    return array_map('intval', array_values($this->getPrefixProps('user_behavior_id')));
138
  }
139
140
  public function getAnswers($bhvrs) {
141
    $answers = [];
142
    $user_bhvrs = array_combine($this->getUserBehaviorProps(), $bhvrs);
143
    foreach($user_bhvrs as $property => $user_bhvr) {
144
      $behavior_id = intval(substr($property, -1, 1));
145
      foreach($this->behaviorToAnswers($behavior_id) as $answer_letter => $answer) {
146
        $question_id = \common\models\Question::$TYPES[$answer_letter];
147
        array_push($answers, [
148
                               'behavior_id'    => $user_bhvr->behavior_id,
149
                               'category_id'    => $user_bhvr->category_id,
150
                               'user_bhvr_id' => $user_bhvr->id,
151
                               'question_id'  => $question_id,
152
                               'answer'       => $answer,
153
                             ]);
154
      }
155
    }
156
    return $answers;
157
  }
158
159
  public function saveAnswers(int $user_id, array $bhvrs) {
160
    $result = true;
161
162
    foreach($this->getAnswers($bhvrs) as $answer) {
163
      $model = Yii::$container->get(\common\interfaces\QuestionInterface::class);
164
      $model->user_id = $user_id;
165
      $model->behavior_id = $answer['behavior_id'];
166
      $model->category_id = $answer['category_id'];
167
      $model->user_behavior_id = $answer['user_bhvr_id'];
168
      $model->date = new Expression("now()::timestamp");
169
      $model->question = $answer['question_id'];
170
      $model->answer = $answer['answer'];
171
      if(!$model->save()) {
172
        $result = false;
173
      }
174
    }
175
    return $result;
176
  }
177
}
178