1441 |
ariadna |
1 |
<?php
|
|
|
2 |
// This file is part of Moodle - http://moodle.org/
|
|
|
3 |
//
|
|
|
4 |
// Moodle is free software: you can redistribute it and/or modify
|
|
|
5 |
// it under the terms of the GNU General Public License as published by
|
|
|
6 |
// the Free Software Foundation, either version 3 of the License, or
|
|
|
7 |
// (at your option) any later version.
|
|
|
8 |
//
|
|
|
9 |
// Moodle is distributed in the hope that it will be useful,
|
|
|
10 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
11 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
12 |
// GNU General Public License for more details.
|
|
|
13 |
//
|
|
|
14 |
// You should have received a copy of the GNU General Public License
|
|
|
15 |
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
16 |
|
|
|
17 |
namespace core_table;
|
|
|
18 |
|
|
|
19 |
use flexible_table;
|
|
|
20 |
use moodle_recordset;
|
|
|
21 |
use stdClass;
|
|
|
22 |
|
|
|
23 |
defined('MOODLE_INTERNAL') || die();
|
|
|
24 |
|
|
|
25 |
global $CFG;
|
|
|
26 |
|
|
|
27 |
require_once("{$CFG->libdir}/tablelib.php");
|
|
|
28 |
|
|
|
29 |
/**
|
|
|
30 |
* A table whose data is provided by SQL queries.
|
|
|
31 |
*
|
|
|
32 |
* @package core_table
|
|
|
33 |
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
|
|
34 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
35 |
*/
|
|
|
36 |
class sql_table extends flexible_table {
|
|
|
37 |
/** @var string The SQL query to count records */
|
|
|
38 |
public $countsql = null;
|
|
|
39 |
|
|
|
40 |
/** @var array The parameters for the Count SQL */
|
|
|
41 |
public $countparams = null;
|
|
|
42 |
|
|
|
43 |
/** @var object sql for querying db. Has fields 'fields', 'from', 'where', 'params' */
|
|
|
44 |
public $sql = null;
|
|
|
45 |
|
|
|
46 |
/** @var array|\Traversable Data fetched from the db */
|
|
|
47 |
public $rawdata = null;
|
|
|
48 |
|
|
|
49 |
/** @var bool Overriding default for this */
|
|
|
50 |
|
|
|
51 |
public $is_sortable = true; // phpcs:ignore moodle.NamingConventions.ValidVariableName.MemberNameUnderscore
|
|
|
52 |
|
|
|
53 |
/** @var bool Overriding default for this */
|
|
|
54 |
public $is_collapsible = true; // phpcs:ignore moodle.NamingConventions.ValidVariableName.MemberNameUnderscore
|
|
|
55 |
|
|
|
56 |
/**
|
|
|
57 |
* Create a new instance of the sql_table.
|
|
|
58 |
*
|
|
|
59 |
* @param string $uniqueid a string identifying this table.Used as a key in
|
|
|
60 |
* session vars.
|
|
|
61 |
*/
|
|
|
62 |
public function __construct($uniqueid) {
|
|
|
63 |
parent::__construct($uniqueid);
|
|
|
64 |
// Set some sensible defaults.
|
|
|
65 |
$this->set_attribute('class', 'generaltable generalbox');
|
|
|
66 |
}
|
|
|
67 |
|
|
|
68 |
/**
|
|
|
69 |
* Build the table from the fetched data.
|
|
|
70 |
*
|
|
|
71 |
* Take the data returned from the db_query and go through all the rows
|
|
|
72 |
* processing each col using either col_{columnname} method or other_cols
|
|
|
73 |
* method or if other_cols returns NULL then put the data straight into the
|
|
|
74 |
* table.
|
|
|
75 |
*
|
|
|
76 |
* After calling this function, don't forget to call close_recordset.
|
|
|
77 |
*/
|
|
|
78 |
public function build_table() {
|
|
|
79 |
if (!$this->rawdata) {
|
|
|
80 |
return;
|
|
|
81 |
}
|
|
|
82 |
|
|
|
83 |
foreach ($this->rawdata as $row) {
|
|
|
84 |
$formattedrow = $this->format_row($row);
|
|
|
85 |
$this->add_data_keyed($formattedrow, $this->get_row_class($row));
|
|
|
86 |
}
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
/**
|
|
|
90 |
* Closes recordset (for use after building the table).
|
|
|
91 |
*/
|
|
|
92 |
public function close_recordset() {
|
|
|
93 |
if (
|
|
|
94 |
$this->rawdata && ($this->rawdata instanceof \core\dml\recordset_walk ||
|
|
|
95 |
$this->rawdata instanceof moodle_recordset)
|
|
|
96 |
) {
|
|
|
97 |
$this->rawdata->close();
|
|
|
98 |
$this->rawdata = null;
|
|
|
99 |
}
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
/**
|
|
|
103 |
* Get any extra classes names to add to this row in the HTML.
|
|
|
104 |
*
|
|
|
105 |
* @param array $row the data for this row.
|
|
|
106 |
* @return string added to the class="" attribute of the tr.
|
|
|
107 |
*/
|
|
|
108 |
public function get_row_class($row) {
|
|
|
109 |
return '';
|
|
|
110 |
}
|
|
|
111 |
|
|
|
112 |
/**
|
|
|
113 |
* Set the SQL used to count records.
|
|
|
114 |
*
|
|
|
115 |
* This is only needed if you want to use different sql to count rows.
|
|
|
116 |
* Used for example when perhaps all db JOINS are not needed when counting
|
|
|
117 |
* records. You don't need to call this function the count_sql
|
|
|
118 |
* will be generated automatically.
|
|
|
119 |
*
|
|
|
120 |
* We need to count rows returned by the db seperately to the query itself
|
|
|
121 |
* as we need to know how many pages of data we have to display.
|
|
|
122 |
*
|
|
|
123 |
* @param string $sql
|
|
|
124 |
* @param null|array $params
|
|
|
125 |
*/
|
|
|
126 |
public function set_count_sql($sql, ?array $params = null) {
|
|
|
127 |
$this->countsql = $sql;
|
|
|
128 |
$this->countparams = $params;
|
|
|
129 |
}
|
|
|
130 |
|
|
|
131 |
/**
|
|
|
132 |
* Set the sql to query the db. Query will be :
|
|
|
133 |
* SELECT $fields FROM $from WHERE $where
|
|
|
134 |
* Of course you can use sub-queries, JOINS etc. by putting them in the
|
|
|
135 |
* appropriate clause of the query.
|
|
|
136 |
*
|
|
|
137 |
* @param string $fields
|
|
|
138 |
* @param string $from
|
|
|
139 |
* @param string $where
|
|
|
140 |
* @param array $params
|
|
|
141 |
*/
|
|
|
142 |
public function set_sql($fields, $from, $where, array $params = []) {
|
|
|
143 |
$this->sql = new stdClass();
|
|
|
144 |
$this->sql->fields = $fields;
|
|
|
145 |
$this->sql->from = $from;
|
|
|
146 |
$this->sql->where = $where;
|
|
|
147 |
$this->sql->params = $params;
|
|
|
148 |
}
|
|
|
149 |
|
|
|
150 |
/**
|
|
|
151 |
* Query the db. Store results in the table object for use by build_table.
|
|
|
152 |
*
|
|
|
153 |
* @param int $pagesize size of page for paginated displayed table.
|
|
|
154 |
* @param bool $useinitialsbar do you want to use the initials bar. Bar
|
|
|
155 |
* will only be used if there is a fullname column defined for the table.
|
|
|
156 |
*/
|
|
|
157 |
public function query_db($pagesize, $useinitialsbar = true) {
|
|
|
158 |
global $DB;
|
|
|
159 |
if (!$this->is_downloading()) {
|
|
|
160 |
if ($this->countsql === null) {
|
|
|
161 |
$this->countsql = 'SELECT COUNT(1) FROM ' . $this->sql->from . ' WHERE ' . $this->sql->where;
|
|
|
162 |
$this->countparams = $this->sql->params;
|
|
|
163 |
}
|
|
|
164 |
$grandtotal = $DB->count_records_sql($this->countsql, $this->countparams);
|
|
|
165 |
if ($useinitialsbar && !$this->is_downloading()) {
|
|
|
166 |
$this->initialbars(true);
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
[$wsql, $wparams] = $this->get_sql_where();
|
|
|
170 |
if ($wsql) {
|
|
|
171 |
$this->countsql .= ' AND ' . $wsql;
|
|
|
172 |
$this->countparams = array_merge($this->countparams, $wparams);
|
|
|
173 |
|
|
|
174 |
$this->sql->where .= ' AND ' . $wsql;
|
|
|
175 |
$this->sql->params = array_merge($this->sql->params, $wparams);
|
|
|
176 |
|
|
|
177 |
$total = $DB->count_records_sql($this->countsql, $this->countparams);
|
|
|
178 |
} else {
|
|
|
179 |
$total = $grandtotal;
|
|
|
180 |
}
|
|
|
181 |
|
|
|
182 |
$this->pagesize($pagesize, $total);
|
|
|
183 |
}
|
|
|
184 |
|
|
|
185 |
// Fetch the attempts.
|
|
|
186 |
$sort = $this->get_sql_sort();
|
|
|
187 |
if ($sort) {
|
|
|
188 |
$sort = "ORDER BY $sort";
|
|
|
189 |
}
|
|
|
190 |
$sql = "SELECT
|
|
|
191 |
{$this->sql->fields}
|
|
|
192 |
FROM {$this->sql->from}
|
|
|
193 |
WHERE {$this->sql->where}
|
|
|
194 |
{$sort}";
|
|
|
195 |
|
|
|
196 |
if (!$this->is_downloading()) {
|
|
|
197 |
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
|
|
|
198 |
} else {
|
|
|
199 |
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params);
|
|
|
200 |
}
|
|
|
201 |
}
|
|
|
202 |
|
|
|
203 |
/**
|
|
|
204 |
* Convenience method to call a number of methods for you to display the
|
|
|
205 |
* table.
|
|
|
206 |
*
|
|
|
207 |
* @param int $pagesize
|
|
|
208 |
* @param bool $useinitialsbar
|
|
|
209 |
* @param string $downloadhelpbutton
|
|
|
210 |
*/
|
|
|
211 |
public function out($pagesize, $useinitialsbar, $downloadhelpbutton = '') {
|
|
|
212 |
global $DB;
|
|
|
213 |
if (!$this->columns) {
|
|
|
214 |
$onerow = $DB->get_record_sql(
|
|
|
215 |
"SELECT {$this->sql->fields} FROM {$this->sql->from} WHERE {$this->sql->where}",
|
|
|
216 |
$this->sql->params,
|
|
|
217 |
IGNORE_MULTIPLE
|
|
|
218 |
);
|
|
|
219 |
// If columns is not set then define columns as the keys of the rows returned
|
|
|
220 |
// from the db.
|
|
|
221 |
$this->define_columns(array_keys((array)$onerow));
|
|
|
222 |
$this->define_headers(array_keys((array)$onerow));
|
|
|
223 |
}
|
|
|
224 |
$this->pagesize = $pagesize;
|
|
|
225 |
$this->setup();
|
|
|
226 |
$this->query_db($pagesize, $useinitialsbar);
|
|
|
227 |
$this->build_table();
|
|
|
228 |
$this->close_recordset();
|
|
|
229 |
$this->finish_output();
|
|
|
230 |
}
|
|
|
231 |
}
|
|
|
232 |
|
|
|
233 |
// Alias this class to the old name.
|
|
|
234 |
// This file will be autoloaded by the legacyclasses autoload system.
|
|
|
235 |
// In future all uses of this class will be corrected and the legacy references will be removed.
|
|
|
236 |
class_alias(sql_table::class, \table_sql::class);
|