Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.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_mfa\local\form;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  require_once($CFG->libdir . '/form/text.php');
  21  
  22  /**
  23   * MFA Verification code element.
  24   *
  25   * @package     tool_mfa
  26   * @author      Peter Burnett <peterburnett@catalyst-au.net>
  27   * @copyright   Catalyst IT
  28   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29   */
  30  class verification_field extends \MoodleQuickForm_text {
  31  
  32      /** @var bool */
  33      private $appendjs;
  34  
  35      /**
  36       * Verification field is a text entry box that features some useful extras.
  37       *
  38       * Contains JS to autosubmit the auth page when code is entered, as well as additional styling.
  39       *
  40       * @param array $attributes
  41       * @param boolean $auth is this constructed in auth.php loginform_* definitions. Set to false to prevent autosubmission of form.
  42       */
  43      public function __construct($attributes = null, $auth = true) {
  44          global $PAGE;
  45  
  46          // Force attributes.
  47          if (empty($attributes)) {
  48              $attributes = [];
  49          }
  50  
  51          $attributes['autocomplete'] = 'one-time-code';
  52          $attributes['inputmode'] = 'numeric';
  53          $attributes['pattern'] = '[0-9]*';
  54          $attributes['class'] = 'tool-mfa-verification-code font-weight-bold';
  55          $attributes['maxlength'] = 6;
  56  
  57          // If we aren't on the auth page, this might be part of a larger form such as for setup.
  58          // We shouldn't autofocus here, as it probably isn't the only element, or main target.
  59          if ($auth) {
  60              $attributes['autofocus'] = 'autofocus';
  61          }
  62  
  63          // If we are on the auth page, load JS for element.
  64          $this->appendjs = false;
  65          if ($auth) {
  66              $PAGE->requires->js_call_amd('tool_mfa/autosubmit_verification_code', 'init', []);
  67          }
  68  
  69          // Force element name to match JS.
  70          $elementname = 'verificationcode';
  71          $elementlabel = get_string('verificationcode', 'tool_mfa');
  72  
  73          return parent::__construct($elementname, $elementlabel, $attributes);
  74      }
  75  
  76      // @codingStandardsIgnoreStart
  77      /**
  78       * Returns HTML for this form element.
  79       *
  80       * @return string
  81       */
  82      public function toHtml(): string {
  83          // Empty the value after all attributes decided.
  84          $this->_attributes['value'] = '';
  85          $result = parent::toHtml();
  86  
  87          $submitjs = "<script>
  88              document.querySelector('#id_verificationcode').addEventListener('keyup', function() {
  89                  if (this.value.length == 6) {
  90                      // Submits the closes form (parent).
  91                      this.closest('form').submit();
  92                  }
  93              });
  94              </script>";
  95  
  96          if ($this->appendjs) {
  97              $result .= $submitjs;
  98          }
  99          return $result;
 100      }
 101      // @codingStandardsIgnoreEnd
 102  
 103      /**
 104       * Setup and return the script for autosubmission while inside the secure layout.
 105       *
 106       * @return string the JS to inline attach to the rendered object.
 107       */
 108      public function secure_js(): string {
 109          // Empty the value after all attributes decided.
 110          $this->_attributes['value'] = '';
 111  
 112          return "<script>
 113              document.querySelector('#id_verificationcode').addEventListener('keyup', function() {
 114                  if (this.value.length == 6) {
 115                      // Submits the closes form (parent).
 116                      this.closest('form').submit();
 117                  }
 118              });
 119          </script>";
 120      }
 121  }