12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547 |
- <?php
- /**
- * @file
- * Sample hooks demonstrating usage in Webform.
- */
- /**
- * @defgroup webform_hooks Webform Module Hooks
- * @{
- * Webform's hooks enable other modules to intercept events within Webform, such
- * as the completion of a submission or adding validation. Webform's hooks also
- * allow other modules to provide additional components for use within forms.
- */
- /**
- * Define callbacks that can be used as select list options.
- *
- * When users create a select component, they may select a pre-built list of
- * certain options. Webform core provides a few of these lists such as the
- * United States, countries of the world, and days of the week. This hook
- * provides additional lists that may be utilized.
- *
- * @see webform_options_example()
- * @see hook_webform_select_options_info_alter()
- *
- * @return array
- * An array of callbacks that can be used for select list options. This array
- * should be keyed by the "name" of the pre-defined list. The values should
- * be an array with the following additional keys:
- * - title: The translated title for this list.
- * - options callback: The name of a function implementing
- * callback_webform_options() that will return the list.
- * - options arguments: Any additional arguments to send to the callback.
- * - file: Optional. The file containing the options callback, relative to
- * the module root.
- */
- function hook_webform_select_options_info() {
- $items = array();
- $items['days'] = array(
- 'title' => t('Days of the week'),
- 'options callback' => 'webform_options_days',
- 'file' => 'includes/webform.options.inc',
- );
- return $items;
- }
- /**
- * Alter the list of select list options provided by Webform and other modules.
- *
- * @see hook_webform_select_options_info()
- */
- function hook_webform_select_options_info_alter(&$items) {
- // Remove the days of the week options.
- unset($items['days']);
- }
- /**
- * Define a list of options that Webform may use in a select component.
- *
- * Callback for hook_webform_select_options_info().
- *
- * @param $component
- * The Webform component array for the select component being displayed.
- * @param $flat
- * Boolean value indicating whether the returned list needs to be a flat array
- * of key => value pairs. Select components support up to one level of
- * nesting, but when results are displayed, the list needs to be returned
- * without the nesting.
- * @param $arguments
- * The "options arguments" specified in hook_webform_select_options_info().
- *
- * @return array
- * An array of key => value pairs suitable for a select list's #options
- * FormAPI property.
- */
- function callback_webform_options($component, $flat, $arguments) {
- $options = array(
- 'one' => t('Pre-built option one'),
- 'two' => t('Pre-built option two'),
- 'three' => t('Pre-built option three'),
- );
- return $options;
- }
- /**
- * Respond to the loading of Webform submissions.
- *
- * @param $submissions
- * An array of Webform submissions that are being loaded, keyed by the
- * submission ID. Modifications to the submissions are done by reference.
- */
- function hook_webform_submission_load(&$submissions) {
- foreach ($submissions as $sid => $submission) {
- $submissions[$sid]->new_property = 'foo';
- }
- }
- /**
- * Respond to the creation of a new submission from form values.
- *
- * This hook is called when a user has completed a submission to initialize the
- * submission object. After this object has its values populated, it will be
- * saved by webform_submission_insert(). Note that this hook is only called for
- * new submissions, not for submissions being edited. If responding to the
- * saving of all submissions, it's recommended to use
- * hook_webform_submission_presave().
- *
- * @param $submission
- * The submission object that has been created.
- * @param $node
- * The Webform node for which this submission is being saved.
- * @param $account
- * The user account that is creating the submission.
- * @param $form_state
- * The contents of form state that is the basis for this submission.
- *
- * @see webform_submission_create()
- */
- function hook_webform_submission_create_alter(&$submission, &$node, &$account, &$form_state) {
- $submission->new_property = TRUE;
- }
- /**
- * Modify a Webform submission, prior to saving it in the database.
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission that is about to be saved to the database.
- */
- function hook_webform_submission_presave($node, &$submission) {
- // Update some component's value before it is saved.
- $component_id = 4;
- $submission->data[$component_id][0] = 'foo';
- }
- /**
- * Respond to a Webform submission being inserted.
- *
- * Note that this hook is called after a submission has already been saved to
- * the database. If needing to modify the submission prior to insertion, use
- * hook_webform_submission_presave().
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission that was just inserted into the database.
- */
- function hook_webform_submission_insert($node, $submission) {
- // Insert a record into a 3rd-party module table when a submission is added.
- db_insert('mymodule_table')
- ->fields(array(
- 'nid' => $node->nid,
- 'sid' => $submission->sid,
- 'foo' => 'foo_data',
- ))
- ->execute();
- }
- /**
- * Respond to a Webform submission being updated.
- *
- * Note that this hook is called after a submission has already been saved to
- * the database. If needing to modify the submission prior to updating, use
- * hook_webform_submission_presave().
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission that was just updated in the database.
- */
- function hook_webform_submission_update($node, $submission) {
- // Update a record in a 3rd-party module table when a submission is updated.
- db_update('mymodule_table')
- ->fields(array(
- 'foo' => 'foo_data',
- ))
- ->condition('nid', $node->nid)
- ->condition('sid', $submission->sid)
- ->execute();
- }
- /**
- * Respond to a Webform submission being deleted.
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission that was just deleted from the database.
- */
- function hook_webform_submission_delete($node, $submission) {
- // Delete a record from a 3rd-party module table when a submission is deleted.
- db_delete('mymodule_table')
- ->condition('nid', $node->nid)
- ->condition('sid', $submission->sid)
- ->execute();
- }
- /**
- * Provide a list of actions that can be executed on a submission.
- *
- * Some actions are displayed in the list of submissions such as edit, view, and
- * delete. All other actions are displayed only when viewing the submission.
- * These additional actions may be specified in this hook. Examples included
- * directly in the Webform module include PDF, print, and resend e-mails. Other
- * modules may extend this list by using this hook.
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission on which the actions may be performed.
- *
- * @return array
- * List of action.
- */
- function hook_webform_submission_actions($node, $submission) {
- $actions = array();
- if (webform_results_access($node)) {
- $actions['myaction'] = array(
- 'title' => t('Do my action'),
- 'href' => 'node/' . $node->nid . '/submission/' . $submission->sid . '/myaction',
- 'query' => drupal_get_destination(),
- );
- }
- return $actions;
- }
- /**
- * Modify the draft to be presented for editing.
- *
- * When drafts are enabled for the webform, by default, a pre-existing draft is
- * presented when the webform is displayed to that user. To allow multiple
- * drafts, implement this alter function to set the $sid to NULL, or use your
- * application's business logic to determine whether a new draft or which of
- * the pre-existing drafts should be presented.
- *
- * @param int $sid
- * The id of the most recent submission to be presented for editing. Change
- * to a different draft's sid or set to NULL for a new draft.
- * @param array $context
- * Array of context with indices 'nid' and 'uid'.
- */
- function hook_webform_draft_alter(&$sid, array $context) {
- if ($_GET['newdraft']) {
- $sid = NULL;
- }
- }
- /**
- * Alter the display of a Webform submission.
- *
- * This function applies to both e-mails sent by Webform and normal display of
- * submissions when viewing through the administrative interface.
- *
- * @param $renderable
- * The Webform submission in a renderable array, similar to FormAPI's
- * structure. This variable must be passed in by-reference. Important
- * properties of this array include #node, #submission, #email, and #format,
- * which can be used to find the context of the submission that is being
- * rendered.
- */
- function hook_webform_submission_render_alter(&$renderable) {
- // Remove page breaks from sent e-mails.
- if (isset($renderable['#email'])) {
- foreach (element_children($renderable) as $key) {
- if ($renderable[$key]['#component']['type'] == 'pagebreak') {
- unset($renderable[$key]);
- }
- }
- }
- }
- /**
- * Modify a loaded Webform component.
- *
- * IMPORTANT: This hook does not actually exist because components are loaded
- * in bulk as part of webform_node_load(). Use hook_node_load() to modify loaded
- * components when the node is loaded. This example is provided merely to point
- * to hook_node_load().
- *
- * @see hook_nodeapi()
- * @see webform_node_load()
- */
- function hook_webform_component_load() {
- // This hook does not exist. Instead use hook_node_load().
- }
- /**
- * Modify a Webform component before it is saved to the database.
- *
- * Note that most of the time this hook is not necessary, because Webform will
- * automatically add data to the component based on the component form. Using
- * hook_form_alter() will be sufficient in most cases.
- *
- * @param $component
- * The Webform component being saved.
- *
- * @see hook_form_alter()
- * @see webform_component_edit_form()
- */
- function hook_webform_component_presave(&$component) {
- $component['extra']['new_option'] = 'foo';
- }
- /**
- * Respond to a Webform component being inserted into the database.
- */
- function hook_webform_component_insert($component) {
- // Insert a record into a 3rd-party module table when a component is inserted.
- db_insert('mymodule_table')
- ->fields(array(
- 'nid' => $component['nid'],
- 'cid' => $component['cid'],
- 'foo' => 'foo_data',
- ))
- ->execute();
- }
- /**
- * Respond to a Webform component being updated in the database.
- */
- function hook_webform_component_update($component) {
- // Update a record in a 3rd-party module table when a component is updated.
- db_update('mymodule_table')
- ->fields(array(
- 'foo' => 'foo_data',
- ))
- ->condition('nid', $component['nid'])
- ->condition('cid', $component['cid'])
- ->execute();
- }
- /**
- * Respond to a Webform component being deleted.
- */
- function hook_webform_component_delete($component) {
- // Delete a record in a 3rd-party module table when a component is deleted.
- db_delete('mymodule_table')
- ->condition('nid', $component['nid'])
- ->condition('cid', $component['cid'])
- ->execute();
- }
- /**
- * Alter the entire analysis before rendering to the page on the Analysis tab.
- *
- * This alter hook allows modification of the entire analysis of a node's
- * Webform results. The resulting analysis is displayed on the Results ->
- * Analysis tab on the Webform.
- *
- * @param array $analysis
- * A Drupal renderable array, passed by reference, containing the entire
- * contents of the analysis page. This typically will contain the following
- * two major keys:
- * - form: The form for configuring the shown analysis.
- * - components: The list of analyses for each analysis-enabled component
- * for the node. Each keyed by its component ID.
- */
- function hook_webform_analysis_alter(array &$analysis) {
- $node = $analysis['#node'];
- // Add an additional piece of information to every component's analysis:
- foreach (element_children($analysis['components']) as $cid) {
- $component = $node->components[$cid];
- $analysis['components'][$cid]['chart'] = array(
- '#markup' => t('Chart for the @name component', array('@name' => $component['name'])),
- );
- }
- }
- /**
- * Alter data when displaying an analysis on that component.
- *
- * This hook modifies the data from an individual component's analysis results.
- * It can be used to add additional analysis, or to modify the existing results.
- * If needing to alter the entire set of analyses rather than an individual
- * component, hook_webform_analysis_alter() may be used instead.
- *
- * @param array $data
- * An array containing the result of a components analysis hook, passed by
- * reference. This is passed directly from a component's
- * _webform_analysis_component() function. See that hook for more information
- * on this value.
- * @param object $node
- * The node object that contains the component being analyzed.
- * @param array $component
- * The Webform component array whose analysis results are being displayed.
- *
- * @see _webform_analysis_component()
- * @see hook_webform_analysis_alter()
- */
- function hook_webform_analysis_component_data_alter(array &$data, $node, array $component) {
- if ($component['type'] === 'textfield') {
- // Do not display rows that contain a zero value.
- foreach ($data as $row_number => $row_data) {
- if ($row_data[1] === 0) {
- unset($data[$row_number]);
- }
- }
- }
- }
- /**
- * Alter a Webform submission's header when exported.
- */
- function hook_webform_csv_header_alter(&$header, $component) {
- // Use the machine name for component headers, but only for the webform
- // with node 5 and components that are text fields.
- if ($component['nid'] == 5 && $component['type'] == 'textfield') {
- $header[2] = $component['form_key'];
- }
- }
- /**
- * Alter a Webform submission's data when exported.
- */
- function hook_webform_csv_data_alter(&$data, $component, $submission) {
- // If a value of a field was left blank, use the value from another
- // field.
- if ($component['cid'] == 1 && empty($data)) {
- $data = $submission->data[2]['value'][0];
- }
- }
- /**
- * Define components to Webform.
- *
- * @return array
- * An array of components, keyed by machine name. Required properties are
- * "label" and "description". The "features" array defines which capabilities
- * the component has, such as being displayed in e-mails or csv downloads.
- * A component like "markup" for example would not show in these locations.
- * The possible features of a component include:
- *
- * - csv
- * - email
- * - email_address
- * - email_name
- * - required
- * - conditional
- * - spam_analysis
- * - group
- * - private
- *
- * Note that most of these features do not indicate the default state, but
- * determine if the component can have this property at all. Setting
- * "required" to TRUE does not mean that a component's fields will always be
- * required, but instead give the option to the administrator to choose the
- * requiredness. See the example implementation for details on how these
- * features may be set.
- *
- * An optional "file" may be specified to be loaded when the component is
- * needed. A set of callbacks will be established based on the name of the
- * component. All components follow the pattern:
- *
- * _webform_[callback]_[component]
- *
- * Where [component] is the name of the key of the component and [callback] is
- * any of the following:
- *
- * - defaults
- * - edit
- * - render
- * - display
- * - submit
- * - delete
- * - help
- * - theme
- * - analysis
- * - table
- * - csv_headers
- * - csv_data
- *
- * See the sample component implementation for details on each one of these
- * callbacks.
- *
- * @see webform_components()
- */
- function hook_webform_component_info() {
- $components = array();
- $components['textfield'] = array(
- 'label' => t('Textfield'),
- 'description' => t('Basic textfield type.'),
- 'features' => array(
- // This component includes an analysis callback. Defaults to TRUE.
- 'analysis' => TRUE,
- // Add content to CSV downloads. Defaults to TRUE.
- 'csv' => TRUE,
- // This component supports default values. Defaults to TRUE.
- 'default_value' => FALSE,
- // This component supports a description field. Defaults to TRUE.
- 'description' => FALSE,
- // Show this component in e-mailed submissions. Defaults to TRUE.
- 'email' => TRUE,
- // Allow this component to be used as an e-mail FROM or TO address.
- // Defaults to FALSE.
- 'email_address' => FALSE,
- // Allow this component to be used as an e-mail SUBJECT or FROM name.
- // Defaults to FALSE.
- 'email_name' => TRUE,
- // This component may be toggled as required or not. Defaults to TRUE.
- 'required' => TRUE,
- // This component supports a title attribute. Defaults to TRUE.
- 'title' => FALSE,
- // This component has a title that can be toggled as displayed or not.
- 'title_display' => TRUE,
- // This component has a title that can be displayed inline.
- 'title_inline' => TRUE,
- // If this component can be used as a conditional SOURCE. All components
- // may always be displayed conditionally, regardless of this setting.
- // Defaults to TRUE.
- 'conditional' => TRUE,
- // If this component allows other components to be grouped within it
- // (like a fieldset or tabs). Defaults to FALSE.
- 'group' => FALSE,
- // If this component can be used for SPAM analysis.
- 'spam_analysis' => FALSE,
- // If this component saves a file that can be used as an e-mail
- // attachment. Defaults to FALSE.
- 'attachment' => FALSE,
- // If this component reflects a time range and should use labels such as
- // "Before" and "After" when exposed as filters in Views module.
- 'views_range' => FALSE,
- // Set this to FALSE if this component cannot be used as a private
- // component. If this is not FALSE, in your implementation of
- // _webform_defaults_COMPONENT(), set ['extra']['private'] property to
- // TRUE or FALSE.
- 'private' => FALSE,
- ),
- // Specify the conditional behaviour of this component.
- // Examples are 'string', 'date', 'time', 'numeric', 'select'.
- // Defaults to 'string'.
- 'conditional_type' => 'string',
- 'file' => 'components/textfield.inc',
- );
- return $components;
- }
- /**
- * Alter the list of available Webform components.
- *
- * @param $components
- * A list of existing components as defined by hook_webform_component_info().
- *
- * @see hook_webform_component_info()
- */
- function hook_webform_component_info_alter(&$components) {
- // Completely remove a component.
- unset($components['grid']);
- // Change the name of a component.
- $components['textarea']['label'] = t('Text box');
- }
- /**
- * Alter the list of Webform component default values.
- *
- * @param $defaults
- * A list of component defaults as defined by _webform_defaults_COMPONENT().
- * @param $type
- * The component type whose defaults are being provided.
- *
- * @see _webform_defaults_component()
- */
- function hook_webform_component_defaults_alter(&$defaults, $type) {
- // Alter a default for all component types.
- $defaults['required'] = 1;
- // Add a default for a new field added via hook_form_alter() or
- // hook_form_FORM_ID_alter() for all component types.
- $defaults['extra']['added_field'] = t('Added default value');
- // Add or alter defaults for specific component types:
- switch ($type) {
- case 'select':
- $defaults['extra']['optrand'] = 1;
- break;
- case 'textfield':
- case 'textarea':
- $defaults['extra']['another_added_field'] = t('Another added default value');
- }
- }
- /**
- * Alter access to a Webform submission.
- *
- * @param $node
- * The Webform node on which this submission was made.
- * @param $submission
- * The Webform submission.
- * @param $op
- * The operation to be performed on the submission. Possible values are:
- * - "view"
- * - "edit"
- * - "delete"
- * - "list"
- * @param $account
- * A user account object.
- *
- * @return bool
- * TRUE if the current user has access to submission,
- * or FALSE otherwise.
- */
- function hook_webform_submission_access($node, $submission, $op = 'view', $account = NULL) {
- switch ($op) {
- case 'view':
- return TRUE;
- case 'edit':
- return FALSE;
- case 'delete':
- return TRUE;
- case 'list':
- return TRUE;
- }
- }
- /**
- * Determine if a user has access to see the results of a webform.
- *
- * Note in addition to the view access to the results granted here, the $account
- * must also have view access to the Webform node in order to see results.
- * Access via this hook is in addition (adds permission) to the standard
- * webform access.
- *
- * @param $node
- * The Webform node to check access on.
- * @param $account
- * The user account to check access on.
- *
- * @return bool
- * TRUE or FALSE if the user can access the webform results.
- *
- * @see webform_results_access()
- */
- function hook_webform_results_access($node, $account) {
- // Let editors view results of unpublished webforms.
- if ($node->status == 0 && in_array('editor', $account->roles)) {
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
- /**
- * Determine if a user has access to clear the results of a webform.
- *
- * Access via this hook is in addition (adds permission) to the standard
- * webform access (delete all webform submissions).
- *
- * @param object $node
- * The Webform node to check access on.
- * @param object $account
- * The user account to check access on.
- *
- * @return bool
- * TRUE or FALSE if the user can access the webform results.
- *
- * @see webform_results_clear_access()
- */
- function hook_webform_results_clear_access($node, $account) {
- return user_access('my additional access', $account);
- }
- /**
- * Overrides the node_access and user_access permissions.
- *
- * Overrides the node_access and user_access permission to access and edit
- * webform components, e-mails, conditions, and form settings.
- *
- * Return NULL to defer to other modules. If all implementations defer, then
- * access to the node's EDIT tab plus 'edit webform components' permission
- * determines access. To grant access, return TRUE; to deny access, return
- * FALSE. If more than one implementation return TRUE/FALSE, all must be TRUE
- * to grant access.
- *
- * In this way, access to the EDIT tab of the node may be decoupled from
- * access to the WEBFORM tab. When returning TRUE, consider all aspects of
- * access as this will be the only test. For example, 'return TRUE;' would grant
- * annonymous access to creating webform components, which seldom be desired.
- *
- * @param object $node
- * The Webform node to check access on.
- * @param object $account
- * The user account to check access on.
- *
- * @return bool|null
- * TRUE or FALSE if the user can access the webform results, or NULL if
- * access should be deferred to other implementations of this hook or
- * node_access('update') plus user_access('edit webform components').
- *
- * @see webform_node_update_access()
- */
- function hook_webform_update_access($node, $account) {
- // Allow anyone who can see webform_editable_by_user nodes and who has
- // 'my webform component edit access' permission to see, edit, and delete the
- // webform components, e-mails, conditionals, and form settings.
- if ($node->type == 'webform_editable_by_user') {
- return node_access('view', $node, $account) && user_access('my webform component edit access', $account);
- }
- }
- /**
- * Return an array of files associated with the component.
- *
- * The output of this function will be used to attach files to e-mail messages.
- *
- * @param $component
- * A Webform component array.
- * @param $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database schema.
- *
- * @return array
- * An array of files, each file is an array with following keys:
- * - filepath: The relative path to the file.
- * - filename: The name of the file including the extension.
- * - filemime: The mimetype of the file.
- * This will result in an array looking something like this:
- *
- * @code
- * array[0] => array(
- * 'filepath' => '/sites/default/files/attachment.txt',
- * 'filename' => 'attachment.txt',
- * 'filemime' => 'text/plain',
- * );
- * @endcode
- */
- function _webform_attachments_component($component, $value) {
- $files = array();
- $files[] = (array) file_load($value[0]);
- return $files;
- }
- /**
- * Alter default settings for a newly created webform node.
- *
- * @param array $defaults
- * Default settings for a newly created webform node as defined by
- * webform_node_defaults().
- *
- * @see webform_node_defaults()
- */
- function hook_webform_node_defaults_alter(array &$defaults) {
- $defaults['allow_draft'] = '1';
- }
- /**
- * Add additional fields to submission data downloads.
- *
- * @return array
- * Keys and titles for default submission information.
- *
- * @see hook_webform_results_download_submission_information_data()
- */
- function hook_webform_results_download_submission_information_info() {
- return array(
- 'field_key_1' => t('Field Title 1'),
- 'field_key_2' => t('Field Title 2'),
- );
- }
- /**
- * Return values for submission data download fields.
- *
- * @param $token
- * The name of the token being replaced.
- * @param $submission
- * The data for an individual submission from webform_get_submissions().
- * @param array $options
- * A list of options that define the output format. These are generally passed
- * through from the GUI interface.
- * @param $serial_start
- * The starting position for the Serial column in the output.
- * @param $row_count
- * The number of the row being generated.
- *
- * @return string
- * Value for requested submission information field.
- *
- * @see hook_webform_results_download_submission_information_info()
- */
- function hook_webform_results_download_submission_information_data($token, $submission, array $options, $serial_start, $row_count) {
- switch ($token) {
- case 'field_key_1':
- return 'Field Value 1';
- case 'field_key_2':
- return 'Field Value 2';
- }
- }
- /**
- * Alter the query that will produce the list of submission IDs to be
- * downloaded.
- *
- * @param object $query
- * The query object that is being built up to provide the list of submission
- * IDs.
- *
- * @see webform_download_sids_query()
- */
- function hook_webform_download_sids_query_alter(&$query) {
- global $user;
- // check if component value matches a node ID and author of that node.
- $query->join('webform_submitted_data', 'wsd', 'ws.sid = wsd.sid');
- $query->condition('wsd.cid', 2);
- $query->join('node', 'n', 'wsd.data = n.nid');
- $query->condition('n.uid', $user->uid);
- }
- /**
- * @}
- */
- /**
- * @defgroup webform_component Sample Webform Component
- * @{
- * In each of these examples, the word "component" should be replaced with the,
- * name of the component type (such as textfield or select). These are not
- * actual hooks, but instead samples of how Webform integrates with its own
- * built-in components.
- */
- /**
- * Specify the default properties of a component.
- *
- * @return array
- * An array defining the default structure of a component.
- */
- function _webform_defaults_component() {
- return array(
- 'name' => '',
- 'form_key' => NULL,
- 'required' => 0,
- 'pid' => 0,
- 'weight' => 0,
- 'extra' => array(
- 'options' => '',
- 'questions' => '',
- 'optrand' => 0,
- 'qrand' => 0,
- 'description' => '',
- 'description_above' => FALSE,
- 'private' => FALSE,
- 'analysis' => TRUE,
- ),
- );
- }
- /**
- * 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 array $component
- * A Webform component array.
- * @param array $form
- * The form array.
- * @param array $form_state
- * The form state array.
- *
- * @return array
- * Return $form with whatever changes are desired.
- */
- function _webform_edit_component(array $component, array $form, array $form_state) {
- // Disabling the description if not wanted.
- $form['description']['#access'] = FALSE;
- // Most options are stored in the "extra" array, which stores any settings
- // unique to a particular component type.
- $form['extra']['options'] = array(
- '#type' => 'textarea',
- '#title' => t('Options'),
- '#default_value' => $component['extra']['options'],
- '#description' => t('Key-value pairs may be entered separated by pipes. i.e. safe_key|Some readable option') . ' ' . theme('webform_token_help'),
- '#cols' => 60,
- '#rows' => 5,
- '#weight' => -3,
- '#required' => TRUE,
- );
- return $form;
- }
- /**
- * Render a Webform component to be part of a form.
- *
- * @param $component
- * A Webform component array.
- * @param $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 $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.
- * @param $submission
- * The submission from which this component is being rendered. Usually not
- * needed. Used by _webform_render_date() to validate using the submission's
- * completion date.
- *
- * @return array
- * $form_item
- *
- * @see _webform_client_form_add_component()
- */
- function _webform_render_component($component, $value = NULL, $filter = TRUE, $submission = NULL) {
- $form_item = array(
- '#type' => 'textfield',
- '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'],
- '#required' => $component['required'],
- '#weight' => $component['weight'],
- '#description' => $filter ? webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
- '#default_value' => $filter ? webform_replace_tokens($component['value']) : $component['value'],
- '#theme_wrappers' => array('webform_element'),
- );
- if (isset($value)) {
- $form_item['#default_value'] = $value[0];
- }
- return $form_item;
- }
- /**
- * Allow modules to modify a webform component that will be rendered in a form.
- *
- * @param array $element
- * The display element as returned by _webform_render_component().
- * @param array $component
- * A Webform component array.
- *
- * @see _webform_render_component()
- */
- function hook_webform_component_render_alter(array &$element, array &$component) {
- if ($component['cid'] == 10) {
- $element['#title'] = 'My custom title';
- $element['#default_value'] = 42;
- }
- }
- /**
- * 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 $component
- * A Webform component array.
- * @param $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database table schema.
- * @param $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.
- * @param $submission
- * The submission. Used to generate tokens.
- *
- * @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_component($component, $value, $format = 'html', $submission = array()) {
- return array(
- '#title' => $component['name'],
- '#weight' => $component['weight'],
- '#theme' => 'webform_display_textfield',
- '#theme_wrappers' => $format == 'html' ? array('webform_element') : array('webform_element_text'),
- '#post_render' => array('webform_element_wrapper'),
- '#field_prefix' => $component['extra']['field_prefix'],
- '#field_suffix' => $component['extra']['field_suffix'],
- '#component' => $component,
- '#format' => $format,
- '#value' => isset($value[0]) ? $value[0] : '',
- );
- }
- /**
- * Allow modules to modify a "display only" webform component.
- *
- * @param array $element
- * The display element as returned by _webform_display_component().
- * @param array $component
- * A Webform component array.
- *
- * @see _webform_display_component()
- */
- function hook_webform_component_display_alter(array &$element, array &$component) {
- if ($component['cid'] == 10) {
- $element['#title'] = 'My custom title';
- $element['#default_value'] = 42;
- }
- }
- /**
- * Performs the conditional action set on an implemented component.
- *
- * Setting the form element allows form validation functions to see the value
- * that webform has set for the given component.
- *
- * @param array $component
- * The webform component array whose value is being set for the currently-
- * edited submission.
- * @param array $element
- * The form element currently being set.
- * @param array $form_state
- * The form's state.
- * @param string $value
- * The value to be set, as defined in the conditional action.
- */
- function _webform_action_set_component(array $component, array &$element, array &$form_state, $value) {
- $element['#value'] = $value;
- form_set_value($element, $value, $form_state);
- }
- /**
- * 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 $component
- * A Webform component array.
- * @param $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_component($component, $value) {
- // Clean up a phone number into 123-456-7890 format.
- if ($component['extra']['phone_number']) {
- $number = preg_replace('/[^0-9]/', '', $value[0]);
- if (strlen($number) == 7) {
- $number = substr($number, 0, 3) . '-' . substr($number, 3, 4);
- }
- else {
- $number = substr($number, 0, 3) . '-' . substr($number, 3, 3) . '-' . substr($number, 6, 4);
- }
- }
- $value[0] = $number;
- return $value;
- }
- /**
- * Delete operation for a component or submission.
- *
- * @param $component
- * A Webform component array.
- * @param $value
- * An array of information containing the submission result, directly
- * correlating to the webform_submitted_data database schema.
- */
- function _webform_delete_component($component, $value) {
- // Delete corresponding files when a submission is deleted.
- if (!empty($value[0]) && ($file = webform_get_file($value[0]))) {
- file_usage_delete($file, 'webform');
- file_delete($file);
- }
- }
- /**
- * Module specific instance of hook_help().
- *
- * This allows each Webform component to add information into hook_help().
- */
- function _webform_help_component($section) {
- switch ($section) {
- case 'admin/config/content/webform#grid_description':
- return t('Allows creation of grid questions, denoted by radio buttons.');
- }
- }
- /**
- * Module specific instance of hook_theme().
- *
- * This allows each Webform component to add information into hook_theme(). If
- * you specify a file to include, you must define the path to the module that
- * this file belongs to.
- */
- function _webform_theme_component() {
- return array(
- 'webform_grid' => array(
- 'render element' => 'element',
- 'file' => 'components/grid.inc',
- 'path' => drupal_get_path('module', 'webform'),
- ),
- 'webform_display_grid' => array(
- 'render element' => 'element',
- 'file' => 'components/grid.inc',
- 'path' => drupal_get_path('module', 'webform'),
- ),
- );
- }
- /**
- * 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 $component
- * An array of information describing the component, directly correlating to
- * the webform_component database schema.
- * @param $sids
- * An optional array of submission IDs (sid). If supplied, the analysis will
- * be limited to these sids.
- * @param $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.
- * @param $join
- * An optional SelectQuery object to be used to join with the submissions
- * table to restrict the submissions being analyzed.
- *
- * @return array
- * An array containing one or more of the following keys:
- * - table_rows: If this component has numeric data that can be represented in
- * a grid, return the values here. This array assumes a 2-dimensional
- * structure, with the first value being a label and subsequent values
- * containing a decimal or integer.
- * - table_header: If this component has more than a single set of values,
- * include a table header so each column can be labeled.
- * - other_data: If your component has non-numeric data to include, such as
- * a description or link, include that in the other_data array. Each item
- * may be a string or an array of values that matches the number of columns
- * in the table_header property.
- * At the very least, either table_rows or other_data should be provided.
- * Note that if you want your component's analysis to be available by default
- * without the user specifically enabling it, you must set
- * $component['extra']['analysis'] = TRUE in your
- * _webform_defaults_component() callback.
- *
- * @see _webform_defaults_component()
- */
- function _webform_analysis_component($component, $sids = array(), $single = FALSE, $join = NULL) {
- // Generate the list of options and questions.
- $options = _webform_select_options_from_text($component['extra']['options'], TRUE);
- $questions = _webform_select_options_from_text($component['extra']['questions'], TRUE);
- // Generate a lookup table of results.
- $query = db_select('webform_submitted_data', 'wsd')
- ->fields('wsd', array('no', 'data'))
- ->condition('nid', $component['nid'])
- ->condition('cid', $component['cid'])
- ->condition('data', '', '<>')
- ->groupBy('no')
- ->groupBy('data');
- $query->addExpression('COUNT(sid)', 'datacount');
- if (count($sids)) {
- $query->condition('sid', $sids, 'IN');
- }
- if ($join) {
- $query->innerJoin($join, 'ws2_', 'wsd.sid = ws2_.sid');
- }
- $result = $query->execute();
- $counts = array();
- foreach ($result as $data) {
- $counts[$data->no][$data->data] = $data->datacount;
- }
- // Create an entire table to be put into the returned row.
- $rows = array();
- $header = array('');
- // Add options as a header row.
- foreach ($options as $option) {
- $header[] = $option;
- }
- // Add questions as each row.
- foreach ($questions as $qkey => $question) {
- $row = array($question);
- foreach ($options as $okey => $option) {
- $row[] = !empty($counts[$qkey][$okey]) ? $counts[$qkey][$okey] : 0;
- }
- $rows[] = $row;
- }
- $other = array();
- $other[] = l(t('More information'), 'node/' . $component['nid'] . '/webform-results/analysis/' . $component['cid']);
- return array(
- 'table_header' => $header,
- 'table_rows' => $rows,
- 'other_data' => $other,
- );
- }
- /**
- * 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 $component
- * A Webform component array.
- * @param $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_component($component, $value) {
- $questions = array_values(_webform_component_options($component['extra']['questions']));
- $output = '';
- // Set the value as a single string.
- if (is_array($value)) {
- foreach ($value as $item => $value) {
- if ($value !== '') {
- $output .= $questions[$item] . ': ' . check_plain($value) . '<br />';
- }
- }
- }
- else {
- $output = check_plain(!isset($value['0']) ? '' : $value['0']);
- }
- return $output;
- }
- /**
- * 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 $component
- * A Webform component array.
- * @param $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_component($component, $export_options) {
- $header = array();
- $header[0] = array('');
- $header[1] = array($export_options['header_keys'] ? $component['form_key'] : $component['name']);
- $items = _webform_component_options($component['extra']['questions']);
- $count = 0;
- foreach ($items as $key => $item) {
- // Empty column per sub-field in main header.
- if ($count != 0) {
- $header[0][] = '';
- $header[1][] = '';
- }
- // The value for this option.
- $header[2][] = $item;
- $count++;
- }
- 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 $component
- * A Webform component array.
- * @param $export_options
- * An array of options that may configure export of this field.
- * @param $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_component($component, $export_options, $value) {
- $questions = array_keys(_webform_select_options($component['extra']['questions']));
- $return = array();
- foreach ($questions as $key => $question) {
- $return[] = isset($value[$key]) ? $value[$key] : '';
- }
- return $return;
- }
- /**
- * Fix the view field(s) that are automatically generated for number components.
- *
- * Provides each component the opportunity to adjust how this component is
- * displayed in a view as a field in a view table. For example, a component may
- * modify how it responds to click-sorting. Or it may add additional fields,
- * such as a grid component having a column for each question.
- *
- * @param array $component
- * A Webform component array.
- * @param array $fields
- * An array of field-definition arrays. Will be passed one field definition,
- * which may be modified. Additional fields may be added to the array.
- *
- * @return array
- * The modified $fields array.
- */
- function _webform_view_field_component(array $component, array $fields) {
- foreach ($fields as &$field) {
- $field['webform_datatype'] = 'number';
- }
- return $fields;
- }
- /**
- * Modify the how a view was expanded to show all the components.
- *
- * This alter function is only called when the view is actually modified. It
- * provides modules an opportunity to alter the changes that webform made to
- * the view.
- *
- * This hook is called from webform_views_pre_view. If another module also
- * changes views by implementing this same views hook, the relative order of
- * execution of the two implementations will depend upon the module weights of
- * the two modules. Using hook_webform_view_alter instead guarantees an
- * opportunity to modify the view AFTER webform.
- *
- * @param object $view
- * The view object.
- * @param string $display_id
- * The display_id that was expanded by webform.
- * @param array $args
- * The arguments that were passed to the view.
- */
- function hook_webform_view_alter($view, $display_id, array $args) {
- // Don't show component with cid == 4.
- $fields = $view->get_items('field', $display_id);
- foreach ($fields as $id => $field) {
- if (isset($field['webform_cid']) && $field['webform_cid'] == 4) {
- unset($fields[$id]);
- }
- }
- $view->display[$display_id]->handler->set_option('fields', $fields);
- }
- /**
- * Modify the list of mail systems that are capable of sending HTML email.
- *
- * @param array &$systems
- * An array of mail system class names.
- */
- function hook_webform_html_capable_mail_systems_alter(array &$systems) {
- if (module_exists('my_module')) {
- $systems[] = 'MyModuleMailSystem';
- }
- }
- /**
- * Define a list of webform exporters.
- *
- * @return array
- * A list of the available exporters provided by the module.
- *
- * @see webform_webform_exporters()
- */
- function hook_webform_exporters() {
- $exporters = array(
- 'webform_exporter_custom' => array(
- 'title' => t('Webform exporter name'),
- 'description' => t('The description for this exporter.'),
- 'handler' => 'webform_exporter_custom',
- 'file' => drupal_get_path('module', 'yourmodule') . '/includes/webform_exporter_custom.inc',
- 'weight' => 10,
- ),
- );
- return $exporters;
- }
- /**
- * Modify the list of webform exporters definitions.
- *
- * @param array &$exporters
- * A list of all available webform exporters.
- */
- function hook_webform_exporters_alter(array &$exporters) {
- $exporters['excel']['handler'] = 'customized_excel_exporter';
- $exporters['excel']['file'] = drupal_get_path('module', 'yourmodule') . '/includes/customized_excel_exporter.inc';
- }
- /**
- * Declare conditional types and their operators.
- *
- * Each conditional type defined here may then be referenced in
- * hook_webform_component_info(). For each type this hook also declares a set of
- * operators that may be applied to a component of this conditional type in
- * conditionals.
- *
- * @return array
- * A 2-dimensional array of operator configurations. The configurations are
- * keyed first by their conditional type then by operator key. Each operator
- * declaration is an array with the following keys:
- * - label: Translated label for this operator that is shown in the UI.
- * - comparison callback: A callback for server-side evaluation.
- * - js comparison callback: A JavaScript callback for client-side evaluation.
- * The callback will be looked for in the Drupal.webform object.
- * - form callback (optional): A form callback that allows configuring
- * additional parameters for this operator. Default:
- * 'webform_conditional_operator_text'.
- *
- * @see hook_webform_component_info()
- * @see callback_webform_conditional_comparision_operator()
- * @see callback_webform_conditional_rule_value_form()
- */
- function hook_webform_conditional_operator_info() {
- $operators = array();
- $operators['string']['not_equal'] = array(
- 'label' => t('is not'),
- 'comparison callback' => 'webform_conditional_operator_string_not_equal',
- 'js comparison callback' => 'conditionalOperatorStringNotEqual',
- );
- return $operators;
- }
- /**
- * Alter the list of operators and conditional types.
- *
- * @param array $operators
- * A data structure as described in hook_webform_conditional_operator_info().
- *
- * @see hook_webform_conditional_operator_info()
- */
- function hook_webform_conditional_operators_alter(array &$operators) {
- $operators['string']['not_equal']['label'] = t('not equal');
- }
- /**
- * Evaluate the operator for a given set of values.
- *
- * This function will be called two times with potentially different kinds of
- * values: Once in _webform_client_form_validate() before any of the validate
- * handlers or the _webform_submit_COMPONENT() callback is called, and once in
- * webform_client_form_pages() after those handlers have been called.
- *
- * @param array $input_values
- * The values received from the browser.
- * @param mixed $rule_value
- * The value as configured in the form callback.
- * @param array $component
- * The component for which we are evaluating the operator.
- *
- * @return bool
- * The operation result.
- */
- function callback_webfom_conditional_comparison_operator(array $input_values, $rule_value, array $component) {
- foreach ($input_values as $value) {
- if (strcasecmp($value, $rule_value)) {
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- * Define a form element that configures your operator.
- *
- * @param object $node
- * The node for which the conditionals are being configured.
- *
- * @return string|string[]
- * Either a single rendered form element or a rendered form element per
- * component (keyed by cid). Make sure that none of the rendered strings
- * contains any HTML IDs as the form element will be rendered multiple times.
- * The JavaScript will take care of adding the appropriate name attributes.
- *
- * @see _webform_conditional_expand_value_forms()
- */
- function callback_webform_conditional_rule_value_form($node) {
- $forms = [];
- foreach ($node->webform['components'] as $cid => $component) {
- if (webform_component_property($component['type'], 'conditional_type') == 'newsletter') {
- $element = [
- '#type' => 'select',
- '#options' => [
- 'yes' => t('Opt-in'),
- 'no' => t('No opt-in'),
- ],
- ];
- $forms[$cid] = drupal_render($element);
- }
- }
- return $forms;
- }
- /**
- * @}
- */
|