PageRenderTime 74ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/mem_form/mem_form.php

https://bitbucket.org/mrdale/txp-plugins
PHP | 1930 lines | 1501 code | 360 blank | 69 comment | 221 complexity | f0200b4f86b80d0ed4fb2dc140e427b1 MD5 | raw file
  1. <?php
  2. // This is a PLUGIN TEMPLATE for Textpattern CMS.
  3. // Copy this file to a new name like abc_myplugin.php. Edit the code, then
  4. // run this file at the command line to produce a plugin for distribution:
  5. // $ php abc_myplugin.php > abc_myplugin-0.1.txt
  6. // Plugin name is optional. If unset, it will be extracted from the current
  7. // file name. Plugin names should start with a three letter prefix which is
  8. // unique and reserved for each plugin author ("abc" is just an example).
  9. // Uncomment and edit this line to override:
  10. $plugin['name'] = 'mem_form';
  11. // Allow raw HTML help, as opposed to Textile.
  12. // 0 = Plugin help is in Textile format, no raw HTML allowed (default).
  13. // 1 = Plugin help is in raw HTML. Not recommended.
  14. # $plugin['allow_html_help'] = 1;
  15. $plugin['version'] = '0.8.7';
  16. $plugin['author'] = 'Michael Manfre';
  17. $plugin['author_uri'] = 'http://manfre.net/';
  18. $plugin['description'] = 'A library plugin that provides support for html forms.';
  19. // Plugin load order:
  20. // The default value of 5 would fit most plugins, while for instance comment
  21. // spam evaluators or URL redirectors would probably want to run earlier
  22. // (1...4) to prepare the environment for everything else that follows.
  23. // Values 6...9 should be considered for plugins which would work late.
  24. // This order is user-overrideable.
  25. $plugin['order'] = '5';
  26. // Plugin 'type' defines where the plugin is loaded
  27. // 0 = public : only on the public side of the website (default)
  28. // 1 = public+admin : on both the public and admin side
  29. // 2 = library : only when include_plugin() or require_plugin() is called
  30. // 3 = admin : only on the admin side (no AJAX)
  31. // 4 = admin+ajax : only on the admin side (AJAX supported)
  32. // 5 = public+admin+ajax : on both the public and admin side (AJAX supported)
  33. $plugin['type'] = '2';
  34. // Plugin "flags" signal the presence of optional capabilities to the core plugin loader.
  35. // Use an appropriately OR-ed combination of these flags.
  36. // The four high-order bits 0xf000 are available for this plugin's private use
  37. if (!defined('PLUGIN_HAS_PREFS')) define('PLUGIN_HAS_PREFS', 0x0001); // This plugin wants to receive "plugin_prefs.{$plugin['name']}" events
  38. if (!defined('PLUGIN_LIFECYCLE_NOTIFY')) define('PLUGIN_LIFECYCLE_NOTIFY', 0x0002); // This plugin wants to receive "plugin_lifecycle.{$plugin['name']}" events
  39. $plugin['flags'] = '0';
  40. // Plugin 'textpack' is optional. It provides i18n strings to be used in conjunction with gTxt().
  41. // Syntax:
  42. // ## arbitrary comment
  43. // #@event
  44. // #@language ISO-LANGUAGE-CODE
  45. // abc_string_name => Localized String
  46. /** Uncomment me, if you need a textpack
  47. $plugin['textpack'] = <<<EOT
  48. #@admin
  49. #@language en-gb
  50. abc_sample_string => Sample String
  51. abc_one_more => One more
  52. #@language de-de
  53. abc_sample_string => Beispieltext
  54. abc_one_more => Noch einer
  55. EOT;
  56. **/
  57. // End of textpack
  58. if (!defined('txpinterface'))
  59. @include_once('zem_tpl.php');
  60. # --- BEGIN PLUGIN CODE ---
  61. $mem_glz_custom_fields_plugin = load_plugin('glz_custom_fields');
  62. // needed for MLP
  63. define( 'MEM_FORM_PREFIX' , 'mem_form' );
  64. global $mem_form_lang;
  65. if (!is_array($mem_form_lang))
  66. {
  67. $mem_form_lang = array(
  68. 'error_file_extension' => 'File upload failed for field {label}.',
  69. 'error_file_failed' => 'Failed to upload file for field {label}.',
  70. 'error_file_size' => 'Failed to upload File for field {label}. File is too large.',
  71. 'field_missing' => 'The field {label} is required.',
  72. 'form_expired' => 'The form has expired.',
  73. 'form_misconfigured' => 'The mem_form is misconfigured. You must specify the "form" attribute.',
  74. 'form_sorry' => 'The form is currently unavailable.',
  75. 'form_used' => 'This form has already been used to submit.',
  76. 'general_inquiry' => '',
  77. 'invalid_email' => 'The email address {email} is invalid.',
  78. 'invalid_host' => 'The host {domain} is invalid.',
  79. 'invalid_utf8' => 'Invalid UTF8 string for field {label}.',
  80. 'invalid_value' => 'The value "{value}" is invalid for the input field {label}.',
  81. 'invalid_format' => 'The input field {label} must match the format "{example}".',
  82. 'invalid_too_many_selected' => 'The input field {label} only allows {count} selected {plural}.',
  83. 'item' => 'item',
  84. 'items' => 'items',
  85. 'max_warning' => 'The input field {label} must be smaller than {max} characters long.',
  86. 'min_warning' => 'The input field {label} must be at least {min} characters long.',
  87. 'refresh' => 'Refresh',
  88. 'spam' => 'Your submission was blocked by a spam filter.',
  89. 'submitted_thanks' => 'You have successfully submitted the form. Thank you.',
  90. );
  91. }
  92. register_callback( 'mem_form_enumerate_strings' , 'l10n.enumerate_strings' );
  93. function mem_form_enumerate_strings($event , $step='' , $pre=0)
  94. {
  95. global $mem_form_lang;
  96. $r = array (
  97. 'owner' => 'mem_form', # Change to your plugin's name
  98. 'prefix' => MEM_FORM_PREFIX, # Its unique string prefix
  99. 'lang' => 'en-gb', # The language of the initial strings.
  100. 'event' => 'public', # public/admin/common = which interface the strings will be loaded into
  101. 'strings' => $mem_form_lang, # The strings themselves.
  102. );
  103. return $r;
  104. }
  105. function mem_form_gTxt($what,$args = array())
  106. {
  107. global $mem_form_lang, $textarray;
  108. $key = strtolower( MEM_FORM_PREFIX . '-' . $what );
  109. if (isset($textarray[$key]))
  110. {
  111. $str = $textarray[$key];
  112. }
  113. else
  114. {
  115. $key = strtolower($what);
  116. if (isset($mem_form_lang[$key]))
  117. $str = $mem_form_lang[$key];
  118. elseif (isset($textarray[$key]))
  119. $str = $textarray[$key];
  120. else
  121. $str = $what;
  122. }
  123. if( !empty($args) )
  124. $str = strtr( $str , $args );
  125. return $str;
  126. }
  127. function mem_form($atts, $thing='', $default=false)
  128. {
  129. global $sitename, $prefs, $file_max_upload_size, $mem_form_error, $mem_form_submit,
  130. $mem_form, $mem_form_labels, $mem_form_values, $mem_form_default_break,
  131. $mem_form_default, $mem_form_type, $mem_form_thanks_form,
  132. $mem_glz_custom_fields_plugin;
  133. extract(mem_form_lAtts(array(
  134. 'form' => '',
  135. 'thanks_form' => '',
  136. 'thanks' => graf(mem_form_gTxt('submitted_thanks')),
  137. 'label' => '',
  138. 'type' => '',
  139. 'redirect' => '',
  140. 'redirect_form' => '',
  141. 'class' => 'memForm',
  142. 'enctype' => '',
  143. 'file_accept' => '',
  144. 'max_file_size' => $file_max_upload_size,
  145. 'form_expired_msg' => mem_form_gTxt('form_expired'),
  146. 'show_error' => 1,
  147. 'show_input' => 1,
  148. 'default_break' => br,
  149. ), $atts));
  150. if (empty($type) or (empty($form) && empty($thing))) {
  151. trigger_error('Argument not specified for mem_form tag', E_USER_WARNING);
  152. return '';
  153. }
  154. $out = '';
  155. // init error structure
  156. mem_form_error();
  157. $mem_form_type = $type;
  158. $mem_form_default = is_array($default) ? $default : array();
  159. callback_event('mem_form.defaults');
  160. unset($atts['show_error'], $atts['show_input']);
  161. $mem_form_id = md5(serialize($atts).preg_replace('/[\t\s\r\n]/','',$thing));
  162. $mem_form_submit = (ps('mem_form_id') == $mem_form_id);
  163. $nonce = doSlash(ps('mem_form_nonce'));
  164. $renonce = false;
  165. if ($mem_form_submit) {
  166. safe_delete('txp_discuss_nonce', 'issue_time < date_sub(now(), interval 10 minute)');
  167. if ($rs = safe_row('used', 'txp_discuss_nonce', "nonce = '$nonce'"))
  168. {
  169. if ($rs['used'])
  170. {
  171. unset($mem_form_error);
  172. mem_form_error(mem_form_gTxt('form_used'));
  173. $renonce = true;
  174. $_POST['mem_form_submit'] = TRUE;
  175. $_POST['mem_form_id'] = $mem_form_id;
  176. $_POST['mem_form_nonce'] = $nonce;
  177. }
  178. }
  179. else
  180. {
  181. mem_form_error($form_expired_msg);
  182. $renonce = true;
  183. }
  184. }
  185. if ($mem_form_submit and $nonce and !$renonce)
  186. {
  187. $mem_form_nonce = $nonce;
  188. }
  189. elseif (!$show_error or $show_input)
  190. {
  191. $mem_form_nonce = md5(uniqid(rand(), true));
  192. safe_insert('txp_discuss_nonce', "issue_time = now(), nonce = '$mem_form_nonce'");
  193. }
  194. $form = ($form) ? fetch_form($form) : $thing;
  195. $form = parse($form);
  196. if ($mem_form_submit && empty($mem_form_error))
  197. {
  198. // let plugins validate after individual fields are validated
  199. callback_event('mem_form.validate');
  200. }
  201. if (!$mem_form_submit) {
  202. # don't show errors or send mail
  203. }
  204. elseif (mem_form_error())
  205. {
  206. if ($show_error or !$show_input)
  207. {
  208. $out .= mem_form_display_error();
  209. if (!$show_input) return $out;
  210. }
  211. }
  212. elseif ($show_input and is_array($mem_form))
  213. {
  214. if ($mem_glz_custom_fields_plugin) {
  215. // prep the values
  216. glz_custom_fields_before_save();
  217. }
  218. callback_event('mem_form.spam');
  219. /// load and check spam plugins/
  220. $evaluator =& get_mem_form_evaluator();
  221. $is_spam = $evaluator->is_spam();
  222. if ($is_spam) {
  223. return mem_form_gTxt('spam');
  224. }
  225. $mem_form_thanks_form = ($thanks_form ? fetch_form($thanks_form) : $thanks);
  226. safe_update('txp_discuss_nonce', "used = '1', issue_time = now()", "nonce = '$nonce'");
  227. $result = callback_event('mem_form.submit');
  228. if (mem_form_error()) {
  229. $out .= mem_form_display_error();
  230. $redirect = false;
  231. }
  232. $thanks_form = $mem_form_thanks_form;
  233. unset($mem_form_thanks_form);
  234. if (!empty($result))
  235. return $result;
  236. if (mem_form_error() and $show_input)
  237. {
  238. // no-op, reshow form with errors
  239. }
  240. else if ($redirect)
  241. {
  242. $_POST = array();
  243. while (@ob_end_clean());
  244. $uri = hu.ltrim($redirect,'/');
  245. if (empty($_SERVER['FCGI_ROLE']) and empty($_ENV['FCGI_ROLE']))
  246. {
  247. txp_status_header('303 See Other');
  248. header('Location: '.$uri);
  249. header('Connection: close');
  250. header('Content-Length: 0');
  251. }
  252. else
  253. {
  254. $uri = htmlspecialchars($uri);
  255. $refresh = mem_form_gTxt('refresh');
  256. if (!empty($redirect_form))
  257. {
  258. $redirect_form = fetch_form($redirect_form);
  259. echo str_replace('{uri}', $uri, $redirect_form);
  260. }
  261. if (empty($redirect_form))
  262. {
  263. echo <<<END
  264. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  265. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  266. <head>
  267. <title>$sitename</title>
  268. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  269. <meta http-equiv="refresh" content="0;url=$uri" />
  270. </head>
  271. <body>
  272. <a href="$uri">$refresh</a>
  273. </body>
  274. </html>
  275. END;
  276. }
  277. }
  278. exit;
  279. }
  280. else {
  281. return '<div class="memThanks" id="mem'.$mem_form_id.'">' .
  282. $thanks_form . '</div>';
  283. }
  284. }
  285. if ($show_input)
  286. {
  287. $file_accept = (!empty($file_accept) ? ' accept="'.$file_accept.'"' : '');
  288. $class = htmlspecialchars($class);
  289. $enctype = !empty($enctype) ? ' enctype="'.$enctype.'"' : '';
  290. return '<form method="post"'.((!$show_error and $mem_form_error) ? '' : ' id="mem'.$mem_form_id.'"').' class="'.$class.'" action="'.htmlspecialchars(serverSet('REQUEST_URI')).'#mem'.$mem_form_id.'"'.$file_accept.$enctype.'>'.
  291. ( $label ? n.'<fieldset>' : n.'<div>' ).
  292. ( $label ? n.'<legend>'.htmlspecialchars($label).'</legend>' : '' ).
  293. $out.
  294. n.'<input type="hidden" name="mem_form_nonce" value="'.$mem_form_nonce.'" />'.
  295. n.'<input type="hidden" name="mem_form_id" value="'.$mem_form_id.'" />'.
  296. (!empty($max_file_size) ? n.'<input type="hidden" name="MAX_FILE_SIZE" value="'.$max_file_size.'" />' : '' ).
  297. callback_event('mem_form.display','',1).
  298. $form.
  299. callback_event('mem_form.display').
  300. ( $label ? (n.'</fieldset>') : (n.'</div>') ).
  301. n.'</form>';
  302. }
  303. return '';
  304. }
  305. function mem_form_text($atts)
  306. {
  307. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  308. extract(mem_form_lAtts(array(
  309. 'break' => $mem_form_default_break,
  310. 'default' => '',
  311. 'isError' => '',
  312. 'label' => mem_form_gTxt('text'),
  313. 'placeholder' => '',
  314. 'max' => 100,
  315. 'min' => 0,
  316. 'name' => '',
  317. 'class' => 'memText',
  318. 'required' => 1,
  319. 'size' => '',
  320. 'password' => 0,
  321. 'format' => '',
  322. 'example' => '',
  323. 'escape_value' => 1,
  324. 'attrs' => ''
  325. ), $atts));
  326. $min = intval($min);
  327. $max = intval($max);
  328. $size = intval($size);
  329. if (empty($name)) $name = mem_form_label2name($label);
  330. if ($mem_form_submit)
  331. {
  332. $value = trim(ps($name));
  333. $utf8len = preg_match_all("/./su", $value, $utf8ar);
  334. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  335. if (strlen($value) == 0 && $required)
  336. {
  337. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  338. $isError = true;
  339. }
  340. elseif ($required && !empty($format) && !preg_match($format, $value))
  341. {
  342. //echo "format=$format<br />value=$value<br />";
  343. $mem_form_error[] = mem_form_gTxt('invalid_format', array('{label}'=>$hlabel, '{example}'=> htmlspecialchars($example)));
  344. $isError = true;
  345. }
  346. elseif (strlen($value))
  347. {
  348. if (!$utf8len)
  349. {
  350. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  351. $isError = true;
  352. }
  353. elseif ($min and $utf8len < $min)
  354. {
  355. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  356. $isError = true;
  357. }
  358. elseif ($max and $utf8len > $max)
  359. {
  360. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  361. $isError = true;
  362. }
  363. else
  364. {
  365. $isError = false === mem_form_store($name, $label, $value);
  366. }
  367. }
  368. }
  369. else
  370. {
  371. if (isset($mem_form_default[$name]))
  372. $value = $mem_form_default[$name];
  373. else
  374. $value = $default;
  375. }
  376. $size = ($size) ? ' size="'.$size.'"' : '';
  377. $maxlength = ($max) ? ' maxlength="'.$max.'"' : '';
  378. $placeholder = ($placeholder) ? ' placeholder="'.htmlspecialchars($placeholder).'"' : '';
  379. $isError = $isError ? "errorElement" : '';
  380. $memRequired = $required ? 'memRequired' : '';
  381. $class = htmlspecialchars($class);
  382. if ($escape_value)
  383. {
  384. $value = htmlspecialchars($value);
  385. }
  386. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  387. '<input type="'.($password ? 'password' : 'text').'" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" value="'.$value.'"'.$size.$maxlength.$placeholder.
  388. ( !empty($attrs) ? ' ' . $attrs : '').' />';
  389. }
  390. function mem_form_file($atts)
  391. {
  392. global $mem_form_submit, $mem_form_error, $mem_form_default, $file_max_upload_size, $tempdir, $mem_form_default_break;
  393. extract(mem_form_lAtts(array(
  394. 'break' => $mem_form_default_break,
  395. 'isError' => '',
  396. 'label' => mem_form_gTxt('file'),
  397. 'name' => '',
  398. 'class' => 'memFile',
  399. 'size' => '',
  400. 'accept' => '',
  401. 'no_replace' => 1,
  402. 'max_file_size' => $file_max_upload_size,
  403. 'required' => 1,
  404. 'default' => FALSE,
  405. ), $atts));
  406. $fname = ps('file_'.$name);
  407. $frealname = ps('file_info_'.$name.'_name');
  408. $ftype = ps('file_info_'.$name.'_type');
  409. if (empty($name)) $name = mem_form_label2name($label);
  410. $out = '';
  411. if ($mem_form_submit)
  412. {
  413. if (!empty($fname))
  414. {
  415. // see if user uploaded a different file to replace already uploaded
  416. if (isset($_FILES[$name]) && !empty($_FILES[$name]['tmp_name']))
  417. {
  418. // unlink last temp file
  419. if (file_exists($fname) && substr_compare($fname, $tempdir, 0, strlen($tempdir), 1)==0)
  420. unlink($fname);
  421. $fname = '';
  422. }
  423. else
  424. {
  425. // pass through already uploaded filename
  426. mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  427. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  428. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  429. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  430. }
  431. }
  432. if (empty($fname))
  433. {
  434. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  435. $fname = $_FILES[$name]['tmp_name'];
  436. $frealname = $_FILES[$name]['name'];
  437. $ftype = $_FILES[$name]['type'];
  438. $err = 0;
  439. switch ($_FILES[$name]['error']) {
  440. case UPLOAD_ERR_OK:
  441. if (is_uploaded_file($fname) and $max_file_size >= filesize($fname))
  442. mem_form_store($name, $label, $_FILES[$name]);
  443. elseif (!is_uploaded_file($fname)) {
  444. if ($required) {
  445. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  446. $err = 1;
  447. }
  448. }
  449. else {
  450. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  451. $err = 1;
  452. }
  453. break;
  454. case UPLOAD_ERR_NO_FILE:
  455. if ($required) {
  456. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  457. $err = 1;
  458. }
  459. break;
  460. case UPLOAD_ERR_EXTENSION:
  461. $mem_form_error[] = mem_form_gTxt('error_file_extension', array('{label}'=>$hlabel));
  462. $err = 1;
  463. break;
  464. case UPLOAD_ERR_INI_SIZE:
  465. case UPLOAD_ERR_FORM_SIZE:
  466. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  467. $err = 1;
  468. break;
  469. default:
  470. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  471. $err = 1;
  472. break;
  473. }
  474. if (!$err)
  475. {
  476. // store as a txp tmp file to be used later
  477. $fname = get_uploaded_file($fname);
  478. $err = false === mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  479. if ($err)
  480. {
  481. // clean up file
  482. @unlink($fname);
  483. }
  484. else
  485. {
  486. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  487. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($_FILES[$name]['name'])."' />"
  488. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($_FILES[$name]['type'])."' />";
  489. }
  490. }
  491. $isError = $err ? 'errorElement' : '';
  492. }
  493. }
  494. else
  495. {
  496. if (isset($mem_form_default[$name]))
  497. $value = $mem_form_default[$name];
  498. else if (is_array($default))
  499. $value = $default;
  500. if (is_array(@$value))
  501. {
  502. $fname = @$value['tmp_name'];
  503. $frealname = @$value['name'];
  504. $ftype = @$value['type'];
  505. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  506. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  507. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  508. }
  509. }
  510. $memRequired = $required ? 'memRequired' : '';
  511. $class = htmlspecialchars($class);
  512. $size = ($size) ? ' size="'.$size.'"' : '';
  513. $accept = (!empty($accept) ? ' accept="'.$accept.'"' : '');
  514. $field_out = '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break;
  515. if (!empty($frealname) && $no_replace)
  516. {
  517. $field_out .= '<div id="'.$name.'">'.htmlspecialchars($frealname) . ' <span id="'.$name.'_ftype">('. htmlspecialchars($ftype).')</span></div>';
  518. }
  519. else
  520. {
  521. $field_out .= '<input type="file" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"' .$size.' />';
  522. }
  523. return $out.$field_out;
  524. }
  525. function mem_form_textarea($atts, $thing='')
  526. {
  527. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  528. extract(mem_form_lAtts(array(
  529. 'break' => $mem_form_default_break,
  530. 'cols' => 58,
  531. 'default' => '',
  532. 'isError' => '',
  533. 'label' => mem_form_gTxt('textarea'),
  534. 'placeholder' => '',
  535. 'max' => 10000,
  536. 'min' => 0,
  537. 'name' => '',
  538. 'class' => 'memTextarea',
  539. 'required' => 1,
  540. 'rows' => 8,
  541. 'escape_value' => 1,
  542. 'attrs' => ''
  543. ), $atts));
  544. $min = intval($min);
  545. $max = intval($max);
  546. $cols = intval($cols);
  547. $rows = intval($rows);
  548. if (empty($name)) $name = mem_form_label2name($label);
  549. if ($mem_form_submit)
  550. {
  551. $value = preg_replace('/^\s*[\r\n]/', '', rtrim(ps($name)));
  552. $utf8len = preg_match_all("/./su", ltrim($value), $utf8ar);
  553. $hlabel = htmlspecialchars($label);
  554. if (strlen(ltrim($value)))
  555. {
  556. if (!$utf8len)
  557. {
  558. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  559. $isError = true;
  560. }
  561. elseif ($min and $utf8len < $min)
  562. {
  563. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  564. $isError = true;
  565. }
  566. elseif ($max and $utf8len > $max)
  567. {
  568. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  569. $isError = true;
  570. }
  571. else
  572. {
  573. $isError = false === mem_form_store($name, $label, $value);
  574. }
  575. }
  576. elseif ($required)
  577. {
  578. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  579. $isError = true;
  580. }
  581. }
  582. else
  583. {
  584. if (isset($mem_form_default[$name]))
  585. $value = $mem_form_default[$name];
  586. else if (!empty($default))
  587. $value = $default;
  588. else
  589. $value = parse($thing);
  590. }
  591. $isError = $isError ? 'errorElement' : '';
  592. $memRequired = $required ? 'memRequired' : '';
  593. $class = htmlspecialchars($class);
  594. $placeholder = ($placeholder) ? ' placeholder="'.htmlspecialchars($placeholder).'"' : '';
  595. if ($escape_value)
  596. {
  597. $value = htmlspecialchars($value);
  598. }
  599. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  600. '<textarea id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" cols="'.$cols.'" rows="'.$rows.'"'.$placeholder.
  601. ( !empty($attrs) ? ' ' . $attrs : '').'>'.$value.'</textarea>';
  602. }
  603. function mem_form_email($atts)
  604. {
  605. global $mem_form_error, $mem_form_submit, $mem_form_from, $mem_form_default, $mem_form_default_break;
  606. extract(mem_form_lAtts(array(
  607. 'default' => '',
  608. 'isError' => '',
  609. 'label' => mem_form_gTxt('email'),
  610. 'placeholder' => '',
  611. 'max' => 100,
  612. 'min' => 0,
  613. 'name' => '',
  614. 'required' => 1,
  615. 'break' => $mem_form_default_break,
  616. 'size' => '',
  617. 'class' => 'memEmail',
  618. ), $atts));
  619. if (empty($name)) $name = mem_form_label2name($label);
  620. if ($mem_form_submit)
  621. {
  622. $email = trim(ps($name));
  623. if (strlen($email))
  624. {
  625. if (!is_valid_email($email))
  626. {
  627. $mem_form_error[] = mem_form_gTxt('invalid_email', array('{email}'=>htmlspecialchars($email)));
  628. $isError = true;
  629. }
  630. else
  631. {
  632. preg_match("/@(.+)$/", $email, $match);
  633. $domain = $match[1];
  634. if (is_callable('checkdnsrr') and checkdnsrr('textpattern.com.','A') and !checkdnsrr($domain.'.','MX') and !checkdnsrr($domain.'.','A'))
  635. {
  636. $mem_form_error[] = mem_form_gTxt('invalid_host', array('{domain}'=>htmlspecialchars($domain)));
  637. $isError = true;
  638. }
  639. else
  640. {
  641. $mem_form_from = $email;
  642. }
  643. }
  644. }
  645. }
  646. else
  647. {
  648. if (isset($mem_form_default[$name]))
  649. $email = $mem_form_default[$name];
  650. else
  651. $email = $default;
  652. }
  653. return mem_form_text(array(
  654. 'default' => $email,
  655. 'isError' => $isError,
  656. 'label' => $label,
  657. 'placeholder' => $placeholder,
  658. 'max' => $max,
  659. 'min' => $min,
  660. 'name' => $name,
  661. 'required' => $required,
  662. 'break' => $break,
  663. 'size' => $size,
  664. 'class' => $class,
  665. ));
  666. }
  667. function mem_form_select_section($atts)
  668. {
  669. extract(mem_form_lAtts(array(
  670. 'exclude' => '',
  671. 'sort' => 'name ASC',
  672. 'delimiter' => ',',
  673. ),$atts,false));
  674. if (!empty($exclude)) {
  675. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  676. $exclusion = array_map('strtolower', $exclusion);
  677. if (count($exclusion))
  678. $exclusion = join($delimiter, quote_list($exclusion));
  679. }
  680. $where = empty($exclusion) ? '1=1' : 'LOWER(name) NOT IN ('.$exclusion.')';
  681. $sort = empty($sort) ? '' : ' ORDER BY '. doSlash($sort);
  682. $rs = safe_rows('name, title','txp_section',$where . $sort);
  683. $items = array();
  684. $values = array();
  685. if ($rs) {
  686. foreach($rs as $r) {
  687. $items[] = $r['title'];
  688. $values[] = $r['name'];
  689. }
  690. }
  691. unset($atts['exclude'], $atts['sort']);
  692. $atts['items'] = join($delimiter, $items);
  693. $atts['values'] = join($delimiter, $values);
  694. return mem_form_select($atts);
  695. }
  696. function mem_form_select_category($atts)
  697. {
  698. extract(mem_form_lAtts(array(
  699. 'root' => 'root',
  700. 'exclude' => '',
  701. 'delimiter' => ',',
  702. 'type' => 'article'
  703. ),$atts,false));
  704. $rs = getTree($root, $type);
  705. if (!empty($exclude)) {
  706. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  707. $exclusion = array_map('strtolower', $exclusion);
  708. }
  709. else
  710. $exclusion = array();
  711. $items = array();
  712. $values = array();
  713. if ($rs) {
  714. foreach ($rs as $cat) {
  715. if (count($exclusion) && in_array(strtolower($cat['name']), $exclusion))
  716. continue;
  717. $items[] = $cat['title'];
  718. $values[] = $cat['name'];
  719. }
  720. }
  721. unset($atts['root'], $atts['type']);
  722. $atts['items'] = join($delimiter, $items);
  723. $atts['values'] = join($delimiter, $values);
  724. return mem_form_select($atts);
  725. }
  726. function mem_form_select_range($atts)
  727. {
  728. global $mem_form_default_break;
  729. $latts = mem_form_lAtts(array(
  730. 'start' => 0,
  731. 'stop' => false,
  732. 'step' => 1,
  733. 'name' => '',
  734. 'break' => $mem_form_default_break,
  735. 'delimiter' => ',',
  736. 'isError' => '',
  737. 'label' => mem_form_gTxt('option'),
  738. 'first' => FALSE,
  739. 'required' => 1,
  740. 'select_limit' => FALSE,
  741. 'as_csv' => FALSE,
  742. 'selected' => '',
  743. 'class' => 'memSelect',
  744. 'attrs' => ''
  745. ), $atts);
  746. if ($stop === false)
  747. {
  748. trigger_error(gTxt('missing_required_attribute', array('{name}' => 'stop')), E_USER_ERROR);
  749. }
  750. $step = empty($latts['step']) ? 1 : assert_int($latts['step']);
  751. $start= assert_int($latts['start']);
  752. $stop = assert_int($latts['stop']);
  753. // fixup start/stop based upon step direction
  754. $start = $step > 0 ? min($start, $stop) : max($start, $stop);
  755. $stop = $step > 0 ? max($start, $stop) : min($start, $stop);
  756. $values = array();
  757. for($i=$start; $i >= $start && $i < $stop; $i += $step)
  758. {
  759. array_push($values, $i);
  760. }
  761. // intentional trample
  762. $latts['items'] = $latts['values'] = implode($latts['delimiter'], $values);
  763. return mem_form_select($latts);
  764. }
  765. function mem_form_select($atts)
  766. {
  767. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  768. extract(mem_form_lAtts(array(
  769. 'name' => '',
  770. 'break' => $mem_form_default_break,
  771. 'delimiter' => ',',
  772. 'isError' => '',
  773. 'label' => mem_form_gTxt('option'),
  774. 'items' => mem_form_gTxt('general_inquiry'),
  775. 'values' => '',
  776. 'first' => FALSE,
  777. 'required' => 1,
  778. 'select_limit' => FALSE,
  779. 'as_csv' => FALSE,
  780. 'selected' => '',
  781. 'class' => 'memSelect',
  782. 'attrs' => ''
  783. ), $atts, false));
  784. if (empty($name)) $name = mem_form_label2name($label);
  785. if (!empty($items) && $items[0] == '<') $items = parse($items);
  786. if (!empty($values) && $values[0] == '<') $values = parse($values);
  787. if ($first !== FALSE) {
  788. $items = $first.$delimiter.$atts['items'];
  789. $values = $first.$delimiter.$atts['values'];
  790. }
  791. $select_limit = empty($select_limit) ? 1 : assert_int($select_limit);
  792. $items = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$items)));
  793. $values = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$values)));
  794. if ($select_limit > 1)
  795. {
  796. $selected = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$seelcted)));
  797. }
  798. else
  799. {
  800. $selected = array(trim($selected));
  801. }
  802. $use_values_array = (count($items) == count($values));
  803. if ($mem_form_submit)
  804. {
  805. if (strpos($name, '[]'))
  806. {
  807. $value = ps(substr($name, 0, strlen($name)-2));
  808. $selected = $value;
  809. if ($as_csv)
  810. {
  811. $value = implode($delimiter, $value);
  812. }
  813. }
  814. else
  815. {
  816. $value = trim(ps($name));
  817. $selected = array($value);
  818. }
  819. if (!empty($selected))
  820. {
  821. if (count($selected) <= $select_limit)
  822. {
  823. foreach ($selected as $v)
  824. {
  825. $is_valid = ($use_values_array && in_array($v, $values)) or (!$use_values_array && in_array($v, $items));
  826. if (!$is_valid)
  827. {
  828. $invalid_value = $v;
  829. break;
  830. }
  831. }
  832. if ($is_valid)
  833. {
  834. $isError = false === mem_form_store($name, $label, $value);
  835. }
  836. else
  837. {
  838. $mem_form_error[] = mem_form_gTxt('invalid_value', array('{label}'=> htmlspecialchars($label), '{value}'=> htmlspecialchars($invalid_value)));
  839. $isError = true;
  840. }
  841. }
  842. else
  843. {
  844. $mem_form_error[] = mem_form_gTxt('invalid_too_many_selected', array(
  845. '{label}'=> htmlspecialchars($label),
  846. '{count}'=> $select_limit,
  847. '{plural}'=> ($select_limit==1 ? mem_form_gTxt('item') : mem_form_gTxt('items'))
  848. ));
  849. $isError = true;
  850. }
  851. }
  852. elseif ($required)
  853. {
  854. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  855. $isError = true;
  856. }
  857. }
  858. else if (isset($mem_form_default[$name]))
  859. {
  860. $selected = array($mem_form_default[$name]);
  861. }
  862. $out = '';
  863. foreach ($items as $item)
  864. {
  865. $v = $use_values_array ? array_shift($values) : $item;
  866. $sel = !empty($selected) && in_array($v, $selected);
  867. $out .= n.t.'<option'.($use_values_array ? ' value="'.$v.'"' : '').($sel ? ' selected="selected">' : '>').
  868. (strlen($item) ? htmlspecialchars($item) : ' ').'</option>';
  869. }
  870. $isError = $isError ? 'errorElement' : '';
  871. $memRequired = $required ? 'memRequired' : '';
  872. $class = htmlspecialchars($class);
  873. $multiple = $select_limit > 1 ? ' multiple="multiple"' : '';
  874. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  875. n.'<select id="'.$name.'" name="'.$name.'" class="'.$class.' '.$memRequired.$isError.'"' . $multiple .
  876. ( !empty($attrs) ? ' ' . $attrs : '').'>'.
  877. $out.
  878. n.'</select>';
  879. }
  880. function mem_form_checkbox($atts)
  881. {
  882. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  883. extract(mem_form_lAtts(array(
  884. 'break' => $mem_form_default_break,
  885. 'checked' => 0,
  886. 'isError' => '',
  887. 'label' => mem_form_gTxt('checkbox'),
  888. 'name' => '',
  889. 'class' => 'memCheckbox',
  890. 'required' => 1,
  891. 'attrs' => ''
  892. ), $atts));
  893. if (empty($name)) $name = mem_form_label2name($label);
  894. if ($mem_form_submit)
  895. {
  896. $value = (bool) ps($name);
  897. if ($required and !$value)
  898. {
  899. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  900. $isError = true;
  901. }
  902. else
  903. {
  904. $isError = false === mem_form_store($name, $label, $value ? gTxt('yes') : gTxt('no'));
  905. }
  906. }
  907. else {
  908. if (isset($mem_form_default[$name]))
  909. $value = $mem_form_default[$name];
  910. else
  911. $value = $checked;
  912. }
  913. $isError = $isError ? 'errorElement' : '';
  914. $memRequired = $required ? 'memRequired' : '';
  915. $class = htmlspecialchars($class);
  916. return '<input type="checkbox" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"'.
  917. ( !empty($attrs) ? ' ' . $attrs : '').
  918. ($value ? ' checked="checked"' : '').' />'.$break.
  919. '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>';
  920. }
  921. function mem_form_serverinfo($atts)
  922. {
  923. global $mem_form_submit;
  924. extract(mem_form_lAtts(array(
  925. 'label' => '',
  926. 'name' => ''
  927. ), $atts));
  928. if (empty($name)) $name = mem_form_label2name($label);
  929. if (strlen($name) and $mem_form_submit)
  930. {
  931. if (!$label) $label = $name;
  932. mem_form_store($name, $label, serverSet($name));
  933. }
  934. }
  935. function mem_form_secret($atts, $thing = '')
  936. {
  937. global $mem_form_submit;
  938. extract(mem_form_lAtts(array(
  939. 'name' => '',
  940. 'label' => mem_form_gTxt('secret'),
  941. 'value' => ''
  942. ), $atts));
  943. $name = mem_form_label2name($name ? $name : $label);
  944. if ($mem_form_submit)
  945. {
  946. if ($thing)
  947. $value = trim(parse($thing));
  948. else
  949. $value = trim(parse($value));
  950. mem_form_store($name, $label, $value);
  951. }
  952. return '';
  953. }
  954. function mem_form_hidden($atts, $thing='')
  955. {
  956. global $mem_form_submit, $mem_form_default;
  957. extract(mem_form_lAtts(array(
  958. 'name' => '',
  959. 'label' => mem_form_gTxt('hidden'),
  960. 'value' => '',
  961. 'isError' => '',
  962. 'required' => 1,
  963. 'class' => 'memHidden',
  964. 'escape_value' => 1,
  965. 'attrs' => ''
  966. ), $atts));
  967. $name = mem_form_label2name($name ? $name : $label);
  968. if ($mem_form_submit)
  969. {
  970. $value = preg_replace('/^\s*[\r\n]/', '', rtrim(ps($name)));
  971. $utf8len = preg_match_all("/./su", ltrim($value), $utf8ar);
  972. $hlabel = htmlspecialchars($label);
  973. if (strlen($value))
  974. {
  975. if (!$utf8len)
  976. {
  977. $mem_form_error[] = mem_form_gTxt('invalid_utf8', $hlabel);
  978. $isError = true;
  979. }
  980. else
  981. {
  982. $isError = false === mem_form_store($name, $label, $value);
  983. }
  984. }
  985. }
  986. else
  987. {
  988. if (isset($mem_form_default[$name]))
  989. $value = $mem_form_default[$name];
  990. else if ($thing)
  991. $value = trim(parse($thing));
  992. }
  993. $isError = $isError ? 'errorElement' : '';
  994. $memRequired = $required ? 'memRequired' : '';
  995. if ($escape_value)
  996. {
  997. $value = htmlspecialchars($value);
  998. }
  999. return '<input type="hidden" class="'.$class.' '.$memRequired.$isError.' '.$name
  1000. . '" name="'.$name.'" value="'.$value.'" id="'.$name.'" '.$attrs.'/>';
  1001. }
  1002. function mem_form_radio($atts)
  1003. {
  1004. global $mem_form_error, $mem_form_submit, $mem_form_values, $mem_form_default, $mem_form_default_break;
  1005. extract(mem_form_lAtts(array(
  1006. 'break' => $mem_form_default_break,
  1007. 'checked' => 0,
  1008. 'group' => '',
  1009. 'label' => mem_form_gTxt('option'),
  1010. 'name' => '',
  1011. 'class' => 'memRadio',
  1012. 'isError' => '',
  1013. 'attrs' => '',
  1014. 'value' => false
  1015. ), $atts));
  1016. static $cur_name = '';
  1017. static $cur_group = '';
  1018. if (!$name and !$group and !$cur_name and !$cur_group) {
  1019. $cur_group = mem_form_gTxt('radio');
  1020. $cur_name = $cur_group;
  1021. }
  1022. if ($group and !$name and $group != $cur_group) $name = $group;
  1023. if ($name) $cur_name = $name;
  1024. else $name = $cur_name;
  1025. if ($group) $cur_group = $group;
  1026. else $group = $cur_group;
  1027. $id = 'q'.md5($name.'=>'.$label);
  1028. $name = mem_form_label2name($name);
  1029. $value = $value === false ? $id : $value;
  1030. if ($mem_form_submit)
  1031. {
  1032. $is_checked = (ps($name) == $value);
  1033. if ($is_checked or $checked and !isset($mem_form_values[$name]))
  1034. {
  1035. $isError = false === mem_form_store($name, $group, $value);
  1036. }
  1037. }
  1038. else
  1039. {
  1040. if (isset($mem_form_default[$name]))
  1041. $is_checked = $mem_form_default[$name] == $value;
  1042. else
  1043. $is_checked = $checked;
  1044. }
  1045. $class = htmlspecialchars($class);
  1046. $isError = $isError ? ' errorElement' : '';
  1047. return '<input value="'.$value.'" type="radio" id="'.$id.'" class="'.$class.' '.$name.$isError.'" name="'.$name.'"'.
  1048. ( !empty($attrs) ? ' ' . $attrs : '').
  1049. ( $is_checked ? ' checked="checked" />' : ' />').$break.
  1050. '<label for="'.$id.'" class="'.$class.' '.$name.'">'.htmlspecialchars($label).'</label>';
  1051. }
  1052. function mem_form_submit($atts, $thing='')
  1053. {
  1054. global $mem_form_submit;
  1055. extract(mem_form_lAtts(array(
  1056. 'button' => 0,
  1057. 'label' => mem_form_gTxt('save'),
  1058. 'name' => 'mem_form_submit',
  1059. 'class' => 'memSubmit',
  1060. ), $atts));
  1061. $label = htmlspecialchars($label);
  1062. $name = htmlspecialchars($name);
  1063. $class = htmlspecialchars($class);
  1064. if ($mem_form_submit)
  1065. {
  1066. $value = ps($name);
  1067. if (!empty($value) && $value == $label)
  1068. {
  1069. // save the clicked button value
  1070. mem_form_store($name, $label, $value);
  1071. }
  1072. }
  1073. if ($button or strlen($thing))
  1074. {
  1075. return '<button type="submit" class="'.$class.'" name="'.$name.'" value="'.$label.'">'.($thing ? trim(parse($thing)) : $label).'</button>';
  1076. }
  1077. else
  1078. {
  1079. return '<input type="submit" class="'.$class.'" name="'.$name.'" value="'.$label.'" />';
  1080. }
  1081. }
  1082. function mem_form_lAtts($arr, $atts, $warn=true)
  1083. {
  1084. foreach(array('button', 'checked', 'required', 'show_input', 'show_error') as $key)
  1085. {
  1086. if (isset($atts[$key]))
  1087. {
  1088. $atts[$key] = ($atts[$key] === 'yes' or intval($atts[$key])) ? 1 : 0;
  1089. }
  1090. }
  1091. if (isset($atts['break']) and $atts['break'] == 'br') $atts['break'] = '<br />';
  1092. return lAtts($arr, $atts, $warn);
  1093. }
  1094. function mem_form_label2name($label)
  1095. {
  1096. $label = trim($label);
  1097. if (strlen($label) == 0) return 'invalid';
  1098. if (strlen($label) <= 32 and preg_match('/^[a-zA-Z][A-Za-z0-9:_-]*$/', $label)) return $label;
  1099. else return 'q'.md5($label);
  1100. }
  1101. function mem_form_store($name, $label, $value)
  1102. {
  1103. global $mem_form, $mem_form_labels, $mem_form_values;
  1104. $mem_form[$label] = $value;
  1105. $mem_form_labels[$name] = $label;
  1106. $mem_form_values[$name] = $value;
  1107. $is_valid = false !== callback_event('mem_form.store_value', $name);
  1108. // invalid data, unstore it
  1109. if (!$is_valid)
  1110. mem_form_remove($name);
  1111. return $is_valid;
  1112. }
  1113. function mem_form_remove($name)
  1114. {
  1115. global $mem_form, $mem_form_labels, $mem_form_values;
  1116. $label = $mem_form_labels[$name];
  1117. unset($mem_form_labels[$name], $mem_form[$label], $mem_form_values[$name]);
  1118. }
  1119. function mem_form_display_error()
  1120. {
  1121. global $mem_form_error;
  1122. $out = n.'<ul class="memError">';
  1123. foreach (array_unique($mem_form_error) as $error)
  1124. {
  1125. $out .= n.t.'<li>'.$error.'</li>';
  1126. }
  1127. $out .= n.'</ul>';
  1128. return $out;
  1129. }
  1130. function mem_form_value($atts, $thing)
  1131. {
  1132. global $mem_form_submit, $mem_form_values, $mem_form_default;
  1133. extract(mem_form_lAtts(array(
  1134. 'name' => '',
  1135. 'wraptag' => '',
  1136. 'class' => '',
  1137. 'attributes'=> '',
  1138. 'id' => '',
  1139. ), $atts));
  1140. $out = '';
  1141. if ($mem_form_submit)
  1142. {
  1143. if (isset($mem_form_values[$name]))
  1144. $out = $mem_form_values[$name];
  1145. }
  1146. else {
  1147. if (isset($mem_form_default[$name]))
  1148. $out = $mem_form_default[$name];
  1149. }
  1150. return doTag($out, $wraptag, $class, $attributes, $id);
  1151. }
  1152. function mem_form_error($err=NULL)
  1153. {
  1154. global $mem_form_error;
  1155. if (!is_array($mem_form_error))
  1156. $mem_form_error = array();
  1157. if ($err == NULL)
  1158. return !empty($mem_form_error) ? $mem_form_error : false;
  1159. $mem_form_error[] = $err;
  1160. }
  1161. function mem_form_default($key,$val=NULL)
  1162. {
  1163. global $mem_form_default;
  1164. if (is_array($key))
  1165. {
  1166. foreach ($key as $k=>$v)
  1167. {
  1168. mem_form_default($k,$v);
  1169. }
  1170. return;
  1171. }
  1172. $name = mem_form_label2name($key);
  1173. if ($val == NULL)
  1174. {
  1175. return (isset($mem_form_default[$name]) ? $mem_form_default[$name] : false);
  1176. }
  1177. $mem_form_default[$name] = $val;
  1178. return $val;
  1179. }
  1180. function mem_form_mail($from,$reply,$to,$subject,$msg, $content_type='text/plain')
  1181. {
  1182. global $prefs;
  1183. if (!is_callable('mail'))
  1184. return false;
  1185. $deliverTo = '';
  1186. if (is_array($to)) {
  1187. $bcc = isset($to['bcc']) ? mem_form_strip($to['bcc']) : '';
  1188. $deliverTo = isset($to['to']) ? mem_form_strip($to['to']) : '';
  1189. } else {
  1190. $bcc = '';
  1191. $deliverTo = mem_form_strip($to);
  1192. }
  1193. $from = mem_form_strip($from);
  1194. $reply = mem_form_strip($reply);
  1195. $subject = mem_form_strip($subject);
  1196. $msg = mem_form_strip($msg,FALSE);
  1197. if ($prefs['override_emailcharset'] and is_callable('utf8_decode')) {
  1198. $charset = 'ISO-8859-1';
  1199. $subject = utf8_decode($subject);
  1200. $msg = utf8_decode($msg);
  1201. }
  1202. else {
  1203. $charset = 'UTF-8';
  1204. }
  1205. $subject = mem_form_mailheader($subject,'text');
  1206. $sep = !is_windows() ? "\n" : "\r\n";
  1207. $headers = 'From: ' . $from .
  1208. ($bcc ? ($sep . 'Bcc: ' . $bcc) : '') .
  1209. ($reply ? ($sep.'Reply-To: '.$reply) : '') .
  1210. $sep.'X-Mailer: Textpattern (mem_form)' .
  1211. $sep.'X-Originating-IP: '.mem_form_strip((!empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'].' via ' : '').$_SERVER['REMOTE_ADDR']) .
  1212. $sep.'Content-Transfer-Encoding: 8bit' .
  1213. $sep.'Content-Type: '.$content_type.'; charset="'.$charset.'"';
  1214. return mail($deliverTo, $subject, $msg, $headers);
  1215. }
  1216. function mem_form_mailheader($string, $type)
  1217. {
  1218. global $prefs;
  1219. if (!strstr($string,'=?') and !preg_match('/[\x00-\x1F\x7F-\xFF]/', $string)) {
  1220. if ("phrase" == $type) {
  1221. if (preg_match('/[][()<>@,;:".\x5C]/', $string)) {
  1222. $string = '"'. strtr($string, array("\\" => "\\\\", '"' => '\"')) . '"';
  1223. }
  1224. }
  1225. elseif ("text" != $type) {
  1226. trigger_error('Unknown encode_mailheader type', E_USER_WARNING);
  1227. }
  1228. return $string;
  1229. }
  1230. if ($prefs['override_emailcharset']) {
  1231. $start = '=?ISO-8859-1?B?';
  1232. $pcre = '/.{1,42}/s';
  1233. }
  1234. else {
  1235. $start = '=?UTF-8?B?';
  1236. $pcre = '/.{1,45}(?=[\x00-\x7F\xC0-\xFF]|$)/s';
  1237. }
  1238. $end = '?=';
  1239. $sep = is_windows() ? "\r\n" : "\n";
  1240. preg_match_all($pcre, $string, $matches);
  1241. return $start . join($end.$sep.' '.$start, array_map('base64_encode',$matches[0])) . $end;
  1242. }
  1243. function mem_form_strip($str, $header = TRUE) {
  1244. if ($header) $str = strip_rn($str);
  1245. return preg_replace('/[\x00]/', ' ', $str);
  1246. }
  1247. ///////////////////////////////////////////////
  1248. // Spam Evaluator
  1249. class mem_form_evaluation
  1250. {
  1251. var $status;
  1252. function mem_form_evaluation() {
  1253. $this->status = 0;
  1254. }
  1255. function add_status($rating=-1) {
  1256. $this->status += $rating;
  1257. }
  1258. function get_status() {
  1259. return $this->status;
  1260. }
  1261. function is_spam() {
  1262. return ($this->status < 0);
  1263. }
  1264. }
  1265. function &get_mem_form_evaluator()
  1266. {
  1267. static $instance;
  1268. if(!isset($instance)) {
  1269. $instance = new mem_form_evaluation();
  1270. }
  1271. return $instance;
  1272. }
  1273. # --- END PLUGIN CODE ---
  1274. if (0) {
  1275. ?>
  1276. <!--
  1277. # --- BEGIN PLUGIN HELP ---
  1278. <h1>mem_form plugin</h1>
  1279. <h2>Summary</h2>
  1280. <p>This plugin provides <span class="caps">HTML</span> form capabilities for other plugins. This allows for consistent form tags and behaviors, while reducing overall plugin size and development time.</p>
  1281. <h2>Author Contact</h2>
  1282. <p><a href="mailto:mmanfre@gmail.com?subject=Textpattern%20mem_form%20plugin" rel="nofollow">Michael Manfre</a><br />
  1283. <a href="http://manfre.net" rel="nofollow">http://manfre.net</a></p>
  1284. <h2>License</h2>
  1285. <p>This plugin is licensed under the <a href="http://www.fsf.org/licensing/licenses/info/GPLv2.html" rel="nofollow">GPLv2</a>.</p>
  1286. <h2>Tags</h2>
  1287. <ul>
  1288. <li><a href="#mem_form" rel="nofollow">mem_form</a></li>
  1289. <li><a href="#mem_form_checkbox" rel="nofollow">mem_form_checkbox</a></li>
  1290. <li><a href="#mem_form_email" rel="nofollow">mem_form_email</a></li>
  1291. <li><a href="#mem_form_file" rel="nofollow">mem_form_file</a></li>
  1292. <li><a href="#mem_form_hidden" rel="nofollow">mem_form_hidden</a></li>
  1293. <li><a href="#mem_form_radio" rel="nofollow">mem_form_radio</a></li>
  1294. <li><a href="#mem_form_secret" rel="nofollow">mem_form_secret</a></li>
  1295. <li><a href="#mem_form_select" rel="nofollow">mem_form_select</a></li>
  1296. <li><a href="#mem_form_select_category" rel="nofollow">mem_form_select_category</a></li>
  1297. <li><a href="#mem_form_select_range" rel="nofollow">mem_form_select_range</a></li>
  1298. <li><a href="#mem_form_select_section" rel="nofollow">mem_form_select_section</a></li>
  1299. <li><a href="#mem_form_serverinfo" rel="nofollow">mem_form_serverinfo</a></li>
  1300. <li><a href="#mem_form_submit" rel="nofollow">mem_form_submit</a></li>
  1301. <li><a href="#mem_form_text" rel="nofollow">mem_form_text</a></li>
  1302. <li><a href="#mem_form_textarea" rel="nofollow">mem_form_textarea</a></li>
  1303. <li><a href="#mem_form_value" rel="nofollow">mem_form_value</a></li>
  1304. </ul>
  1305. <h3>mem_form</h3>
  1306. <p>This tag will create an <span class="caps">HTML</span> form and contains all of the processing and validation.</p>
  1307. <ul>
  1308. <li><span>form</span> <span>string</span> Name of a form that will be parsed to display the form.</li>
  1309. <li><span>thanks_form</span> <span>string</span> Name of a form that will be parsed upon successful form submission.</li>
  1310. <li><span>label</span> <span>string</span> Accessible name for the form.</li>
  1311. <li><span>type</span> <span>string</span> Name of the form to identify itself to bound plugin.</li>
  1312. <li><span>thanks</span> <span>string</span> Message to display to user upon successful form submission.</li>
  1313. <li><span>redirect</span> <span>url</span> <span class="caps">URL</span> to redirect upon successful form submission. Overrides &#8220;thanks&#8221; and &#8220;thanks_form&#8221;.</li>
  1314. <li><span>redirect_form</span> <span>string</span> Name of a form that will be parsed as displayed to the user on a redirect. The string &#8220;<em>{uri}</em>&#8221; will be replaced with the redirect url.</li>
  1315. <li><span>enctype</span> <span>string</span> <span class="caps">HTML</span> encoding type used when the form is submitted. <code>enctype=&quot;multipart/form-data&quot;</code> is required when using mem_form_file.</li>
  1316. <li><span>default_break</span> <span>string</span> Separator between label tag and input tag to be used as the default for every mem_form compatible field contained in the form. Default is &lt;br&gt;</li>
  1317. </ul>
  1318. <h3>mem_form_checkbox</h3>
  1319. <p>This will output an <span class="caps">HTML</span> checkbox field.</p>
  1320. <ul>
  1321. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1322. <li><span>checked</span> <span>int</span> Is this box checked. Default &#8220;0&#8221;.</li>
  1323. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1324. <li><span>name</span> <span>string</span> Input field name.</li>
  1325. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1326. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1327. </ul>
  1328. <h3>mem_form_email</h3>
  1329. <p>This will output an <span class="caps">HTML</span> text input field and validates the submitted value as an email address.</p>
  1330. <ul>
  1331. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1332. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1333. <li><span>name</span> <span>string</span> Input field name.</li>
  1334. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1335. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1336. <li><span>default</span> <span>string</span> The default value.</li>
  1337. <li><span>max</span> <span>int</span> Max character length.</li>
  1338. <li><span>min</span> <span>int</span> Min character length.</li>
  1339. <li><span>size</span> <span>int</span> Size of input field.</li>
  1340. </ul>
  1341. <h3>mem_form_file</h3>
  1342. <p>+p(tag-summary). This will output an <span class="caps">HTML</span> file input field. You must add the <code>enctype=&quot;multipart/form-data&quot;</code> attribute to your enclosing mem_form for this to work.</p>
  1343. <ul>
  1344. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1345. <li><span>name</span> <span>string</span> Input field name.</li>
  1346. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1347. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1348. <li><span>no_replace</span> <span>int</span> Specifies whether a user can upload another file and replace the existing file that will be submitted on successful completion of the form. If &#8220;1&#8221;, the file input field will be replaced with details about the already uploaded file.</li>
  1349. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1350. <li><span>size</span> <span>int</span> Size of input field.</li>
  1351. <li><span>max_file_size</span> <span>int</span> Maximum size for the uploaded file. Checked server-side.</li>
  1352. <li><span>accept</span> <span>string</span> The <span class="caps">HTML</span> file input field&#8217;s &#8220;accept&#8221; argument that specifies which file types the field should permit.</li>
  1353. </ul>
  1354. <h3>mem_form_hidden</h3>
  1355. <p>This will output an <span class="caps">HTML</span> hidden text input field.</p>
  1356. <ul>
  1357. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1358. <li><span>name</span> <span>string</span> Input field name.</li>
  1359. <li><span>value</span> <span>string</span> The input value.</li>
  1360. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1361. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1362. <li><span>escape_value</span> <span>int</span> Set to &#8220;0&#8221; to prevent html escaping the value. Default &#8220;1&#8221;.</li>
  1363. </ul>
  1364. <h3>mem_form_radio</h3>
  1365. <p>This will output an <span class="caps">HTML</span> radio button.</p>
  1366. <ul>
  1367. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1368. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1369. <li><span>name</span> <span>string</span> Input field name.</li>
  1370. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1371. <li><span>group</span> <span>string</span> A name that identifies a group of radio buttons.</li>
  1372. <li><span>value</span> <span>string</span> The value of the radio button. If not set, a unique value is generated.</li>
  1373. <li><span>checked</span> <span>int</span> Is this box checked. Default &#8220;0&#8221;.</li>
  1374. </ul>
  1375. <h3>mem_form_secret</h3>
  1376. <p>This will output nothing in <span class="caps">HTML</span> and is meant to pass information to the sumbit handler plugins.</p>
  1377. <ul>
  1378. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1379. <li><span>name</span> <span>string</span> Input field name.</li>
  1380. <li><span>value</span> <span>string</span> The input value.</li>
  1381. </ul>
  1382. <h3>mem_form_select</h3>
  1383. <p>This will output an <span class="caps">HTML</span> select field.</p>
  1384. <ul>
  1385. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1386. <li><span>name</span> <span>string</span> Input field name.</li>
  1387. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1388. <li><span>delimiter</span> <span>string</span> List separator. Default &#8220;,&#8221;</li>
  1389. <li><span>items</span> <span>string</span> Delimited list containing a select list display values.</li>
  1390. <li><span>values</span> <span>string</span> Delimited list containing a select list item values.</li>
  1391. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1392. <li><span>selected</span> <span>string</span> The value of the selected item.</li>
  1393. <li><span>first</span> <span>string</span> Display value of the first item in the list. E.g. &#8220;Select a Section&#8221; or &#8220;&#8221; for a blank option.</li>
  1394. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1395. <li><span>select_limit</span> <span>int</span> Specifies the maximum number of items that may be selected. If set to a value greater than 1, a multiselect will be used. The stored value will be an array.</li>
  1396. <li><span>as_csv</span> <span>int</span> If set to 1, the value will be stored as a delimited string of values instead of an array. This does nothing when select_limit is less than 2.</li>
  1397. </ul>
  1398. <h3>mem_form_select_category</h3>
  1399. <p>This will output an <span class="caps">HTML</span> select field populated with the specified Textpattern categories.</p>
  1400. <ul>
  1401. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1402. <li><span>name</span> <span>string</span> Input field name.</li>
  1403. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1404. <li><span>delimiter</span> <span>string</span> List separator. Default &#8220;,&#8221;</li>
  1405. <li><span>items</span> <span>string</span> Delimited list containing a select list display values.</li>
  1406. <li><span>values</span> <span>string</span> Delimited list containing a select list item values.</li>
  1407. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1408. <li><span>selected</span> <span>string</span> The value of the selected item.</li>
  1409. <li><span>first</span> <span>string</span> Display value of the first item in the list. E.g. &#8220;Select a Section&#8221; or &#8220;&#8221; for a blank option.</li>
  1410. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1411. <li><span>exclude</span> <span>string</span> List of item values that will not be included.</li>
  1412. <li><span>sort</span> <span>string</span> How will the list values be sorted.</li>
  1413. <li><span>type</span> <span>string</span> Category type name. E.g. &#8220;article&#8221;</li>
  1414. </ul>
  1415. <p>h3(tag#mem_form_select_range) . mem_form_select_range</p>
  1416. <p>This will output an <span class="caps">HTML</span> select field populated with a range of numbers.</p>
  1417. <ul>
  1418. <li><span>start</span> <span>int</span> The initial number to include. Default is 0.</li>
  1419. <li><span>stop</span> <span>int</span> The largest/smallest number to include.</li>
  1420. <li><span>step</span> <span>int</span> The increment between numbers in the range. Default is 1.</li>
  1421. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1422. <li><span>name</span> <span>string</span> Input field name.</li>
  1423. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1424. <li><span>delimiter</span> <span>string</span> List separator. Default &#8220;,&#8221;</li>
  1425. <li><span>items</span> <span>string</span> Delimited list containing a select list display values.</li>
  1426. <li><span>values</span> <span>string</span> Delimited list containing a select list item values.</li>
  1427. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1428. <li><span>selected</span> <span>string</span> The value of the selected item.</li>
  1429. <li><span>first</span> <span>string</span> Display value of the first item in the list. E.g. &#8220;Select a Section&#8221; or &#8220;&#8221; for a blank option.</li>
  1430. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1431. <li><span>exclude</span> <span>string</span> List of item values that will not be included.</li>
  1432. <li><span>sort</span> <span>string</span> How will the list values be sorted.</li>
  1433. <li><span>type</span> <span>string</span> Category type name. E.g. &#8220;article&#8221;</li>
  1434. </ul>
  1435. <h3>mem_form_select_section</h3>
  1436. <p>This will output an <span class="caps">HTML</span> select field populated with the specified Textpattern sections.</p>
  1437. <ul>
  1438. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1439. <li><span>name</span> <span>string</span> Input field name.</li>
  1440. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1441. <li><span>delimiter</span> <span>string</span> List separator. Default &#8220;,&#8221;</li>
  1442. <li><span>items</span> <span>string</span> Delimited list containing a select list display values.</li>
  1443. <li><span>values</span> <span>string</span> Delimited list containing a select list item values.</li>
  1444. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1445. <li><span>selected</span> <span>string</span> The value of the selected item.</li>
  1446. <li><span>first</span> <span>string</span> Display value of the first item in the list. E.g. &#8220;Select a Section&#8221; or &#8220;&#8221; for a blank option.</li>
  1447. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1448. <li><span>exclude</span> <span>string</span> List of item values that will not be included.</li>
  1449. <li><span>sort</span> <span>string</span> How will the list values be sorted.</li>
  1450. </ul>
  1451. <h3>mem_form_serverinfo</h3>
  1452. <p>This will output no <span class="caps">HTML</span> and is used to pass server information to the plugin handling the form submission.</p>
  1453. <ul>
  1454. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1455. <li><span>name</span> <span>string</span> Input field name.</li>
  1456. </ul>
  1457. <h3>mem_form_submit</h3>
  1458. <p>This will output either an <span class="caps">HTML</span> submit input field or an <span class="caps">HTML</span> button.</p>
  1459. <ul>
  1460. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1461. <li><span>name</span> <span>string</span> Input field name.</li>
  1462. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1463. <li><span>button</span> <span>int</span> If &#8220;1&#8221;, an html button tag will be used instead of an input tag.</li>
  1464. </ul>
  1465. <h3>mem_form_text</h3>
  1466. <p>This will output an <span class="caps">HTML</span> text input field.</p>
  1467. <ul>
  1468. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1469. <li><span>name</span> <span>string</span> Input field name.</li>
  1470. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1471. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1472. <li><span>default</span> <span>string</span> The default value.</li>
  1473. <li><span>format</span> <span>string</span> A regex pattern that will be matched against the input value. You must escape all backslashes &#8216;\&#8217;. E.g &#8220;/\\d/&#8221; is a single digit.</li>
  1474. <li><span>example</span> <span>string</span> An example of a correctly formatted input value.</li>
  1475. <li><span>password</span> <span>int</span> Specifies if the input field is a password field.</li>
  1476. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1477. <li><span>max</span> <span>int</span> Max character length.</li>
  1478. <li><span>min</span> <span>int</span> Min character length.</li>
  1479. <li><span>size</span> <span>int</span> Size of input field.</li>
  1480. <li><span>escape_value</span> <span>int</span> Set to &#8220;0&#8221; to prevent html escaping the value. Default &#8220;1&#8221;.</li>
  1481. </ul>
  1482. <h3>mem_form_textarea</h3>
  1483. <p>This will output an <span class="caps">HTML</span> textarea.</p>
  1484. <ul>
  1485. <li><span>label</span> <span>string</span> Friendly name for the input field. If set, this will output an <span class="caps">HTML</span> &lt;label&gt; tag linked to the input field.</li>
  1486. <li><span>name</span> <span>string</span> Input field name.</li>
  1487. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1488. <li><span>break</span> <span>string</span> Separator between label tag and input tag.</li>
  1489. <li><span>default</span> <span>string</span> The default value.</li>
  1490. <li><span>max</span> <span>int</span> Max character length.</li>
  1491. <li><span>min</span> <span>int</span> Min character length.</li>
  1492. <li><span>required</span> <span>int</span> Specifies if input is required.</li>
  1493. <li><span>rows</span> <span>int</span> Number of rows in the textarea.</li>
  1494. <li><span>cols</span> <span>int</span> Number of columns in the textarea.</li>
  1495. <li><span>escape_value</span> <span>int</span> Set to &#8220;0&#8221; to prevent html escaping the value. Default &#8220;1&#8221;.</li>
  1496. </ul>
  1497. <h3>mem_form_value</h3>
  1498. <p>This will output the value associated with a form field. Useful to mix <span class="caps">HTML</span> input fields with mem_form.</p>
  1499. <ul>
  1500. <li><span>id</span> <span>string</span> ID for output wrap tag.</li>
  1501. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class name.</li>
  1502. <li><span>class</span> <span>string</span> <span class="caps">CSS</span> class.</li>
  1503. <li><span>wraptag</span> <span>string</span> <span class="caps">HTML</span> tag to wrap around the value.</li>
  1504. <li><span>attributes</span> <span>string</span> Additional <span class="caps">HTML</span> tag attributes that should be passed to the output tag.</li>
  1505. </ul>
  1506. <h2>Exposed Functions</h2>
  1507. <h3>mem_form_mail</h3>
  1508. <p>This will send an email message.</p>
  1509. <ul>
  1510. <li><span>Return Value</span> <span>bool</span> Returns true or false, indicating whether the email was successfully given to the mail system. This does not indicate the validity of the email address or that the recipient actually received the email.</li>
  1511. <li><span>from</span> <span>string</span> The From email address.</li>
  1512. <li><span>reply</span> <span>string</span> The Reply To email address.</li>
  1513. <li><span>to</span> <span>string</span> The To email address(es).</li>
  1514. <li><span>subject</span> <span>string</span> The email&#8217;s Subject.</li>
  1515. <li><span>msg</span> <span>string</span> The email message.</li>
  1516. </ul>
  1517. <h3>mem_form_error</h3>
  1518. <p>This will set or get errors associated with the form.</p>
  1519. <ul>
  1520. <li><span>Return Value</span> <span>mixed</span> If err is <span class="caps">NULL</span>, then it will return an array of errors that have been set.</li>
  1521. <li><span>err</span> <span>string</span> An error that will be added to the list of form errors that will be displayed to the form user.</li>
  1522. </ul>
  1523. <h3>mem_form_default</h3>
  1524. <p>This will get or set a default value for a form.</p>
  1525. <ul>
  1526. <li><span>Return Value</span> <span>mixed</span> If <span>val is <span class="caps">NULL</span>, then it will return the default value set for the input field matching %(atts-name)key</span>. If <span>key</span> does not exist, then it will return <span class="caps">FALSE</span>.</li>
  1527. <li><span>key</span> <span>string</span> The name of the input field.</li>
  1528. <li><span>val</span> <span>string</span> If specified, this will be specified as the default value for the input field named &#8220;key&#8221;.</li>
  1529. </ul>
  1530. <h3>mem_form_store</h3>
  1531. <p>This will store the name, label and value for a field in to the appropriate global variables.</p>
  1532. <ul>
  1533. <li><span>name</span> <span>string</span> The name of the field.</li>
  1534. <li><span>label</span> <span>string</span> The label of the field.</li>
  1535. <li><span>value</span> <span>mixed</span> The value of the field.</li>
  1536. </ul>
  1537. <h3>mem_form_remove</h3>
  1538. <p>This will remove the information associated with a field that has been stored.</p>
  1539. <ul>
  1540. <li><span>name</span> <span>string</span> The name of the field.</li>
  1541. </ul>
  1542. <h2>Global Variables</h2>
  1543. <p>This library allows other plugins to hook in to events with the <code>register_callback</code> function.</p>
  1544. <ul>
  1545. <li><span>$mem_form_type</span> <span>string</span> A text value that allows a plugin determine if it should process the current form.</li>
  1546. <li><span>$mem_form_submit</span> <span>bool</span> This specifies if the form is doing a postback.</li>
  1547. <li><span>$mem_form_default</span> <span>array</span> An array containing the default values to use when displaying the form.</li>
  1548. <li><span>$mem_form</span> <span>array</span> An array mapping all input labels to their values.</li>
  1549. <li><span>$mem_form_labels</span> <span>array</span> An array mapping all input names to their labels.</li>
  1550. <li><span>$mem_form_values</span> <span>array</span> An array mapping all input names to their values.</li>
  1551. <li><span>$mem_form_thanks_form</span> <span>string</span> Contains the message that will be shown to the user after a successful submission. Either the &#8220;thanks_form&#8221; or the &#8220;thanks&#8221; attribute. A plugin can modify this value or return a string to over</li>
  1552. </ul>
  1553. <h2>Plugin Events</h2>
  1554. <h3>mem_form.defaults</h3>
  1555. <p>Allows a plugin to alter the default values for a form prior to being displayed.</p>
  1556. <h3>mem_form.display</h3>
  1557. <p>Allows a plugin to insert additional html in the rendered html form tag.</p>
  1558. <h3>mem_form.submit</h3>
  1559. <p>Allows a plugin to act upon a successful form submission.</p>
  1560. <h3>mem_form.spam</h3>
  1561. <p>Allows a plugin to test a submission as spam. The function get_mem_form_evaluator() returns the evaluator.</p>
  1562. <h3>mem_form.store_value</h3>
  1563. <p>On submit, this event is called for each field that passed the builtin checks and was just stored in to the global variables. The callback step is the field name. This callback can be used for custom field validation. If the value is invalid, return <span class="caps">FALSE</span>. Warning: This event is called for each field even if a previously checked field has failed.</p>
  1564. <h3>mem_form.validate</h3>
  1565. <p>This event is called on form submit, after the individual fields are parsed and validated. This event is not called if there are any errors after the fields are validated. Any multi-field or form specific validation should happen here. Use mem_form_error() to set any validation error messages to prevent a successful post.</p>
  1566. # --- END PLUGIN HELP ---
  1567. -->
  1568. <?php
  1569. }
  1570. ?>