[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
classes
/
form
/
[
Home
]
File: Form.php
<?php /** * @defgroup form Form * Implements a toolkit for the server-side implementation of forms, including * initializing forms with presets, reading submitted content, validating * content, and saving the results. */ /** * @file classes/form/Form.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 Form * * @ingroup core * * @brief Class defining basic operations for handling HTML forms. */ namespace PKP\form; use APP\core\Application; use APP\notification\NotificationManager; use APP\template\TemplateManager; use PKP\core\PKPRequest; use PKP\facades\Locale; use PKP\form\validation\FormValidator; use PKP\notification\PKPNotification; use PKP\plugins\Hook; use PKP\session\SessionManager; class Form { /** @var string The template file containing the HTML form */ public $_template; /** @var array Associative array containing form data */ public $_data; /** @var array Validation checks for this form */ public $_checks; /** @var array Errors occurring in form validation */ public $_errors; /** @var array Array of field names where an error occurred and the associated error message */ public $errorsArray; /** @var array Array of field names where an error occurred */ public $errorFields; /** @var array Array of errors for the form section currently being processed */ public $formSectionErrors; /** @var array Client-side validation rules */ public $cssValidation; /** @var string Symbolic name of required locale */ public $requiredLocale; /** @var array Set of supported locales */ public $supportedLocales; /** @var string Default form locale */ public $defaultLocale; /** * Constructor. * * @param string $template the path to the form template file * @param null|mixed $requiredLocale * @param null|mixed $supportedLocales */ public function __construct($template = null, $callHooks = true, $requiredLocale = null, $supportedLocales = null) { if ($requiredLocale === null) { $requiredLocale = Locale::getPrimaryLocale(); } $this->requiredLocale = $requiredLocale; if ($supportedLocales === null) { $supportedLocales = Locale::getSupportedFormLocales(); } $this->supportedLocales = $supportedLocales; $this->defaultLocale = Locale::getLocale(); $this->_template = $template; $this->_data = []; $this->_checks = []; $this->_errors = []; $this->errorsArray = []; $this->errorFields = []; $this->formSectionErrors = []; if ($callHooks === true) { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::Constructor" // Note that class names are always lower case. $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name Hook::call(strtolower_codesafe(end($classNameParts)) . '::Constructor', [$this, &$template]); } } // // Setters and Getters // /** * Set the template * * @param string $template */ public function setTemplate($template) { $this->_template = $template; } /** * Get the template * * @return string */ public function getTemplate() { return $this->_template; } /** * Get the required locale for this form (i.e. the locale for which * required fields must be set, all others being optional) * * @return string */ public function getRequiredLocale() { return $this->requiredLocale; } // // Public Methods // /** * Display the form. * * @param PKPRequest $request * @param string $template the template to be rendered, mandatory * if no template has been specified on class instantiation. */ public function display($request = null, $template = null) { $this->fetch($request, $template, true); } /** * Returns a string of the rendered form * * @param PKPRequest $request * @param string $template the template to be rendered, mandatory * if no template has been specified on class instantiation. * @param bool $display * * @return string the rendered form */ public function fetch($request, $template = null, $display = false) { // Set custom template. if (!is_null($template)) { $this->_template = $template; } // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::display" // Note that class names are always lower case. $returner = null; $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name if (Hook::call(strtolower_codesafe(end($classNameParts)) . '::display', [$this, &$returner])) { return $returner; } $templateMgr = TemplateManager::getManager($request); $templateMgr->setCacheability(TemplateManager::CACHEABILITY_NO_STORE); $context = $request->getContext(); // Attach this form object to the Form Builder Vocabulary for validation to work $fbv = $templateMgr->getFBV(); $fbv->setForm($this); $templateMgr->assign(array_merge( $this->_data, [ 'isError' => !$this->isValid(), 'errors' => $this->getErrorsArray(), 'formLocales' => $this->supportedLocales, 'formLocale' => $this->getDefaultFormLocale(), ] )); if (!$templateMgr->getTemplateVars('primaryLocale')) { $templateMgr->assign([ 'primaryLocale' => $context ? $context->getPrimaryLocale() : (Application::isInstalled() ? $request->getSite()->getPrimaryLocale() : null), ]); } if ($display) { $templateMgr->display($this->_template); $returner = null; } else { $returner = $templateMgr->fetch($this->_template); } // Reset the FBV's form in case template manager fetches another template not within a form. $fbv->setForm(null); return $returner; } /** * Get the value of a form field. * * @param string $key * * @return mixed */ public function getData($key) { return $this->_data[$key] ?? null; } /** * Set the value of one or several form fields. * * @param string|array $key If a string, then set a single field. If an associative array, then set many. * @param null|mixed $value */ public function setData($key, $value = null) { if (is_array($key)) { foreach ($key as $aKey => $aValue) { $this->setData($aKey, $aValue); } } else { $this->_data[$key] = $value; } } /** * Initialize form data for a new form. */ public function initData() { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::initData" // Note that class and function names are always lower // case. $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name Hook::call(strtolower_codesafe(end($classNameParts) . '::initData'), [$this]); } /** * Assign form data to user-submitted data. * Can be overridden from subclasses. */ public function readInputData() { // Default implementation does nothing. } /** * Validate form data. * * @param bool $callHooks True (default) iff hooks are to be called. */ public function validate($callHooks = true) { if (!isset($this->errorsArray)) { $this->getErrorsArray(); } foreach ($this->_checks as $check) { if (!isset($this->errorsArray[$check->getField()]) && !$check->isValid()) { if (method_exists($check, 'getErrorFields') && method_exists($check, 'isArray') && call_user_func([&$check, 'isArray'])) { $errorFields = call_user_func([&$check, 'getErrorFields']); for ($i = 0, $count = count($errorFields); $i < $count; $i++) { $this->addError($errorFields[$i], $check->getMessage()); $this->errorFields[$errorFields[$i]] = 1; } } else { $this->addError($check->getField(), $check->getMessage()); $this->errorFields[$check->getField()] = 1; } } } if ($callHooks === true) { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::validate" // Note that class and function names are always lower // case. $value = null; $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name if (Hook::call(strtolower_codesafe(end($classNameParts) . '::validate'), [$this, &$value])) { return $value; } } if (!SessionManager::isDisabled()) { $request = Application::get()->getRequest(); $user = $request->getUser(); if (!$this->isValid() && $user) { // Create a form error notification. $notificationManager = new NotificationManager(); $notificationManager->createTrivialNotification( $user->getId(), PKPNotification::NOTIFICATION_TYPE_FORM_ERROR, ['contents' => $this->getErrorsArray()] ); } } return $this->isValid(); } /** * Execute the form's action. * (Note that it is assumed that the form has already been validated.) * * @return mixed Result from the consumer to be passed to the caller. Send a true-ish result if you want the caller to do something with the return value. */ public function execute(...$functionArgs) { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::execute" // Note that class and function names are always lower // case. $returner = null; $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name Hook::call(strtolower_codesafe(end($classNameParts) . '::execute'), array_merge([$this], $functionArgs, [&$returner])); return $returner; } /** * Get the list of field names that need to support multiple locales * * @return array */ public function getLocaleFieldNames() { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::getLocaleFieldNames" // Note that class and function names are always lower // case. $returner = []; $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name Hook::call(strtolower_codesafe(end($classNameParts) . '::getLocaleFieldNames'), [$this, &$returner]); return $returner; } /** * Get the default form locale. * * @return string */ public function getDefaultFormLocale() { $formLocale = $this->defaultLocale; if (!isset($this->supportedLocales[$formLocale])) { $formLocale = $this->requiredLocale; } return $formLocale; } /** * Set the default form locale. * * @param string $defaultLocale */ public function setDefaultFormLocale($defaultLocale) { $this->defaultLocale = $defaultLocale; } /** * Add a supported locale. * * @param string $supportedLocale */ public function addSupportedFormLocale($supportedLocale) { if (!in_array($supportedLocale, $this->supportedLocales)) { $site = Application::get()->getRequest()->getSite(); $siteSupportedLocales = $site->getSupportedLocaleNames(); if (array_key_exists($supportedLocale, $siteSupportedLocales)) { $this->supportedLocales[$supportedLocale] = $siteSupportedLocales[$supportedLocale]; } } } /** * Adds specified user variables to input data. * * @param array $vars the names of the variables to read */ public function readUserVars($vars) { // Call hooks based on the calling entity, assuming // this method is only called by a subclass. Results // in hook calls named e.g. "papergalleyform::readUserVars" // Note that class and function names are always lower // case. $classNameParts = explode('\\', get_class($this)); // Separate namespace info from class name Hook::call(strtolower_codesafe(end($classNameParts) . '::readUserVars'), [$this, &$vars]); $request = Application::get()->getRequest(); foreach ($vars as $k) { $this->setData($k, $request->getUserVar($k)); } } /** * Add a validation check to the form. * * @param FormValidator $formValidator */ public function addCheck($formValidator) { $this->_checks[] = & $formValidator; } /** * Add an error to the form. * Errors are typically assigned as the form is validated. * * @param string $field the name of the field where the error occurred */ public function addError($field, $message) { $this->_errors[] = new FormError($field, $message); } /** * Add an error field for highlighting on form * * @param string $field the name of the field where the error occurred */ public function addErrorField($field) { $this->errorFields[$field] = 1; } /** * Check if form passes all validation checks. * * @return bool */ public function isValid() { return empty($this->_errors); } /** * Return set of errors that occurred in form validation. * If multiple errors occurred processing a single field, only the first error is included. * * @return array erroneous fields and associated error messages */ public function getErrorsArray() { $this->errorsArray = []; foreach ($this->_errors as $error) { if (!isset($this->errorsArray[$error->getField()])) { $this->errorsArray[$error->getField()] = $error->getMessage(); } } return $this->errorsArray; } // // Private helper methods // /** * Convert PHP variable (literals or arrays) into HTML containing * hidden input fields. * * @param string $name Name of variable * @param mixed $value Value of variable * @param array $stack Names of array keys (for recursive calling) * * @return string HTML hidden form elements describing the parameters. */ public function _decomposeArray($name, $value, $stack) { $returner = ''; if (is_array($value)) { foreach ($value as $key => $subValue) { $newStack = $stack; $newStack[] = $key; $returner .= $this->_decomposeArray($name, $subValue, $newStack); } } else { $name = htmlentities($name, ENT_COMPAT); $value = htmlentities($value, ENT_COMPAT); $returner .= '<input type="hidden" name="' . $name; while (($item = array_shift($stack)) !== null) { $item = htmlentities($item, ENT_COMPAT); $returner .= '[' . $item . ']'; } $returner .= '" value="' . $value . "\" />\n"; } return $returner; } } if (!PKP_STRICT_MODE) { class_alias('\PKP\form\Form', '\Form'); }