addressfield_tokens.components.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <?php
  2. /**
  3. * @file
  4. * Webform Component information for an address field type
  5. */
  6. /**
  7. * Specify the default properties of a component.
  8. *
  9. * @return
  10. * An array defining the default structure of a component.
  11. */
  12. function _webform_defaults_addressfield() {
  13. return array(
  14. 'name' => '',
  15. 'form_key' => NULL,
  16. 'required' => 0,
  17. 'pid' => 0,
  18. 'weight' => 0,
  19. 'extra' => array(
  20. 'title_display' => 0,
  21. 'private' => FALSE,
  22. 'attributes' => array(),
  23. 'description' => '',
  24. 'available_countries' => array(),
  25. 'csv_separate' => 0,
  26. ),
  27. );
  28. }
  29. /**
  30. * Generate the form for editing a component.
  31. * Create a set of form elements to be displayed on the form for editing this
  32. * component. Use care naming the form items, as this correlates directly to the
  33. * database schema. The component "Name" and "Description" fields are added to
  34. * every component type and are not necessary to specify here (although they
  35. * may be overridden if desired).
  36. *
  37. * @param $component
  38. * A Webform component array.
  39. *
  40. * @return
  41. * An array of form items to be displayed on the edit component page
  42. */
  43. function _webform_edit_addressfield($component) {
  44. $form = array();
  45. $form['extra']['available_countries'] = array(
  46. '#type' => 'select',
  47. '#multiple' => TRUE,
  48. '#title' => t('Available countries'),
  49. '#description' => t('If no countries are selected, all countries will be available.'),
  50. '#options' => _addressfield_country_options_list(),
  51. '#default_value' => $component['extra']['available_countries'],
  52. );
  53. $form['extra']['csv_separate'] = array(
  54. '#type' => 'radios',
  55. '#title' => t('CSV download'),
  56. '#description' => t('How would you like addresses presented in CSV downloads?'),
  57. '#options' => array(
  58. 0 => t('Display entire address in a single column'),
  59. 1 => t('Display each address component in a separate column'),
  60. ),
  61. '#default_value' => $component['extra']['csv_separate'],
  62. );
  63. return $form;
  64. }
  65. /**
  66. * Render a Webform component to be part of a form.
  67. *
  68. * @param $component
  69. * A Webform component array.
  70. * @param $value
  71. * If editing an existing submission or resuming a draft, this will contain
  72. * an array of values to be shown instead of the default in the component
  73. * configuration. This value will always be an array, keyed numerically for
  74. * each value saved in this field.
  75. * @param $filter
  76. * Whether or not to filter the contents of descriptions and values when
  77. * rendering the component. Values need to be unfiltered to be editable by
  78. * Form Builder.
  79. *
  80. * @see _webform_client_form_add_component()
  81. */
  82. function _webform_render_addressfield($component, $value = NULL, $filter = TRUE) {
  83. $element = array(
  84. '#type' => 'fieldset',
  85. '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
  86. '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
  87. '#attributes' => $component['extra']['attributes'],
  88. '#theme_wrappers' => array('webform_element'),
  89. '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
  90. '#required' => $component['required'],
  91. '#weight' => $component['weight'],
  92. '#translatable' => array(
  93. 'title',
  94. 'description',
  95. ),
  96. );
  97. $available = !empty($component['extra']['available_countries']) ? $component['extra']['available_countries'] : NULL;
  98. // Get the current address
  99. if (!empty($value[0])) {
  100. if (is_string($value[0])) {
  101. $address = unserialize($value[0]);
  102. }
  103. else {
  104. $address = $value[0];
  105. }
  106. }
  107. elseif (!empty($component['value'])) {
  108. $address = $component['value'];
  109. }
  110. else {
  111. $address = _webform_addressfield($component['cid']);
  112. }
  113. if (empty($address)) {
  114. $address = addressfield_default_values($available);
  115. }
  116. // Generate the address form.
  117. $context = array(
  118. 'mode' => 'form',
  119. );
  120. $element += addressfield_generate($address, array('address'), $context);
  121. if (!empty($available)) {
  122. $element['country']['#options'] = array_intersect_key($element['country']['#options'], $available);
  123. }
  124. $element['country']['#element_validate'] = array('_webform_addressfield_country_validate');
  125. $element['country']['#cid'] = $component['cid'];
  126. $element['country']['#limit_validation_errors'] = array();
  127. $form_state = array();
  128. drupal_alter('field_widget_addressfield_standard_form', $element, $form_state, $context);
  129. return $element;
  130. }
  131. /**
  132. * Stores an addressfield submitted in a webform component. Ideally we should store
  133. * it in the $form_state instead, but there appears to be no way to get it to actually
  134. * pass through to _webform_render_addressfield().
  135. *
  136. * @param $cid integer The ID of the webform component.
  137. * @param $address array If set, this address will be stored with the given $cid.
  138. * @return array The address stored with the given $cid, if there is one; otherwise, NULL.
  139. */
  140. function _webform_addressfield($cid, $address = NULL) {
  141. $out = &drupal_static(__FUNCTION__, array());
  142. if (isset($address)) {
  143. $out[$cid] = $address;
  144. }
  145. if (isset($out[$cid])) {
  146. return $out[$cid];
  147. }
  148. return NULL;
  149. }
  150. /**
  151. * Validates a country, and if it changes, rebuilds the form for the new country
  152. */
  153. function _webform_addressfield_country_validate(&$element, &$form_state) {
  154. // If the country was changed, rebuild the form.
  155. if ($element['#default_value'] != $element['#value']) {
  156. $form_state['rebuild'] = TRUE;
  157. }
  158. $cid = $element['#cid'];
  159. $parents = $element['#parents'];
  160. array_pop($parents);
  161. // Search through the form values to find the current address.
  162. $address = drupal_array_get_nested_value($form_state['values'], $parents);
  163. _webform_addressfield($cid, $address);
  164. }
  165. /**
  166. * Display the result of a submission for a component.
  167. * The output of this function will be displayed under the "Results" tab then
  168. * "Submissions". This should output the saved data in some reasonable manner.
  169. *
  170. * @param $component
  171. * A Webform component array.
  172. * @param $value
  173. * An array of information containing the submission result, directly
  174. * correlating to the webform_submitted_data database table schema.
  175. * @param $format
  176. * Either 'html' or 'text'. Defines the format that the content should be
  177. * returned as. Make sure that returned content is run through check_plain()
  178. * or other filtering functions when returning HTML.
  179. *
  180. * @return
  181. * A renderable element containing at the very least these properties:
  182. * - #title
  183. * - #weight
  184. * - #component
  185. * - #format
  186. * - #value
  187. * Webform also uses #theme_wrappers to output the end result to the user,
  188. * which will properly format the label and content for use within an e-mail
  189. * (such as wrapping the text) or as HTML (ensuring consistent output).
  190. */
  191. function _webform_display_addressfield($component, $value, $format = 'html') {
  192. $address = NULL;
  193. if (isset($value[0])) {
  194. $address = $value[0];
  195. if (is_string($address)) {
  196. $address = unserialize($address);
  197. }
  198. }
  199. return array(
  200. '#title' => $component['name'],
  201. '#weight' => $component['weight'],
  202. '#theme' => $format == 'html' ? 'addressfield_formatter' : 'addressfield_formatter__linear',
  203. '#theme_wrappers' => $format == 'html' ? array('webform_element' ) : array('webform_element_text'),
  204. '#post_render' => array('webform_element_wrapper'),
  205. '#component' => $component,
  206. '#format' => $format,
  207. '#address' => $address,
  208. );
  209. }
  210. /**
  211. * A hook for changing the input values before saving to the database.
  212. * Webform expects a component to consist of a single field, or a single array
  213. * of fields. If you have a component that requires a deeper form tree
  214. * you must flatten the data into a single array using this callback
  215. * or by setting #parents on each field to avoid data loss and/or unexpected
  216. * behavior.
  217. * Note that Webform will save the result of this function directly into the
  218. * database.
  219. *
  220. * @param $component
  221. * A Webform component array.
  222. * @param $value
  223. * The POST data associated with the user input.
  224. *
  225. * @return
  226. * An array of values to be saved into the database. Note that this should be
  227. * a numerically keyed array.
  228. */
  229. function _webform_submit_addressfield($component, $value) {
  230. return serialize($value);
  231. }
  232. /**
  233. * Calculate and returns statistics about results for this component.
  234. * This takes into account all submissions to this webform. The output of this
  235. * function will be displayed under the "Results" tab then "Analysis".
  236. *
  237. * @param $component
  238. * An array of information describing the component, directly correlating to
  239. * the webform_component database schema.
  240. * @param $sids
  241. * An optional array of submission IDs (sid). If supplied, the analysis will
  242. * be limited to these sids.
  243. * @param $single
  244. * Boolean flag determining if the details about a single component are being
  245. * shown. May be used to provided detailed information about a single
  246. * component's analysis, such as showing "Other" options within a select list.
  247. *
  248. * @return
  249. * An array of data rows, each containing a statistic for this component's
  250. * submissions.
  251. */
  252. function _webform_analysis_addressfield($component, $sids = array(), $single = FALSE) {
  253. // TODO Update this function
  254. // Generate the list of options and questions.
  255. $query = db_select('webform_submitted_data', 'wsd')
  256. ->fields('wsd', array('data'))
  257. ->condition('nid', $component['nid'])
  258. ->condition('cid', $component['cid']);
  259. if ( count($sids) ) {
  260. $query->condition('sid', $sids, 'IN');
  261. }
  262. $non_blanks = 0;
  263. $submissions = 0;
  264. $results = $query->execute();
  265. foreach ($results as $row) {
  266. if ( drupal_strlen(trim($row->data)) > 0 ) {
  267. $non_blanks++;
  268. }
  269. $submissions++;
  270. }
  271. $rows[0] = array(
  272. t('Left Blank'),
  273. ( $submissions - $non_blanks )
  274. );
  275. $rows[1] = array(
  276. t('User entered value'),
  277. $non_blanks
  278. );
  279. return $rows;
  280. }
  281. /**
  282. * Return the result of a component value for display in a table.
  283. * The output of this function will be displayed under the "Results" tab then
  284. * "Table".
  285. *
  286. * @param $component
  287. * A Webform component array.
  288. * @param $value
  289. * An array of information containing the submission result, directly
  290. * correlating to the webform_submitted_data database schema.
  291. *
  292. * @return
  293. * Textual output formatted for human reading.
  294. */
  295. function _webform_table_addressfield($component, $value) {
  296. if (!empty($value[0])) {
  297. return theme('addressfield_formatter', array( 'address' => $value[0] ));
  298. }
  299. return '';
  300. }
  301. /**
  302. * Return the header for this component to be displayed in a CSV file.
  303. * The output of this function will be displayed under the "Results" tab then
  304. * "Download".
  305. *
  306. * @param $component
  307. * A Webform component array.
  308. * @param $export_options
  309. * An array of options that may configure export of this field.
  310. *
  311. * @return
  312. * An array of data to be displayed in the first three rows of a CSV file, not
  313. * including either prefixed or trailing commas.
  314. */
  315. function _webform_csv_headers_addressfield($component, $export_options) {
  316. $header = array();
  317. if (!empty($component['extra']['csv_separate']) && $component['extra']['csv_separate'] == 1) {
  318. $header[0] = array();
  319. $header[1] = array();
  320. $header[2] = array();
  321. foreach (addressfield_tokens_property_names() as $key => $name) {
  322. $header[0][] = '';
  323. $header[1][] = (empty($header[1])) ? $component['name'] : '';
  324. $header[2][] = $name;
  325. }
  326. }
  327. else {
  328. $header[0] = array('');
  329. $header[1] = array();
  330. $header[2] = array($component['name']);
  331. }
  332. return $header;
  333. }
  334. /**
  335. * Format the submitted data of a component for CSV downloading.
  336. * The output of this function will be displayed under the "Results" tab then
  337. * "Download".
  338. *
  339. * @param $component
  340. * A Webform component array.
  341. * @param $export_options
  342. * An array of options that may configure export of this field.
  343. * @param $value
  344. * An array of information containing the submission result, directly
  345. * correlating to the webform_submitted_data database schema.
  346. *
  347. * @return
  348. * An array of items to be added to the CSV file. Each value within the array
  349. * will be another column within the file. This function is called once for
  350. * every row of data.
  351. */
  352. function _webform_csv_data_addressfield($component, $export_options, $value) {
  353. if (!empty($component['extra']['csv_separate']) && $component['extra']['csv_separate'] == 1) {
  354. $return = array();
  355. foreach (addressfield_tokens_property_names() as $key => $name) {
  356. $return[] = (isset($value[0][$key])) ? $value[0][$key] : '';
  357. }
  358. return $return;
  359. }
  360. else {
  361. if (!empty($value[0])) {
  362. return theme('addressfield_formatter__linear', array( 'address' => $value[0] ));
  363. }
  364. return '';
  365. }
  366. }