AccountDataProvider::findStatsIds()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 19
c 1
b 0
f 0
nc 8
nop 3
dl 0
loc 26
rs 9.3222
1
<?php
2
/**
3
 * Created for IG Monitoring.
4
 * User: jakim <[email protected]>
5
 * Date: 2019-01-24
6
 */
7
8
namespace app\components\stats\providers;
9
10
11
use app\components\stats\contracts\DataProviderInterface;
12
use app\components\stats\traits\FromToDateTrait;
13
use app\components\stats\traits\StatsAttributesTrait;
14
use app\components\traits\SetAccountTrait;
15
use app\dictionaries\Grouping;
16
use app\models\AccountStats;
17
use Carbon\Carbon;
18
use yii\data\BaseDataProvider;
19
use yii\db\Expression;
20
use yii\helpers\ArrayHelper;
21
22
/**
23
 * Class AccountDataProvider
24
 *
25
 * @package app\components\stats\providers
26
 *
27
 * @property \Carbon\Carbon $from
28
 * @property \Carbon\Carbon $to
29
 */
30
class AccountDataProvider extends BaseDataProvider implements DataProviderInterface
31
{
32
    use FromToDateTrait, SetAccountTrait, StatsAttributesTrait;
33
34
    public $grouping = Grouping::DAILY;
35
36
    public function init()
37
    {
38
        parent::init();
39
        $this->throwExceptionIfFromToAreNotSet();
40
        $this->throwExceptionIfAccountIsNotSet();
41
        $this->throwExceptionIfStatsAttributesIsNotSet();
42
    }
43
44
    /**
45
     * Prepares the data models that will be made available in the current page.
46
     *
47
     * @return array the available data models
48
     */
49
    protected function prepareModels()
50
    {
51
        $models = [];
52
53
        $dbFrom = $this->from->copy()->endOfDay();
54
        $dbFrom = $this->findDbDate($dbFrom);
55
56
        $dbTo = $this->to->copy()->endOfDay()->toDateTimeString();
57
58
        $idsQuery = $this->findStatsIds($dbFrom, $dbTo, false);
0 ignored issues
show
Bug introduced by
It seems like $dbFrom can also be of type false; however, parameter $dbFrom of app\components\stats\pro...rovider::findStatsIds() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

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

58
        $idsQuery = $this->findStatsIds(/** @scrutinizer ignore-type */ $dbFrom, $dbTo, false);
Loading history...
59
        $data = $this->findDataModels($idsQuery);
60
61
        foreach ($data as $stats) {
62
            foreach ($this->statsAttributes as $statsAttribute) {
63
                $value = ArrayHelper::getValue($stats, $statsAttribute, 0);
64
                $models[$stats['created_at']][$statsAttribute] = $value;
65
            }
66
        }
67
68
        return $models;
69
    }
70
71
    /**
72
     * Prepares the keys associated with the currently available data models.
73
     *
74
     * @param array $models the available data models
75
     * @return array the keys
76
     */
77
    protected function prepareKeys($models)
78
    {
79
        return array_keys($models);
80
    }
81
82
    /**
83
     * Returns a value indicating the total number of data models in this data provider.
84
     *
85
     * @return int total number of data models in this data provider.
86
     */
87
    protected function prepareTotalCount()
88
    {
89
        return count($this->models);
90
    }
91
92
    protected function findDbDate(Carbon $date)
93
    {
94
        return AccountStats::find()
95
            ->select('created_at')
96
            ->andWhere(['account_id' => $this->account->id])
97
            ->andWhere(['<=', 'created_at', $date->toDateTimeString()])
98
            ->orderBy('created_at DESC')
99
            ->limit(1)
100
            ->scalar();
101
    }
102
103
    protected function findStatsIds(?string $dbFrom, ?string $dbTo, bool $asQuery = false)
104
    {
105
        switch ($this->grouping) {
106
            case Grouping::MONTHLY:
107
                $groupBy = new Expression('DATE_FORMAT(created_at, \'%Y-%m\')');
108
                break;
109
            case Grouping::WEEKLY:
110
                $groupBy = new Expression('DATE_FORMAT(created_at, \'%Y-%u\')');
111
                break;
112
            case Grouping::DAILY:
113
            default:
114
                $groupBy = new Expression('DATE(created_at)');
115
        }
116
117
        $q = AccountStats::find()
118
            ->select(new Expression('MAX(id) as id'))
119
            ->andWhere(['account_id' => $this->account->id])
120
            ->andFilterWhere(['>=', 'created_at', $dbFrom])
121
            ->andWhere(['<=', 'created_at', $dbTo])
122
            ->groupBy($groupBy);
123
124
        if ($asQuery) {
125
            return $q;
126
        }
127
128
        return $q->column();
129
    }
130
131
    /**
132
     * @param $ids
133
     * @return \app\models\AccountStats[]|array|\yii\db\ActiveRecord[]
134
     */
135
    protected function findDataModels($ids)
136
    {
137
        $columns = array_map(function ($attr) {
138
            return "account_stats.{$attr}";
139
        }, $this->statsAttributes);
140
        $columns[] = new Expression('DATE(created_at) as created_at');
141
142
        return AccountStats::find()
143
            ->select($columns)
144
            ->andWhere(['account_id' => $this->account->id])
145
            ->andWhere(['id' => $ids])
146
            ->orderBy('id ASC')
147
            ->asArray()
148
            ->all();
149
    }
150
}