/** * Provides a duration chooser, with a text box for a number and a * select box to choose the units, in days, weeks, months, years, or 'no end date'. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_expiry(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); $result = ''; $name = Pieform::hsc($element['name']); if (!isset($element['defaultvalue'])) { $element['defaultvalue'] = null; } $global = $form->get_property('method') == 'get' ? $_GET : $_POST; // Get the value of the element for rendering. if (isset($element['value'])) { $seconds = $element['value']; $values = pieform_element_expiry_get_expiry_from_seconds($element['value']); } else { if ($form->is_submitted() && isset($global[$element['name']]) && isset($global[$element['name'] . '_units'])) { $values = array('number' => $global[$element['name']], 'units' => $global[$element['name'] . '_units']); $seconds = $values['number'] * pieform_element_expiry_seconds_in($values['units']); } else { if (isset($element['defaultvalue'])) { $seconds = $element['defaultvalue']; $values = pieform_element_expiry_get_expiry_from_seconds($seconds); } else { $values = array('number' => '', 'units' => 'noenddate'); $seconds = null; } } } // @todo probably create with an actual input element, as tabindex doesn't work here for one thing // Same with the select. And do the events using mochikit signal instead of dom events $numberinput = '<input'; $numberinput .= $values['units'] == 'noenddate' && empty($element['rules']['required']) ? ' disabled="disabled"' : ''; $numberinput .= ' type="text" size="4" name="' . $name . '"'; $numberinput .= ' id="' . $formname . '_' . $name . '" value="' . Pieform::hsc($values['number']) . '" tabindex="' . Pieform::hsc($element['tabindex']) . '"'; $numberinput .= (isset($element['error']) ? ' class="error"' : '') . ">\n"; $uselect = '<select onchange="' . $name . '_change()" '; $uselect .= 'name="' . $name . '_units" id="' . $formname . '_' . $name . '_units"' . ' tabindex="' . Pieform::hsc($element['tabindex']) . "\">\n"; foreach (pieform_element_expire_get_expiry_units() as $u) { // Don't allow 'no end date' if the element is required if ($u == 'noenddate' && !empty($element['rules']['required'])) { continue; } $uselect .= "\t<option value=\"{$u}\"" . ($values['units'] == $u ? ' selected="selected"' : '') . '>' . $form->i18n('element', 'expiry', $u, $element) . "</option>\n"; } $uselect .= "</select>\n"; // Make sure the input is disabled if "no end date" is selected $script = <<<EOJS <script type="text/javascript" language="javascript"> function {$name}_change() { if (\$('{$formname}_{$name}_units').value == 'noenddate') { \$('{$formname}_{$name}').disabled = true; } else { \$('{$formname}_{$name}').disabled = false; } } </script> EOJS; return $numberinput . $uselect . $script; }
/** * Provides a basic checkbox input. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_checkbox(Pieform $form, $element) { /*{{{*/ $checked = false; if (isset($element['rules']['required'])) { throw new PieformException("For pieform_element_checkbox, 'required' is not allowed as a rule. Radio should be used instead."); } if (!empty($element['value'])) { $checked = true; } $global = $form->get_property('method') == 'get' ? $_GET : $_POST; if ($form->is_submitted() && isset($global[$element['name']])) { $checked = true; } else { if (!$form->is_submitted() && !empty($element['defaultvalue'])) { $checked = true; } else { if (!empty($element['readonly']) && !empty($element['defaultvalue'])) { $checked = true; } } } $arialabel = ''; if (!empty($element['arialabel'])) { $arialabel = ' aria-label="' . Pieform::hsc($element['title']) . '"'; } return '<input type="checkbox"' . $form->element_attributes($element) . $arialabel . ($checked ? ' checked="checked"' : '') . '>'; }
/** * Renders a basic HTML <textarea> element. * * @param array $element The element to render * @param Pieform $form The form to render the element for * @return string The HTML for the element */ function pieform_element_textarea(Pieform $form, $element) { /*{{{*/ global $_PIEFORM_TEXTAREAS; $rows = $cols = $style = ''; if (isset($element['height'])) { $style .= 'height:' . $element['height'] . ';'; $rows = intval($element['height'] > 0) ? ceil(intval($element['height']) / 10) : 1; } elseif (isset($element['rows'])) { $rows = $element['rows']; } else { Pieform::info('No value for rows or height specified for textarea "' . $element['name'] . '"'); } if (isset($element['width'])) { $style .= 'width:' . $element['width'] . ';'; $cols = intval($element['width'] > 0) ? ceil(intval($element['width']) / 10) : 1; } elseif (isset($element['cols'])) { $cols = $element['cols']; } else { Pieform::info('No value for cols or width specified for textarea "' . $element['name'] . '"'); } $element['style'] = isset($element['style']) ? $style . $element['style'] : $style; $fullwidth = !empty($element['fullwidth']) ? 'true' : 'false'; if (!empty($element['resizable'])) { $element['class'] = isset($element['class']) && $element['class'] ? $element['class'] . ' resizable' : 'resizable'; $_PIEFORM_TEXTAREAS[] = array('formname' => $form->get_name(), 'elementname' => $form->get_name() . '_' . $element['id'], 'fullwidth' => $fullwidth); } return '<textarea' . ($rows ? ' rows="' . $rows . '"' : '') . ($cols ? ' cols="' . $cols . '"' : '') . $form->element_attributes($element, array('maxlength', 'size')) . '>' . Pieform::hsc($form->get_value($element)) . '</textarea>'; }
/** * Renders form elements all on one line. * * @param Pieform $form The form the element is being rendered for * @param array $element The element that is being rendered * @return string The element rendered inside an appropriate container */ function pieform_renderer_oneline(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); // Set the class of the enclosing <div> to match that of the element $result = '<span'; if (isset($element['name'])) { $result .= ' id="' . $formname . '_' . Pieform::hsc($element['name']) . '_container"'; } if (!empty($element['class'])) { // add form-group classes to all real form fields if (strpos($element['class'], 'html') === false) { // $element['class'] = $element['class'] . ' form-group-inline'; $element['class'] = 'form-group-inline'; } // add bootstrap has-error class to any error fields if (strpos($element['class'], 'error') !== false) { $element['class'] = $element['class'] . ' has-error'; } $result .= ' class="' . Pieform::hsc($element['class']) . '"'; } $result .= '>'; if (isset($element['labelhtml'])) { $result .= $element['labelhtml']; } if (isset($element['prehtml'])) { $result .= '<span class="prehtml">' . $element['prehtml'] . '</span>'; } $result .= $element['html']; if (isset($element['posthtml'])) { $result .= '<span class="posthtml">' . $element['posthtml'] . '</span>'; } $result .= "</span>"; return $result; }
/** * Renders a hidden element. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_hidden(Pieform $form, $element) { /*{{{*/ if (!array_key_exists('value', $element)) { throw new PieformException('The hidden element "' . $element['name'] . '" must have a value set'); } if (!empty($element['sesskey']) && $form->get_property('method') != 'post') { throw new PieformException('Sesskey values should be POSTed'); } $value = $form->get_value($element); if (is_array($value)) { $result = ''; foreach ($value as $k => $v) { if (is_array($v)) { foreach ($v as $subk => $subv) { $result .= '<input type="hidden" name="' . Pieform::hsc($element['name']) . '[' . Pieform::hsc($k) . '][' . Pieform::hsc($subk) . ']" value="' . Pieform::hsc($subv) . "\">\n"; } } else { $result .= '<input type="hidden" name="' . Pieform::hsc($element['name']) . '[' . Pieform::hsc($k) . ']" value="' . Pieform::hsc($v) . "\">\n"; } } return $result; } return '<input type="hidden"' . $form->element_attributes($element, array('accesskey', 'onclick', 'size', 'style', 'tabindex')) . ' value="' . Pieform::hsc($form->get_value($element)) . "\">\n"; }
/** * Renders an <input type="button"> element. * * The element must have the 'value' field set. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element * @todo rename to inputbutton */ function pieform_element_button(Pieform $form, $element) { /*{{{*/ if (!isset($element['value'])) { throw new PieformException('Button elements must have a value'); } if (isset($element['confirm'])) { $element['data-confirm'] = Pieform::hsc($element['confirm']); } $element['class'] .= ' btn'; if (isset($element['usebuttontag']) && $element['usebuttontag'] === true) { $value = ''; $action = ''; $type = 'type="submit" '; if (isset($element['content'])) { $content = $element['content']; $value = 'value="' . Pieform::hsc($element['value']) . '" '; } else { $content = $element['value']; } if (isset($element['action'])) { $action = 'formaction="' . Pieform::hsc($element['action']) . '" '; } $button = '<button ' . $value . $action . $type . $form->element_attributes($element) . '>' . $content . '</button>'; } else { $button = '<input type="button"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($element['value']) . '">'; } return $button; }
/** * Renders form elements inside <div>s. * * @param Pieform $form The form the element is being rendered for * @param array $element The element to be rendered * @return string The element rendered inside an appropriate container */ function pieform_renderer_div(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); // Set the class of the enclosing <div> to match that of the element $result = '<div'; if (isset($element['name'])) { $result .= ' id="' . $formname . '_' . $element['name'] . '_container"'; } if (!empty($element['class'])) { $result .= ' class="' . $element['class'] . '"'; } $result .= '>'; if (isset($element['labelhtml'])) { $result .= $element['labelhtml']; } //$result .= $builtelement; $result .= $element['html']; if (isset($element['helphtml'])) { $result .= ' ' . $element['helphtml']; } // Description - optional description of the element, or other note that should be visible // on the form itself (without the user having to hover over contextual help if ((!$form->has_errors() || $form->get_property('showdescriptiononerror')) && !empty($element['description'])) { $result .= '<div class="description"> ' . Pieform::hsc($element['description']) . "</div>"; } if (!empty($element['error'])) { $result .= '<div class="errmsg">' . Pieform::hsc($element['error']) . '</div>'; } $result .= "</div>\n"; return $result; }
/** * Renders a set of radio buttons for a form * * @param array $element The element to render * @param Pieform $form The form to render the element for * @return string The HTML for the element */ function pieform_element_radio(Pieform $form, $element) { /*{{{*/ if (!isset($element['options']) || !is_array($element['options']) || count($element['options']) < 1) { throw new PieformException('Radio elements should have at least one option'); } $result = ''; $form_value = $form->get_value($element); $id = $element['id']; $separator = "\n"; if (isset($element['separator'])) { $separator = $element['separator'] . $separator; } foreach ($element['options'] as $value => $data) { $uid = $id . substr(md5(microtime()), 0, 4); $element['id'] = $uid; if (is_array($data)) { $text = $data['text']; $description = isset($data['description']) ? $data['description'] : ''; } else { $text = $data; $description = ''; } $result .= '<input type="radio"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($value) . '"' . ($form_value == $value ? ' checked="checked"' : '') . '> <label for="' . $form->get_name() . '_' . $uid . '">' . Pieform::hsc($text) . "</label>" . ($description != '' ? '<div class="radio-description">' . $description . '</div>' : '') . $separator; } $result = substr($result, 0, -strlen($separator)); return $result; }
/** * Renders form elements all on one line. * * @param Pieform $form The form the element is being rendered for * @param array $element The element that is being rendered * @return string The element rendered inside an appropriate container */ function pieform_renderer_oneline(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); // Set the class of the enclosing <div> to match that of the element $result = '<span'; if (isset($element['name'])) { $result .= ' id="' . $formname . '_' . Pieform::hsc($element['name']) . '_container"'; } if (!empty($element['class'])) { $result .= ' class="' . Pieform::hsc($element['class']) . '"'; } $result .= '>'; if (isset($element['labelhtml'])) { $result .= $element['labelhtml']; } if (isset($element['prehtml'])) { $result .= '<span class="prehtml">' . $element['prehtml'] . '</span>'; } $result .= $element['html']; if (isset($element['posthtml'])) { $result .= '<span class="posthtml">' . $element['posthtml'] . '</span>'; } $result .= "</span>"; return $result; }
/** * Provides a javascript calendar for inputting a date. * * General documentation about the calendar is available at * http://www.dynarch.com/static/jscalendar-1.0/doc/html/reference.html * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_calendar(Pieform $form, $element) { /*{{{*/ $id = $form->get_name() . '_' . $element['name']; $value = $form->get_value($element); if ($value) { $value = Pieform::hsc(strftime($element['caloptions']['ifFormat'], $value)); } // Build the HTML $result = '<input type="text"' . $form->element_attributes($element) . ' value="' . $value . '">'; if (isset($element['imagefile'])) { $result .= '<a href="" id="' . $id . '_btn" onclick="return false;" class="pieform-calendar-toggle"' . ' tabindex="' . $element['tabindex'] . '">' . '<img src="' . $element['imagefile'] . '" alt=""></a>'; } else { $result .= '<input type="button" id="' . $id . '_btn" onclick="return false;" class="pieform-calendar-toggle"' . ' value="..." tabindex="' . $element['tabindex'] . '">'; } // Build the configuring javascript $options = array_merge($element['caloptions'], array('inputField' => $id, 'button' => $id . '_btn')); $encodedoptions = json_encode($options); // Some options are callbacks and need their quoting removed foreach (array('dateStatusFunc', 'flatCallback', 'onSelect', 'onClose', 'onUpdate') as $function) { $encodedoptions = preg_replace('/("' . $function . '"):"([a-zA-Z0-9$]+)"/', '\\1:\\2', $encodedoptions); } $result .= '<script type="text/javascript">Calendar.setup(' . $encodedoptions . ');</script>'; return $result; }
/** * Renders form elements all on one line. * * @param Pieform $form The form the element is being rendered for * @param array $element The element that is being rendered * @return string The element rendered inside an appropriate container */ function pieform_renderer_oneline(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); // Set the class of the enclosing <div> to match that of the element $result = '<span'; if (isset($element['name'])) { $result .= ' id="' . $formname . '_' . $element['name'] . '_container"'; } if (!empty($element['class'])) { $result .= ' class="' . $element['class'] . '"'; } $result .= '>'; if (isset($element['title']) && $element['title'] !== '' && $element['type'] != 'fieldset') { if (!empty($element['nolabel'])) { // Don't bother with a label for the element $result .= Pieform::hsc($element['title']); } else { $result .= '<label for="' . $element['id'] . '">' . Pieform::hsc($element['title']) . '</label>'; } if ($form->get_property('requiredmarker') && !empty($element['rules']['required'])) { $result .= ' <span class="requiredmarker">*</span>'; } } $result .= $element['html']; $result .= "</span>"; return $result; }
/** * Renders a submit button * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_submit(Pieform $form, $element) { /*{{{*/ if (isset($element['confirm'])) { $element['onclick'] = 'return confirm(' . json_encode($element['confirm']) . ');'; } return '<input type="submit"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($form->get_value($element)) . '">'; }
/** * Renders an <input type="button"> element. * * The element must have the 'value' field set. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element * @todo rename to inputbutton */ function pieform_element_button(Pieform $form, $element) { /*{{{*/ if (!isset($element['value'])) { throw new PieformException('Button elements must have a value'); } return '<input type="button"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($element['value']) . '">'; }
/** * Renders a fieldset. Fieldsets contain other elements, and do not count as a * "true" element, in that they do not have a value and cannot be validated. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_fieldset(Pieform $form, $element) { /*{{{*/ global $_PIEFORM_FIELDSETS; $result = "\n<fieldset"; if (!empty($element['collapsible']) || !empty($element['class'])) { if (!isset($element['legend']) || $element['legend'] === '') { Pieform::info('Collapsible fieldsets should have a legend so they can be toggled'); } $classes = array('collapsible'); $formname = $form->get_name(); if (!isset($_PIEFORM_FIELDSETS['forms'][$formname])) { $_PIEFORM_FIELDSETS['forms'][$formname] = array('formname' => $formname); } // Work out whether any of the children have errors on them $error = false; foreach ($element['elements'] as $subelement) { if (isset($subelement['error'])) { $error = true; break; } } if (!empty($element['collapsed']) && !$error) { $classes[] = 'collapsed'; } if (!empty($element['class'])) { $classes[] = Pieform::hsc($element['class']); } $result .= ' class="' . implode(' ', $classes) . '"'; } $result .= ">\n"; if (isset($element['legend'])) { $result .= '<legend>'; if (!empty($element['collapsible'])) { $result .= '<a href="">' . Pieform::hsc($element['legend']) . '</a>'; } else { $result .= Pieform::hsc($element['legend']); } // Help icon if (!empty($element['help'])) { $function = $form->get_property('helpcallback'); if (function_exists($function)) { $result .= $function($form, $element); } else { $result .= '<span class="help"><a href="" title="' . Pieform::hsc($element['help']) . '" onclick="return false;">?</a></span>'; } } $result .= "</legend>\n"; } foreach ($element['elements'] as $subname => $subelement) { if ($subelement['type'] == 'hidden') { throw new PieformError("You cannot put hidden elements in fieldsets"); } $result .= "\t" . pieform_render_element($form, $subelement); } $result .= "</fieldset>\n"; return $result; }
/** * Renders a basic HTML <input type="file"> element. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_file(Pieform $form, $element) { /*{{{*/ $result = ''; if (isset($element['maxfilesize']) && is_int($element['maxfilesize'])) { $result = '<input type="hidden" name="MAX_FILE_SIZE" value="' . $element['maxfilesize'] . '"/>'; } $result .= '<input type="file"' . $form->element_attributes($element) . (isset($element['accept']) ? ' accept="' . Pieform::hsc($element['accept']) . '"' : '') . '>'; return $result; }
/** * Renders an <input type="image"> button * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_image(Pieform $form, $element) { /*{{{*/ if (!isset($element['src'])) { throw new PieformException('"image" elements must have a "src" for the image'); } if (!isset($element['value'])) { $element['value'] = true; } return '<input type="image" src="' . Pieform::hsc($element['src']) . '"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($form->get_value($element)) . '">'; }
/** * Renders a set of radio buttons for a form * * @param Pieform $form The form to render the element for * @param array $element The element to render. In addition to the standard Pieform * element attributes, it can also take the following optional * attributes: * - separator: The HTML string that should separate the radio * buttons (defaults to \n, always has \n appended to it) * - rowsize: How many radio buttons to print per row (defaults to 1) * - nolabels: Don't print the labels next to the individual radio buttons. * @return string The HTML for the element */ function pieform_element_radio(Pieform $form, $element) { if (!isset($element['options']) || !is_array($element['options']) || count($element['options']) < 1) { throw new PieformException('Radio elements should have at least one option'); } $result = ''; $form_value = $form->get_value($element); $id = $element['id']; $separator = "\n"; if (isset($element['separator'])) { $separator = $element['separator'] . $separator; } $rowsize = isset($element['rowsize']) ? (int) $element['rowsize'] : 1; $nolabels = isset($element['nolabels']) ? $element['nolabels'] : false; $classname = ''; if (!empty($element['hiddenlabels'])) { $classname = ' class="accessible-hidden"'; } $titletext = ''; if (!empty($element['title'])) { $titletext = '<span class="accessible-hidden">' . Pieform::hsc($element['title']) . ': </span>'; } $i = 0; foreach ($element['options'] as $value => $data) { $idsuffix = substr(md5(microtime()), 0, 4); $baseid = $element['id']; $element['id'] = $uid = $id . $idsuffix; if (is_array($data)) { $text = $data['text']; $description = isset($data['description']) ? $data['description'] : ''; } else { $text = $data; $description = ''; } $attributes = $form->element_attributes($element); $attributes = preg_replace("/aria-describedby=\"[^\"]*{$baseid}{$idsuffix}_description\\s*[^\"]*\"/", 'aria-describedby="$1_description"', $attributes); $result .= '<div class="radio">'; $result .= '<input type="radio"' . $attributes . ' value="' . Pieform::hsc($value) . '"' . ($form_value == $value ? ' checked="checked"' : '') . '>'; if (!$nolabels) { $result .= ' <label for="' . $form->get_name() . '_' . $uid . '"' . $classname . '>' . $titletext . Pieform::hsc($text) . "</label>" . ($description != '' ? '<div class="description">' . $description . '</div>' : ''); } $result .= '</div>'; $i++; if ($rowsize <= 1 || $i % $rowsize == 0) { $result .= $separator; } } // If there was a separator printed on the end, then remove it if ($rowsize <= 1 || $i % $rowsize == 0) { $result = substr($result, 0, -strlen($separator)); } return $result; }
/** * Provides a size chooser, with a text box for a number and a * select box to choose the units, in bytes, kilobytes, megabytes or gigabytes * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_bytes(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); $result = ''; $name = Pieform::hsc($element['name']); if (!isset($element['defaultvalue'])) { $element['defaultvalue'] = null; } $global = $form->get_property('method') == 'get' ? $_GET : $_POST; // Get the value of the element for rendering. if (isset($element['value'])) { $bytes = $element['value']; $values = pieform_element_bytes_get_bytes_from_bytes($element['value']); } else { if ($form->is_submitted() && isset($global[$element['name']]) && isset($global[$element['name'] . '_units'])) { $values = array('number' => $global[$element['name']], 'units' => $global[$element['name'] . '_units']); $bytes = $values['number'] * pieform_element_bytes_in($values['units']); } else { if (isset($element['defaultvalue'])) { $bytes = $element['defaultvalue']; $values = pieform_element_bytes_get_bytes_from_bytes($bytes); } else { $values = array('number' => '0', 'units' => 'bytes'); $bytes = 0; } } } // @todo probably create with an actual input element, as tabindex doesn't work here for one thing // Same with the select. And do the events using mochikit signal instead of dom events $numberinput = '<div class="with-dropdown js-with-dropdown text">'; $numberinput .= '<label for="' . $formname . '_' . $name . '">' . Pieform::hsc($element['title']) . ': </label><input'; $numberinput .= ' type="text" size="6" name="' . $name . '"'; $numberinput .= ' id="' . $formname . '_' . $name . '" value="' . Pieform::hsc($values['number']) . '" tabindex="' . Pieform::hsc($element['tabindex']) . '"'; $numberinput .= 'class="with-dropdown js-with-dropdown form-control text' . (isset($element['error']) ? ' error"' : '') . '"'; if (isset($element['description'])) { $numberinput .= ' aria-describedby="' . $form->element_descriptors($element) . '"'; } $numberinput .= "></div>\n"; $uselect = '<div class="dropdown-connect js-dropdown-connect select">'; $uselect .= '<label for="' . $formname . '_' . $name . '_units" class="accessible-hidden sr-only">' . get_string('units') . '</label>'; $uselect .= '<span class="picker"><select class="form-control dropdown-connect js-dropdown-connect select" name="' . $name . '_units" id="' . $formname . '_' . $name . '_units"' . ' tabindex="' . Pieform::hsc($element['tabindex']) . '"'; if (isset($element['description'])) { $uselect .= ' aria-describedby="' . $form->element_descriptors($element) . '"'; } $uselect .= ">\n"; foreach (pieform_element_bytes_get_bytes_units() as $u) { $uselect .= "\t<option value=\"{$u}\"" . ($values['units'] == $u ? ' selected="selected"' : '') . '>' . $form->i18n('element', 'bytes', $u, $element) . "</option>\n"; } $uselect .= "</select></span></div>\n"; $fieldset = '<div id="' . $formname . '_' . $name . '_fieldset" class="dropdown-group js-dropdown-group form-group">' . '<fieldset class="pieform-fieldset dropdown-group js-dropdown-group">' . $numberinput . $uselect . '</fieldset></div>'; return $fieldset; }
/** * Renders a "cancel" button. Custom buttons are rendered nearly the same as * normal submit buttons, only their name is changed (for use by the Pieform * class internally). * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_cancel(Pieform $form, $element) { /*{{{*/ if (!isset($element['value'])) { throw new PieformException('Cancel elements must have a value'); } if (isset($element['confirm'])) { $element['onclick'] = 'return confirm(' . json_encode($element['confirm']) . ');'; } $attributes = $form->element_attributes($element); $attributes = preg_replace('/name="(.*)"/', 'name="cancel_$1"', $attributes); $attributes = preg_replace('/id="(.*)"/', 'id="cancel_$1"', $attributes); return '<input type="submit"' . $attributes . ' value="' . Pieform::hsc($element['value']) . '">'; }
/** * Provides a basic text field input. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_text(Pieform $form, $element) { /*{{{*/ $value = Pieform::hsc($form->get_value($element)); $html = ''; // If hidewhenempty is set, the text box is hidden by a link which expands it. if (!empty($element['hidewhenempty']) && $value == '') { $inputid = hsc($form->get_name() . '_' . $element['name']); $linktext = $element['expandtext'] ? hsc($element['expandtext']) : get_string('edit'); $html .= '<a class="btn btn-default" href="" ' . "onclick=\"addElementClass('{$inputid}_expand', 'hidden'); removeElementClass('{$inputid}', 'hidden'); return false;\"" . "id=\"{$inputid}_expand\">" . $linktext . '</a>'; $element['class'] .= ' hidden'; } return $html . '<input type="text"' . $form->element_attributes($element) . ' value="' . $value . '">'; }
/** * Makes sure that the submitted value is specified in the 'options' index of * the element. This prevents malicious people from doing things like * submitting values that aren't in a select box. * * @param Pieform $form The form the rule is being applied to * @param string $field The field to check * @param string $element The element being checked * @return string The error message, if the value is invalid. */ function pieform_rule_validateoptions(Pieform $form, $field, $element) { /*{{{*/ // Get the value into an array as a key if it's a scalar, since // the actual check involves array keys $field = (array) $field; $options = $element['type'] == 'select' ? pieform_element_select_get_options($element) : $element['options']; $allowedvalues = array_keys($options); foreach ($field as $key) { if (!in_array($key, $allowedvalues)) { return sprintf($form->i18n('rule', 'validateoptions', 'validateoptions', $element), Pieform::hsc($key)); } } }
/** * Renders a fieldset. Fieldsets contain other elements, and do not count as a * "true" element, in that they do not have a value and cannot be validated. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_fieldset(Pieform $form, $element) { /*{{{*/ $result = "\n<fieldset"; if (!empty($element['collapsible']) || !empty($element['class'])) { if (!isset($element['legend']) || $element['legend'] === '') { Pieform::info('Collapsible fieldsets should have a legend so they can be toggled'); } $classes = array('collapsible'); // Work out whether any of the children have errors on them $error = false; foreach ($element['elements'] as $subelement) { if (isset($subelement['error'])) { $error = true; break; } } if (!empty($element['collapsed']) && !$error) { $classes[] = 'collapsed'; } if (!empty($element['class'])) { $classes[] = $element['class']; } $result .= ' class="' . implode(' ', $classes) . '"'; } $result .= ">\n"; if (isset($element['legend'])) { $result .= '<legend'; if (!empty($element['collapsible'])) { $id = substr(md5(microtime()), 0, 4); $result .= ' id="' . $id . '">'; $result .= '<script type="text/javascript">'; $result .= "var a = A({'href':'', 'tabindex':{$form->get_property('tabindex')}}, " . json_encode($element['legend']) . "); "; $result .= "connect(a, 'onclick', function(e) { toggleElementClass('collapsed', \$('{$id}').parentNode); e.stop(); });"; $result .= "replaceChildNodes('{$id}', a);</script>"; } else { $result .= '>' . Pieform::hsc($element['legend']); } $result .= "</legend>\n"; } foreach ($element['elements'] as $subname => $subelement) { if ($subelement['type'] == 'hidden') { throw new PieformError("You cannot put hidden elements in fieldsets"); } $result .= "\t" . pieform_render_element($form, $subelement); } $result .= "</fieldset>\n"; return $result; }
/** * Renders a drag & drop sortable list using Javascript and CSS. * Useful for ranking answers to a question. * * Based on ToolMan DHTML Library. See: http://tool-man.org/examples/sorting.html * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_rank(Pieform $form, $element) { /*{{{*/ $optionsavailable = true; if (!isset($element['options']) || !is_array($element['options']) || count($element['options']) < 1) { $optionsavailable = false; Pieform::info('Rank elements should have at least one option'); } if (!empty($element['collapseifoneoption']) && isset($element['options']) && is_array($element['options']) && count($element['options']) == 1) { foreach ($element['options'] as $key => $value) { if (is_array($value)) { $value = $value['value']; } $result = Pieform::hsc($value) . '<input type="hidden" name="' . Pieform::hsc($element['name']) . '" value="' . Pieform::hsc($key) . '">'; } return $result; } $result = '<ul' . $form->element_attributes($element) . ">\n"; if (!$optionsavailable) { $result .= "\t<li> </li>\n</ul>"; return $result; } // Values are serialized like: a|b|c|d // so we need to unserialze them... $values = explode('|', $form->get_value($element)); $optionselected = false; foreach ($element['options'] as $key => $value) { // Get the value to display/put in the value attribute if (is_array($value)) { if (!isset($value['value'])) { Pieform::info('No value set for option "' . $key . '" of rank element "' . $element['name'] . '"'); $value = ''; } else { $value = $value['value']; } } $result .= "\t<li itemID=\"" . Pieform::hsc($key) . "\">" . Pieform::hsc($value) . "</li>\n"; } if (!$optionselected && !is_array($values) && $values !== null) { Pieform::info('Invalid value for rank "' . $element['name'] . '"'); } $result .= '</ul>'; return $result; }
/** * Provides a size chooser, with a text box for a number and a * select box to choose the units, in bytes, kilobytes, megabytes or gigabytes * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_bytes(Pieform $form, $element) { /*{{{*/ $formname = $form->get_name(); $result = ''; $name = Pieform::hsc($element['name']); if (!isset($element['defaultvalue'])) { $element['defaultvalue'] = null; } $global = $form->get_property('method') == 'get' ? $_GET : $_POST; // Get the value of the element for rendering. if (isset($element['value'])) { $bytes = $element['value']; $values = pieform_element_bytes_get_bytes_from_bytes($element['value']); } else { if ($form->is_submitted() && isset($global[$element['name']]) && isset($global[$element['name'] . '_units'])) { $values = array('number' => $global[$element['name']], 'units' => $global[$element['name'] . '_units']); $bytes = $values['number'] * pieform_element_bytes_in($values['units']); } else { if (isset($element['defaultvalue'])) { $bytes = $element['defaultvalue']; $values = pieform_element_bytes_get_bytes_from_bytes($bytes); } else { $values = array('number' => '0', 'units' => 'bytes'); $bytes = 0; } } } // @todo probably create with an actual input element, as tabindex doesn't work here for one thing // Same with the select. And do the events using mochikit signal instead of dom events $numberinput = '<input'; $numberinput .= ' type="text" size="6" name="' . $name . '"'; $numberinput .= ' id="' . $formname . '_' . $name . '" value="' . Pieform::hsc($values['number']) . '" tabindex="' . Pieform::hsc($element['tabindex']) . '"'; $numberinput .= (isset($element['error']) ? ' class="error"' : '') . ">\n"; $uselect = '<select name="' . $name . '_units" id="' . $formname . '_' . $name . '_units"' . ' tabindex="' . Pieform::hsc($element['tabindex']) . "\">\n"; foreach (pieform_element_bytes_get_bytes_units() as $u) { $uselect .= "\t<option value=\"{$u}\"" . ($values['units'] == $u ? ' selected="selected"' : '') . '>' . $form->i18n('element', 'bytes', $u, $element) . "</option>\n"; } $uselect .= "</select>\n"; return $numberinput . $uselect; }
/** * Renders an <input type="image"> button * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_image(Pieform $form, $element) { /*{{{*/ if (!isset($element['src'])) { throw new PieformException('"image" elements must have a "src" for the image'); } if (!isset($element['value'])) { $element['value'] = true; } if (isset($element['confirm'])) { $element['onclick'] = 'return confirm(' . json_encode($element['confirm']) . ');'; } if (!isset($element['alt'])) { if (isset($element['elementtitle'])) { $element['alt'] = $element['elementtitle']; } else { $element['alt'] = ''; } } return '<input type="image" src="' . Pieform::hsc($element['src']) . '"' . ' alt="' . Pieform::hsc($element['alt']) . '"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($form->get_value($element)) . '">'; }
/** * Renders a textarea, but with extra javascript to turn it into a wysiwyg * textarea. * * @todo support resizable. * * @param array $element The element to render * @param Pieform $form The form to render the element for * @return string The HTML for the element */ function pieform_element_wysiwyg(Pieform $form, $element) { global $_PIEFORM_WYSIWYGS; $_PIEFORM_WYSIWYGS[] = $form->get_name() . '_' . $element['name']; if (is_html_editor_enabled()) { if (!$form->get_property('elementclasses')) { $element['class'] = isset($element['class']) && $element['class'] !== '' ? $element['class'] . ' wysiwyg' : 'wysiwyg'; } } $rows = $cols = $style = ''; if (isset($element['height'])) { $style .= 'height:' . $element['height'] . ';'; $rows = intval($element['height'] > 0) ? ceil(intval($element['height']) / 10) : 1; } elseif (isset($element['rows'])) { $rows = $element['rows']; } else { log_warn('No value for rows or height specified for textarea ' . $element['name']); } if (isset($element['width'])) { $style .= 'width:' . $element['width'] . ';'; $cols = intval($element['width'] > 0) ? ceil(intval($element['width']) / 10) : 1; } elseif (isset($element['cols'])) { $cols = $element['cols']; } else { log_warn('No value for cols or width specified for textarea ' . $element['name']); } $element['style'] = isset($element['style']) ? $style . $element['style'] : $style; if (is_html_editor_enabled()) { $value = Pieform::hsc($form->get_value($element)); } else { // Replace <br>s as added by wysiwyg editor or nl2br with a newline $value = preg_replace("#<br />\\s#", "\n", $form->get_value($element)); // As placed in the value by the wysiwyg editor $value = str_replace('</p><p>', "\n\n", $value); // Find the last </p> and replace with newlines $value = preg_replace('#</p>\\s#', "\n", $value); $value = strip_tags($value); } return '<textarea' . ($rows ? ' rows="' . $rows . '"' : '') . ($cols ? ' cols="' . $cols . '"' : '') . $form->element_attributes($element, array('maxlength', 'size')) . '>' . $value . '</textarea>'; }
/** * Provides a control that allows the user to input where in a list they want * to put something. Handy for indicating the order of some objects. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_weight(Pieform $form, $element) { pieform_element_weight_validate_element($element); $default = isset($element['defaultvalue']) ? intval($element['defaultvalue']) : 0; $result = '<input type="radio"' . $form->element_attributes($element) . ' value="0"'; if ($default == 0) { $result .= ' checked="checked"'; } $result .= '>'; $i = 0; foreach ($element['existing'] as $existing) { $i++; $result .= "<br>" . Pieform::hsc($existing['title']); $result .= "<br><input type=\"radio\"" . $form->element_attributes($element) . " value=\"{$i}\""; if ($i == $default) { $result .= ' checked="checked"'; } $result .= '>'; } return $result; return '<input type="text"' . $form->element_attributes($element) . ' value="' . Pieform::hsc($form->get_value($element)) . '">'; }
/** * * @package mahara * @subpackage form-element * @author Catalyst IT Ltd * @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later * @copyright For copyright information on Mahara, please see the README file distributed with this software. * */ function pieform_element_checkboxes(Pieform $form, $element) { /*{{{*/ $global = $form->get_property('method') == 'get' ? $_GET : $_POST; $submitted = $form->is_submitted(); if ($submitted) { $value = isset($global[$element['name']]) ? $global[$element['name']] : array(); } $result = ''; if (count($element['elements']) > 1) { $id = hsc($form->get_name() . '_' . $element['name']) . '_container'; $result .= '<a href="" onclick="pieform_element_checkboxes_update(\'' . $id . '\', true); return false;">' . get_string('selectall') . '</a>' . ' ' . ' <a href="" onclick="pieform_element_checkboxes_update(\'' . $id . '\', false); return false;">' . get_string('selectnone') . '</a>'; } $result .= '<div class="cl"></div>'; $element['name'] .= '[]'; // Number of characters in checkbox labels (use 0 or false for no limit). $labelwidth = isset($element['labelwidth']) ? (int) $element['labelwidth'] : 17; $elementtitle = ''; if (isset($element['title'])) { $elementtitle = '<span class="accessible-hidden">' . $element['title'] . ': </span>'; } foreach ($element['elements'] as $e) { $id = $form->get_name() . '_' . $element['id']; $idsuffix = substr(md5(microtime()), 0, 4); if (!$submitted || !empty($e['disabled'])) { $checked = $e['defaultvalue']; } else { $checked = !empty($value[$e['value']]) || in_array($e['value'], $value); } $attributes = $form->element_attributes($element); $attributes = preg_replace("/\\bid=\"{$id}\"/", "id=\"{$id}{$idsuffix}\"", $attributes); $title = $labelwidth ? str_shorten_text($e['title'], $labelwidth, true) : $e['title']; $result .= '<div class="checkboxes-option"><input type="checkbox" value="' . $e['value'] . '" ' . $attributes . ($checked ? ' checked="checked"' : '') . (!empty($e['disabled']) ? ' disabled' : '') . '>' . ' <label class="checkbox" for="' . $id . $idsuffix . '">' . $elementtitle . Pieform::hsc($title) . '</label></div>'; } $result .= '<div class="cl"></div>'; return $result; }
/** * Provides a javascript color selector for inputting a hex color value. * * General documentation about the JavaScript Color Picker (Chooser) is available at * http://jscolor.com/ * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_color(Pieform $form, $element) { $result = ''; $name = Pieform::hsc($element['name']); $baseid = Pieform::hsc($form->get_name() . '_' . $element['name']); $value = Pieform::hsc($element['defaultvalue']); $transparent = !empty($element['options']['transparent']) && $element['options']['transparent'] == true; // Transparency optional control if ($transparent) { $optional = <<<EOF <script type="application/javascript"> var {$baseid}_oldval = ''; function {$baseid}_toggle(x) { if ( x.checked ) { {$baseid}_oldval = \$('{$baseid}').value; \$('{$baseid}').value = ''; \$('{$baseid}').disabled = true; } else { \$('{$baseid}').value = {$baseid}_oldval; \$('{$baseid}').disabled = false; } } </script> EOF; $title = ''; if (!empty($element['title'])) { $title = '<span class="accessible-hidden sr-only">' . $element['title'] . ':</span>'; } $optional .= ' <input type="checkbox" ' . (isset($element['defaultvalue']) && $element['defaultvalue'] == 'transparent' ? 'checked="checked" ' : '') . 'name="' . $name . '_optional" id="' . $baseid . '_optional" onchange="' . $baseid . '_toggle(this)" ' . 'tabindex="' . Pieform::hsc($element['tabindex']) . '">'; $optional .= ' <label for="' . $baseid . '_optional">' . $title . $form->i18n('element', 'color', 'transparent', $element) . '</label> '; $result .= $optional; } // Color Picker (Chooser) $result .= '<input type="text" name="' . $name . '_color" id="' . $baseid . '"' . ($transparent && (!isset($element['defaultvalue']) || $element['defaultvalue'] == 'transparent') ? ' disabled="disabled"' : '') . ($transparent ? ' class="color {hash:true,required:false}"' : ' class="color {hash:true}"') . ' value="' . ($value == 'transparent' ? '' : $value) . '">'; return $result; }
/** * Browser for files area. * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_filebrowser(Pieform $form, $element) { require_once 'license.php'; global $USER, $_PIEFORM_FILEBROWSERS; $smarty = smarty_core(); // See if the filebrowser has indicated it's a group element if (!empty($element['group'])) { $group = $element['group']; } else { // otherwise check if the form knows it's in a group setting $group = $form->get_property('group'); } // See if the filebrowser has indicated it's an institution element if (!empty($element['institution'])) { $institution = $element['institution']; } else { // otherwise check if the form knows it's in an institution setting $institution = $form->get_property('institution'); } $formid = $form->get_name(); $prefix = $formid . '_' . $element['name']; if (!empty($element['tabs'])) { $tabdata = pieform_element_filebrowser_configure_tabs($element['tabs'], $prefix); $smarty->assign('tabs', $tabdata); if (!$group && $tabdata['owner'] == 'group') { $group = $tabdata['ownerid']; } else { if (!$institution) { if ($tabdata['owner'] == 'institution') { $institution = $tabdata['ownerid']; } else { if ($tabdata['owner'] == 'site') { $institution = 'mahara'; } } } } } $userid = $group || $institution ? null : $USER->get('id'); // refresh quotas if ($userid) { $USER->quota_refresh(); } $folder = $element['folder']; if ($group && !pieform_element_filebrowser_view_group_folder($group, $folder)) { $folder = null; } $path = pieform_element_filebrowser_get_path($folder); $smarty->assign('folder', $folder); $smarty->assign('foldername', $path[0]->title); $smarty->assign('path', array_reverse($path)); $smarty->assign('highlight', $element['highlight'][0]); $smarty->assign('edit', !empty($element['edit']) ? $element['edit'] : -1); if (isset($element['browse'])) { $smarty->assign('browse', (int) $element['browse']); } $config = array_map('intval', $element['config']); if ($group && $config['edit']) { $smarty->assign('groupinfo', pieform_element_filebrowser_get_groupinfo($group)); } if ($config['select']) { if (function_exists($element['selectlistcallback'])) { if ($form->is_submitted() && $form->has_errors() && isset($_POST[$prefix . '_selected']) && is_array($_POST[$prefix . '_selected'])) { $value = array_keys($_POST[$prefix . '_selected']); } else { if (isset($element['defaultvalue'])) { $value = $element['defaultvalue']; } else { $value = null; } } // check to see if attached artefact items in $value array are actually allowed // to be seen by this user if (!empty($value)) { foreach ($value as $k => $v) { $file = artefact_instance_from_id($v); if (!$file instanceof ArtefactTypeFile && !$file instanceof ArtefactTypeFolder || !$USER->can_view_artefact($file)) { unset($value[$k]); } } } $selected = $element['selectlistcallback']($value); } $smarty->assign('selectedlist', $selected); $selectedliststr = json_encode($selected); } if ($config['uploadagreement']) { if (get_config_plugin('artefact', 'file', 'usecustomagreement')) { $smarty->assign('agreementtext', get_field('site_content', 'content', 'name', 'uploadcopyright')); } else { $smarty->assign('agreementtext', get_string('uploadcopyrightdefaultcontent', 'install')); } } else { if (!isset($config['simpleupload'])) { $config['simpleupload'] = 1; } } $licensing = '<div class="fileuploadlicense">' . license_form_files($prefix) . '</div>'; $smarty->assign('licenseform', $licensing); if ($config['resizeonuploaduseroption'] == 1) { $smarty->assign('resizeonuploadenable', get_config_plugin('artefact', 'file', 'resizeonuploadenable')); $smarty->assign('resizeonuploadmaxwidth', get_config_plugin('artefact', 'file', 'resizeonuploadmaxwidth')); $smarty->assign('resizeonuploadmaxheight', get_config_plugin('artefact', 'file', 'resizeonuploadmaxheight')); } if ($config['upload']) { $maxuploadsize = display_size(get_max_upload_size(!$institution && !$group)); $smarty->assign('maxuploadsize', $maxuploadsize); $smarty->assign('phpmaxfilesize', get_max_upload_size(false)); if ($group) { $smarty->assign('uploaddisabled', !pieform_element_filebrowser_edit_group_folder($group, $folder)); } } if (!empty($element['browsehelp'])) { $config['plugintype'] = $form->get_property('plugintype'); $config['pluginname'] = $form->get_property('pluginname'); $config['browsehelp'] = $element['browsehelp']; } $config['showtags'] = !empty($config['tag']) ? (int) $userid : 0; $config['editmeta'] = (int) ($userid && !$config['edit'] && !empty($config['tag'])); $smarty->assign('config', $config); $filters = isset($element['filters']) ? $element['filters'] : null; $filedata = ArtefactTypeFileBase::get_my_files_data($folder, $userid, $group, $institution, $filters); $smarty->assign('filelist', $filedata); $configstr = json_encode($config); $fileliststr = json_encode($filedata); $smarty->assign('prefix', $prefix); $accepts = isset($element['accept']) ? 'accept="' . Pieform::hsc($element['accept']) . '"' : ''; $smarty->assign('accepts', $accepts); $initjs = "{$prefix} = new FileBrowser('{$prefix}', {$folder}, {$configstr}, config);\n{$prefix}.filedata = {$fileliststr};"; if ($config['select']) { $initjs .= "{$prefix}.selecteddata = {$selectedliststr};"; } if (isset($tabdata)) { $initjs .= "{$prefix}.tabdata = " . json_encode($tabdata) . ';'; } $_PIEFORM_FILEBROWSERS[$prefix]['views_js'] = $initjs; $initjs .= "addLoadEvent({$prefix}.init);"; $initjs .= "upload_max_filesize = '" . get_real_size(ini_get('upload_max_filesize')) . "';"; $smarty->assign('initjs', $initjs); $smarty->assign('querybase', $element['page'] . (strpos($element['page'], '?') === false ? '?' : '&')); $params = 'folder=' . $folder; if ($group) { $params .= '&group=' . $group; } if ($institution) { $params .= '&institution=' . $institution; } $switchwidth = ArtefactTypeFileBase::get_switch_width(); $smarty->assign('switchwidth', $switchwidth); $smarty->assign('folderparams', $params); return $smarty->fetch('artefact:file:form/filebrowser.tpl'); }