Proyectos de Subversion Moodle

Rev

| 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 tool_brickfield\output\printable;
18
 
19
use tool_brickfield\local\tool\bfpdf;
20
use core\chart_bar;
21
use core\chart_pie;
22
use core\chart_series;
23
use tool_brickfield\accessibility;
24
use tool_brickfield\area_base;
25
use tool_brickfield\local\tool\filter;
26
use tool_brickfield\manager;
27
 
28
/**
29
 * tool_brickfield/printable renderer
30
 *
31
 * @package    tool_brickfield
32
 * @copyright  2020 onward: Brickfield Education Labs, https://www.brickfield.ie
33
 * @author     Mike Churchward
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class renderer extends \tool_brickfield\output\renderer {
37
    /**
38
     * Render the page containing the Printable report.
39
     *
40
     * @param \stdClass $data Report data.
41
     * @param filter $filter Display filters.
42
     * @return String HTML showing charts.
43
     * @throws \coding_exception
44
     * @throws \dml_exception
45
     * @throws \moodle_exception
46
     */
47
    public function display(\stdClass $data, filter $filter): string {
48
        $css = '';
49
 
50
        // Page data.
51
        $out = '';
52
 
53
        if (empty($filter->target)) {
54
            $linkname = get_string('printable:downloadpdf', 'tool_brickfield');
55
            $link = new \moodle_url(
56
                accessibility::get_plugin_url(),
57
                [
58
                    'tab' => 'printable',
59
                    'courseid' => $filter->courseid,
60
                    'target' => 'pdf',
61
                ]
62
            );
63
            $htmlicon = new \pix_icon('t/print', $linkname);
64
            $class = 'tool_brickfield_floatprinticon';
65
            $printlink = $this->action_link($link, $linkname, null, ['class' => $class, 'title' => $linkname], $htmlicon);
66
        }
67
 
68
        $out .= \html_writer::tag('h3', accessibility::get_title($filter, $data->countdata));
69
        $out .= !empty($printlink) ? $printlink : '';
70
 
71
        $div1 = \html_writer::div($this->pix_icon('f/award',
72
                get_string('totalactivities', manager::PLUGINNAME), manager::PLUGINNAME).
73
            get_string('totalactivitiescount', manager::PLUGINNAME, $data->combodata['total']), '',
74
            ['class' => 'col-sm-3'.$css]);
75
        $div2 = \html_writer::div($this->pix_icon('f/done2',
76
                get_string('passed', manager::PLUGINNAME), manager::PLUGINNAME).
77
            get_string('passedcount', manager::PLUGINNAME, $data->combodata['passed']), '',
78
            ['class' => 'col-sm-3'.$css]);
79
        $div3 = \html_writer::div($this->pix_icon('f/error',
80
                get_string('failed', manager::PLUGINNAME), manager::PLUGINNAME).
81
            get_string('failedcount', manager::PLUGINNAME, $data->combodata['failed']), '',
82
            ['class' => 'col-sm-3'.$css]);
83
        $out .= \html_writer::div($div1.$div2.$div3, '', ['id' => 'rowa', 'class' => 'row h4']);
84
 
85
        $out .= \html_writer::div('&nbsp;'); // Padding row.
86
        $str1 = \html_writer::tag('h4', get_string('toperrors', manager::PLUGINNAME));
87
 
88
        $table = new \html_table();
89
        $table->head  = [
90
            get_string('tblcheck', manager::PLUGINNAME),
91
            get_string('count', manager::PLUGINNAME),
92
        ];
93
        $table->size = ['80%', '20%'];
94
        $table->align = ['left', 'center'];
95
        $data->checkcountdata = !empty($data->checkcountdata) ? $data->checkcountdata : [];
96
        foreach ($data->checkcountdata as $key => $value) {
97
            if ($value->checkcount > 0) {
98
                $table->data[] = [$value->checkname, $value->checkcount];
99
            }
100
        }
101
 
102
        if (count($data->checkcountdata) > 0) {
103
            $str1 .= \html_writer::table($table, true);
104
        } else {
105
            $str1 .= \html_writer::tag('p', get_string('noerrorsfound', manager::PLUGINNAME));
106
        }
107
        $out .= \html_writer::start_div('row', ['id' => 'row2']);
108
        $out .= \html_writer::div($str1, '', ['class' => 'col-sm-4']);
109
 
110
        $str2 = \html_writer::tag('h4', get_string('toptargets', manager::PLUGINNAME));
111
        $table = new \html_table();
112
        $table->head  = [
113
            get_string('tbltarget', manager::PLUGINNAME),
114
            get_string('count', manager::PLUGINNAME),
115
        ];
116
        $table->size = ['80%', '20%'];
117
        $table->align = ['left', 'center'];
118
        $data->toptargetdata = !empty($data->toptargetdata) ? $data->toptargetdata : [];
119
        $table->data = $data->toptargetdata;
120
        if (count($data->toptargetdata) > 0) {
121
            $str2 .= \html_writer::table($table, true);
122
        } else {
123
            $str2 .= \html_writer::tag('p', get_string('noerrorsfound', manager::PLUGINNAME));
124
        }
125
        $out .= \html_writer::div($str2, '', ['class' => 'col-sm-4']);
126
 
127
        $str3 = \html_writer::tag('h4', get_string('taberrors', manager::PLUGINNAME));
128
        $table = new \html_table();
129
        $table->head  = [
130
            get_string('checktype', manager::PLUGINNAME),
131
            get_string('count', manager::PLUGINNAME),
132
        ];
133
        $table->size = ['80%', '20%'];
134
        $table->align = ['left', 'center'];
135
        foreach ($data->groupdata as $key => $group) {
136
            $checkgroup = area_base::checkgroup_name($key);
137
            $tmplabel = get_string('checktype:' . $checkgroup, manager::PLUGINNAME);
138
            $icon = $this->pix_icon('f/' . $checkgroup, $tmplabel, manager::PLUGINNAME);
139
            $table->data[] = [get_string('checktype:' . $checkgroup, manager::PLUGINNAME), $group->errorinstances];
140
        }
141
        $str3 .= \html_writer::table($table, true);
142
        $out .= \html_writer::div($str3, '', ['class' => 'col-sm-4']);
143
 
144
        $out .= \html_writer::end_div(); // End row2.
145
 
146
        $out .= \html_writer::start_div('row', ['id' => 'row3']);
147
 
148
        foreach ($data->combotardata as $key => &$combotar) {
149
            $combotar['passed'] = $combotar['total'] - $combotar['failed'];
150
            $combos[] = $combotar['total'] - $combotar['failed'];
151
            $combosf[] = $combotar['failed'];
152
        }
153
 
154
        $str4 = \html_writer::tag('h4', get_string('targetratio', manager::PLUGINNAME));
155
        $table = new \html_table();
156
        $table->head  = [
157
            get_string('tbltarget', manager::PLUGINNAME),
158
            get_string('passed', manager::PLUGINNAME),
159
            get_string('failed', manager::PLUGINNAME),
160
            get_string('total')
161
            ];
162
 
163
        foreach ($data->combotardata as $tar => $tarvalue) {
164
            $table->data[] = [$data->tarlabels[$tar],
165
                $tarvalue['passed'], $tarvalue['failed'], $tarvalue['total']];
166
        }
167
 
168
        $table->size = ['40%', '20%', '20%', '20%'];
169
        $table->align = ['left', 'center', 'center', 'center'];
170
        $str4 .= \html_writer::table($table, true);
171
        $out .= \html_writer::div($str4, '', ['class' => 'col-sm-4']);
172
 
173
        $str5 = \html_writer::tag('h4', get_string('titleerrorscount', manager::PLUGINNAME, $data->errordetailscount));
174
        $table = new \html_table();
175
        $table->head  = [
176
            get_string('tbltarget', manager::PLUGINNAME),
177
            get_string('tblcheck', manager::PLUGINNAME),
178
            get_string('tblline', manager::PLUGINNAME),
179
            get_string('tblhtmlcode', manager::PLUGINNAME)
180
            ];
181
        $data->errordata = !empty($data->errordata) ? $data->errordata : [];
182
        foreach ($data->errordata as $err) {
183
            $err->htmlcode = htmlentities($err->htmlcode, ENT_COMPAT);
184
            $row = [$data->tarlabels[$err->component], $err->shortname, $err->errline, $err->htmlcode];
185
            $table->data[] = $row;
186
        }
187
 
188
        $table->size = ['10%', '25%', '5%', '60%'];
189
        if (count($data->errordata) > 0) {
190
            $str5 .= \html_writer::table($table, true);
191
        } else {
192
            $str5 .= \html_writer::tag('p', get_string('noerrorsfound', manager::PLUGINNAME));
193
        }
194
        $out .= \html_writer::div($str5, '', ['class' => 'col-sm-8']);
195
 
196
        $out .= \html_writer::end_div(); // End row3.
197
 
198
        if ($filter->target == 'pdf') {
199
            // Converting divs to spans for better PDF display.
200
            $out = str_replace(['<div>', '</div>'], ['<span>', '</span>'], $out);
201
        }
202
 
203
        return $out;
204
    }
205
 
206
    /**
207
     * Return the path to use for PDF images.
208
     *
209
     * @return string
210
     */
211
    private function image_path(): string {
212
        global $CFG;
213
        return $CFG->wwwroot . '/admin/tool/brickfield/pix/pdf/';
214
    }
215
 
216
    /**
217
     * Renders the accessability report using the pdflib.
218
     *
219
     * @param \stdClass $data Report data.
220
     * @param filter $filter Display filters.
221
     * @throws \coding_exception
222
     * @throws \dml_exception
223
     * @throws \moodle_exception
224
     * @return void
225
     */
226
    public function pdf_renderer(\stdClass $data, filter $filter) {
227
        $pdf = new bfpdf();
228
 
229
        $pdf->setFooterFont(Array('Helvetica', '', 10));
230
        $pdf->setPrintHeader(false);
231
        $pdf->SetCreator(PDF_CREATOR);
232
        $pdf->SetAuthor('Brickfield Accessibility Report');
233
        $pdf->SetTitle('Brickfield Accessibility Report');
234
        $pdf->SetFont('Helvetica');
235
 
236
        // Set default monospaced font.
237
        $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
238
 
239
        // Set margins.
240
        $pdf->SetMargins(20, 20, 20, 100);
241
 
242
        $pdf->AddPage('P');
243
        $errorreporting = error_reporting(0);
244
 
245
        // Get current date for current user.
246
        $date = new \DateTime("now", \core_date::get_user_timezone_object());
247
        $pdf->SetLineWidth(0.0);
248
 
249
        $html = '
250
            <h1>' . get_string('accessibilityreport', manager::PLUGINNAME) . '</h1>
251
            <h2>'. accessibility::get_title($filter, $data->countdata) .'</h2>
252
            <p>' . userdate($date->getTimestamp()) . '</p>
253
            <table cellspacing="0" cellpadding="1">
254
                <tr>
255
                    <td>
256
                        <img src="' . $this->image_path() . 'tachometer-alt-solid.svg" width="15" height="15">' .
257
                        get_string('totalactivitiescount', manager::PLUGINNAME, $data->combodata['total']) .
258
                    '</td>
259
                    <td>
260
                        <img src="' . $this->image_path() . 'check-square-regular.svg" width="15" height="15">' .
261
                        get_string('passedcount', manager::PLUGINNAME, $data->combodata['passed']) .
262
                    '</td>
263
                    <td>
264
                        <img src="' . $this->image_path() . 'times-circle-regular.svg" width="15" height="15">' .
265
                        get_string('failedcount', manager::PLUGINNAME, $data->combodata['failed']) .
266
                    '</td>
267
                </tr>
268
            </table>';
269
 
270
        $pdf->writeHTML($html);
271
 
272
        if (!empty($data->checkcountdata)) {
273
            $pdf->writeHTML($this->get_errors_table($data));
274
 
275
            $tablegroup = '<table><tr>
276
                <td width="45%">'. $this->get_group_table($data) . '</td>
277
                <td width="10%"></td>
278
                <td width="45%">'. $this->get_inaccessible_table($data) . '</td>
279
            </tr></table>';
280
 
281
            $pdf->writeHTML($tablegroup);
282
 
283
            $pdf->AddPage('P');
284
        } else {
285
            $pdf->writeHTML('<div>'.get_string('noerrorsfound', manager::PLUGINNAME).'</div><div></div>');
286
        }
287
 
288
        $pdf->writeHTML($this->get_ratio_table($data));
289
 
290
        // Output the pdf.
291
        @$pdf->Output(get_string('pdf:filename', 'tool_brickfield', $filter->courseid).
292
            '_' . userdate($date->getTimestamp(), '%Y_%m_%d') . '.pdf', 'D');
293
        error_reporting($errorreporting);
294
 
295
    }
296
 
297
    /**
298
     * Builds the HTML for a styled table used in the pdf report.
299
     *
300
     * @param array $headers The headers of the table.
301
     * @param array $data The table data.
302
     * @param string $title The title of the table.
303
     * @param array $widths The widths of the table columns.
304
     * @return string The HTML code of the table.
305
     */
306
    public function render_table(array $headers, array $data, string $title, array $widths): string {
307
        $numheaders = count($headers);
308
        $html = '';
309
        $html .= '<table cellspacing="0" cellpadding="5"  style="background-color: #ffffff;">';
310
        $html .= '<tr><td style="border-bottom:.1 solid #333333;" colspan="'.$numheaders.'"><h3>'.$title.'</h3></td></tr>';
311
        $html .= '<tr>';
312
 
313
        for ($i = 0; $i < $numheaders; ++$i) {
314
            $align = $i > 0 ? "center" : "left";
315
            $html .= '<th style="text-align:'.$align.';" width="'.$widths[$i].'">';
316
            $html .= '<b>'.$headers[$i].'</b>';
317
            $html .= '</th>';
318
        }
319
        $html .= '</tr>';
320
        $j = 1;
321
        foreach ($data as $row) {
322
            ++$j;
323
            $color = $j % 2 == 1 ? "#FFFFFF" : "#F2F2F2";
324
            $html .= '<tr border ="1" style="background-color:'.$color.';">';
325
            for ($i = 0; $i < $numheaders; ++$i) {
326
                $align = $i > 0 ? "center" : "left";
327
                $html .= '<td width="'.$widths[$i].'" style="text-align:'.$align.';, background-color:'.$color.';">';
328
                $html .= $row[$i];
329
                $html .= '</td>';
330
            }
331
            $html .= '</tr>';
332
        }
333
        $html .= '</table>';
334
        return $html;
335
    }
336
 
337
    /**
338
     * Gets the Activity Pass Ratio table.
339
     *
340
     * @param \stdClass $data Report data.
341
     * @return string The HTML code of the table.
342
     */
343
    public function get_ratio_table(\stdClass $data): string {
344
        $headers = [
345
        get_string('tbltarget', manager::PLUGINNAME),
346
        get_string('passed', manager::PLUGINNAME),
347
        get_string('failed', manager::PLUGINNAME),
348
        get_string('total')
349
        ];
350
 
351
        $tabledata = [];
352
        foreach ($data->combotardata as $tar => $tarvalue) {
353
            $tabledata[] = [
354
                $data->tarlabels[$tar],
355
                $tarvalue['total'] - $tarvalue['failed'],
356
                $tarvalue['failed'],
357
                $tarvalue['total']
358
            ];
359
        }
360
 
361
        return $this->render_table(
362
        $headers,
363
        $tabledata,
364
        get_string('targetratio', manager::PLUGINNAME),
365
        ["40%", "20%", "20%", "20%"]
366
        );
367
    }
368
 
369
    /**
370
     * Gets the Check Errors table.
371
     *
372
     * @param \stdClass $data Report data.
373
     * @return string The HTML code of the table.
374
     */
375
    public function get_group_table(\stdClass $data): string {
376
        $headers = [
377
        get_string('checktype', manager::PLUGINNAME),
378
        get_string('count', manager::PLUGINNAME),
379
        ];
380
 
381
        $tabledata = [];
382
 
383
        // Numbers are constants from \tool_brickfield\area_base::checkgroup.
384
        $icons = [
385
            area_base::CHECKGROUP_IMAGE  => $this->image_path() . 'image-regular.svg',
386
            area_base::CHECKGROUP_LAYOUT => $this->image_path() . 'th-large-solid.svg',
387
            area_base::CHECKGROUP_LINK   => $this->image_path() . 'link.png',
388
            area_base::CHECKGROUP_MEDIA  => $this->image_path() . 'play-circle-regular.svg',
389
            area_base::CHECKGROUP_TABLE  => $this->image_path() . 'table-solid.svg',
390
            area_base::CHECKGROUP_TEXT   => $this->image_path() . 'font-solid.svg',
391
        ];
392
 
393
        foreach ($data->groupdata as $key => $group) {
394
            $checkgroup = area_base::checkgroup_name($key);
395
            $icon = $icons[$key];
396
            $tabledata[] = ['<img src="'.$icon.'" width="15" height="15">' . ' ' .
397
                get_string('checktype:' . $checkgroup, manager::PLUGINNAME), $group->errorinstances];
398
        }
399
 
400
        return $this->render_table(
401
            $headers,
402
            $tabledata,
403
            get_string('taberrors', manager::PLUGINNAME),
404
            ["70%", "30%"]
405
        );
406
    }
407
 
408
    /**
409
     * Gets the Failed Activities table.
410
     *
411
     * @param \stdClass $data Report data.
412
     * @return string The HTML code of the table.
413
     */
414
    public function get_inaccessible_table(\stdClass $data): string {
415
        $headers = [get_string('tbltarget', manager::PLUGINNAME),
416
        get_string('count', manager::PLUGINNAME)];
417
 
418
        $tabledata = [];
419
 
420
        foreach ($data->toptargetdata as $key => $value) {
421
            if ($value->errorsum > 0) {
422
                $tabledata[] = [$value->component, $value->errorsum];
423
            }
424
        }
425
        return $this->render_table(
426
            $headers,
427
            $tabledata,
428
            get_string('toptargets', manager::PLUGINNAME),
429
            ["70%", "30%"]
430
        );
431
    }
432
 
433
    /**
434
     * Gets the Top Errors table.
435
     *
436
     * @param \stdClass $data Report data.
437
     * @return string The HTML code of the table.
438
     */
439
    public function get_errors_table(\stdClass $data): string {
440
        $headers = [get_string('tblcheck', manager::PLUGINNAME), get_string('count', manager::PLUGINNAME)];
441
        $tabledata = [];
442
 
443
        $data->checkcountdata = !empty($data->checkcountdata) ? $data->checkcountdata : [];
444
 
445
        foreach ($data->checkcountdata as $value) {
446
            if ($value->checkcount > 0) {
447
                $tabledata[] = [$value->checkname, $value->checkcount];
448
            }
449
        }
450
        return $this->render_table($headers, $tabledata, get_string('toperrors', manager::PLUGINNAME), ["80%", "20%"]);
451
    }
452
}