123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- <?php
- /**
- * @file
- * Webform Component information for an address field type.
- */
- /**
- * Specify the default properties of a component.
- *
- * @return array
- * An array defining the default structure of a component.
- */
- function _webform_defaults_addressfield() {
- return array(
- 'name' => '',
- 'form_key' => NULL,
- 'required' => 0,
- 'pid' => 0,
- 'weight' => 0,
- 'extra' => array(
- 'title_display' => 0,
- 'private' => FALSE,
- 'attributes' => array(),
- 'description' => '',
- 'available_countries' => array(),
- 'default_country' => '',
- 'format_handlers' => array(),
- 'csv_separate' => 0,
- ),
- );
- }
- /**
- * Generate the form for editing a component.
- *
- * Create a set of form elements to be displayed on the form for editing this
- * component. Use care naming the form items, as this correlates directly to the
- * database schema. The component "Name" and "Description" fields are added to
- * every component type and are not necessary to specify here (although they
- * may be overridden if desired).
- *
- * @param mixed $component
- * A Webform component array.
- *
- * @return array
- * An array of form items to be displayed on the edit component page
- */
- function _webform_edit_addressfield($component) {
- $form = array();
- $form['extra']['available_countries'] = array(
- '#type' => 'select',
- '#multiple' => TRUE,
- '#title' => t('Available countries'),
- '#description' => t('If no countries are selected, all countries will be available.'),
- '#options' => _addressfield_country_options_list(),
- '#default_value' => $component['extra']['available_countries'],
- );
- $form['extra']['default_country'] = array(
- '#type' => 'select',
- '#multiple' => FALSE,
- '#title' => t('Default country'),
- '#description' => t('Select which country should be selected as the default.'),
- '#options' => array_merge(array(0 => t('- None -')), _addressfield_country_options_list()),
- '#default_value' => $component['extra']['default_country'],
- );
- $form['extra']['format_handlers'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Format handlers'),
- '#options' => addressfield_format_plugins_options(),
- '#required' => TRUE,
- '#default_value' => !empty($component['extra']['format_handlers']) ? $component['extra']['format_handlers'] : array('address'),
- );
- $form['extra']['csv_separate'] = array(
- '#type' => 'radios',
- '#title' => t('CSV download'),
- '#description' => t('How would you like addresses presented in CSV downloads?'),
- '#options' => array(
- 0 => t('Display entire address in a single column'),
- 1 => t('Display each address component in a separate column'),
- ),
- '#default_value' => $component['extra']['csv_separate'],
- );
- return $form;
- }
- /**
- * Render a Webform component to be part of a form.
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $value
- * If editing an existing submission or resuming a draft, this will contain
- * an array of values to be shown instead of the default in the component
- * configuration. This value will always be an array, keyed numerically for
- * each value saved in this field.
- * @param bool $filter
- * Whether or not to filter the contents of descriptions and values when
- * rendering the component. Values need to be unfiltered to be editable by
- * Form Builder.
- *
- * @return array
- * Form element.
- *
- * @see _webform_client_form_add_component()
- */
- function _webform_render_addressfield($component, $value = NULL, $filter = TRUE) {
- $element = array(
- '#type' => 'fieldset',
- '#title' => $filter ? _webform_filter_xss($component['name']) : $component['name'],
- '#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
- '#attributes' => $component['extra']['attributes'],
- '#theme_wrappers' => array('webform_element'),
- '#description' => $filter ? _webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
- '#required' => $component['required'],
- '#weight' => $component['weight'],
- '#translatable' => array(
- 'title',
- 'description',
- ),
- );
- $available = !empty($component['extra']['available_countries']) ? $component['extra']['available_countries'] : NULL;
- // Get the current address.
- $address = _addressfield_tokens_expand_value($value);
- if (empty($address)) {
- if (!empty($component['value'])) {
- $address = $component['value'];
- }
- else {
- $address = _webform_addressfield($component['cid']);
- }
- }
- if (empty($address)) {
- $address = _webform_addressfield_default_values($available, $component);
- }
- // Generate the address form.
- $context = array(
- 'mode' => 'form',
- 'instance' => array(
- 'required' => $component['required'],
- ),
- 'form_key' => $component['form_key'],
- );
- $handlers = !empty($component['extra']['format_handlers']) ? $component['extra']['format_handlers'] : array('address');
- $element += addressfield_generate($address, $handlers, $context);
- if (empty($address['country'])) {
- $element['street_block']['#access'] = FALSE;
- $element['locality_block']['#access'] = FALSE;
- }
- if (isset($element['country'])) {
- if (!empty($available)) {
- $element['country']['#options'] = array_intersect_key($element['country']['#options'], $available);
- // Hide the country element only if there is one option and the whole field
- // is required, otherwise there will always be an additional None option.
- // @see addressfield_format_address_hide_country()
- if (!empty($handlers['address-hide-country']) && count($element['country']['#options']) == 1 && $component['required']) {
- $element['country']['#access'] = FALSE;
- }
- }
- $element['country']['#default_value'] = $address['country'];
- $element['country']['#element_validate'] = array('_webform_addressfield_country_validate');
- $element['country']['#cid'] = $component['cid'];
- $element['country']['#limit_validation_errors'] = array();
- }
- $form_state = array();
- drupal_alter('field_widget_addressfield_standard_form', $element, $form_state, $context);
- return $element;
- }
- function _webform_addressfield_default_values($available, $component) {
- $default_country = !empty($component['extra']['default_country'])
- ? $component['extra']['default_country']
- : addressfield_tokens_default_country();
- $default_values = array(
- 'country' => $default_country,
- 'name_line' => '',
- 'first_name' => '',
- 'last_name' => '',
- 'organisation_name' => '',
- 'administrative_area' => '',
- 'sub_administrative_area' => '',
- 'locality' => '',
- 'dependent_locality' => '',
- 'postal_code' => '',
- 'thoroughfare' => '',
- 'premise' => '',
- 'sub_premise' => '',
- 'data' => '',
- );
- return ($default_values);
- }
- /**
- * Stores an addressfield submitted in a webform component.
- *
- * Ideally store it in the $form_state instead, but there appears to be no way
- * to get it to actually pass through to _webform_render_addressfield().
- *
- * @param int $cid
- * The ID of the webform component.
- * @param mixed $address
- * If set, this address will be stored with the given $cid.
- *
- * @return array
- * The address stored with the given $cid, if there is one; otherwise, NULL.
- */
- function _webform_addressfield($cid, $address = NULL) {
- $out = &drupal_static(__FUNCTION__, array());
- if (isset($address)) {
- $out[$cid] = $address;
- }
- if (isset($out[$cid])) {
- return $out[$cid];
- }
- return NULL;
- }
- /**
- * Validates a country, and if changed, rebuilds the form for the new country.
- */
- function _webform_addressfield_country_validate(&$element, &$form_state) {
- // If the country was changed, rebuild the form.
- if (!isset($element['#default_value']) || $element['#default_value'] != $element['#value']) {
- $form_state['rebuild'] = TRUE;
- }
- $cid = $element['#cid'];
- $parents = $element['#parents'];
- array_pop($parents);
- // Search through the form values to find the current address.
- $address = drupal_array_get_nested_value($form_state['values'], $parents);
- _webform_addressfield($cid, $address);
- }
- /**
- * Display the result of a submission for a component.
- *
- * The output of this function will be displayed under the "Results" tab then
- * "Submissions". This should output the saved data in some reasonable manner.
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database table schema.
- * @param string $format
- * Either 'html' or 'text'. Defines the format that the content should be
- * returned as. Make sure that returned content is run through check_plain()
- * or other filtering functions when returning HTML.
- *
- * @return array
- * A renderable element containing at the very least these properties:
- * - #title
- * - #weight
- * - #component
- * - #format
- * - #value
- * Webform also uses #theme_wrappers to output the end result to the user,
- * which will properly format the label and content for use within an e-mail
- * (such as wrapping the text) or as HTML (ensuring consistent output).
- */
- function _webform_display_addressfield($component, $value, $format = 'html') {
- $address = _addressfield_tokens_expand_value($value);
- return array(
- '#title' => $component['name'],
- '#weight' => $component['weight'],
- '#theme' => $format == 'html' ? 'addressfield_formatter' : 'addressfield_formatter__linear',
- '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
- '#post_render' => array('webform_element_wrapper'),
- '#component' => $component,
- '#format' => $format,
- '#address' => $address ? $address : NULL,
- '#handlers' => $component['extra']['format_handlers'],
- );
- }
- /**
- * A hook for changing the input values before saving to the database.
- *
- * Webform expects a component to consist of a single field, or a single array
- * of fields. If you have a component that requires a deeper form tree
- * you must flatten the data into a single array using this callback
- * or by setting #parents on each field to avoid data loss and/or unexpected
- * behavior.
- * Note that Webform will save the result of this function directly into the
- * database.
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $value
- * The POST data associated with the user input.
- *
- * @return array
- * An array of values to be saved into the database. Note that this should be
- * a numerically keyed array.
- */
- function _webform_submit_addressfield($component, $value) {
- return serialize($value);
- }
- /**
- * Calculate and returns statistics about results for this component.
- *
- * This takes into account all submissions to this webform. The output of this
- * function will be displayed under the "Results" tab then "Analysis".
- *
- * @param mixed $component
- * An array of information describing the component, directly correlating to
- * the webform_component database schema.
- * @param mixed $sids
- * An optional array of submission IDs (sid). If supplied, the analysis will
- * be limited to these sids.
- * @param bool $single
- * Boolean flag determining if the details about a single component are being
- * shown. May be used to provided detailed information about a single
- * component's analysis, such as showing "Other" options within a select list.
- *
- * @return array
- * An array of data rows, each containing a statistic for this component's
- * submissions.
- */
- function _webform_analysis_addressfield($component, $sids = array(), $single = FALSE) {
- // @todo Update this function
- // Generate the list of options and questions.
- $query = db_select('webform_submitted_data', 'wsd')
- ->fields('wsd', array('data'))
- ->condition('nid', $component['nid'])
- ->condition('cid', $component['cid']);
- if (count($sids)) {
- $query->condition('sid', $sids, 'IN');
- }
- $non_blanks = 0;
- $submissions = 0;
- $results = $query->execute();
- foreach ($results as $row) {
- if (drupal_strlen(trim($row->data)) > 0) {
- $non_blanks++;
- }
- $submissions++;
- }
- $rows[0] = array(
- t('Left Blank'),
- ($submissions - $non_blanks),
- );
- $rows[1] = array(
- t('User entered value'),
- $non_blanks,
- );
- return array('table_rows' => $rows);
- }
- /**
- * Return the result of a component value for display in a table.
- *
- * The output of this function will be displayed under the "Results" tab then
- * "Table".
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database schema.
- *
- * @return string
- * Textual output formatted for human reading.
- */
- function _webform_table_addressfield($component, $value) {
- $address = _addressfield_tokens_expand_value($value);
- if ($address) {
- return theme('addressfield_formatter', array('address' => $address));
- }
- return '';
- }
- /**
- * Return the header for this component to be displayed in a CSV file.
- *
- * The output of this function will be displayed under the "Results" tab then
- * "Download".
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $export_options
- * An array of options that may configure export of this field.
- *
- * @return array
- * An array of data to be displayed in the first three rows of a CSV file, not
- * including either prefixed or trailing commas.
- */
- function _webform_csv_headers_addressfield($component, $export_options) {
- $header = array();
- if (!empty($component['extra']['csv_separate']) && $component['extra']['csv_separate'] == 1) {
- $header[0] = array();
- $header[1] = array();
- $header[2] = array();
- foreach (addressfield_tokens_property_names() as $key => $name) {
- $header[0][] = '';
- $header[1][] = (empty($header[1])) ? $component['name'] : '';
- $header[2][] = $name;
- }
- }
- else {
- $header[0] = array('');
- $header[1] = array('');
- $header[2] = array($component['name']);
- }
- return $header;
- }
- /**
- * Format the submitted data of a component for CSV downloading.
- *
- * The output of this function will be displayed under the "Results" tab then
- * "Download".
- *
- * @param mixed $component
- * A Webform component array.
- * @param mixed $export_options
- * An array of options that may configure export of this field.
- * @param mixed $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database schema.
- *
- * @return array
- * An array of items to be added to the CSV file. Each value within the array
- * will be another column within the file. This function is called once for
- * every row of data.
- */
- function _webform_csv_data_addressfield($component, $export_options, $value) {
- $address = _addressfield_tokens_expand_value($value);
- if (!empty($component['extra']['csv_separate']) && $component['extra']['csv_separate'] == 1) {
- // Each address component should be in a separate column.
- $return = array();
- foreach (addressfield_tokens_property_names() as $key => $name) {
- $return[] = (isset($address[$key])) ? $address[$key] : '';
- }
- return $return;
- }
- else {
- // The entire address should be displayed in the one column.
- if ($address) {
- return theme('addressfield_formatter__linear', array('address' => $address));
- }
- return '';
- }
- }
- /**
- * Expand a raw address submission as loaded from the database to an array.
- *
- * @param string $value
- * An array of information containing the submission result, directly
- * correlating to the {webform_submitted_data} database schema.
- *
- * @return array|false
- * An associative array of address fields, or FALSE on failure.
- */
- function _addressfield_tokens_expand_value($value) {
- if (isset($value[0]) && is_string($value[0])) {
- return unserialize($value[0]);
- }
- return FALSE;
- }
|