<?php
/**
* @defgroup FormBuilderVocabulary Form Builder Vocabulary
* Implements a form construction toolkit for generating standard form markup.
*/
/**
* @file classes/form/FormBuilderVocabulary.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class FormBuilderVocabulary
*
* @ingroup core
*
* @brief Class defining Form Builder Vocabulary methods.
*
* Form Builder Vocabulary - FBV
* Generates form markup in templates using {fbvX} calls.
* Group form areas with the {fbvFormArea} call. These sections mark off groups of semantically
* related form sections.
* Parameters:
* id: The form area ID
* class (optional): Any additional classes
* title (optional): Title of the area
* Group form sections with the {fbvFormSection} call. These sections organize directly related form elements.
* Parameters:
* id: The section ID
* class (optional): Any additional classes
* title (optional): Title of the area
* Form submit/cancel buttons should be created with {fbvFormButtons}
* Parameters:
* submitText (optional): Text to display for the submit link (default is 'Ok')
* submitDisabled (optional): Whether the submit button should be disabled
* confirmSubmit (optional): Text to display in a confirmation dialog that must be okayed
* before the form is submitted
* cancelText (optional): Text to display for the cancel link (default is 'Cancel')
* hideCancel (optional): Whether the submit button should be disabled
* cancelAction (optional): A LinkAction object to execute when cancel is clicked
* cancelUrl (optional): URL to redirect to when cancel is clicked
* Form elements are created with {fbvElement type="type"} plus any additional parameters.
* Each specific element type may have other additional attributes (see their method comments)
* Parameters:
* type: The form element type (one of the cases in the smartyFBVElement method)
* id: The element ID
* class (optional): Any additional classes
* required (optional) whether the section should have a 'required' label (adds span.required)
* for (optional): What the section's label is for
* inline: Adds .inline to the element's parent container and causes it to display inline with other elements
* size: One of $fbvStyles.size.SMALL (adds .quarter to element's parent container) or $fbvStyles.size.MEDIUM (adds
* .half to element's parentcontainer)
* required: Adds an asterisk and a .required class to the element's label
*/
namespace PKP\form;
use Exception;
class FormBuilderVocabulary
{
/** @var Form associated with this object, if any. Will inform smarty which forms to label as required */
public $_form;
/** @var array Styles organized by parameter name */
public $_fbvStyles;
/**
* Constructor.
*
* @param object $form Form associated with this object
*/
public function __construct($form = null)
{
$this->_fbvStyles = [
'size' => ['SMALL' => 'SMALL', 'MEDIUM' => 'MEDIUM', 'LARGE' => 'LARGE'],
'height' => ['SHORT' => 'SHORT', 'MEDIUM' => 'MEDIUM', 'TALL' => 'TALL']
];
}
//
// Setters and Getters
//
/**
* Set the form
*
* @param object $form
*/
public function setForm($form)
{
if ($form) {
assert($form instanceof \PKP\form\Form);
}
$this->_form = $form;
}
/**
* Get the form
*
* @return Form
*/
public function getForm()
{
return $this->_form;
}
/**
* Get the form style constants
*
* @return array
*/
public function getStyles()
{
return $this->_fbvStyles;
}
//
// Public Methods
//
/**
* A form area that contains form sections.
*
* @param array $params
* @param string $content
* @param object $smarty
* @param bool $repeat
*/
public function smartyFBVFormArea($params, $content, $smarty, &$repeat)
{
assert(isset($params['id']));
if (!$repeat) {
$smarty->assign([
'FBV_class' => $params['class'] ?? null,
'FBV_id' => $params['id'],
'FBV_content' => $content ?? null,
'FBV_translate' => $params['translate'] ?? true,
'FBV_title' => $params['title'] ?? null,
]);
return $smarty->fetch('form/formArea.tpl');
}
return '';
}
/**
* A form section that contains controls in a variety of layout possibilities.
*
* @param array $params
* @param string $content
* @param object $smarty
* @param bool $repeat
*/
public function smartyFBVFormSection($params, $content, $smarty, &$repeat)
{
$form = $this->getForm();
if (!$repeat) {
$smarty->assign('FBV_required', $params['required'] ?? false);
$smarty->assign('FBV_id', $params['id'] ?? null);
// Since $content will contain input fields that may have unique Ids appended, the 'for'
// attribute on the form section's label needs to include this. Look for the assigned
// form element within $content and extract the full id. Default to the passed in param
// otherwise.
if (!empty($params['for'])) {
if (preg_match('/id="(' . preg_quote($params['for'], '/') . '\-[^"]+)"/', $content, $matches)) {
$smarty->assign('FBV_labelFor', $matches[1]);
} else {
$smarty->assign('FBV_labelFor', $params['for']);
}
} else {
$smarty->assign('FBV_labelFor', null);
}
$smarty->assign([
'FBV_title' => $params['title'] ?? null,
'FBV_label' => $params['label'] ?? null,
'FBV_layoutInfo' => $this->_getLayoutInfo($params),
'FBV_description' => $params['description'] ?? null,
'FBV_content' => $content ?? null,
'FBV_translate' => $params['translate'] ?? true,
]);
$class = $params['class'] ?? null;
// Check if we are using the Form class and if there are any errors
if (isset($form) && !empty($form->formSectionErrors)) {
$class = $class . (empty($class) ? '' : ' ') . 'error';
$smarty->assign('FBV_sectionErrors', $form->formSectionErrors);
$form->formSectionErrors = [];
} else {
$smarty->assign('FBV_sectionErrors', null);
}
// If we are displaying checkboxes or radio options, we'll need to use a
// list to organize our elements -- Otherwise we use divs and spans
if (isset($params['list']) && $params['list'] != false) {
$smarty->assign('FBV_listSection', true);
} else {
// Double check that we don't have lists in the content.
// This is a kludge but the only way to make sure we've
// set the list parameter when we're using lists
if (substr(trim($content), 0, 4) == '<li>') {
throw new Exception('FBV: list attribute not set on form section containing lists');
}
$smarty->assign('FBV_listSection', false);
}
$smarty->assign('FBV_class', $class);
$smarty->assign('FBV_layoutColumns', empty($params['layout']) ? false : true);
return $smarty->fetch('form/formSection.tpl');
} else {
if (isset($form)) {
$form->formSectionErrors = [];
}
}
return '';
}
/**
* Submit and (optional) cancel button for a form.
*
* @param array $params
* @param object $smarty
*/
public function smartyFBVFormButtons($params, $smarty)
{
$smarty->assign([
'FBV_submitText' => $params['submitText'] ?? 'common.ok',
'FBV_submitDisabled' => isset($params['submitDisabled']) ? (bool)$params['submitDisabled'] : false,
'FBV_confirmSubmit' => $params['confirmSubmit'] ?? null,
'FBV_cancelText' => $params['cancelText'] ?? 'common.cancel',
'FBV_hideCancel' => isset($params['hideCancel']) ? (bool)$params['hideCancel'] : false,
'FBV_cancelAction' => $params['cancelAction'] ?? null,
'FBV_cancelUrl' => $params['cancelUrl'] ?? null,
'FBV_cancelUrlTarget' => $params['cancelUrlTarget'] ?? '',
'FBV_translate' => $params['translate'] ?? true,
'FBV_saveText' => $params['saveText'] ?? null,
]);
return $smarty->fetch('form/formButtons.tpl');
}
/**
* Base form element.
*
* @param array $params
* @param object $smarty
* @param null|mixed $content
*/
public function smartyFBVElement($params, $smarty, $content = null)
{
if (!isset($params['type'])) {
throw new Exception('FBV: Element type not set');
}
if (!isset($params['id'])) {
throw new Exception('FBV: Element ID not set');
}
// Set up the element template
$smarty->assign([
'FBV_id' => $params['id'],
'FBV_class' => $params['class'] ?? null,
'FBV_required' => $params['required'] ?? false,
'FBV_layoutInfo' => $this->_getLayoutInfo($params),
'FBV_label' => $params['label'] ?? null,
'FBV_for' => $params['for'] ?? null,
'FBV_tabIndex' => $params['tabIndex'] ?? null,
'FBV_translate' => $params['translate'] ?? true,
'FBV_keepLabelHtml' => $params['keepLabelHtml'] ?? false,
]);
// Unset these parameters so they don't get assigned twice
unset($params['class']);
// Find fields that the form class has marked as required and add the 'required' class to them
$params = $this->_addClientSideValidation($params);
$smarty->assign('FBV_validation', $params['validation'] ?? null);
// Set up the specific field's template
switch (strtolower_codesafe($params['type'])) {
case 'autocomplete':
$content = $this->_smartyFBVAutocompleteInput($params, $smarty);
break;
case 'button':
case 'submit':
$content = $this->_smartyFBVButton($params, $smarty);
break;
case 'checkbox':
$content = $this->_smartyFBVCheckbox($params, $smarty);
unset($params['label']);
break;
case 'checkboxgroup':
$content = $this->_smartyFBVCheckboxGroup($params, $smarty);
unset($params['label']);
break;
case 'file':
$content = $this->_smartyFBVFileInput($params, $smarty);
break;
case 'hidden':
$content = $this->_smartyFBVHiddenInput($params, $smarty);
break;
case 'keyword':
$content = $this->_smartyFBVKeywordInput($params, $smarty);
break;
case 'interests':
$content = $this->_smartyFBVInterestsInput($params, $smarty);
break;
case 'radio':
$content = $this->_smartyFBVRadioButton($params, $smarty);
unset($params['label']);
break;
case 'email':
case 'search':
case 'tel':
case 'text':
case 'url':
$content = $this->_smartyFBVTextInput($params, $smarty);
break;
case 'select':
$content = $this->_smartyFBVSelect($params, $smarty);
break;
case 'textarea':
$content = $this->_smartyFBVTextArea($params, $smarty);
break;
default: assert(false);
}
unset($params['type']);
return $content;
}
//
// Private methods
//
/**
* Form button.
* parameters: label (or value), disabled (optional), type (optional)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVButton($params, $smarty)
{
// the type of this button. the default value is 'button' (but could be 'submit')
$buttonParams = '';
$smarty->assign(['FBV_label' => null, 'FBV_disabled' => false]);
foreach ($params as $key => $value) {
switch ($key) {
case 'inline':
case 'translate':
break;
case 'label':
case 'type':
case 'disabled':
$smarty->assign('FBV_' . $key, $value);
break;
default: $buttonParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_buttonParams', $buttonParams);
return $smarty->fetch('form/button.tpl');
}
/**
* Form Autocomplete text input. (actually two inputs, label and value)
* parameters: disabled (optional), name (optional - assigned value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVAutocompleteInput($params, $smarty)
{
assert(isset($params['autocompleteUrl']) && isset($params['id']));
// This id will be used for the hidden input that should be read by the Form.
$autocompleteId = $params['id'];
// We then override the id parameter to differentiate it from the hidden element
// and make sure that the text input is not read by the Form class.
$params['id'] = $autocompleteId . '_input';
// We set this now, so that we unset the param for the text input.
$smarty->assign([
'FBV_autocompleteUrl' => $params['autocompleteUrl'],
'FBV_autocompleteValue' => $params['autocompleteValue'] ?? null,
'FBV_disableSync' => isset($params['disableSync']) ? true : null,
]);
unset($params['autocompleteUrl'], $params['autocompleteValue']);
$smarty->assign([
'FBV_textInput' => $this->_smartyFBVTextInput($params, $smarty),
'FBV_id' => $autocompleteId,
]);
return $smarty->fetch('form/autocompleteInput.tpl');
}
/**
* Form text input.
* parameters: disabled (optional), name (optional - assigned value of 'id' by default), multilingual (optional)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVTextInput($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['subLabelTranslate'] = isset($params['subLabelTranslate']) ? (bool) $params['subLabelTranslate'] : true;
$params['uniqId'] = uniqid();
$textInputParams = '';
$smarty->assign([
'FBV_isPassword' => isset($params['password']) ? true : false,
'FBV_isTypeURL' => $params['type'] === 'url' ? true : false,
'FBV_isTypeSearch' => $params['type'] === 'search' ? true : false,
'FBV_isTypeEmail' => $params['type'] === 'email' ? true : false,
'FBV_isTypeTel' => $params['type'] === 'tel' ? true : false,
'FBV_disabled' => false,
'FBV_readonly' => false,
'FBV_multilingual' => false,
'FBV_name' => null,
'FBV_value' => null,
'FBV_label_content' => null,
'FBV_uniqId' => null,
'FBV_urlValidationErrorMessage' => null,
]);
foreach ($params as $key => $value) {
switch ($key) {
case 'label':
$smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
case 'type':
case 'size':
case 'inline':
case 'subLabelTranslate':
break;
case 'urlValidationErrorMsg':
if ($params['type'] === 'url') {
$smarty->assign('FBV_urlValidationErrorMessage', __($value));
}
break;
case 'placeholder':
$textInputParams .= 'placeholder="' . htmlspecialchars(__($value), ENT_QUOTES) . '" ';
break;
case 'disabled':
case 'readonly':
case 'multilingual':
case 'name':
case 'id':
case 'value':
case 'uniqId':
$smarty->assign('FBV_' . $key, $value);
break;
case 'required':
$smarty->assign('FBV_' . $key, $value);
break;
case 'validation':
$smarty->assign('FBV_' . $key, $value);
// no break
default:
$textInputParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_textInputParams', $textInputParams);
return $smarty->fetch('form/textInput.tpl');
}
/**
* Form text area.
* parameters:
* - value: string for single language inputs, array (xx_YY => language_value) for multilingual
* - name: string (optional - assigned value based on ID by default)
* - disabled: boolean (default false)
* - multilingual: boolean (default false)
* - rich: false (default), true, or 'extended'
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVTextArea($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['rows'] = $params['rows'] ?? 10;
$params['cols'] = $params['cols'] ?? 80;
$params['subLabelTranslate'] = isset($params['subLabelTranslate']) ? (bool) $params['subLabelTranslate'] : true;
$params['uniqId'] = uniqid();
$textAreaParams = '';
$smarty->assign([
'FBV_label_content' => null,
'FBV_disabled' => false,
'FBV_readonly' => false,
'FBV_multilingual' => false,
'FBV_value' => null,
'FBV_height' => null,
'FBV_rich' => false,
'FBV_variables' => null,
'FBV_variablesType' => null,
]);
foreach ($params as $key => $value) {
switch ($key) {
case 'name':
case 'value':
case 'rows':
case 'cols':
case 'rich':
case 'disabled':
case 'readonly':
case 'multilingual':
case 'uniqId':
case 'variablesType':
case 'variables':
case 'required':
$smarty->assign('FBV_' . $key, $value);
break;
case 'label': $smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
case 'type': break;
case 'size': break;
case 'inline': break;
case 'subLabelTranslate': break;
case 'height':
$styles = $this->getStyles();
switch ($value) {
case $styles['height']['SHORT']: $smarty->assign('FBV_height', 'short');
break;
case $styles['height']['MEDIUM']: $smarty->assign('FBV_height', 'medium');
break;
case $styles['height']['TALL']: $smarty->assign('FBV_height', 'tall');
break;
default:
throw new Exception('FBV: invalid height specified for textarea.');
}
break;
case 'id': break; // if we don't do this, the textarea ends up with two id attributes because FBV_id is also set.
default: $textAreaParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars((string) $value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_textAreaParams', $textAreaParams);
return $smarty->fetch('form/textarea.tpl');
}
/**
* Hidden input element.
* parameters: value, id, name (optional - assigned value of 'id' by default), disabled (optional), multilingual (optional)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVHiddenInput($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$hiddenInputParams = '';
$smarty->assign(['FBV_id' => null, 'FBV_value' => null]);
foreach ($params as $key => $value) {
switch ($key) {
case 'name':
case 'id':
case 'value':
$smarty->assign('FBV_' . $key, $value);
break;
case 'label': break;
case 'type': break;
default: $hiddenInputParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_hiddenInputParams', $hiddenInputParams);
return $smarty->fetch('form/hiddenInput.tpl');
}
/**
* Form select control.
* parameters: from [array], selected [array index], defaultLabel (optional), defaultValue (optional), disabled (optional),
* translate (optional), name (optional - value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVSelect($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['translate'] = $params['translate'] ?? true;
$params['subLabelTranslate'] = isset($params['subLabelTranslate']) ? (bool) $params['subLabelTranslate'] : true;
$selectParams = '';
$smarty->assign([
'FBV_label' => null,
'FBV_from' => null,
'FBV_selected' => null,
'FBV_label_content' => null,
'FBV_defaultValue' => null,
'FBV_defaultLabel' => null,
'FBV_required' => false,
'FBV_disabled' => false,
]);
foreach ($params as $key => $value) {
switch ($key) {
case 'from':
case 'selected':
case 'translate':
case 'defaultValue':
case 'defaultLabel':
case 'disabled':
case 'required':
$smarty->assign('FBV_' . $key, $value);
break;
case 'type':
case 'inline':
case 'size':
break;
case 'subLabelTranslate': break;
case 'label': $smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
default: $selectParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value ?? '', ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_selectParams', $selectParams);
return $smarty->fetch('form/select.tpl');
}
/**
* Form checkbox group control.
* parameters: from [array], selected [array index], defaultLabel (optional), defaultValue (optional), disabled (optional),
* translate (optional), name (optional - value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVCheckboxGroup($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['translate'] = isset($params['translate']) ? (bool)$params['translate'] : true;
$params['subLabelTranslate'] = isset($params['subLabelTranslate']) ? (bool) $params['subLabelTranslate'] : true;
$checkboxParams = '';
$smarty->assign(['FBV_from' => null, 'FBV_selected' => false, 'FBV_label_content' => null, 'FBV_defaultValue' => null, 'FBV_defaultLabel' => null]);
foreach ($params as $key => $value) {
switch ($key) {
case 'from':
case 'selected':
case 'defaultValue':
case 'defaultLabel':
case 'translate':
case 'name':
case 'validation':
case 'disabled':
$smarty->assign('FBV_' . $key, $value);
break;
case 'type': break;
case 'inline': break;
case 'subLabelTranslate': break;
default: $checkboxParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_checkboxParams', $checkboxParams);
return $smarty->fetch('form/checkboxGroup.tpl');
}
/**
* Checkbox input control.
* parameters: label, disabled (optional), translate (optional), name (optional - value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVCheckbox($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['translate'] = isset($params['translate']) ? (bool)$params['translate'] : true;
$checkboxParams = '';
$smarty->assign(['FBV_id' => null, 'FBV_label' => null, 'FBV_checked' => false, 'FBV_disabled' => false]);
foreach ($params as $key => $value) {
switch ($key) {
case 'type': break;
case 'id':
case 'label':
case 'translate':
case 'checked':
case 'disabled':
$smarty->assign('FBV_' . $key, $value);
break;
default: $checkboxParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_checkboxParams', $checkboxParams);
return $smarty->fetch('form/checkbox.tpl');
}
/**
* Radio input control.
* parameters: label, disabled (optional), translate (optional), name (optional - value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVRadioButton($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['translate'] = $params['translate'] ?? true;
if (isset($params['label']) && isset($params['content'])) {
throw new Exception('FBV: radio button cannot have both a content and a label parameter. Label has precedence.');
}
$radioParams = '';
$smarty->assign(['FBV_id' => null, 'FBV_label' => null, 'FBV_content' => null, 'FBV_checked' => false, 'FBV_disabled' => false]);
foreach ($params as $key => $value) {
switch ($key) {
case 'type': break;
case 'id':
case 'label':
case 'translate':
case 'checked':
case 'disabled':
case 'content':
$smarty->assign('FBV_' . $key, $value);
break;
default: $radioParams .= htmlspecialchars($key, ENT_QUOTES) . '="' . htmlspecialchars($value, ENT_QUOTES) . '" ';
}
}
$smarty->assign('FBV_radioParams', $radioParams);
return $smarty->fetch('form/radioButton.tpl');
}
/**
* File upload input.
* parameters: submit (optional - name of submit button to include), disabled (optional), name (optional - value of 'id' by default)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVFileInput($params, $smarty)
{
$params['name'] = $params['name'] ?? $params['id'];
$params['translate'] = $params['translate'] ?? true;
$smarty->assign(['FBV_id' => null, 'FBV_label_content' => null, 'FBV_checked' => false, 'FBV_disabled' => false, 'FBV_submit' => null]);
foreach ($params as $key => $value) {
switch ($key) {
case 'type': break;
case 'id':
case 'submit':
case 'name':
case 'disabled':
$smarty->assign('FBV_' . $key, $value);
break;
case 'label': $smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
}
}
return $smarty->fetch('form/fileInput.tpl');
}
/**
* Keyword input.
* parameters: available - all available keywords (for autosuggest); current - user's current keywords
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVKeywordInput($params, $smarty)
{
$params['uniqId'] = uniqid();
$smarty->assign(['FBV_id' => null, 'FBV_label' => null, 'FBV_label_content' => null, 'FBV_currentKeywords' => null, 'FBV_multilingual' => false, 'FBV_sourceUrl' => null, 'FBV_disabled' => false]);
$emptyFormLocaleMap = array_fill_keys(array_keys($smarty->getTemplateVars('formLocales')), []);
$smarty->assign('FBV_availableKeywords', $emptyFormLocaleMap);
foreach ($params as $key => $value) {
switch ($key) {
case 'type': break;
case 'id':
case 'uniqId':
case 'disabled':
case 'multilingual':
$smarty->assign('FBV_' . $key, $value);
break;
case 'label': $smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
case 'available': $smarty->assign(
'FBV_availableKeywords',
$thing = array_merge(
$emptyFormLocaleMap,
$value
)
);
break;
case 'current': $smarty->assign('FBV_currentKeywords', $value);
break;
case 'sourceUrl': $smarty->assign('FBV_sourceUrl', $value);
break;
}
}
return $smarty->fetch('form/keywordInput.tpl');
}
/**
* Reviewing interests input.
* parameters: interests - current users's keywords (array)
*
* @param array $params
* @param object $smarty
*/
public function _smartyFBVInterestsInput($params, $smarty)
{
$smarty->assign(['FBV_id' => null, 'FBV_label' => null, 'FBV_label_content' => null, 'FBV_interests' => null]);
$params['subLabelTranslate'] = isset($params['subLabelTranslate']) ? (bool) $params['subLabelTranslate'] : true;
foreach ($params as $key => $value) {
switch ($key) {
case 'type': break;
case 'id':
case 'interests':
$smarty->assign('FBV_' . $key, $value);
break;
case 'label': $smarty->assign('FBV_label_content', $this->_smartyFBVSubLabel($params, $smarty));
break;
}
}
return $smarty->fetch('form/interestsInput.tpl');
}
/**
* Custom Smarty function for labelling/highlighting of form fields.
*
* @param array $params can contain 'name' (field name/ID), 'required' (required field), 'key' (localization key), 'label' (non-localized label string), 'suppressId' (boolean)
* @param \Smarty $smarty
*/
public function _smartyFBVSubLabel($params, $smarty)
{
assert(isset($params['label']));
$returner = '';
$smarty->assign(['FBV_suppressId' => null, 'FBV_label' => null, 'FBV_required' => false, 'FBV_uniqId' => null, 'FBV_multilingual' => false]);
foreach ($params as $key => $value) {
switch ($key) {
case 'subLabelTranslate': $smarty->assign('FBV_subLabelTranslate', $value);
break;
case 'label':
case 'uniqId':
case 'multilingual':
case 'suppressId':
case 'required':
$smarty->assign('FBV_' . $key, $value);
break;
}
}
$form = $this->getForm();
if (isset($form) && isset($form->errorFields[$params['name']])) {
$smarty->assign('FBV_error', true);
$errors = $form->getErrorsArray();
$smarty->assign('FBV_subLabelTranslate', false);
$smarty->assign('FBV_label', $errors[$params['name']]);
} else {
$smarty->assign('FBV_error', false);
}
$returner = $smarty->fetch('form/subLabel.tpl');
return $returner;
}
/**
* Assign the appropriate class name to the element for client-side validation
*
* @param array $params
* return array
*/
public function _addClientSideValidation($params)
{
$form = $this->getForm();
if (isset($form)) {
// Assign the appropriate class name to the element for client-side validation
$fieldId = $params['id'];
if (isset($form->cssValidation[$fieldId])) {
$params['validation'] = implode(' ', $form->cssValidation[$fieldId]);
}
}
return $params;
}
/**
* Cycle through layout parameters to add the appropriate classes to the element's parent container
*
* @param array $params
*
* @return string
*/
public function _getLayoutInfo($params)
{
$classes = [];
foreach ($params as $key => $value) {
switch ($key) {
case 'size':
switch ($value) {
case 'SMALL': $classes[] = 'pkp_helpers_quarter';
break;
case 'MEDIUM': $classes[] = 'pkp_helpers_half';
break;
case 'LARGE': $classes[] = 'pkp_helpers_threeQuarter';
break;
}
break;
case 'inline':
if ($value) {
$classes[] = 'inline';
} break;
}
}
if (!empty($classes)) {
return implode(' ', $classes);
} else {
return null;
}
}
/**
* Custom Smarty function for labelling/highlighting of form fields.
*
* @param array $params can contain 'name' (field name/ID), 'required' (required field), 'key' (localization key), 'label' (non-localized label string), 'suppressId' (boolean)
* @param \Smarty $smarty
*/
public function smartyFieldLabel($params, $smarty)
{
$returner = '';
if (isset($params) && !empty($params)) {
if (isset($params['key'])) {
$params['label'] = __($params['key'], $params ?? []);
}
$form = $this->getForm();
if (isset($form) && isset($form->errorFields[$params['name']])) {
$smarty->assign('FBV_class', 'error ' . $params['class']);
} else {
$smarty->assign('FBV_class', $params['class']);
}
$smarty->assign(['FBV_suppressId' => null, 'FBV_label' => null, 'FBV_required' => false, 'FBV_disabled' => false, 'FBV_name' => null]);
foreach ($params as $key => $value) {
switch ($key) {
case 'label':
case 'required':
case 'suppressId':
case 'disabled':
case 'name':
$smarty->assign('FBV_' . $key, $value);
break;
}
}
$returner = $smarty->fetch('form/fieldLabel.tpl');
}
return $returner;
}
}
if (!PKP_STRICT_MODE) {
class_alias('\PKP\form\FormBuilderVocabulary', '\FormBuilderVocabulary');
}
|