Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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_cache\output;
18
 
19
use context;
1441 ariadna 20
use core_cache\factory as cache_factory;
21
use core_cache\store as cache_store;
1 efrain 22
use core_collator;
23
use html_table;
24
use html_table_cell;
25
use html_table_row;
26
use html_writer;
27
use lang_string;
28
use moodle_url;
29
use single_select;
30
 
31
/**
32
 * The cache renderer (mainly admin interfaces).
33
 *
34
 * @package    core_cache
35
 * @copyright  2012 Sam Hemelryk
36
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
38
class renderer extends \plugin_renderer_base {
39
    /**
40
     * Displays store summaries.
41
     *
42
     * @param array $storeinstancesummaries information about each store instance,
43
     *      as returned by core_cache\administration_helper::get_store_instance_summaries().
44
     * @param array $storepluginsummaries information about each store plugin as
45
     *      returned by core_cache\administration_helper::get_store_plugin_summaries().
46
     * @return string HTML
47
     */
48
    public function store_instance_summariers(array $storeinstancesummaries, array $storepluginsummaries) {
49
        $table = new html_table();
1441 ariadna 50
        $table->head = [
1 efrain 51
            get_string('storename', 'cache'),
52
            get_string('plugin', 'cache'),
53
            get_string('storeready', 'cache'),
54
            get_string('mappings', 'cache'),
55
            get_string('modes', 'cache'),
56
            get_string('supports', 'cache'),
57
            get_string('locking', 'cache') . ' ' . $this->output->help_icon('locking', 'cache'),
58
            get_string('actions', 'cache'),
1441 ariadna 59
        ];
60
        $table->colclasses = [
1 efrain 61
            'storename',
62
            'plugin',
63
            'storeready',
64
            'mappings',
65
            'modes',
66
            'supports',
67
            'locking',
1441 ariadna 68
            'actions',
69
        ];
70
        $table->data = [];
1 efrain 71
 
72
        $defaultstoreactions = get_string('defaultstoreactions', 'cache');
73
 
74
        foreach ($storeinstancesummaries as $name => $storesummary) {
75
            $htmlactions = cache_factory::get_administration_display_helper()->get_store_instance_actions($name, $storesummary);
1441 ariadna 76
            $modes = [];
1 efrain 77
            foreach ($storesummary['modes'] as $mode => $enabled) {
78
                if ($enabled) {
1441 ariadna 79
                    $modes[] = get_string('mode_' . $mode, 'cache');
1 efrain 80
                }
81
            }
82
 
1441 ariadna 83
            $supports = [];
1 efrain 84
            foreach ($storesummary['supports'] as $support => $enabled) {
85
                if ($enabled) {
1441 ariadna 86
                    $supports[] = get_string('supports_' . $support, 'cache');
1 efrain 87
                }
88
            }
89
 
90
            $info = '';
91
            if (!empty($storesummary['default'])) {
1441 ariadna 92
                $info = $this->output->pix_icon('i/info', $defaultstoreactions, '', ['class' => 'icon']);
1 efrain 93
            }
94
 
95
            $isready = $storesummary['isready'] && $storesummary['requirementsmet'];
1441 ariadna 96
            $readycell = new html_table_cell();
1 efrain 97
            if ($isready) {
98
                $readycell->text = $this->output->pix_icon('i/valid', '1');
99
            }
100
 
101
            $storename = $storesummary['name'];
102
            if (!empty($storesummary['default'])) {
1441 ariadna 103
                $storename = get_string('store_' . $storesummary['name'], 'cache');
1 efrain 104
            }
105
            if (!$isready && (int)$storesummary['mappings'] > 0) {
106
                $readycell->text = $this->output->help_icon('storerequiresattention', 'cache');
107
                $readycell->attributes['class'] = 'store-requires-attention';
108
            }
109
 
110
            $lock = $storesummary['lock']['name'];
111
            if (!empty($storesummary['lock']['default'])) {
112
                $lock = get_string($storesummary['lock']['name'], 'cache');
113
            }
114
 
1441 ariadna 115
            $row = new html_table_row([
1 efrain 116
                $storename,
1441 ariadna 117
                get_string('pluginname', 'cachestore_' . $storesummary['plugin']),
1 efrain 118
                $readycell,
119
                $storesummary['mappings'],
120
                join(', ', $modes),
121
                join(', ', $supports),
122
                $lock,
1441 ariadna 123
                $info . join(', ', $htmlactions),
124
            ]);
125
            $row->attributes['class'] = 'store-' . $name;
1 efrain 126
            if ($storesummary['default']) {
127
                $row->attributes['class'] .= ' default-store';
128
            }
129
            $table->data[] = $row;
130
        }
131
 
1441 ariadna 132
        $html  = html_writer::start_tag('div', ['id' => 'core-cache-store-summaries']);
1 efrain 133
        $html .= $this->output->heading(get_string('storesummaries', 'cache'), 3);
134
        $html .= html_writer::table($table);
135
        $html .= html_writer::end_tag('div');
136
        return $html;
137
    }
138
 
139
    /**
140
     * Displays plugin summaries.
141
     *
142
     * @param array $storepluginsummaries information about each store plugin as
143
     *      returned by core_cache\administration_helper::get_store_plugin_summaries().
144
     * @return string HTML
145
     */
146
    public function store_plugin_summaries(array $storepluginsummaries) {
147
        $table = new html_table();
1441 ariadna 148
        $table->head = [
1 efrain 149
            get_string('plugin', 'cache'),
150
            get_string('storeready', 'cache'),
151
            get_string('stores', 'cache'),
152
            get_string('modes', 'cache'),
153
            get_string('supports', 'cache'),
154
            get_string('actions', 'cache'),
1441 ariadna 155
        ];
156
        $table->colclasses = [
1 efrain 157
            'plugin',
158
            'storeready',
159
            'stores',
160
            'modes',
161
            'supports',
1441 ariadna 162
            'actions',
163
        ];
164
        $table->data = [];
1 efrain 165
 
166
        foreach ($storepluginsummaries as $name => $plugin) {
167
            $htmlactions = cache_factory::get_administration_display_helper()->get_store_plugin_actions($name, $plugin);
168
 
1441 ariadna 169
            $modes = [];
1 efrain 170
            foreach ($plugin['modes'] as $mode => $enabled) {
171
                if ($enabled) {
1441 ariadna 172
                    $modes[] = get_string('mode_' . $mode, 'cache');
1 efrain 173
                }
174
            }
175
 
1441 ariadna 176
            $supports = [];
1 efrain 177
            foreach ($plugin['supports'] as $support => $enabled) {
178
                if ($enabled) {
1441 ariadna 179
                    $supports[] = get_string('supports_' . $support, 'cache');
1 efrain 180
                }
181
            }
182
 
1441 ariadna 183
            $row = new html_table_row([
1 efrain 184
                $plugin['name'],
185
                ($plugin['requirementsmet']) ? $this->output->pix_icon('i/valid', '1') : '',
186
                $plugin['instances'],
187
                join(', ', $modes),
188
                join(', ', $supports),
1441 ariadna 189
                join(', ', $htmlactions),
190
            ]);
1 efrain 191
 
1441 ariadna 192
            $row->attributes['class'] = 'plugin-' . $name;
1 efrain 193
            $table->data[] = $row;
194
        }
195
 
1441 ariadna 196
        $html  = html_writer::start_tag('div', ['id' => 'core-cache-plugin-summaries']);
1 efrain 197
        $html .= $this->output->heading(get_string('pluginsummaries', 'cache'), 3);
198
        $html .= html_writer::table($table);
199
        $html .= html_writer::end_tag('div');
200
        return $html;
201
    }
202
 
203
    /**
204
     * Displays definition summaries.
205
     *
206
     * @param array $definitionsummaries information about each definition, as returned by
207
     *      core_cache\administration_helper::get_definition_summaries().
208
     * @param context $context the system context.
209
     *
210
     * @return string HTML.
211
     */
212
    public function definition_summaries(array $definitionsummaries, context $context) {
213
        $table = new html_table();
1441 ariadna 214
        $table->head = [
1 efrain 215
            get_string('definition', 'cache'),
216
            get_string('mode', 'cache'),
217
            get_string('component', 'cache'),
218
            get_string('area', 'cache'),
219
            get_string('mappings', 'cache'),
220
            get_string('sharing', 'cache'),
221
            get_string('canuselocalstore', 'cache'),
1441 ariadna 222
            get_string('actions', 'cache'),
223
        ];
224
        $table->colclasses = [
1 efrain 225
            'definition',
226
            'mode',
227
            'component',
228
            'area',
229
            'mappings',
230
            'sharing',
231
            'canuselocalstore',
1441 ariadna 232
            'actions',
233
        ];
234
        $table->data = [];
1 efrain 235
 
236
        core_collator::asort_array_of_arrays_by_key($definitionsummaries, 'name');
237
 
238
        $none = new lang_string('none', 'cache');
239
        foreach ($definitionsummaries as $id => $definition) {
240
            $htmlactions = cache_factory::get_administration_display_helper()->get_definition_actions($context, $definition);
241
            if (!empty($definition['mappings'])) {
242
                $mapping = join(', ', $definition['mappings']);
243
            } else {
1441 ariadna 244
                $mapping = '<em>' . $none . '</em>';
1 efrain 245
            }
246
 
247
            $uselocalcachecol = get_string('no');
248
            if ($definition['mode'] != cache_store::MODE_REQUEST) {
249
                if (isset($definition['canuselocalstore']) && $definition['canuselocalstore']) {
250
                    $uselocalcachecol = get_string('yes');
251
                }
252
            }
253
 
1441 ariadna 254
            $row = new html_table_row([
1 efrain 255
                $definition['name'],
1441 ariadna 256
                get_string('mode_' . $definition['mode'], 'cache'),
1 efrain 257
                $definition['component'],
258
                $definition['area'],
259
                $mapping,
260
                join(', ', $definition['selectedsharingoption']),
261
                $uselocalcachecol,
1441 ariadna 262
                join(', ', $htmlactions),
263
            ]);
264
            $row->attributes['class'] = 'definition-' . $definition['component'] . '-' . $definition['area'];
1 efrain 265
            $table->data[] = $row;
266
        }
267
 
1441 ariadna 268
        $html  = html_writer::start_tag('div', ['id' => 'core-cache-definition-summaries']);
1 efrain 269
        $html .= $this->output->heading(get_string('definitionsummaries', 'cache'), 3);
270
        $html .= html_writer::table($table);
271
 
1441 ariadna 272
        $url = new moodle_url('/cache/admin.php', ['action' => 'rescandefinitions', 'sesskey' => sesskey()]);
1 efrain 273
        $link = html_writer::link($url, get_string('rescandefinitions', 'cache'));
1441 ariadna 274
        $html .= html_writer::tag('div', $link, ['id' => 'core-cache-rescan-definitions']);
1 efrain 275
 
276
        $html .= html_writer::end_tag('div');
277
        return $html;
278
    }
279
 
280
    /**
281
     * Displays mode mappings
282
     *
283
     * @param string $applicationstore
284
     * @param string $sessionstore
285
     * @param string $requeststore
286
     * @param moodle_url $editurl
287
     * @return string HTML
288
     */
289
    public function mode_mappings($applicationstore, $sessionstore, $requeststore, moodle_url $editurl) {
290
        $table = new html_table();
1441 ariadna 291
        $table->colclasses = [
1 efrain 292
            'mode',
293
            'mapping',
1441 ariadna 294
        ];
295
        $table->rowclasses = [
1 efrain 296
            'mode_application',
297
            'mode_session',
1441 ariadna 298
            'mode_request',
299
        ];
300
        $table->head = [
1 efrain 301
            get_string('mode', 'cache'),
302
            get_string('mappings', 'cache'),
1441 ariadna 303
        ];
304
        $table->data = [
305
            [get_string('mode_' . cache_store::MODE_APPLICATION, 'cache'), $applicationstore],
306
            [get_string('mode_' . cache_store::MODE_SESSION, 'cache'), $sessionstore],
307
            [get_string('mode_' . cache_store::MODE_REQUEST, 'cache'), $requeststore],
308
        ];
1 efrain 309
 
1441 ariadna 310
        $html = html_writer::start_tag('div', ['id' => 'core-cache-mode-mappings']);
1 efrain 311
        $html .= $this->output->heading(get_string('defaultmappings', 'cache'), 3);
312
        $html .= html_writer::table($table);
313
        $link = html_writer::link($editurl, get_string('editmappings', 'cache'));
1441 ariadna 314
        $html .= html_writer::tag('div', $link, ['class' => 'edit-link']);
1 efrain 315
        $html .= html_writer::end_tag('div');
316
        return $html;
317
    }
318
 
319
    /**
320
     * Display basic information about lock instances.
321
     *
322
     * @todo Add some actions so that people can configure lock instances.
323
     *
324
     * @param array $locks
325
     * @return string
326
     */
327
    public function lock_summaries(array $locks) {
328
        $table = new html_table();
1441 ariadna 329
        $table->colclasses = [
1 efrain 330
            'name',
331
            'type',
332
            'default',
333
            'uses',
1441 ariadna 334
            'actions',
335
        ];
336
        $table->rowclasses = [
1 efrain 337
            'lock_name',
338
            'lock_type',
339
            'lock_default',
340
            'lock_uses',
341
            'lock_actions',
1441 ariadna 342
        ];
343
        $table->head = [
1 efrain 344
            get_string('lockname', 'cache'),
345
            get_string('locktype', 'cache'),
346
            get_string('lockdefault', 'cache'),
347
            get_string('lockuses', 'cache'),
1441 ariadna 348
            get_string('actions', 'cache'),
349
        ];
350
        $table->data = [];
1 efrain 351
        $tick = $this->output->pix_icon('i/valid', '');
352
        foreach ($locks as $lock) {
1441 ariadna 353
            $actions = [];
1 efrain 354
            if ($lock['uses'] === 0 && !$lock['default']) {
1441 ariadna 355
                $url = new moodle_url('/cache/admin.php', ['lock' => $lock['name'], 'action' => 'deletelock']);
1 efrain 356
                $actions[] = html_writer::link($url, get_string('delete', 'cache'));
357
            }
1441 ariadna 358
            $table->data[] = new html_table_row([
1 efrain 359
                new html_table_cell($lock['name']),
360
                new html_table_cell($lock['type']),
361
                new html_table_cell($lock['default'] ? $tick : ''),
362
                new html_table_cell($lock['uses']),
1441 ariadna 363
                new html_table_cell(join(' ', $actions)),
364
            ]);
1 efrain 365
        }
366
 
1441 ariadna 367
        $html = html_writer::start_tag('div', ['id' => 'core-cache-lock-summary']);
1 efrain 368
        $html .= $this->output->heading(get_string('locksummary', 'cache'), 3);
369
        $html .= html_writer::table($table);
370
        $html .= html_writer::end_tag('div');
371
        return $html;
372
    }
373
 
374
    /**
375
     * Renders additional actions for locks, such as Add.
376
     *
377
     * @return string
378
     */
379
    public function additional_lock_actions(): string {
1441 ariadna 380
        $url = new moodle_url('/cache/admin.php', ['action' => 'newlockinstance']);
1 efrain 381
        $select = new single_select($url, 'lock', cache_factory::get_administration_display_helper()->get_addable_lock_options());
382
        $select->label = get_string('addnewlockinstance', 'cache');
383
 
1441 ariadna 384
        $html = html_writer::start_tag('div', ['id' => 'core-cache-lock-additional-actions']);
385
        $html .= html_writer::tag('div', $this->output->render($select), ['class' => 'new-instance']);
1 efrain 386
        $html .= html_writer::end_tag('div');
387
        return $html;
388
    }
389
 
390
    /**
391
     * Renders an array of notifications for the cache configuration screen.
392
     *
393
     * Takes an array of notifications with the form:
394
     * $notifications = array(
395
     *     array('This is a success message', true),
396
     *     array('This is a failure message', false),
397
     * );
398
     *
399
     * @param array $notifications
400
     * @return string
401
     */
1441 ariadna 402
    public function notifications(array $notifications = []) {
1 efrain 403
        if (count($notifications) === 0) {
404
            // There are no notifications to render.
405
            return '';
406
        }
407
        $html = html_writer::start_div('notifications');
408
        foreach ($notifications as $notification) {
1441 ariadna 409
            [$message, $notifysuccess] = $notification;
1 efrain 410
            $html .= $this->notification($message, ($notifysuccess) ? 'notifysuccess' : 'notifyproblem');
411
        }
412
        $html .= html_writer::end_div();
413
        return $html;
414
    }
415
 
416
    /**
417
     * Creates the two tables which display on the usage page.
418
     *
1441 ariadna 419
     * @param array $usage Usage information (from \core_cache\helper::usage)
1 efrain 420
     * @return array Array of 2 tables (main and summary table)
421
     * @throws \coding_exception
422
     */
423
    public function usage_tables(array $usage): array {
424
        $table = new \html_table();
425
        $table->id = 'usage_main';
426
        $table->head = [
427
            get_string('definition', 'cache'),
428
            get_string('storename', 'cache'),
429
            get_string('plugin', 'cache'),
430
            get_string('usage_items', 'cache'),
431
            get_string('usage_mean', 'cache'),
432
            get_string('usage_sd', 'cache'),
433
            get_string('usage_total', 'cache'),
1441 ariadna 434
            get_string('usage_totalmargin', 'cache'), ];
1 efrain 435
        $table->align = [
436
            'left', 'left', 'left',
1441 ariadna 437
            'right', 'right', 'right', 'right', 'right',
1 efrain 438
        ];
439
        $table->data = [];
440
 
441
        $summarytable = new \html_table();
442
        $summarytable->id = 'usage_summary';
443
        $summarytable->head = [
444
            get_string('storename', 'cache'),
445
            get_string('plugin', 'cache'),
446
            get_string('usage_total', 'cache'),
1441 ariadna 447
            get_string('usage_realtotal', 'cache'),
1 efrain 448
        ];
449
        $summarytable->align = [
450
            'left', 'left',
451
            'right', 'right',
452
        ];
453
        $summarytable->data = [];
454
        $summarytable->attributes['class'] = 'generaltable w-auto';
455
        $storetotals = [];
456
 
457
        // We will highlight all cells that are more than 2% of total size, so work that out first.
458
        $total = 0;
459
        foreach ($usage as $definition) {
460
            foreach ($definition->stores as $storedata) {
461
                $total += $storedata->items * $storedata->mean;
462
            }
463
        }
464
        $highlightover = round($total / 50);
465
 
466
        foreach ($usage as $definition) {
467
            foreach ($definition->stores as $storedata) {
468
                $row = [];
469
                $row[] = s($definition->cacheid);
470
                $row[] = s($storedata->name);
471
                $row[] = s($storedata->class);
472
                if (!$storedata->supported) {
473
                    // We don't have data for this store because it isn't searchable.
474
                    $row[] = '-';
475
                } else {
476
                    $row[] = $storedata->items;
477
                }
478
                if ($storedata->items) {
479
                    $row[] = display_size(round($storedata->mean));
480
                    if ($storedata->items > 1) {
481
                        $row[] = display_size(round($storedata->sd));
482
                    } else {
483
                        $row[] = '';
484
                    }
485
                    $cellsize = round($storedata->items * $storedata->mean);
486
                    $row[] = display_size($cellsize, 1, 'MB');
487
 
488
                    if (!array_key_exists($storedata->name, $storetotals)) {
489
                        $storetotals[$storedata->name] = (object)[
490
                            'plugin' => $storedata->class,
491
                            'total' => 0,
492
                            'storetotal' => $storedata->storetotal,
493
                        ];
494
                    }
495
                    $storetotals[$storedata->name]->total += $cellsize;
496
                } else {
497
                    $row[] = '';
498
                    $row[] = '';
499
                    $cellsize = 0;
500
                    $row[] = '';
501
                }
502
                if ($storedata->margin) {
503
                    // Plus or minus.
504
                    $row[] = '&#xb1;' . display_size($storedata->margin * $storedata->items, 1, 'MB');
505
                } else {
506
                    $row[] = '';
507
                }
508
                $htmlrow = new \html_table_row($row);
509
                if ($cellsize > $highlightover) {
510
                    $htmlrow->attributes = ['class' => 'table-warning'];
511
                }
512
                $table->data[] = $htmlrow;
513
            }
514
        }
515
 
516
        ksort($storetotals);
517
 
518
        foreach ($storetotals as $storename => $storedetails) {
519
            $row = [s($storename), s($storedetails->plugin)];
520
            $row[] = display_size($storedetails->total, 1, 'MB');
521
            if ($storedetails->storetotal !== null) {
522
                $row[] = display_size($storedetails->storetotal, 1, 'MB');
523
            } else {
524
                $row[] = '-';
525
            }
526
            $summarytable->data[] = $row;
527
        }
528
 
529
        return [$table, $summarytable];
530
    }
531
 
532
    /**
533
     * Renders the usage page.
534
     *
535
     * @param \html_table $maintable Main table
536
     * @param \html_table $summarytable Summary table
537
     * @param \moodleform $samplesform Form to select number of samples
538
     * @return string HTML for page
539
     */
540
    public function usage_page(\html_table $maintable, \html_table $summarytable, \moodleform $samplesform): string {
541
        $data = [
542
            'maintable' => \html_writer::table($maintable),
543
            'summarytable' => \html_writer::table($summarytable),
1441 ariadna 544
            'samplesform' => $samplesform->render(),
1 efrain 545
        ];
546
 
547
        return $this->render_from_template('core_cache/usage', $data);
548
    }
549
}