c4d37bf0d4b164d0c6c2defae23fbd31f458248a
[WebKit.git] / Websites / perf.webkit.org / public / include / admin-header.php
1 <?php
2
3 require_once('db.php');
4 require_once('manifest-generator.php');
5
6 ?><!DOCTYPE html>
7 <html>
8 <head>
9 <title>WebKit Perf Monitor</title>
10 <link rel="stylesheet" href="/common.css">
11 <link rel="stylesheet" href="/admin/admin.css">
12 </head>
13 <body>
14 <header id="title">
15 <h1><a href="/">WebKit Perf Monitor</a></h1>
16 <ul>
17     <li><a href="/admin/platforms">Platforms</a></li>
18     <li><a href="/admin/tests">Tests</a></li>
19     <li><a href="/admin/aggregators">Aggregators</a></li>
20     <li><a href="/admin/builders">Builders</a></li>
21     <li><a href="/admin/build-slaves">Slaves</a></li>
22     <li><a href="/admin/triggerables">Triggerables</a></li>
23     <li><a href="/admin/repositories">Repositories</a></li>
24     <li><a href="/admin/bug-trackers">Bug Trackers</a></li>
25     <li><a href="/admin/files">Files</a></li>
26 </ul>
27 </header>
28
29 <div id="mainContents">
30 <?php
31
32 function notice($message) {
33     echo "<p class='notice'>$message</p>";
34 }
35
36 $db = new Database;
37 if (!$db->connect()) {
38     notice('Failed to connect to the database');
39     $db = NULL;
40 } else
41     $action = array_key_exists('action', $_POST) ? $_POST['action'] : NULL;
42
43 function execute_query_and_expect_one_row_to_be_affected($query, $params, $success_message, $failure_message) {
44     global $db;
45
46     foreach ($params as &$param) {
47         if ($param == '')
48             $param = NULL;
49     }
50
51     $affected_rows = $db->query_and_get_affected_rows($query, $params);
52     if ($affected_rows) {
53         assert('$affected_rows == 1');
54         notice($success_message);
55         return true;
56     }
57
58     notice($failure_message);
59     return false;
60 }
61
62 function update_field($table, $prefix, $field_name, $new_value = NULL) {
63     global $db;
64
65     if (!array_key_exists('id', $_POST))
66         return FALSE;
67
68     $id = intval($_POST['id']);
69     $prefixed_field_name = $prefix . '_' . $field_name;
70     $id_field_name = $prefix . '_id';
71
72     if ($new_value == NULL) {
73         if (array_get($_POST, 'updated-column') != $field_name && !array_key_exists($field_name, $_POST))
74             return FALSE;
75         $new_value = array_get($_POST, $field_name);
76     }
77
78     execute_query_and_expect_one_row_to_be_affected("UPDATE $table SET $prefixed_field_name = \$2 WHERE $id_field_name = \$1",
79         array($id, $new_value),
80         "Updated the $prefix $id",
81         "Could not update $prefix $id");
82
83     return TRUE;
84 }
85
86 function regenerate_manifest() {
87     global $db;
88
89     $generator = new ManifestGenerator($db);
90     if (!$generator->generate()) {
91         notice("Failed to generate the manifest (before trying to write into the filesystem).");
92         return FALSE;
93     }
94
95     if (!$generator->store()) {
96         notice("Failed to save the generated manifest into the filesystem");
97         return FALSE;
98     }
99
100     return TRUE;
101 }
102
103 class AdministrativePage {
104     private $table;
105     private $prefix;
106     private $column_to_be_ordered_by;
107     private $column_info;
108
109     function __construct($db, $table, $prefix, $column_info) {
110         $this->db = $db;
111         $this->table = $table;
112         $this->prefix = $prefix;
113         $this->column_info = $column_info;
114     }
115
116     private function name_to_titlecase($name) {
117         return ucwords(str_replace('_', ' ', $name));
118     }
119
120     private function column_label($name) {
121         return array_get($this->column_info[$name], 'label', $this->name_to_titlecase($name));
122     }
123
124     private function render_form_control_for_column($editing_mode, $name, $value = '', $show_update_button_if_needed = FALSE) {
125         $show_update_button = FALSE;
126         switch ($editing_mode) {
127         case 'text':
128             echo <<< END
129 <textarea name="$name" rows="7" cols="50">$value</textarea><br>
130 END;
131             $show_update_button = $show_update_button_if_needed;
132             break;
133         case 'boolean':
134             $checkedness = Database::is_true($value) ? ' checked' : '';
135             echo <<< END
136 <input type="checkbox" name="$name"$checkedness>
137 END;
138             $show_update_button = $show_update_button_if_needed;
139             break;
140         case 'url':
141             echo <<< END
142 <input type="text" name="$name" value="$value" size="70">
143 END;
144             break;
145         default:
146             assert($editing_mode == 'string');
147             echo <<< END
148 <input type="text" name="$name" value="$value">
149 END;
150         }
151
152         if ($show_update_button) {
153             echo <<< END
154
155 <button type="submit" name="action" value="update">Update</button>
156 END;
157         }
158     }
159
160     function render_table($column_to_be_ordered_by) {
161         $column_names = array_keys($this->column_info);
162         $column_to_subcolumn_names = array();
163         foreach ($column_names as $name) {
164             if (array_get($this->column_info[$name], 'pre_insertion'))
165                 continue;
166             $subcolumns = array_get($this->column_info[$name], 'subcolumns', array());
167             if (!$subcolumns || !array_get($this->column_info[$name], 'custom'))
168                 continue;
169             $column_to_subcolumn_names[$name] = $subcolumns;
170         }
171
172         $rowspan_if_needed = $column_to_subcolumn_names ? ' rowspan="2"' : '';
173
174         $headers = "<tr><td$rowspan_if_needed>ID</td>";
175         foreach ($column_names as $name) {
176             if (array_get($this->column_info[$name], 'pre_insertion'))
177                 continue;
178             $label = htmlspecialchars($this->column_label($name));
179             if (array_get($column_to_subcolumn_names, $name)) {
180                 $count = count($column_to_subcolumn_names[$name]);
181                 $headers .= "<td colspan=\"$count\">$label</td>";
182             } else
183                 $headers .= "<td$rowspan_if_needed>$label</td>";
184         }
185         $headers .= "</tr>\n";
186
187         if ($column_to_subcolumn_names) {
188             $headers .= '<tr>';
189             foreach ($column_names as $name) {
190                 $subcolumn_names = array_get($column_to_subcolumn_names, $name);
191                 if (!$subcolumn_names)
192                     continue;
193                 foreach ($subcolumn_names as $label)
194                     $headers .= '<td>' . htmlspecialchars($label) . '</td>';
195             }
196             $headers .= "</tr>\n";
197         }
198
199         echo <<< END
200 <table>
201 <thead>
202 $headers
203 </thead>
204 <tbody>
205
206 END;
207
208         assert(ctype_alnum_underscore($column_to_be_ordered_by));
209         $rows = $this->db->fetch_table($this->table, $this->prefix . '_' . $column_to_be_ordered_by);
210         if ($rows) {
211             foreach ($rows as $row) {
212                 $id = intval($row[$this->prefix . '_id']);
213
214                 $custom_cells_list = array();
215                 $maximum_rows = 1;
216                 foreach ($column_names as $name) {
217                     if (array_get($this->column_info[$name], 'pre_insertion'))
218                         continue;
219
220                     if ($custom = array_get($this->column_info[$name], 'custom')) {
221                         $custom_cells_list[$name] = $custom($row);
222                         $maximum_rows = max($maximum_rows, count($custom_cells_list[$name]));
223                     }
224                 }
225
226                 $rowspan_if_needed = $maximum_rows > 1 ? ' rowspan="' . $maximum_rows . '"' : '';
227
228                 echo "<tr>\n<td$rowspan_if_needed>$id</td>\n";
229                 foreach ($column_names as $name) {
230                     if (array_get($this->column_info[$name], 'pre_insertion'))
231                         continue;
232
233                     if (array_key_exists($name, $custom_cells_list)) {
234                         $this->render_custom_cells(array_get($column_to_subcolumn_names, $name), $custom_cells_list[$name], 0);
235                         continue;
236                     }
237
238                     $value = htmlspecialchars(array_get($row, $this->prefix . '_' . $name), ENT_QUOTES);
239                     $editing_mode = array_get($this->column_info[$name], 'editing_mode');
240                     if (!$editing_mode) {
241                         echo "<td$rowspan_if_needed>$value</td>\n";
242                         continue;
243                     }
244
245                     echo <<< END
246 <td$rowspan_if_needed>
247 <form method="POST">
248 <input type="hidden" name="id" value="$id">
249 <input type="hidden" name="action" value="update">
250 <input type="hidden" name="updated-column" value="$name">
251
252 END;
253                     $this->render_form_control_for_column($editing_mode, $name, $value, TRUE);
254                     echo "</form></td>\n";
255
256                 }
257                 echo "</tr>\n";
258
259                 for ($row = 1; $row < $maximum_rows; $row++) {
260                     echo "<tr>\n";
261                     foreach ($column_names as $name) {
262                         if (array_key_exists($name, $custom_cells_list))
263                             $this->render_custom_cells(array_get($column_to_subcolumn_names, $name), $custom_cells_list[$name], $row);
264                     }
265                     echo "</tr>\n";
266                 }
267             }
268         }
269         echo <<< END
270 </tbody>
271 </table>
272 END;
273     }
274
275     function render_custom_cells($subcolum_names, $rows, $row_index) {
276         $cells = array_get($rows, $row_index, array());
277         if (!is_array($cells))
278             $cells = array($cells);
279
280         if ($subcolum_names && count($cells) <= 1) {
281             $colspan = count($subcolum_names);
282             $content = $cells ? $cells[0] : '';
283             echo "<td colspan=\"$colspan\">$content</td>\n";
284             return;
285         }
286
287         for ($i = 0; $i < ($subcolum_names ? count($subcolum_names) : 1); $i++)
288             echo '<td>' . array_get($cells, $i, '') . '</td>';
289         echo "\n";
290     }
291
292     function render_form_to_add($title = NULL) {
293
294         if (!$title) # Can't use the table name since it needs to be singular.
295             $title = 'New ' . $this->name_to_titlecase($this->prefix);
296
297 echo <<< END
298 <section class="action-field">
299 <h2>$title</h2>
300 <form method="POST">
301
302 END;
303         foreach (array_keys($this->column_info) as $name) {
304             $editing_mode = array_get($this->column_info[$name], 'editing_mode');
305             if (array_get($this->column_info[$name], 'custom') || !$editing_mode)
306                 continue;
307             if (array_get($this->column_info[$name], 'post_insertion'))
308                 continue;
309
310             $label = htmlspecialchars($this->column_label($name));
311             echo "<label>$label<br>\n";
312             $this->render_form_control_for_column($editing_mode, $name);
313             echo "</label><br>\n";
314         }
315
316 echo <<< END
317
318 <button type="submit" name="action" value="add">Add</button>
319 </form>
320 </section>
321 END;
322
323     }
324
325 }
326
327 ?>