xref: /web-bugs/src/Repository/BugRepository.php (revision 49be135f)
1<?php
2
3namespace App\Repository;
4
5/**
6 * Repository class for fetching data from the database table bugdb.
7 */
8class BugRepository
9{
10    /**
11     * Database handler.
12     * @var \PDO
13     */
14    private $dbh;
15
16    /**
17     * Days when bugs with no feedback get closed.
18     */
19    private const FEEDBACK_PERIOD = 7;
20
21    /**
22     * Class constructor.
23     */
24    public function __construct(\PDO $dbh)
25    {
26        $this->dbh = $dbh;
27    }
28
29    /**
30     * Fetch bug data by bug id.
31     */
32    public function findOneById(int $id): array
33    {
34        $sql = 'SELECT b.id, b.package_name, b.bug_type, b.email, b.reporter_name,
35                    b.sdesc, b.ldesc, b.php_version, b.php_os,
36                    b.status, b.ts1, b.ts2, b.assign, b.block_user_comment,
37                    b.private, b.cve_id,
38                    UNIX_TIMESTAMP(b.ts1) AS submitted,
39                    UNIX_TIMESTAMP(b.ts2) AS modified,
40                    COUNT(bug=b.id) AS votes,
41                    IFNULL((SELECT z.project FROM bugdb_pseudo_packages z WHERE z.name = b.package_name LIMIT 1), "php") project,
42                    SUM(reproduced) AS reproduced, SUM(tried) AS tried,
43                    SUM(sameos) AS sameos, SUM(samever) AS samever,
44                    AVG(score)+3 AS average, STD(score) AS deviation
45                FROM bugdb b
46                LEFT JOIN bugdb_votes ON b.id = bug
47                WHERE b.id = ?
48                GROUP BY b.id
49        ';
50
51        $statement = $this->dbh->prepare($sql);
52        $statement->execute([$id]);
53
54        $result = $statement->fetch();
55
56        return $result === false ? [] : $result;
57    }
58
59    /**
60     * Find random bug to resolve for a contributor.
61     */
62    public function findRandom(): array
63    {
64        $sql = "SELECT id
65                FROM bugdb
66                WHERE status NOT IN('Closed', 'Not a bug', 'Duplicate', 'Spam', 'Wont fix', 'No Feedback', 'Suspended')
67                    AND private = 'N'
68                ORDER BY RAND() LIMIT 1
69        ";
70
71        $statement = $this->dbh->prepare($sql);
72        $statement->execute();
73
74        return $statement->fetch(\PDO::FETCH_NUM);
75    }
76
77    /**
78     * Find all bugs that have someone assigned to them.
79     */
80    public function findAllAssigned(): array
81    {
82        $sql = "SELECT id, package_name, bug_type, sdesc, status, assign, UNIX_TIMESTAMP(ts1) AS ts_opened, UNIX_TIMESTAMP(ts2) AS ts_changed
83                FROM `bugdb`
84                WHERE length(assign) > 1
85                    AND status IN ('Assigned', 'Open', 'Re-Opened', 'Feedback', 'Analyzed', 'Verified', 'Critical', 'Suspended')
86                ORDER BY id
87        ";
88
89        $statement = $this->dbh->query($sql);
90
91        $data = [];
92
93        // Populate data with assign field as array key
94        while ($row = $statement->fetch()) {
95            $data[$row['assign']][] = $row;
96        }
97
98        return $data;
99    }
100
101    /**
102     * Find all bugs without feedback by given period time.
103     */
104    public function findAllWithoutFeedback(int $feedbackPeriod = self::FEEDBACK_PERIOD): array
105    {
106        $sql = "SELECT id, package_name, bug_type, email, passwd, sdesc, ldesc,
107                    php_version, php_os, status, ts1, ts2, assign,
108                    UNIX_TIMESTAMP(ts1) AS submitted, private, reporter_name,
109                    UNIX_TIMESTAMP(ts2) AS modified
110                FROM bugdb
111                WHERE status = 'Feedback' AND ts2 < DATE_SUB(NOW(), INTERVAL ? DAY)
112        ";
113
114        $statement = $this->dbh->prepare($sql);
115        $statement->execute([$feedbackPeriod]);
116
117        return $statement->fetchAll();
118    }
119
120    /**
121     * Find all bugs by given bug type.
122     */
123    public function findAllByBugType(string $type = 'All'): array
124    {
125        $sql = 'SELECT b.package_name, b.status, COUNT(*) AS quant FROM bugdb AS b';
126
127        $arguments = [];
128
129        if ($type !== 'All') {
130            $sql .= ' WHERE bug_type = ? ';
131            $arguments[] = $type;
132        }
133
134        $sql .= ' GROUP BY b.package_name, b.status ORDER BY b.package_name, b.status';
135
136        $statement = $this->dbh->prepare($sql);
137        $statement->execute($arguments);
138
139        return $statement->fetchAll();
140    }
141
142    /**
143     * Find bugs for grouping into PHP versions by given bug type.
144     */
145    public function findPhpVersions(string $type = 'All'): array
146    {
147        $sql = "SELECT DATE_FORMAT(ts1, '%Y-%m') as d,
148                    IF(b.php_version LIKE '%Git%', LEFT(b.php_version, LOCATE('Git', b.php_version)+2), b.php_version) AS formatted_version,
149                    COUNT(*) AS quant
150                FROM bugdb AS b
151                WHERE ts1 >= CONCAT(YEAR(NOW())-1, '-', MONTH(NOW()), '-01 00:00:00')
152        ";
153
154        $arguments = [];
155
156        if ($type !== 'All') {
157            $sql .= ' AND bug_type = ? ';
158            $arguments[] = $type;
159        }
160
161        $sql .= ' GROUP BY d, formatted_version ORDER BY d, quant';
162
163        $statement = $this->dbh->prepare($sql);
164        $statement->execute($arguments);
165
166        return $statement->fetchAll();
167    }
168
169    /**
170     * Check if bug with given id exists.
171     */
172    public function exists(int $id): bool
173    {
174        $statement = $this->dbh->prepare('SELECT 1 FROM bugdb WHERE id = ?');
175        $statement->execute([$id]);
176
177        return (bool)$statement->fetchColumn();
178    }
179}
180