Completed
Push — master ( 62d9c0...305eb4 )
by Seth
06:56 queued 04:58
created

src/Snapshots/Snapshot.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace smtech\GradingAnalytics\Snapshots;
4
5
use smtech\GradingAnalytics\Snapshots\Exception\SnapshotException;
6
7
class Snapshot extends CacheableDatabase
8
{
9
    const NOT_ASSOCIATED_WITH_COURSE = 'n/a';
10
11
    /**
12
     * History of the course specified by `$courseOrDepartmentId` in constructor
13
     * @var History
14
     */
15
    protected $history;
16
17
    /**
18
     * Department ID given as `$courseOrDepartmentId` in constructor
19
     * @var [type]
20
     */
21
    protected $departmentId = false;
22
23
    /**
24
     * The domain of this snapshot
25
     * @var Domain
26
     */
27
    protected $domain;
28
29
    /**
30
     * Date timestamp of this snapshot
31
     * @var string
32
     */
33
    protected $timestamp = false;
34
35
    /**
36
     * Course statistics records that make up the snapshot
37
     * @var array
38
     */
39
    protected static $data;
40
41
    /**
42
     * Averages calculated from the data
43
     * @var array
44
     */
45
    protected $averages;
46
47
    public function __construct($databaseProvider, Domain $domain, $courseOrDepartmentId, $isCourseId = true)
48
    {
49
        parent::__construct($databaseProvider);
50
51
        $this->domain = $domain;
52
53
        if ($isCourseId) {
54
            $this->history = new History($this, $courseOrDepartmentId);
55
        } elseif (is_numeric($courseOrDepartmentId)) {
56
            $this->departmentId = $courseOrDepartmentId;
57
        }
58
    }
59
60
    public function getCourseId()
61
    {
62
        if (!empty($this->history)) {
63
            return $this->history->getCourseId();
64
        }
65
        return self::NOT_ASSOCIATED_WITH_COURSE;
66
    }
67
68
    public function getDepartmentId()
69
    {
70
        if ($this->departmentId === false) {
71
            $this->departmentId = $this->history->getDepartmentId();
72
        }
73
        return $this->departmentId;
74
    }
75
76
    public function getDomain()
77
    {
78
        return $this->domain;
79
    }
80
81
    public function getTimestamp()
82
    {
83
        if ($this->timestamp === false) {
84
            if (!empty($this->history)) {
85
                $this->timestamp = $this->history->getCurrentTimestamp();
86
            } else {
87
                if ($response = $this->sql->query("
88
                    SELECT * FROM `course_statistics`
89
                        WHERE
90
                            `course[account_id]` = '" . $this->getDepartmentId() . "'
91
                        ORDER BY
92
                            `timestamp` DESC
93
                        LIMIT 1
94
                ")) {
95
                    if ($row = $response->fetch_assoc()) {
96
                        $this->timestamp = substr($row['timestamp'], 0, 10);
97
                    }
98
                }
99
            }
100
        }
101
        return $this->timestamp;
102
    }
103
104
    public function getAverage(Average $average)
105
    {
106
        if ($this->cacheSnapshot()) {
107
            return $this->averages[$average];
108
        }
109
        return false;
110
    }
111
    public function getSnapshot($teacherFilter = false)
112
    {
113
        if ($this->domain == Domain::COURSE()) {
114
            $snapshot = $this->history->getHistory();
115
            if (is_array($snapshot) && count($snapshot) > 0) {
116
                return $snapshot[0];
117
            }
118
        } elseif ($this->cacheSnapshot()) {
119
            if ($teacherFilter) {
120
                return array_filter(
121
                    static::$data[$this->getCourseId()][$this->getDomain()][$this->getTimestamp()],
122
                    function ($elt) {
123
                        return array_search(
124
                            $teacherFilter,
125
                            unserialize($elt['teacher[id]s'])
126
                        ) !== false;
127
                    }
128
                );
129
            }
130
            return static::$data[$this->getCourseId()][$this->getDomain()][$this->getTimestamp()];
131
        }
132
        return false;
133
    }
134
135
    /*
136
     * need to cache snapshots per timestamp, since different courses
137
     * may have different most recent records that require comparison
138
     * to different snapshots (e.g. a course ending June 1 should be
139
     * compared to June 1 snapshots, but a course ending January 20
140
     * should be compared to January 20 snapshots)
141
     */
142
    public function cacheSnapshot()
143
    {
144
        $domain = $this->getDomain();
145
        if ($domain == Domain::Course()) {
146
            return $this->history->cacheHistory();
147
        } else {
148
            $courseId = $this->getCourseId();
149
            $timestamp = $this->getTimestamp();
150
            if (empty(static::$data[$courseId][$domain][$timestamp])) {
151
                $cache->pushKey(($domain == Domain::DEPARTMENT() ? $this->getDepartmentId() : 'school'));
152
                static::$data[$courseId][$domain][$timestamp] = $cache->getCache($timestamp);
153
                $this->averages = $cache->getCache("$timestamp-averages");
154
                if (empty(static::$data[$courseId][$domain][$timestamp])) {
155
                    if ($response = $this->mysql_query("
156
                        SELECT * FROM `course_statistics`
157
                            WHERE
158
                                " . ($domain == Domain::DEPARTMENT() ?
159
                                        "`course[account_id]` = '" . $this->getDepartmentId() . "' AND" :
160
                                        ''
161
                                    ) . "
162
                                `timestamp` LIKE '$timestamp%'
163
                            GROUP BY
164
                                `course[id]`
165
                            ORDER BY
166
                                `timestamp` DESC
167
                    ")) {
168
                        $total = [
169
                            self::AVERAGE_TURN_AROUND => 0,
170
                            self::AVERAGE_ASSIGNMENT_COUNT => 0
171
                        ];
172
                        $divisor = [
173
                            self::AVERAGE_TURN_AROUND => 0,
174
                            self::AVERAGE_ASSIGNMENT_COUNT => $response->num_rows
175
                        ];
176
177
                        while ($row = $response->fetch_assoc()) {
178
                            static::$data[$courseId][$domain][$timestamp][] = $row;
179
180
                            $total[self::AVERAGE_TURN_AROUND] +=
181
                                $row['average_grading_turn_around'] *
182
                                $row['student_count'] *
183
                                $row['graded_assignment_count'];
184
                            $divisor[self::AVERAGE_TURN_AROUND] +=
185
                                $row['student_count'] *
186
                                $row['graded_assignment_count'];
187
188
                            $total[self::AVERAGE_ASSIGNMENT_COUNT] +=
189
                                $row['assignments_due_count'] +
190
                                $row['dateless_assignment_count'];
191
                        }
192
193
                        for ($i = 0; $i < count($total); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
194
                            $this->averages[$i] = $total[$i] / $divisor[$i];
195
                        }
196
197
                        $cache->setCache($timestamp, static::$data[$courseId][$domain][$timestamp]);
198
                        $cache->setCache("$timestamp-averages", $this->averages);
199
                    }
200
                }
201
            }
202
            return is_array(static::$data) &&
203
                is_array(static::$data[$courseId]) &&
204
                is_array(static::$data[$courseId][$domain]) &&
205
                is_array(static::$data[$courseId][$domain][$timestamp]) &&
206
                count(static::$data[$courseId][$domain][$timestamp]) > 0;
207
        }
208
    }
209
}
210