PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/mem_form/mem_form.php

https://bitbucket.org/Manfre/txp-plugins
PHP | 1825 lines | 1495 code | 295 blank | 35 comment | 195 complexity | e9f889d0dc8ae9e60355313614287058 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // This is a PLUGIN TEMPLATE.
  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. Uncomment and edit this line to override:
  8. # $plugin['name'] = 'abc_plugin';
  9. // 0 = Plugin help is in Textile format, no raw HTML allowed (default).
  10. // 1 = Plugin help is in raw HTML. Not recommended.
  11. # $plugin['allow_html_help'] = 1;
  12. // $Rev$ $LastChangedDate$
  13. $plugin['version'] = '0.8.5';
  14. $plugin['author'] = 'Michael Manfre';
  15. $plugin['author_uri'] = 'http://manfre.net/';
  16. $plugin['description'] = 'A library plugin that provides support for html forms.';
  17. // Plugin types:
  18. // 0 = regular plugin; loaded on the public web side only
  19. // 1 = admin plugin; loaded on both the public and admin side
  20. // 2 = library; loaded only when include_plugin() or require_plugin() is called
  21. $plugin['type'] = 2;
  22. if (!defined('txpinterface'))
  23. @include_once('../zem_tpl.php');
  24. if (0) {
  25. ?>
  26. # --- BEGIN PLUGIN HELP ---
  27. h1(title). mem_form plugin
  28. h2(section summary). Summary
  29. p. This plugin provides HTML form capabilities for other plugins. This allows for consistent form tags and behaviors, while reducing overall plugin size and development time.
  30. h2(section contact). Author Contact
  31. "Michael Manfre":mailto:mmanfre@gmail.com?subject=Textpattern%20mem_form%20plugin
  32. "http://manfre.net":http://manfre.net
  33. h2(section license). License
  34. p. This plugin is licensed under the "GPLv2":http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  35. h2(section tags). Tags
  36. * "mem_form":#mem_form
  37. * "mem_form_checkbox":#mem_form_checkbox
  38. * "mem_form_email":#mem_form_email
  39. * "mem_form_file":#mem_form_file
  40. * "mem_form_hidden":#mem_form_hidden
  41. * "mem_form_radio":#mem_form_radio
  42. * "mem_form_secret":#mem_form_secret
  43. * "mem_form_select":#mem_form_select
  44. * "mem_form_select_category":#mem_form_select_category
  45. * "mem_form_select_range":#mem_form_select_range
  46. * "mem_form_select_section":#mem_form_select_section
  47. * "mem_form_serverinfo":#mem_form_serverinfo
  48. * "mem_form_submit":#mem_form_submit
  49. * "mem_form_text":#mem_form_text
  50. * "mem_form_textarea":#mem_form_textarea
  51. * "mem_form_value":#mem_form_value
  52. h3(tag#mem_form). mem_form
  53. p(tag-summary). This tag will create an HTML form and contains all of the processing and validation.
  54. *(atts) %(atts-name)form% %(atts-type)string% Name of a form that will be parsed to display the form.
  55. * %(atts-name)thanks_form% %(atts-type)string% Name of a form that will be parsed upon successful form submission.
  56. * %(atts-name)label% %(atts-type)string% Accessible name for the form.
  57. * %(atts-name required)type% %(atts-type)string% Name of the form to identify itself to bound plugin.
  58. * %(atts-name)thanks% %(atts-type)string% Message to display to user upon successful form submission.
  59. * %(atts-name)redirect% %(atts-type)url% URL to redirect upon successful form submission. Overrides "thanks" and "thanks_form".
  60. * %(atts-name)redirect_form% %(atts-type)string% Name of a form that will be parsed as displayed to the user on a redirect. The string "_{uri}_" will be replaced with the redirect url.
  61. * %(atts-name)enctype% %(atts-type)string% HTML encoding type used when the form is submitted. @enctype="multipart/form-data"@ is required when using mem_form_file.
  62. * %(atts-name)default_break% %(atts-type)string% 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 <br>
  63. h3(tag#mem_form_checkbox). mem_form_checkbox
  64. p(tag-summary). This will output an HTML checkbox field.
  65. *(atts) %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  66. * %(atts-name)checked% %(atts-type)int% Is this box checked. Default "0".
  67. * %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  68. * %(atts-name)name% %(atts-type)string% Input field name.
  69. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  70. * %(atts-name)class% %(atts-type)string% CSS class name.
  71. h3(tag#mem_form_email). mem_form_email
  72. p(tag-summary). This will output an HTML text input field and validates the submitted value as an email address.
  73. *(atts) %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  74. * %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  75. * %(atts-name)name% %(atts-type)string% Input field name.
  76. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  77. * %(atts-name)class% %(atts-type)string% CSS class name.
  78. * %(atts-name)default% %(atts-type)string% The default value.
  79. * %(atts-name)max% %(atts-type)int% Max character length.
  80. * %(atts-name)min% %(atts-type)int% Min character length.
  81. * %(atts-name)size% %(atts-type)int% Size of input field.
  82. h3(tag#mem_form_file). mem_form_file
  83. +p(tag-summary). This will output an HTML file input field. You must add the @enctype="multipart/form-data"@ attribute to your enclosing mem_form for this to work.
  84. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  85. * %(atts-name)name% %(atts-type)string% Input field name.
  86. * %(atts-name)class% %(atts-type)string% CSS class name.
  87. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  88. * %(atts-name)no_replace% %(atts-type)int% Specifies whether a user can upload another file and replace the existing file that will be submitted on successful completion of the form. If "1", the file input field will be replaced with details about the already uploaded file.
  89. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  90. * %(atts-name)size% %(atts-type)int% Size of input field.
  91. * %(atts-name)max_file_size% %(atts-type)int% Maximum size for the uploaded file. Checked server-side.
  92. * %(atts-name)accept% %(atts-type)string% The HTML file input field's "accept" argument that specifies which file types the field should permit.
  93. h3(tag#mem_form_hidden). mem_form_hidden
  94. p(tag-summary). This will output an HTML hidden text input field.
  95. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  96. * %(atts-name)name% %(atts-type)string% Input field name.
  97. * %(atts-name)value% %(atts-type)string% The input value.
  98. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  99. * %(atts-name)class% %(atts-type)string% CSS class name.
  100. * %(atts-name)escape_value% %(atts-type)int% Set to "0" to prevent html escaping the value. Default "1".
  101. h3(tag#mem_form_radio). mem_form_radio
  102. p(tag-summary). This will output an HTML radio button.
  103. *(atts) %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  104. * %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  105. * %(atts-name)name% %(atts-type)string% Input field name.
  106. * %(atts-name)class% %(atts-type)string% CSS class name.
  107. * %(atts-name)group% %(atts-type)string% A name that identifies a group of radio buttons.
  108. * %(atts-name)value% %(atts-type)string% The value of the radio button. If not set, a unique value is generated.
  109. * %(atts-name)checked% %(atts-type)int% Is this box checked. Default "0".
  110. h3(tag#mem_form_secret). mem_form_secret
  111. p(tag-summary). This will output nothing in HTML and is meant to pass information to the sumbit handler plugins.
  112. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  113. * %(atts-name)name% %(atts-type)string% Input field name.
  114. * %(atts-name)value% %(atts-type)string% The input value.
  115. h3(tag#mem_form_select). mem_form_select
  116. p(tag-summary). This will output an HTML select field.
  117. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  118. * %(atts-name)name% %(atts-type)string% Input field name.
  119. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  120. * %(atts-name)delimiter% %(atts-type)string% List separator. Default ","
  121. * %(atts-name)items% %(atts-type)string% Delimited list containing a select list display values.
  122. * %(atts-name)values% %(atts-type)string% Delimited list containing a select list item values.
  123. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  124. * %(atts-name)selected% %(atts-type)string% The value of the selected item.
  125. * %(atts-name)first% %(atts-type)string% Display value of the first item in the list. E.g. "Select a Section" or "" for a blank option.
  126. * %(atts-name)class% %(atts-type)string% CSS class name.
  127. * %(atts-name)select_limit% %(atts-type)int% 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.
  128. * %(atts-name)as_csv% %(atts-type)int% 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.
  129. h3(tag#mem_form_category). mem_form_select_category
  130. p(tag-summary). This will output an HTML select field populated with the specified Textpattern categories.
  131. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  132. * %(atts-name)name% %(atts-type)string% Input field name.
  133. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  134. * %(atts-name)delimiter% %(atts-type)string% List separator. Default ","
  135. * %(atts-name)items% %(atts-type)string% Delimited list containing a select list display values.
  136. * %(atts-name)values% %(atts-type)string% Delimited list containing a select list item values.
  137. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  138. * %(atts-name)selected% %(atts-type)string% The value of the selected item.
  139. * %(atts-name)first% %(atts-type)string% Display value of the first item in the list. E.g. "Select a Section" or "" for a blank option.
  140. * %(atts-name)class% %(atts-type)string% CSS class name.
  141. * %(atts-name)exclude% %(atts-type)string% List of item values that will not be included.
  142. * %(atts-name)sort% %(atts-type)string% How will the list values be sorted.
  143. * %(atts-name)type% %(atts-type)string% Category type name. E.g. "article"
  144. h3(tag#mem_form_select_range) . mem_form_select_range
  145. p(tag-summary). This will output an HTML select field populated with a range of numbers.
  146. *(atts) %(atts-name)start% %(atts-type)int% The initial number to include. Default is 0.
  147. * %(atts-name)stop% %(atts-type)int% The largest/smallest number to include.
  148. * %(atts-name)step% %(atts-type)int% The increment between numbers in the range. Default is 1.
  149. * %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  150. * %(atts-name)name% %(atts-type)string% Input field name.
  151. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  152. * %(atts-name)delimiter% %(atts-type)string% List separator. Default ","
  153. * %(atts-name)items% %(atts-type)string% Delimited list containing a select list display values.
  154. * %(atts-name)values% %(atts-type)string% Delimited list containing a select list item values.
  155. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  156. * %(atts-name)selected% %(atts-type)string% The value of the selected item.
  157. * %(atts-name)first% %(atts-type)string% Display value of the first item in the list. E.g. "Select a Section" or "" for a blank option.
  158. * %(atts-name)class% %(atts-type)string% CSS class name.
  159. * %(atts-name)exclude% %(atts-type)string% List of item values that will not be included.
  160. * %(atts-name)sort% %(atts-type)string% How will the list values be sorted.
  161. * %(atts-name)type% %(atts-type)string% Category type name. E.g. "article"
  162. h3(tag#mem_form_section). mem_form_select_section
  163. p(tag-summary). This will output an HTML select field populated with the specified Textpattern sections.
  164. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  165. * %(atts-name)name% %(atts-type)string% Input field name.
  166. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  167. * %(atts-name)delimiter% %(atts-type)string% List separator. Default ","
  168. * %(atts-name)items% %(atts-type)string% Delimited list containing a select list display values.
  169. * %(atts-name)values% %(atts-type)string% Delimited list containing a select list item values.
  170. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  171. * %(atts-name)selected% %(atts-type)string% The value of the selected item.
  172. * %(atts-name)first% %(atts-type)string% Display value of the first item in the list. E.g. "Select a Section" or "" for a blank option.
  173. * %(atts-name)class% %(atts-type)string% CSS class name.
  174. * %(atts-name)exclude% %(atts-type)string% List of item values that will not be included.
  175. * %(atts-name)sort% %(atts-type)string% How will the list values be sorted.
  176. h3(tag#mem_form_serverinfo). mem_form_serverinfo
  177. p(tag-summary). This will output no HTML and is used to pass server information to the plugin handling the form submission.
  178. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  179. * %(atts-name)name% %(atts-type)string% Input field name.
  180. h3(tag#mem_form_submit). mem_form_submit
  181. p(tag-summary). This will output either an HTML submit input field or an HTML button.
  182. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  183. * %(atts-name)name% %(atts-type)string% Input field name.
  184. * %(atts-name)class% %(atts-type)string% CSS class name.
  185. * %(atts-name)button% %(atts-type)int% If "1", an html button tag will be used instead of an input tag.
  186. h3(tag#mem_form_text). mem_form_text
  187. p(tag-summary). This will output an HTML text input field.
  188. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  189. * %(atts-name)name% %(atts-type)string% Input field name.
  190. * %(atts-name)class% %(atts-type)string% CSS class name.
  191. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  192. * %(atts-name)default% %(atts-type)string% The default value.
  193. * %(atts-name)format% %(atts-type)string% A regex pattern that will be matched against the input value. You must escape all backslashes '\'. E.g "/\\d/" is a single digit.
  194. * %(atts-name)example% %(atts-type)string% An example of a correctly formatted input value.
  195. * %(atts-name)password% %(atts-type)int% Specifies if the input field is a password field.
  196. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  197. * %(atts-name)max% %(atts-type)int% Max character length.
  198. * %(atts-name)min% %(atts-type)int% Min character length.
  199. * %(atts-name)size% %(atts-type)int% Size of input field.
  200. * %(atts-name)escape_value% %(atts-type)int% Set to "0" to prevent html escaping the value. Default "1".
  201. h3(tag#mem_form_textarea). mem_form_textarea
  202. p(tag-summary). This will output an HTML textarea.
  203. *(atts) %(atts-name)label% %(atts-type)string% Friendly name for the input field. If set, this will output an HTML ==<label>== tag linked to the input field.
  204. * %(atts-name)name% %(atts-type)string% Input field name.
  205. * %(atts-name)class% %(atts-type)string% CSS class name.
  206. * %(atts-name)break% %(atts-type)string% Separator between label tag and input tag.
  207. * %(atts-name)default% %(atts-type)string% The default value.
  208. * %(atts-name)max% %(atts-type)int% Max character length.
  209. * %(atts-name)min% %(atts-type)int% Min character length.
  210. * %(atts-name)required% %(atts-type)int% Specifies if input is required.
  211. * %(atts-name)rows% %(atts-type)int% Number of rows in the textarea.
  212. * %(atts-name)cols% %(atts-type)int% Number of columns in the textarea.
  213. * %(atts-name)escape_value% %(atts-type)int% Set to "0" to prevent html escaping the value. Default "1".
  214. h3(tag#mem_form_value). mem_form_value
  215. p(tag-summary). This will output the value associated with a form field. Useful to mix HTML input fields with mem_form.
  216. *(atts) %(atts-name)id% %(atts-type)string% ID for output wrap tag.
  217. * %(atts-name)class% %(atts-type)string% CSS class name.
  218. * %(atts-name)class% %(atts-type)string% CSS class.
  219. * %(atts-name)wraptag% %(atts-type)string% HTML tag to wrap around the value.
  220. * %(atts-name)attributes% %(atts-type)string% Additional HTML tag attributes that should be passed to the output tag.
  221. h2(section). Exposed Functions
  222. h3(tag). mem_form_mail
  223. p(tag-summary). This will send an email message.
  224. *(atts) %(atts-name)Return Value% %(atts-type)bool% 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.
  225. * %(atts-name)from% %(atts-type)string% The From email address.
  226. * %(atts-name)reply% %(atts-type)string% The Reply To email address.
  227. * %(atts-name)to% %(atts-type)string% The To email address(es).
  228. * %(atts-name)subject% %(atts-type)string% The email's Subject.
  229. * %(atts-name)msg% %(atts-type)string% The email message.
  230. h3(tag). mem_form_error
  231. p(tag-summary). This will set or get errors associated with the form.
  232. *(atts) %(atts-name)Return Value% %(atts-type)mixed% If err is NULL, then it will return an array of errors that have been set.
  233. * %(atts-name optional)err% %(atts-type)string% An error that will be added to the list of form errors that will be displayed to the form user.
  234. h3(tag). mem_form_default
  235. p(tag-summary). This will get or set a default value for a form.
  236. *(atts) %(atts-name)Return Value% %(atts-type)mixed% If %(atts-name)val is NULL, then it will return the default value set for the input field matching %(atts-name)key%. If %(atts-name)key% does not exist, then it will return FALSE.
  237. * %(atts-name)key% %(atts-type%)string% The name of the input field.
  238. * %(atts-name optional)val% %(atts-type)string% If specified, this will be specified as the default value for the input field named "key".
  239. h3(tag). mem_form_store
  240. p(tag-summary). This will store the name, label and value for a field in to the appropriate global variables.
  241. *(atts) %(atts-name)name% %(atts-type)string% The name of the field.
  242. * %(atts-name)label% %(atts-type%)string% The label of the field.
  243. * %(atts-name)value% %(atts-type)mixed% The value of the field.
  244. h3(tag). mem_form_remove
  245. p(tag-summary). This will remove the information associated with a field that has been stored.
  246. *(atts) %(atts-name)name% %(atts-type)string% The name of the field.
  247. h2(section). Global Variables
  248. p. This library allows other plugins to hook in to events with the @register_callback@ function.
  249. *(atts) %(atts-name)$mem_form_type% %(atts-type)string% A text value that allows a plugin determine if it should process the current form.
  250. * %(atts-name)$mem_form_submit% %(atts-type)bool% This specifies if the form is doing a postback.
  251. * %(atts-name)$mem_form_default% %(atts-type)array% An array containing the default values to use when displaying the form.
  252. * %(atts-name)$mem_form% %(atts-type)array% An array mapping all input labels to their values.
  253. * %(atts-name)$mem_form_labels% %(atts-type)array% An array mapping all input names to their labels.
  254. * %(atts-name)$mem_form_values% %(atts-type)array% An array mapping all input names to their values.
  255. * %(atts-name)$mem_form_thanks_form% %(atts-type)string% Contains the message that will be shown to the user after a successful submission. Either the "thanks_form" or the "thanks" attribute. A plugin can modify this value or return a string to over
  256. h2(section). Plugin Events
  257. h3(event). mem_form.defaults
  258. p(event-summary). Allows a plugin to alter the default values for a form prior to being displayed.
  259. h3(event). mem_form.display
  260. p(event-summary). Allows a plugin to insert additional html in the rendered html form tag.
  261. h3(event). mem_form.submit
  262. p(event-summary). Allows a plugin to act upon a successful form submission.
  263. h3(event). mem_form.spam
  264. p(event-summary). Allows a plugin to test a submission as spam. The function get_mem_form_evaluator() returns the evaluator.
  265. h3(event). mem_form.store_value
  266. p(event-summary). 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 FALSE. Warning: This event is called for each field even if a previously checked field has failed.
  267. h3(event). mem_form.validate
  268. p(event-summary). 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.
  269. # --- END PLUGIN HELP ---
  270. <?php
  271. }
  272. # --- BEGIN PLUGIN CODE ---
  273. $mem_glz_custom_fields_plugin = load_plugin('glz_custom_fields');
  274. // needed for MLP
  275. define( 'MEM_FORM_PREFIX' , 'mem_form' );
  276. global $mem_form_lang;
  277. if (!is_array($mem_form_lang))
  278. {
  279. $mem_form_lang = array(
  280. 'error_file_extension' => 'File upload failed for field {label}.',
  281. 'error_file_failed' => 'Failed to upload file for field {label}.',
  282. 'error_file_size' => 'Failed to upload File for field {label}. File is too large.',
  283. 'field_missing' => 'The field {label} is required.',
  284. 'form_expired' => 'The form has expired.',
  285. 'form_misconfigured' => 'The mem_form is misconfigured. You must specify the "form" attribute.',
  286. 'form_sorry' => 'The form is currently unavailable.',
  287. 'form_used' => 'This form has already been used to submit.',
  288. 'general_inquiry' => '',
  289. 'invalid_email' => 'The email address {email} is invalid.',
  290. 'invalid_host' => 'The host {domain} is invalid.',
  291. 'invalid_utf8' => 'Invalid UTF8 string for field {label}.',
  292. 'invalid_value' => 'The value "{value}" is invalid for the input field {label}.',
  293. 'invalid_format' => 'The input field {label} must match the format "{example}".',
  294. 'invalid_too_many_selected' => 'The input field {label} only allows {count} selected {plural}.',
  295. 'item' => 'item',
  296. 'items' => 'items',
  297. 'max_warning' => 'The input field {label} must be smaller than {max} characters long.',
  298. 'min_warning' => 'The input field {label} must be at least {min} characters long.',
  299. 'refresh' => 'Refresh',
  300. 'spam' => 'Your submission was blocked by a spam filter.',
  301. 'submitted_thanks' => 'You have successfully submitted the form. Thank you.',
  302. );
  303. }
  304. register_callback( 'mem_form_enumerate_strings' , 'l10n.enumerate_strings' );
  305. function mem_form_enumerate_strings($event , $step='' , $pre=0)
  306. {
  307. global $mem_form_lang;
  308. $r = array (
  309. 'owner' => 'mem_form', # Change to your plugin's name
  310. 'prefix' => MEM_FORM_PREFIX, # Its unique string prefix
  311. 'lang' => 'en-gb', # The language of the initial strings.
  312. 'event' => 'public', # public/admin/common = which interface the strings will be loaded into
  313. 'strings' => $mem_form_lang, # The strings themselves.
  314. );
  315. return $r;
  316. }
  317. function mem_form_gTxt($what,$args = array())
  318. {
  319. global $mem_form_lang, $textarray;
  320. $key = strtolower( MEM_FORM_PREFIX . '-' . $what );
  321. if (isset($textarray[$key]))
  322. {
  323. $str = $textarray[$key];
  324. }
  325. else
  326. {
  327. $key = strtolower($what);
  328. if (isset($mem_form_lang[$key]))
  329. $str = $mem_form_lang[$key];
  330. elseif (isset($textarray[$key]))
  331. $str = $textarray[$key];
  332. else
  333. $str = $what;
  334. }
  335. if( !empty($args) )
  336. $str = strtr( $str , $args );
  337. return $str;
  338. }
  339. function mem_form($atts, $thing='', $default=false)
  340. {
  341. global $sitename, $prefs, $file_max_upload_size, $mem_form_error, $mem_form_submit,
  342. $mem_form, $mem_form_labels, $mem_form_values, $mem_form_default_break,
  343. $mem_form_default, $mem_form_type, $mem_form_thanks_form,
  344. $mem_glz_custom_fields_plugin;
  345. extract(mem_form_lAtts(array(
  346. 'form' => '',
  347. 'thanks_form' => '',
  348. 'thanks' => graf(mem_form_gTxt('submitted_thanks')),
  349. 'label' => '',
  350. 'type' => '',
  351. 'redirect' => '',
  352. 'redirect_form' => '',
  353. 'class' => 'memForm',
  354. 'enctype' => '',
  355. 'file_accept' => '',
  356. 'max_file_size' => $file_max_upload_size,
  357. 'form_expired_msg' => mem_form_gTxt('form_expired'),
  358. 'show_error' => 1,
  359. 'show_input' => 1,
  360. 'default_break' => br,
  361. ), $atts));
  362. if (empty($type) or (empty($form) && empty($thing))) {
  363. trigger_error('Argument not specified for mem_form tag', E_USER_WARNING);
  364. return '';
  365. }
  366. $out = '';
  367. // init error structure
  368. mem_form_error();
  369. $mem_form_type = $type;
  370. $mem_form_default = is_array($default) ? $default : array();
  371. callback_event('mem_form.defaults');
  372. unset($atts['show_error'], $atts['show_input']);
  373. $mem_form_id = md5(serialize($atts).preg_replace('/[\t\s\r\n]/','',$thing));
  374. $mem_form_submit = (ps('mem_form_id') == $mem_form_id);
  375. $nonce = doSlash(ps('mem_form_nonce'));
  376. $renonce = false;
  377. if ($mem_form_submit) {
  378. safe_delete('txp_discuss_nonce', 'issue_time < date_sub(now(), interval 10 minute)');
  379. if ($rs = safe_row('used', 'txp_discuss_nonce', "nonce = '$nonce'"))
  380. {
  381. if ($rs['used'])
  382. {
  383. unset($mem_form_error);
  384. mem_form_error(mem_form_gTxt('form_used'));
  385. $renonce = true;
  386. $_POST['mem_form_submit'] = TRUE;
  387. $_POST['mem_form_id'] = $mem_form_id;
  388. $_POST['mem_form_nonce'] = $nonce;
  389. }
  390. }
  391. else
  392. {
  393. mem_form_error($form_expired_msg);
  394. $renonce = true;
  395. }
  396. }
  397. if ($mem_form_submit and $nonce and !$renonce)
  398. {
  399. $mem_form_nonce = $nonce;
  400. }
  401. elseif (!$show_error or $show_input)
  402. {
  403. $mem_form_nonce = md5(uniqid(rand(), true));
  404. safe_insert('txp_discuss_nonce', "issue_time = now(), nonce = '$mem_form_nonce'");
  405. }
  406. $form = ($form) ? fetch_form($form) : $thing;
  407. $form = parse($form);
  408. if ($mem_form_submit && empty($mem_form_error))
  409. {
  410. // let plugins validate after individual fields are validated
  411. callback_event('mem_form.validate');
  412. }
  413. if (!$mem_form_submit) {
  414. # don't show errors or send mail
  415. }
  416. elseif (mem_form_error())
  417. {
  418. if ($show_error or !$show_input)
  419. {
  420. $out .= mem_form_display_error();
  421. if (!$show_input) return $out;
  422. }
  423. }
  424. elseif ($show_input and is_array($mem_form))
  425. {
  426. if ($mem_glz_custom_fields_plugin) {
  427. // prep the values
  428. glz_custom_fields_before_save();
  429. }
  430. callback_event('mem_form.spam');
  431. /// load and check spam plugins/
  432. $evaluator =& get_mem_form_evaluator();
  433. $is_spam = $evaluator->is_spam();
  434. if ($is_spam) {
  435. return mem_form_gTxt('spam');
  436. }
  437. $mem_form_thanks_form = ($thanks_form ? fetch_form($thanks_form) : $thanks);
  438. safe_update('txp_discuss_nonce', "used = '1', issue_time = now()", "nonce = '$nonce'");
  439. $result = callback_event('mem_form.submit');
  440. if (mem_form_error()) {
  441. $out .= mem_form_display_error();
  442. $redirect = false;
  443. }
  444. $thanks_form = $mem_form_thanks_form;
  445. unset($mem_form_thanks_form);
  446. if (!empty($result))
  447. return $result;
  448. if (mem_form_error() and $show_input)
  449. {
  450. // no-op, reshow form with errors
  451. }
  452. else if ($redirect)
  453. {
  454. $_POST = array();
  455. while (@ob_end_clean());
  456. $uri = hu.ltrim($redirect,'/');
  457. if (empty($_SERVER['FCGI_ROLE']) and empty($_ENV['FCGI_ROLE']))
  458. {
  459. txp_status_header('303 See Other');
  460. header('Location: '.$uri);
  461. header('Connection: close');
  462. header('Content-Length: 0');
  463. }
  464. else
  465. {
  466. $uri = htmlspecialchars($uri);
  467. $refresh = mem_form_gTxt('refresh');
  468. if (!empty($redirect_form))
  469. {
  470. $redirect_form = fetch_form($redirect_form);
  471. echo str_replace('{uri}', $uri, $redirect_form);
  472. }
  473. if (empty($redirect_form))
  474. {
  475. echo <<<END
  476. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  477. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  478. <head>
  479. <title>$sitename</title>
  480. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  481. <meta http-equiv="refresh" content="0;url=$uri" />
  482. </head>
  483. <body>
  484. <a href="$uri">$refresh</a>
  485. </body>
  486. </html>
  487. END;
  488. }
  489. }
  490. exit;
  491. }
  492. else {
  493. return '<div class="memThanks" id="mem'.$mem_form_id.'">' .
  494. $thanks_form . '</div>';
  495. }
  496. }
  497. if ($show_input)
  498. {
  499. $file_accept = (!empty($file_accept) ? ' accept="'.$file_accept.'"' : '');
  500. $class = htmlspecialchars($class);
  501. $enctype = !empty($enctype) ? ' enctype="'.$enctype.'"' : '';
  502. 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.'>'.
  503. ( $label ? n.'<fieldset>' : n.'<div>' ).
  504. ( $label ? n.'<legend>'.htmlspecialchars($label).'</legend>' : '' ).
  505. $out.
  506. n.'<input type="hidden" name="mem_form_nonce" value="'.$mem_form_nonce.'" />'.
  507. n.'<input type="hidden" name="mem_form_id" value="'.$mem_form_id.'" />'.
  508. (!empty($max_file_size) ? n.'<input type="hidden" name="MAX_FILE_SIZE" value="'.$max_file_size.'" />' : '' ).
  509. callback_event('mem_form.display','',1).
  510. $form.
  511. callback_event('mem_form.display').
  512. ( $label ? (n.'</fieldset>') : (n.'</div>') ).
  513. n.'</form>';
  514. }
  515. return '';
  516. }
  517. function mem_form_text($atts)
  518. {
  519. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  520. extract(mem_form_lAtts(array(
  521. 'break' => $mem_form_default_break,
  522. 'default' => '',
  523. 'isError' => '',
  524. 'label' => mem_form_gTxt('text'),
  525. 'max' => 100,
  526. 'min' => 0,
  527. 'name' => '',
  528. 'class' => 'memText',
  529. 'required' => 1,
  530. 'size' => '',
  531. 'password' => 0,
  532. 'format' => '',
  533. 'example' => '',
  534. 'escape_value' => 1
  535. ), $atts));
  536. $min = intval($min);
  537. $max = intval($max);
  538. $size = intval($size);
  539. if (empty($name)) $name = mem_form_label2name($label);
  540. if ($mem_form_submit)
  541. {
  542. $value = trim(ps($name));
  543. $utf8len = preg_match_all("/./su", $value, $utf8ar);
  544. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  545. if (strlen($value) == 0 && $required)
  546. {
  547. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  548. $isError = true;
  549. }
  550. elseif ($required && !empty($format) && !preg_match($format, $value))
  551. {
  552. //echo "format=$format<br />value=$value<br />";
  553. $mem_form_error[] = mem_form_gTxt('invalid_format', array('{label}'=>$hlabel, '{example}'=> htmlspecialchars($example)));
  554. $isError = true;
  555. }
  556. elseif (strlen($value))
  557. {
  558. if (!$utf8len)
  559. {
  560. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  561. $isError = true;
  562. }
  563. elseif ($min and $utf8len < $min)
  564. {
  565. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  566. $isError = true;
  567. }
  568. elseif ($max and $utf8len > $max)
  569. {
  570. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  571. $isError = true;
  572. }
  573. else
  574. {
  575. $isError = false === mem_form_store($name, $label, $value);
  576. }
  577. }
  578. }
  579. else
  580. {
  581. if (isset($mem_form_default[$name]))
  582. $value = $mem_form_default[$name];
  583. else
  584. $value = $default;
  585. }
  586. $size = ($size) ? ' size="'.$size.'"' : '';
  587. $maxlength = ($max) ? ' maxlength="'.$max.'"' : '';
  588. $isError = $isError ? "errorElement" : '';
  589. $memRequired = $required ? 'memRequired' : '';
  590. $class = htmlspecialchars($class);
  591. if ($escape_value)
  592. {
  593. $value = htmlspecialchars($value);
  594. }
  595. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  596. '<input type="'.($password ? 'password' : 'text').'" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" value="'.$value.'"'.$size.$maxlength.' />';
  597. }
  598. function mem_form_file($atts)
  599. {
  600. global $mem_form_submit, $mem_form_error, $mem_form_default, $file_max_upload_size, $tempdir, $mem_form_default_break;
  601. extract(mem_form_lAtts(array(
  602. 'break' => $mem_form_default_break,
  603. 'isError' => '',
  604. 'label' => mem_form_gTxt('file'),
  605. 'name' => '',
  606. 'class' => 'memFile',
  607. 'size' => '',
  608. 'accept' => '',
  609. 'no_replace' => 1,
  610. 'max_file_size' => $file_max_upload_size,
  611. 'required' => 1,
  612. 'default' => FALSE,
  613. ), $atts));
  614. $fname = ps('file_'.$name);
  615. $frealname = ps('file_info_'.$name.'_name');
  616. $ftype = ps('file_info_'.$name.'_type');
  617. if (empty($name)) $name = mem_form_label2name($label);
  618. $out = '';
  619. if ($mem_form_submit)
  620. {
  621. if (!empty($fname))
  622. {
  623. // see if user uploaded a different file to replace already uploaded
  624. if (isset($_FILES[$name]) && !empty($_FILES[$name]['tmp_name']))
  625. {
  626. // unlink last temp file
  627. if (file_exists($fname) && substr_compare($fname, $tempdir, 0, strlen($tempdir), 1)==0)
  628. unlink($fname);
  629. $fname = '';
  630. }
  631. else
  632. {
  633. // pass through already uploaded filename
  634. mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  635. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  636. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  637. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  638. }
  639. }
  640. if (empty($fname))
  641. {
  642. $hlabel = empty($label) ? htmlspecialchars($name) : htmlspecialchars($label);
  643. $fname = $_FILES[$name]['tmp_name'];
  644. $frealname = $_FILES[$name]['name'];
  645. $ftype = $_FILES[$name]['type'];
  646. $err = 0;
  647. switch ($_FILES[$name]['error']) {
  648. case UPLOAD_ERR_OK:
  649. if (is_uploaded_file($fname) and $max_file_size >= filesize($fname))
  650. mem_form_store($name, $label, $_FILES[$name]);
  651. elseif (!is_uploaded_file($fname)) {
  652. if ($required) {
  653. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  654. $err = 1;
  655. }
  656. }
  657. else {
  658. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  659. $err = 1;
  660. }
  661. break;
  662. case UPLOAD_ERR_NO_FILE:
  663. if ($required) {
  664. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  665. $err = 1;
  666. }
  667. break;
  668. case UPLOAD_ERR_EXTENSION:
  669. $mem_form_error[] = mem_form_gTxt('error_file_extension', array('{label}'=>$hlabel));
  670. $err = 1;
  671. break;
  672. case UPLOAD_ERR_INI_SIZE:
  673. case UPLOAD_ERR_FORM_SIZE:
  674. $mem_form_error[] = mem_form_gTxt('error_file_size', array('{label}'=>$hlabel));
  675. $err = 1;
  676. break;
  677. default:
  678. $mem_form_error[] = mem_form_gTxt('error_file_failed', array('{label}'=>$hlabel));
  679. $err = 1;
  680. break;
  681. }
  682. if (!$err)
  683. {
  684. // store as a txp tmp file to be used later
  685. $fname = get_uploaded_file($fname);
  686. $err = false === mem_form_store($name, $label, array('tmp_name'=>$fname, 'name' => $frealname, 'type' => $ftype));
  687. if ($err)
  688. {
  689. // clean up file
  690. @unlink($fname);
  691. }
  692. else
  693. {
  694. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  695. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($_FILES[$name]['name'])."' />"
  696. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($_FILES[$name]['type'])."' />";
  697. }
  698. }
  699. $isError = $err ? 'errorElement' : '';
  700. }
  701. }
  702. else
  703. {
  704. if (isset($mem_form_default[$name]))
  705. $value = $mem_form_default[$name];
  706. else if (is_array($default))
  707. $value = $default;
  708. if (is_array(@$value))
  709. {
  710. $fname = @$value['tmp_name'];
  711. $frealname = @$value['name'];
  712. $ftype = @$value['type'];
  713. $out .= "<input type='hidden' name='file_".$name."' value='".htmlspecialchars($fname)."' />"
  714. . "<input type='hidden' name='file_info_".$name."_name' value='".htmlspecialchars($frealname)."' />"
  715. . "<input type='hidden' name='file_info_".$name."_type' value='".htmlspecialchars($ftype)."' />";
  716. }
  717. }
  718. $memRequired = $required ? 'memRequired' : '';
  719. $class = htmlspecialchars($class);
  720. $size = ($size) ? ' size="'.$size.'"' : '';
  721. $accept = (!empty($accept) ? ' accept="'.$accept.'"' : '');
  722. $field_out = '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break;
  723. if (!empty($frealname) && $no_replace)
  724. {
  725. $field_out .= '<div id="'.$name.'">'.htmlspecialchars($frealname) . ' <span id="'.$name.'_ftype">('. htmlspecialchars($ftype).')</span></div>';
  726. }
  727. else
  728. {
  729. $field_out .= '<input type="file" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"' .$size.' />';
  730. }
  731. return $out.$field_out;
  732. }
  733. function mem_form_textarea($atts, $thing='')
  734. {
  735. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  736. extract(mem_form_lAtts(array(
  737. 'break' => $mem_form_default_break,
  738. 'cols' => 58,
  739. 'default' => '',
  740. 'isError' => '',
  741. 'label' => mem_form_gTxt('textarea'),
  742. 'max' => 10000,
  743. 'min' => 0,
  744. 'name' => '',
  745. 'class' => 'memTextarea',
  746. 'required' => 1,
  747. 'rows' => 8,
  748. 'escape_value' => 1
  749. ), $atts));
  750. $min = intval($min);
  751. $max = intval($max);
  752. $cols = intval($cols);
  753. $rows = intval($rows);
  754. if (empty($name)) $name = mem_form_label2name($label);
  755. if ($mem_form_submit)
  756. {
  757. $value = preg_replace('/^\s*[\r\n]/', '', rtrim(ps($name)));
  758. $utf8len = preg_match_all("/./su", ltrim($value), $utf8ar);
  759. $hlabel = htmlspecialchars($label);
  760. if (strlen(ltrim($value)))
  761. {
  762. if (!$utf8len)
  763. {
  764. $mem_form_error[] = mem_form_gTxt('invalid_utf8', array('{label}'=>$hlabel));
  765. $isError = true;
  766. }
  767. elseif ($min and $utf8len < $min)
  768. {
  769. $mem_form_error[] = mem_form_gTxt('min_warning', array('{label}'=>$hlabel, '{min}'=>$min));
  770. $isError = true;
  771. }
  772. elseif ($max and $utf8len > $max)
  773. {
  774. $mem_form_error[] = mem_form_gTxt('max_warning', array('{label}'=>$hlabel, '{max}'=>$max));
  775. $isError = true;
  776. }
  777. else
  778. {
  779. $isError = false === mem_form_store($name, $label, $value);
  780. }
  781. }
  782. elseif ($required)
  783. {
  784. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=>$hlabel));
  785. $isError = true;
  786. }
  787. }
  788. else
  789. {
  790. if (isset($mem_form_default[$name]))
  791. $value = $mem_form_default[$name];
  792. else if (!empty($default))
  793. $value = $default;
  794. else
  795. $value = parse($thing);
  796. }
  797. $isError = $isError ? 'errorElement' : '';
  798. $memRequired = $required ? 'memRequired' : '';
  799. $class = htmlspecialchars($class);
  800. if ($escape_value)
  801. {
  802. $value = htmlspecialchars($value);
  803. }
  804. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  805. '<textarea id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'" cols="'.$cols.'" rows="'.$rows.'">'.$value.'</textarea>';
  806. }
  807. function mem_form_email($atts)
  808. {
  809. global $mem_form_error, $mem_form_submit, $mem_form_from, $mem_form_default, $mem_form_default_break;
  810. extract(mem_form_lAtts(array(
  811. 'default' => '',
  812. 'isError' => '',
  813. 'label' => mem_form_gTxt('email'),
  814. 'max' => 100,
  815. 'min' => 0,
  816. 'name' => '',
  817. 'required' => 1,
  818. 'break' => $mem_form_default_break,
  819. 'size' => '',
  820. 'class' => 'memEmail',
  821. ), $atts));
  822. if (empty($name)) $name = mem_form_label2name($label);
  823. if ($mem_form_submit)
  824. {
  825. $email = trim(ps($name));
  826. if (strlen($email))
  827. {
  828. if (!is_valid_email($email))
  829. {
  830. $mem_form_error[] = mem_form_gTxt('invalid_email', array('{email}'=>htmlspecialchars($email)));
  831. $isError = true;
  832. }
  833. else
  834. {
  835. preg_match("/@(.+)$/", $email, $match);
  836. $domain = $match[1];
  837. if (is_callable('checkdnsrr') and checkdnsrr('textpattern.com.','A') and !checkdnsrr($domain.'.','MX') and !checkdnsrr($domain.'.','A'))
  838. {
  839. $mem_form_error[] = mem_form_gTxt('invalid_host', array('{domain}'=>htmlspecialchars($domain)));
  840. $isError = true;
  841. }
  842. else
  843. {
  844. $mem_form_from = $email;
  845. }
  846. }
  847. }
  848. }
  849. else
  850. {
  851. if (isset($mem_form_default[$name]))
  852. $email = $mem_form_default[$name];
  853. else
  854. $email = $default;
  855. }
  856. return mem_form_text(array(
  857. 'default' => $email,
  858. 'isError' => $isError,
  859. 'label' => $label,
  860. 'max' => $max,
  861. 'min' => $min,
  862. 'name' => $name,
  863. 'required' => $required,
  864. 'break' => $break,
  865. 'size' => $size,
  866. 'class' => $class,
  867. ));
  868. }
  869. function mem_form_select_section($atts)
  870. {
  871. extract(mem_form_lAtts(array(
  872. 'exclude' => '',
  873. 'sort' => 'name ASC',
  874. 'delimiter' => ',',
  875. ),$atts,false));
  876. if (!empty($exclude)) {
  877. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  878. $exclusion = array_map('strtolower', $exclusion);
  879. if (count($exclusion))
  880. $exclusion = join($delimiter, quote_list($exclusion));
  881. }
  882. $where = empty($exclusion) ? '1=1' : 'LOWER(name) NOT IN ('.$exclusion.')';
  883. $sort = empty($sort) ? '' : ' ORDER BY '. doSlash($sort);
  884. $rs = safe_rows('name, title','txp_section',$where . $sort);
  885. $items = array();
  886. $values = array();
  887. if ($rs) {
  888. foreach($rs as $r) {
  889. $items[] = $r['title'];
  890. $values[] = $r['name'];
  891. }
  892. }
  893. unset($atts['exclude'], $atts['sort']);
  894. $atts['items'] = join($delimiter, $items);
  895. $atts['values'] = join($delimiter, $values);
  896. return mem_form_select($atts);
  897. }
  898. function mem_form_select_category($atts)
  899. {
  900. extract(mem_form_lAtts(array(
  901. 'root' => 'root',
  902. 'exclude' => '',
  903. 'delimiter' => ',',
  904. 'type' => 'article'
  905. ),$atts,false));
  906. $rs = getTree($root, $type);
  907. if (!empty($exclude)) {
  908. $exclusion = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$exclude)));
  909. $exclusion = array_map('strtolower', $exclusion);
  910. }
  911. else
  912. $exclusion = array();
  913. $items = array();
  914. $values = array();
  915. if ($rs) {
  916. foreach ($rs as $cat) {
  917. if (count($exclusion) && in_array(strtolower($cat['name']), $exclusion))
  918. continue;
  919. $items[] = $cat['title'];
  920. $values[] = $cat['name'];
  921. }
  922. }
  923. unset($atts['root'], $atts['type']);
  924. $atts['items'] = join($delimiter, $items);
  925. $atts['values'] = join($delimiter, $values);
  926. return mem_form_select($atts);
  927. }
  928. function mem_form_select_range($atts)
  929. {
  930. global $mem_form_default_break;
  931. $latts = mem_form_lAtts(array(
  932. 'start' => 0,
  933. 'stop' => false,
  934. 'step' => 1,
  935. 'name' => '',
  936. 'break' => $mem_form_default_break,
  937. 'delimiter' => ',',
  938. 'isError' => '',
  939. 'label' => mem_form_gTxt('option'),
  940. 'first' => FALSE,
  941. 'required' => 1,
  942. 'select_limit' => FALSE,
  943. 'as_csv' => FALSE,
  944. 'selected' => '',
  945. 'class' => 'memSelect',
  946. ), $atts);
  947. if ($stop === false)
  948. {
  949. trigger_error(gTxt('missing_required_attribute', array('{name}' => 'stop')), E_USER_ERROR);
  950. }
  951. $step = empty($latts['step']) ? 1 : assert_int($latts['step']);
  952. $start= assert_int($latts['start']);
  953. $stop = assert_int($latts['stop']);
  954. // fixup start/stop based upon step direction
  955. $start = $step > 0 ? min($start, $stop) : max($start, $stop);
  956. $stop = $step > 0 ? max($start, $stop) : min($start, $stop);
  957. $values = array();
  958. for($i=$start; $i >= $start && $i < $stop; $i += $step)
  959. {
  960. array_push($values, $i);
  961. }
  962. // intentional trample
  963. $latts['items'] = $latts['values'] = implode($latts['delimiter'], $values);
  964. return mem_form_select($latts);
  965. }
  966. function mem_form_select($atts)
  967. {
  968. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  969. extract(mem_form_lAtts(array(
  970. 'name' => '',
  971. 'break' => $mem_form_default_break,
  972. 'delimiter' => ',',
  973. 'isError' => '',
  974. 'label' => mem_form_gTxt('option'),
  975. 'items' => mem_form_gTxt('general_inquiry'),
  976. 'values' => '',
  977. 'first' => FALSE,
  978. 'required' => 1,
  979. 'select_limit' => FALSE,
  980. 'as_csv' => FALSE,
  981. 'selected' => '',
  982. 'class' => 'memSelect',
  983. ), $atts, false));
  984. if (empty($name)) $name = mem_form_label2name($label);
  985. if (!empty($items) && $items[0] == '<') $items = parse($items);
  986. if (!empty($values) && $values[0] == '<') $values = parse($values);
  987. if ($first !== FALSE) {
  988. $items = $first.$delimiter.$atts['items'];
  989. $values = $first.$delimiter.$atts['values'];
  990. }
  991. $select_limit = empty($select_limit) ? 1 : assert_int($select_limit);
  992. $items = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$items)));
  993. $values = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$values)));
  994. if ($select_limit > 1)
  995. {
  996. $selected = array_map('trim', explode($delimiter, preg_replace('/[\r\n\t\s]+/', ' ',$seelcted)));
  997. }
  998. else
  999. {
  1000. $selected = array(trim($selected));
  1001. }
  1002. $use_values_array = (count($items) == count($values));
  1003. if ($mem_form_submit)
  1004. {
  1005. if (strpos($name, '[]'))
  1006. {
  1007. $value = ps(substr($name, 0, strlen($name)-2));
  1008. $selected = $value;
  1009. if ($as_csv)
  1010. {
  1011. $value = implode($delimiter, $value);
  1012. }
  1013. }
  1014. else
  1015. {
  1016. $value = trim(ps($name));
  1017. $selected = array($value);
  1018. }
  1019. if (!empty($selected))
  1020. {
  1021. if (count($selected) <= $select_limit)
  1022. {
  1023. foreach ($selected as $v)
  1024. {
  1025. $is_valid = ($use_values_array && in_array($v, $values)) or (!$use_values_array && in_array($v, $items));
  1026. if (!$is_valid)
  1027. {
  1028. $invalid_value = $v;
  1029. break;
  1030. }
  1031. }
  1032. if ($is_valid)
  1033. {
  1034. $isError = false === mem_form_store($name, $label, $value);
  1035. }
  1036. else
  1037. {
  1038. $mem_form_error[] = mem_form_gTxt('invalid_value', array('{label}'=> htmlspecialchars($label), '{value}'=> htmlspecialchars($invalid_value)));
  1039. $isError = true;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. $mem_form_error[] = mem_form_gTxt('invalid_too_many_selected', array(
  1045. '{label}'=> htmlspecialchars($label),
  1046. '{count}'=> $select_limit,
  1047. '{plural}'=> ($select_limit==1 ? mem_form_gTxt('item') : mem_form_gTxt('items'))
  1048. ));
  1049. $isError = true;
  1050. }
  1051. }
  1052. elseif ($required)
  1053. {
  1054. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  1055. $isError = true;
  1056. }
  1057. }
  1058. else if (isset($mem_form_default[$name]))
  1059. {
  1060. $selected = array($mem_form_default[$name]);
  1061. }
  1062. $out = '';
  1063. foreach ($items as $item)
  1064. {
  1065. $v = $use_values_array ? array_shift($values) : $item;
  1066. $sel = !empty($selected) && in_array($v, $selected);
  1067. $out .= n.t.'<option'.($use_values_array ? ' value="'.$v.'"' : '').($sel ? ' selected="selected">' : '>').
  1068. (strlen($item) ? htmlspecialchars($item) : ' ').'</option>';
  1069. }
  1070. $isError = $isError ? 'errorElement' : '';
  1071. $memRequired = $required ? 'memRequired' : '';
  1072. $class = htmlspecialchars($class);
  1073. $multiple = $select_limit > 1 ? ' multiple="multiple"' : '';
  1074. return '<label for="'.$name.'" class="'.$class.' '.$memRequired.$isError.' '.$name.'">'.htmlspecialchars($label).'</label>'.$break.
  1075. n.'<select id="'.$name.'" name="'.$name.'" class="'.$class.' '.$memRequired.$isError.'"' . $multiple . '>'.
  1076. $out.
  1077. n.'</select>';
  1078. }
  1079. function mem_form_checkbox($atts)
  1080. {
  1081. global $mem_form_error, $mem_form_submit, $mem_form_default, $mem_form_default_break;
  1082. extract(mem_form_lAtts(array(
  1083. 'break' => $mem_form_default_break,
  1084. 'checked' => 0,
  1085. 'isError' => '',
  1086. 'label' => mem_form_gTxt('checkbox'),
  1087. 'name' => '',
  1088. 'class' => 'memCheckbox',
  1089. 'required' => 1
  1090. ), $atts));
  1091. if (empty($name)) $name = mem_form_label2name($label);
  1092. if ($mem_form_submit)
  1093. {
  1094. $value = (bool) ps($name);
  1095. if ($required and !$value)
  1096. {
  1097. $mem_form_error[] = mem_form_gTxt('field_missing', array('{label}'=> htmlspecialchars($label)));
  1098. $isError = true;
  1099. }
  1100. else
  1101. {
  1102. $isError = false === mem_form_store($name, $label, $value ? gTxt('yes') : gTxt('no'));
  1103. }
  1104. }
  1105. else {
  1106. if (isset($mem_form_default[$name]))
  1107. $value = $mem_form_default[$name];
  1108. else
  1109. $value = $checked;
  1110. }
  1111. $isError = $isError ? 'errorElement' : '';
  1112. $memRequired = $required ? 'memRequired' : '';
  1113. $class = htmlspecialchars($class);
  1114. return '<input type="checkbox" id="'.$name.'" class="'.$class.' '.$memRequired.$isError.'" name="'.$name.'"'.
  1115. ($value ? ' checked="checked"'

Large files files are truncated, but you can click here to view the full file