Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   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\local\tool;
  18  
  19  use tool_brickfield\manager;
  20  
  21  /**
  22   * Class printable.
  23   *
  24   * @package tool_brickfield
  25   * @copyright  2020 onward: Brickfield Education Labs, www.brickfield.ie
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  class printable extends tool {
  29  
  30      /**
  31       * Provide a name for this tool, suitable for display on pages.
  32       * @return mixed|string
  33       * @throws \coding_exception
  34       */
  35      public static function toolname(): string {
  36          return get_string('printable:toolname', 'tool_brickfield');
  37      }
  38  
  39      /**
  40       * Provide a short name for this tool, suitable for menus and selectors.
  41       * @return mixed|string
  42       * @throws \coding_exception
  43       */
  44      public static function toolshortname(): string {
  45          return get_string('printable:toolshortname', 'tool_brickfield');
  46      }
  47  
  48      /**
  49       * Provide a lowercase name identifying this plugin. Should really be the same as the directory name.
  50       * @return string
  51       */
  52      public function pluginname(): string {
  53          return 'printable';
  54      }
  55  
  56      /**
  57       * Return the data for renderer / template display.
  58       * @return \stdClass
  59       * @throws \coding_exception
  60       * @throws \dml_exception
  61       */
  62      protected function fetch_data(): \stdClass {
  63          global $DB;
  64  
  65          $filter = $this->get_filter();
  66          if (!$filter->has_course_filters()) {
  67              return (object)[
  68                  'valid' => false,
  69                  'error' => get_string('error:nocoursespecified', 'tool_brickfield'),
  70              ];
  71          } else if (!$filter->validate_filters()) {
  72              return (object)[
  73                  'valid' => false,
  74                  'error' => $filter->get_errormessage(),
  75              ];
  76          }
  77  
  78          $data = (object)[
  79              'valid' => true,
  80              'error' => '',
  81          ];
  82  
  83          $config = get_config(manager::PLUGINNAME);
  84          $perpage = isset($config->perpagefix) ? $config->perpagefix : $config->perpage;
  85  
  86          list($wheresql, $params) = $filter->get_course_sql();
  87  
  88          $combo = [];
  89          $sqlcombo = 'SELECT distinct '.$DB->sql_concat_join("''", ['area.component', 'area.contextid']).' as tmpid,
  90                      sum(res.errorcount)
  91                 FROM {' . manager::DB_AREAS . '} area
  92           INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
  93           INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
  94                WHERE 1=1 ' . $wheresql . '
  95              group by area.component, area.contextid';
  96          $combodata = $DB->get_records_sql_menu($sqlcombo, $params);
  97  
  98          $combo['total'] = count($combodata);
  99          $combo['failed'] = 0;
 100          foreach ($combodata as $count) {
 101              if ($count != 0) {
 102                  $combo['failed']++;
 103              }
 104          }
 105          $combo['passed'] = ($combo['total'] - $combo['failed']);
 106  
 107          $data->combodata = $combo;
 108  
 109          $sql = 'SELECT che.checkgroup, SUM(res.errorcount) as errorinstances
 110                FROM {' . manager::DB_AREAS . '} area
 111          INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
 112          INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
 113          INNER JOIN {' . manager::DB_CHECKS . '} che ON che.id = res.checkid
 114               WHERE 1=1 ' . $wheresql . ' GROUP BY che.checkgroup
 115            ORDER BY che.checkgroup';
 116  
 117          $groupdata = $DB->get_records_sql($sql, $params);
 118  
 119          $data->groupdata = $groupdata;
 120  
 121          // Adding check displaynames from language strings.
 122  
 123          $wheresql = ' and area.courseid = ?';
 124          $params = [$filter->courseid];
 125  
 126          $sql4 = 'SELECT area.component, sum(res.errorcount) as errorsum
 127                 FROM {' . manager::DB_AREAS . '} area
 128          INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
 129          INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
 130               WHERE 1=1 ' . $wheresql . ' GROUP BY area.component
 131            ORDER BY errorsum DESC';
 132          $toptargetdataraw = $DB->get_records_sql($sql4, $params, 0, 5);
 133          $toptargetdata = [];
 134          foreach ($toptargetdataraw as $top) {
 135              $top->component = tool::get_module_label($top->component);
 136              if ($top->errorsum != 0) {
 137                  $toptargetdata[] = $top;
 138              }
 139          }
 140          $data->toptargetdata = $toptargetdata;
 141  
 142          $sql3 = 'SELECT che.shortname, sum(res.errorcount) as checkcount
 143                FROM {' . manager::DB_AREAS . '} area
 144          INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
 145          INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
 146          INNER JOIN {' . manager::DB_CHECKS . '} che ON che.id = res.checkid
 147               WHERE 1=1 ' . $wheresql . ' AND res.errorcount >= ? GROUP BY che.shortname
 148            ORDER BY checkcount DESC';
 149          $params[] = 1;
 150          $checkcountdata = $DB->get_records_sql($sql3, $params, 0, 5);
 151          foreach ($checkcountdata as $key => &$cdata) {
 152              $cdata->checkname = self::get_check_description($key);
 153          }
 154          $data->checkcountdata = $checkcountdata;
 155  
 156          $sqltar = 'SELECT distinct '.$DB->sql_concat_join("''", ['area.component', 'area.contextid']).' as tmpid,
 157                  component, SUM(errorcount) as errorsum
 158                 FROM {' . manager::DB_AREAS . '} area
 159           INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
 160           INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
 161                WHERE 1=1 '.$wheresql.'
 162             GROUP BY area.component, area.contextid';
 163          $targetdata = $DB->get_records_sql($sqltar, $params);
 164  
 165          $tarlabels = [];
 166          $combotar = [];
 167          foreach ($targetdata as $tar) {
 168              if (!array_key_exists($tar->component, $combotar)) {
 169                  $combotar[$tar->component] = [];
 170                  $combotar[$tar->component]['total'] = 0;
 171                  $combotar[$tar->component]['failed'] = 0;
 172                  $tarlabels[$tar->component] = tool::get_module_label($tar->component);
 173              }
 174              $combotar[$tar->component]['total']++;
 175              if ($tar->errorsum > 0) {
 176                  $combotar[$tar->component]['failed']++;
 177              }
 178          }
 179          ksort($combotar);
 180          $data->combotardata = $combotar;
 181          $data->tarlabels = $tarlabels;
 182  
 183          $errorsql = 'SELECT err.id as errid, res.id as resid, area.component, area.itemid, area.cmid,
 184                     che.shortname, err.linenumber as errline, err.htmlcode
 185                FROM {' . manager::DB_AREAS . '} area
 186          INNER JOIN {' . manager::DB_CONTENT . '} ch ON ch.areaid = area.id AND ch.iscurrent = 1
 187          INNER JOIN {' . manager::DB_RESULTS . '} res ON res.contentid = ch.id
 188          INNER JOIN {' . manager::DB_CHECKS . '} che ON che.id = res.checkid
 189          INNER JOIN {' . manager::DB_ERRORS . '} err ON res.id = err.resultid WHERE 1=1 ' . $wheresql;
 190          $errordata = $DB->get_records_sql($errorsql, $params, 0, $perpage);
 191  
 192          foreach ($errordata as $err) {
 193              $err->shortname = self::get_check_description($err->shortname);
 194              // Truncating HTML with base64 image data, to avoid page overstretching.
 195              $base64detected = parent::base64_img_detected($err->htmlcode);
 196              if ($base64detected) {
 197                  $err->htmlcode = parent::truncate_base64($err->htmlcode);
 198              }
 199          }
 200  
 201          $data->errordata = $errordata;
 202          $data->errordetailscount = $perpage;
 203  
 204          if ($filter->categoryid != 0) {
 205              $data->countdata = count($filter->courseids);
 206          } else {
 207              $countsql = 'select count(distinct courseid) from {' . manager::DB_AREAS . '}';
 208              $countdata = $DB->count_records_sql($countsql, []);
 209              $data->countdata = $countdata;
 210          }
 211  
 212          return $data;
 213      }
 214  
 215      /**
 216       * Get the HTML output for display.
 217       * @return mixed
 218       */
 219      public function get_output() {
 220          global $PAGE;
 221  
 222          $data = $this->get_data();
 223          $filter = $this->get_filter();
 224  
 225          $renderer = $PAGE->get_renderer('tool_brickfield', 'printable');
 226          if ($filter->target == 'pdf') {
 227              $renderer->pdf_renderer($data, $filter);
 228              return '';
 229          } else if ($filter->target == 'html') {
 230              $output = $renderer->header();
 231              return $output . $renderer->display($data, $filter);
 232          } else {
 233              return $renderer->display($data, $filter);
 234          }
 235      }
 236  }