1: <?php
2: /**
3: * This file is part of the PHPLucidFrame library.
4: * Core utility for AJAX form handling and form validation
5: *
6: * @package PHPLucidFrame\Core
7: * @since PHPLucidFrame v 1.0.0
8: * @copyright Copyright (c), PHPLucidFrame.
9: * @link http://phplucidframe.com
10: * @license http://www.opensource.org/licenses/mit-license.php MIT License
11: *
12: * This source file is subject to the MIT license that is bundled
13: * with this source code in the file LICENSE
14: */
15:
16: namespace LucidFrame\Core;
17:
18: /**
19: * Core utility for AJAX form handling and form validation
20: */
21: class Form
22: {
23: /** @var string The HTML form ID */
24: private static $id;
25: /** @var array The error messages and their associated HTML ID */
26: private static $error = array();
27: /** @var boolean TRUE/FALSE for form validation success */
28: private static $success = false;
29: /** @var string The form message */
30: private static $message = '';
31: /** @var string URL to be redirect upon form submission completed */
32: private static $redirect = '';
33: /** @var string The Javascript callback function to be invoked upon form submission completed */
34: private static $callback = '';
35: /** @var array Array of data that need to send to the client */
36: private static $data = array();
37:
38: /**
39: * Constructor
40: */
41: public static function init()
42: {
43: self::$id = '';
44: self::$error = array();
45: self::$success = false;
46: self::$message = '';
47: self::$redirect = '';
48: self::$callback = '';
49: self::$data = array();
50: }
51:
52: /**
53: * Setter for the class properties
54: * @param string $key The property name
55: * @param mixed $value The value to be set
56: * @return void
57: */
58: public static function set($key, $value = '')
59: {
60: self::$$key = $value;
61: }
62:
63: /**
64: * Getter for the class properties
65: * @param string $key The property name
66: * @param mixed $value The default value for the property
67: * @return mixed
68: */
69: public static function get($key, $value = null)
70: {
71: if (isset(self::$$key)) {
72: return self::$$key;
73: }
74:
75: return $value;
76: }
77:
78: /**
79: * Form token generation
80: * @return void
81: */
82: public static function token()
83: {
84: $token = _randomCode(32);
85: session_set(_cfg('formTokenName'), $token);
86: echo '<input type="hidden" name="lc_formToken_' . _cfg('formTokenName') . '" value="' . $token . '" />';
87: }
88:
89: /**
90: * Form token validation
91: * @param array $validations The array of validation rules
92: * @param array $data The optional data array (if no `value` in $validation, it will be looked up in $data)
93: * @return boolean
94: */
95: public static function validate($validations = null, $data = [])
96: {
97: if (!isset($_POST['lc_formToken_' . _cfg('formTokenName')])) {
98: Validation::addError('', _t('Invalid form token.'));
99: return false;
100: }
101:
102: $token = session_get(_cfg('formTokenName'));
103: $postedToken = _post('lc_formToken_' . _cfg('formTokenName'));
104: $result = false;
105: # check token first
106: if ($token == $postedToken) {
107: # check referer if it is requesting in the same site
108: if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER'] && _cfg('siteDomain')) {
109: $siteDomain = _cfg('siteDomain');
110: $siteDomain = preg_replace('/^www\./', '', $siteDomain);
111: $parsedURL = parse_url($_SERVER['HTTP_REFERER']);
112: $parsedURL['host'] = preg_replace('/^www\./', '', $parsedURL['host']);
113: if (strcasecmp($siteDomain, $parsedURL['host']) == 0) {
114: $result = true;
115: }
116: }
117: }
118:
119: if (!$result) {
120: Validation::addError('', _t('Error occurred during form submission. Please refresh the page to try again.'));
121: return false;
122: }
123:
124: if ($validations && Validation::check($validations, $data) === false) {
125: return false;
126: }
127:
128: return true;
129: }
130:
131: /**
132: * AJAX form responder
133: * @param string $formId The HTML form ID
134: * @param array $errors The array of the errors (it is used only for generic form processing)
135: * @param bool $forceJson Send json header
136: * @return void
137: */
138: public static function respond($formId, $errors = null, $forceJson = false)
139: {
140: self::$id = $formId;
141: self::$error = validation_get('errors');
142: $ajaxResponse = $errors === null;
143:
144: if (is_array($errors) && count($errors)) {
145: self::$error = $errors;
146: $ajaxResponse = false;
147: # if no error message and no other message, no need to respond
148: if (count(self::$error) == 0 && empty(self::$message)) {
149: return;
150: }
151: }
152:
153: $response = array(
154: 'formId' => self::$id,
155: 'success' => self::$success ? true : false,
156: 'error' => self::$error,
157: 'msg' => self::$message,
158: 'redirect' => self::$redirect,
159: 'callback' => self::$callback,
160: 'data' => self::$data,
161: );
162:
163: if ($ajaxResponse) {
164: if ($forceJson) {
165: _json($response);
166: } else {
167: echo json_encode($response);
168: }
169: } else {
170: echo '<script type="text/javascript">';
171: echo 'LC.Form.submitHandler(' . json_encode($response) . ')';
172: echo '</script>';
173: }
174: }
175:
176: /**
177: * Permits you to set the value of an input or textarea.
178: * Allows you to safely use HTML and characters such as quotes within form elements without breaking out of the form
179: *
180: * @param string $name The input element field name
181: * @param mixed $defaultValue The default value of the input element (optional)
182: *
183: * @return mixed The value of the input element
184: */
185: public static function value($name, $defaultValue = null)
186: {
187: $value = _post($name);
188:
189: return $value ? _h($value) : _h($defaultValue);
190: }
191:
192: /**
193: * Permits you to set the value to a rich text editor or any input where HTML source is required to be rendered.
194: * Allows you to safely use HTML and characters such as quotes within form elements without breaking out of the form
195: *
196: * @param string $name The input element field name
197: * @param mixed $defaultValue The default value of the input element (optional)
198: *
199: * @return mixed The value of the input element
200: */
201: public static function htmlValue($name, $defaultValue = null)
202: {
203: if (count($_POST)) {
204: if (!isset($_POST[$name])) {
205: return '';
206: }
207: $value = _xss($_POST[$name]);
208:
209: return _h($value);
210: }
211:
212: return _h($defaultValue);
213: }
214:
215: /**
216: * Allow you to select the option of a drop-down list.
217: *
218: * @param string $name The field name of the drop-down list
219: * @param mixed $value The option value to check against
220: * @param mixed $defaultValue The default selected value (optional)
221: *
222: * @return string `'selected="selected"'` if the option is found, otherwise the empty string returned
223: */
224: public static function selected($name, $value, $defaultValue = null)
225: {
226: return self::inputSelection($name, $value, $defaultValue) ? 'selected="selected"' : '';
227: }
228:
229: /**
230: * Allow you to select a checkbox or a radio button
231: *
232: * @param string $name The field name of the checkbox or radio button
233: * @param mixed $value The value to check against
234: * @param mixed $defaultValue The default selected value (optional)
235: *
236: * @return string `'checked="checked"'` if the option is found, otherwise the empty string returned
237: */
238: public static function checked($name, $value, $defaultValue = null)
239: {
240: return self::inputSelection($name, $value, $defaultValue) ? 'checked="checked"' : '';
241: }
242:
243: /**
244: * @param string $name The field name of the checkbox or radio button or drop-down list
245: * @param mixed $value The value to check against
246: * @param mixed $defaultValue The default selected value (optional)
247: *
248: * @return bool TRUE if the option is found, otherwise FALSE
249: * @internal
250: * @ignore
251: *
252: * Allow you to select a checkbox or a radio button or an option of a drop-down list
253: *
254: */
255: public static function inputSelection($name, $value, $defaultValue = null)
256: {
257: if (count($_POST)) {
258: $name = preg_replace('/(\[\])$/', '', $name); // group[] will be replaced as group
259: if (!isset($_POST[$name])) {
260: return '';
261: }
262: $postedValue = _post($name);
263: if (is_array($postedValue) && in_array($value, $postedValue)) {
264: return true;
265: } elseif ($value == $postedValue) {
266: return true;
267: } else {
268: return false;
269: }
270: } else {
271: if (is_array($defaultValue) && in_array($value, $defaultValue)) {
272: return true;
273: } elseif ($value == $defaultValue) {
274: return true;
275: } else {
276: return false;
277: }
278: }
279: }
280: }
281: