Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   1  <?php
   2  ///////////////////////////////////////////////////////////////////////////
   3  //                                                                       //
   4  // NOTICE OF COPYRIGHT                                                   //
   5  //                                                                       //
   6  // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
   7  //          http://moodle.org                                            //
   8  //                                                                       //
   9  // Copyright (C) 1999-onwards Moodle Pty Ltd  http://moodle.com          //
  10  //                                                                       //
  11  // This program is free software; you can redistribute it and/or modify  //
  12  // it under the terms of the GNU General Public License as published by  //
  13  // the Free Software Foundation; either version 2 of the License, or     //
  14  // (at your option) any later version.                                   //
  15  //                                                                       //
  16  // This program is distributed in the hope that it will be useful,       //
  17  // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
  18  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
  19  // GNU General Public License for more details:                          //
  20  //                                                                       //
  21  //          http://www.gnu.org/copyleft/gpl.html                         //
  22  //                                                                       //
  23  ///////////////////////////////////////////////////////////////////////////
  24  
  25  class data_field_multimenu extends data_field_base {
  26  
  27      var $type = 'multimenu';
  28      /**
  29       * priority for globalsearch indexing
  30       *
  31       * @var int
  32       * */
  33      protected static $priority = self::LOW_PRIORITY;
  34  
  35      function display_add_field($recordid = 0, $formdata = null) {
  36          global $DB, $OUTPUT;
  37  
  38          if ($formdata) {
  39              $fieldname = 'field_' . $this->field->id;
  40              if (isset($formdata->$fieldname)) {
  41                  $content = $formdata->$fieldname;
  42              } else {
  43                  $content = array();
  44              }
  45          } else if ($recordid) {
  46              $content = $DB->get_field('data_content', 'content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid));
  47              $content = explode('##', $content);
  48          } else {
  49              $content = array();
  50          }
  51  
  52          $str = '<div title="'.s($this->field->description).'">';
  53          $str .= '<input name="field_' . $this->field->id . '[xxx]" type="hidden" value="xxx"/>'; // hidden field - needed for empty selection
  54  
  55          $str .= '<label for="field_' . $this->field->id . '">';
  56          $str .= '<legend><span class="accesshide">' . $this->field->name;
  57  
  58          if ($this->field->required) {
  59              $str .= '&nbsp;' . get_string('requiredelement', 'form') . '</span></legend>';
  60              $str .= '<div class="inline-req">';
  61              $str .= $OUTPUT->pix_icon('req', get_string('requiredelement', 'form'));
  62              $str .= '</div>';
  63          } else {
  64              $str .= '</span></legend>';
  65          }
  66          $str .= '</label>';
  67          $str .= '<select name="field_' . $this->field->id . '[]" id="field_' . $this->field->id . '"';
  68          $str .= ' multiple="multiple" class="mod-data-input form-control">';
  69  
  70          foreach (explode("\n", $this->field->param1) as $option) {
  71              $option = trim($option);
  72              $str .= '<option value="' . s($option) . '"';
  73  
  74              if (in_array($option, $content)) {
  75                  // Selected by user.
  76                  $str .= ' selected = "selected"';
  77              }
  78  
  79              $str .= '>';
  80              $str .= $option . '</option>';
  81          }
  82          $str .= '</select>';
  83          $str .= '</div>';
  84  
  85          return $str;
  86      }
  87  
  88      function display_search_field($value = '') {
  89          global $CFG, $DB;
  90  
  91          if (is_array($value)){
  92              $content     = $value['selected'];
  93              $allrequired = $value['allrequired'] ? true : false;
  94          } else {
  95              $content     = array();
  96              $allrequired = false;
  97          }
  98  
  99          static $c = 0;
 100  
 101          $str = '<label class="accesshide" for="f_' . $this->field->id . '">' . $this->field->name . '</label>';
 102          $str .= '<select id="f_'.$this->field->id.'" name="f_'.$this->field->id.'[]" multiple="multiple" class="form-control">';
 103  
 104          // display only used options
 105          $varcharcontent =  $DB->sql_compare_text('content', 255);
 106          $sql = "SELECT DISTINCT $varcharcontent AS content
 107                    FROM {data_content}
 108                   WHERE fieldid=? AND content IS NOT NULL";
 109  
 110          $usedoptions = array();
 111          if ($used = $DB->get_records_sql($sql, array($this->field->id))) {
 112              foreach ($used as $data) {
 113                  $valuestr = $data->content;
 114                  if ($valuestr === '') {
 115                      continue;
 116                  }
 117                  $values = explode('##', $valuestr);
 118                  foreach ($values as $value) {
 119                      $usedoptions[$value] = $value;
 120                  }
 121              }
 122          }
 123  
 124          $found = false;
 125          foreach (explode("\n",$this->field->param1) as $option) {
 126              $option = trim($option);
 127              if (!isset($usedoptions[$option])) {
 128                  continue;
 129              }
 130              $found = true;
 131              $str .= '<option value="' . s($option) . '"';
 132  
 133              if (in_array($option, $content)) {
 134                  // Selected by user.
 135                  $str .= ' selected = "selected"';
 136              }
 137              $str .= '>' . $option . '</option>';
 138          }
 139          if (!$found) {
 140              // oh, nothing to search for
 141              return '';
 142          }
 143  
 144          $str .= '</select>';
 145  
 146          $str .= html_writer::checkbox('f_'.$this->field->id.'_allreq', null, $allrequired,
 147              get_string('selectedrequired', 'data'), array('class' => 'mr-1'));
 148  
 149          return $str;
 150  
 151      }
 152  
 153      public function parse_search_field($defaults = null) {
 154          $paramselected = 'f_'.$this->field->id;
 155          $paramallrequired = 'f_'.$this->field->id.'_allreq';
 156  
 157          if (empty($defaults[$paramselected])) { // One empty means the other ones are empty too.
 158              $defaults = array($paramselected => array(), $paramallrequired => 0);
 159          }
 160  
 161          $selected    = optional_param_array($paramselected, $defaults[$paramselected], PARAM_NOTAGS);
 162          $allrequired = optional_param($paramallrequired, $defaults[$paramallrequired], PARAM_BOOL);
 163  
 164          if (empty($selected)) {
 165              // no searching
 166              return '';
 167          }
 168          return array('selected'=>$selected, 'allrequired'=>$allrequired);
 169      }
 170  
 171      function generate_sql($tablealias, $value) {
 172          global $DB;
 173  
 174          static $i=0;
 175          $i++;
 176          $name = "df_multimenu_{$i}_";
 177          $params = array();
 178          $varcharcontent = $DB->sql_compare_text("{$tablealias}.content", 255);
 179  
 180          $allrequired = $value['allrequired'];
 181          $selected    = $value['selected'];
 182  
 183          if ($selected) {
 184              $conditions = array();
 185              $j=0;
 186              foreach ($selected as $sel) {
 187                  $j++;
 188                  $xname = $name.$j;
 189                  $likesel = str_replace('%', '\%', $sel);
 190                  $likeselsel = str_replace('_', '\_', $likesel);
 191                  $conditions[] = "({$tablealias}.fieldid = {$this->field->id} AND ({$varcharcontent} = :{$xname}a
 192                                                                                 OR {$tablealias}.content LIKE :{$xname}b
 193                                                                                 OR {$tablealias}.content LIKE :{$xname}c
 194                                                                                 OR {$tablealias}.content LIKE :{$xname}d))";
 195                  $params[$xname.'a'] = $sel;
 196                  $params[$xname.'b'] = "$likesel##%";
 197                  $params[$xname.'c'] = "%##$likesel";
 198                  $params[$xname.'d'] = "%##$likesel##%";
 199              }
 200              if ($allrequired) {
 201                  return array(" (".implode(" AND ", $conditions).") ", $params);
 202              } else {
 203                  return array(" (".implode(" OR ", $conditions).") ", $params);
 204              }
 205          } else {
 206              return array(" ", array());
 207          }
 208      }
 209  
 210      function update_content($recordid, $value, $name='') {
 211          global $DB;
 212  
 213          $content = new stdClass();
 214          $content->fieldid  = $this->field->id;
 215          $content->recordid = $recordid;
 216          $content->content  = $this->format_data_field_multimenu_content($value);
 217  
 218          if ($oldcontent = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
 219              $content->id = $oldcontent->id;
 220              return $DB->update_record('data_content', $content);
 221          } else {
 222              return $DB->insert_record('data_content', $content);
 223          }
 224      }
 225  
 226      function format_data_field_multimenu_content($content) {
 227          if (!is_array($content)) {
 228              return NULL;
 229          }
 230          $options = explode("\n", $this->field->param1);
 231          $options = array_map('trim', $options);
 232  
 233          $vals = array();
 234          foreach ($content as $key=>$val) {
 235              if ($key === 'xxx') {
 236                  continue;
 237              }
 238              if (!in_array($val, $options)) {
 239                  continue;
 240              }
 241              $vals[] = $val;
 242          }
 243  
 244          if (empty($vals)) {
 245              return NULL;
 246          }
 247  
 248          return implode('##', $vals);
 249      }
 250  
 251  
 252      function display_browse_field($recordid, $template) {
 253          global $DB;
 254  
 255          if ($content = $DB->get_record('data_content', array('fieldid'=>$this->field->id, 'recordid'=>$recordid))) {
 256              if (strval($content->content) === '') {
 257                  return false;
 258              }
 259  
 260              $options = explode("\n",$this->field->param1);
 261              $options = array_map('trim', $options);
 262  
 263              $contentArr = explode('##', $content->content);
 264              $str = '';
 265              foreach ($contentArr as $line) {
 266                  if (!in_array($line, $options)) {
 267                      // hmm, looks like somebody edited the field definition
 268                      continue;
 269                  }
 270                  $str .= $line . "<br />\n";
 271              }
 272              return $str;
 273          }
 274          return false;
 275      }
 276  
 277      /**
 278       * Check if a field from an add form is empty
 279       *
 280       * @param mixed $value
 281       * @param mixed $name
 282       * @return bool
 283       */
 284      function notemptyfield($value, $name) {
 285          unset($value['xxx']);
 286          return !empty($value);
 287      }
 288  
 289      /**
 290       * Returns the presentable string value for a field content.
 291       *
 292       * The returned string should be plain text.
 293       *
 294       * @param stdClass $content
 295       * @return string
 296       */
 297      public static function get_content_value($content) {
 298          $arr = explode('##', $content->content);
 299  
 300          $strvalue = '';
 301          foreach ($arr as $a) {
 302              $strvalue .= $a . ' ';
 303          }
 304  
 305          return trim($strvalue, "\r\n ");
 306      }
 307  
 308      /**
 309       * Return the plugin configs for external functions.
 310       *
 311       * @return array the list of config parameters
 312       * @since Moodle 3.3
 313       */
 314      public function get_config_for_external() {
 315          // Return all the config parameters.
 316          $configs = [];
 317          for ($i = 1; $i <= 10; $i++) {
 318              $configs["param$i"] = $this->field->{"param$i"};
 319          }
 320          return $configs;
 321      }
 322  }