diff --git a/ctools_automodal.api.php b/ctools_automodal.api.php new file mode 100755 index 0000000..36fe648 --- /dev/null +++ b/ctools_automodal.api.php @@ -0,0 +1,82 @@ + 'example-signup', + 'redirect' => 'user', + 'close' => TRUE, + ); + + $paths['contact-us'] = array( + 'style' => 'example-contact', + 'confirm' => array( + 'title' => t('Thank you'), + 'text' => t('Your message has been sent.'), + ), + ); + + return $paths; +} + +/** + * Implements hook_modal_paths_alter(). + */ +function hook_modal_paths_alter(&$paths) { + +} + +/** + * Implements hook_modal_styles(). + */ +function hook_modal_styles() { + $styles = array(); + + $styles['example-contact'] = array( + 'modalSize' => array( + 'type' => 'fixed', + 'width' => 500, + 'height' => 300, + ), + ); + + $styles['example-signup'] = array( + 'modalSize' => array( + 'type' => 'fixed', + 'width' => 500, + 'height' => 500, + ), + ); + + return $styles; +} + +/** + * Implements hook_modal_styles_alter(). + */ +function hook_modal_styles_alter(&$styles) { + +} + +/** + * Implements hook_modal_error_alter(). + */ +function hook_modal_error_alter(&$commands, $path, $error) { + if ($error == ENU_ACCESS_DENIED) { + if (strpos($path, 'user/') !== FALSE) { + $commands[0]['output'] = '' . t('You are already signed in.') . ''; + } + else { + $commands[0]['output'] = '' . $commands[0]['output'] . ''; + } + } +} diff --git a/ctools_automodal.module b/ctools_automodal.module index e706bc2..d5a540c 100644 --- a/ctools_automodal.module +++ b/ctools_automodal.module @@ -1,4 +1,4 @@ - $item) { - if (!empty($item['modal']) && strpos($path, '%ctools_js') === FALSE) { - if ($item['page callback'] == 'drupal_get_form') { - $items["$path/%ctools_js"] = $item; - $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_get_form'; - $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; - $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; - } - else { - $items["$path/%ctools_js"] = $item + array('page arguments' => array()); - $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_get_page'; - array_unshift($items["$path/%ctools_js"]['page arguments'], $item['page callback']); - $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; - $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; + $modal_paths = ctools_automodal_get_modal_paths(); + $modal_regexp_pieces = array(); + + // Create unique node edit links for each content type + // @todo: necessary (taken from node_menu()) node_type_cache_reset(); + foreach (node_type_get_types() as $type) { + $type_url_str = str_replace('_', '-', $type->type); + if (empty($items['node/%node/edit/' . $type_url_str])) { + $items['node/%node/edit/' . $type_url_str] = $items['node/%node/edit']; + $items['node/%node/edit/' . $type_url_str]['type'] = ENU_CALLBACK; + } + } + + //$convert_to_regexp = function ($value) { return preg_replace('/%[^\/]*/', '[^/]+', $value); }; + foreach ($modal_paths as $path) { + if (empty($items[$path])) { + continue; + } + $item = $items[$path]; + + if ($item['page callback'] == 'drupal_get_form') { + $items["$path/%ctools_js"] = $item; + $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_get_form'; + $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; + $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; + } + elseif ($item['page callback'] == 'node_add') { + $items["$path/%ctools_js"] = $item; + $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_node_add'; + $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; + $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; + } + elseif ($item['page callback'] == 'node_page_edit') { + $items["$path/%ctools_js"] = $item; + $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_node_edit'; + $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; + $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; + } + else { + $items["$path/%ctools_js"] = $item + array('page arguments' => array()); + $items["$path/%ctools_js"]['page callback'] = 'ctools_automodal_get_page'; + array_unshift($items["$path/%ctools_js"]['page arguments'], $item['page callback']); + $items["$path/%ctools_js"]['page arguments'][] = substr_count($path, '/') + 1; + $items["$path/%ctools_js"]['type'] = ENU_CALLBACK; + } + + $modal_regexp_pieces[] = _ctools_automodal_menu_alter_regex($path); + $modal_paths[] = $path; + } + + if (!empty($modal_paths)) { + $all_paths = array_keys($items); + $modal_regexp = '@^' . implode('|^', $modal_regexp_pieces) . '@'; + $not_modal_regexp = '@^' . implode('|^', array_map('_ctools_automodal_menu_alter_regex', array_diff(preg_grep($modal_regexp, $all_paths), $modal_paths))) . '@'; + } + else { + $modal_regexp = $not_modal_regexp = ''; + } + + variable_set('ctools_automodal_regexp', $modal_regexp); + variable_set('ctools_automodal_not_regexp', $not_modal_regexp); +} + +/** + * A helper function that matches a path in ctools_automodal_menu_alter(). + */ +function _ctools_automodal_menu_alter_regex($value) { + return preg_replace('/%[^\/]*/', '[^/]+', $value); +} + +/** + * Implements hook_page_delivery_callback_alter() + */ +function ctools_automodal_page_delivery_callback_alter(&$callback) { + // jQuery sets a HTTP_X_REQUESTED_WITH header of 'XLHttpRequest'. + // If a page would normally be delivered as an html page, and it is called + // from jQuery, deliver it instead as an Ajax response. + if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XLHttpRequest' && $callback == 'drupal_deliver_html_page') { + $path = ctools_automodal_get_system_uri(); + if (ctools_automodal_is_path_modal($path)) { + $page_callback_result = ctools_automodal_get_page_callback_error($path); + if (is_int($page_callback_result)) { + ctools_automodal_deliver_error($path, $page_callback_result); } - $modal_paths[] = preg_replace('/%[^\/]*/', '*', $path); } } +} - variable_set('ctools_automodal_paths', $modal_paths); +/** + * Returns URI of the request with stripped "nojs" or "ajax". + * + * @return string + */ +function ctools_automodal_get_system_uri() { + $path = drupal_parse_url(trim(request_uri(), '/')); + $path_parts = explode('/', $path['path']); + if (in_array(end($path_parts), array('nojs', 'ajax'))) { + array_pop($path_parts); + $path = implode('/', $path_parts); + } + return $path; } /** - * Check if an internal Drupal path should be converted to a modal link. + * Check the menu path for access denied and not found errors. + * + * Returns ENU_NOT_FOUND, MENU_ACCESS_DENIED or NULL if no error was found. + * + * @param $path + * @return int|null */ -function ctools_automodal_is_path_modal($path) { - static $modal_paths_regex; +function ctools_automodal_get_page_callback_error($path) { + $page_callback_result = NULL; + if ($router_item = menu_get_item($path)) { + if ($router_item['access'] == FALSE) { + $page_callback_result = ENU_ACCESS_DENIED; + } + } + else { + $page_callback_result = ENU_NOT_FOUND; + } + return $page_callback_result; +} + +/** + * Package and send the result of a page callback to the browser as HTL. + * + * @param $page_callback_result + * The result of a page callback. Can be one of: + * - NULL: to indicate no content. + * - An integer menu status constant: to indicate an error condition. + * - A string of HTL content. + * - A renderable array of content. + * + * @see drupal_deliver_page() + * @see drupal_deliver_html_page() + * @see ajax_prepare_response() + */ +function ctools_automodal_deliver_error($path, $page_callback_result) { + // enu status constants are integers; page content is a string or array. + if (is_int($page_callback_result)) { + $output = ''; + switch ($page_callback_result) { + case ENU_NOT_FOUND: + drupal_set_title(t('Page not found')); + $output = t('The requested page "@path" could not be found.', array('@path' => request_uri())); + break; + + case ENU_ACCESS_DENIED: + drupal_set_title(t('Access denied')); + $output = t('You are not authorized to access this page.'); + break; + + case ENU_SITE_OFFLINE: + drupal_set_title(t('Site maintenance')); + $output = theme('maintenance_page', array('content' => filter_xss_admin(variable_get('maintenance_mode_message', + t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal'))))))); + break; + } + + // If there is any error output render it and exit. + if ($output) { + ctools_include('modal'); + ctools_include('ajax'); + ctools_add_js('ajax-responder'); - if (!isset($modal_paths_regex)) { - $modal_paths = variable_get('ctools_automodal_paths', array()); - foreach ($modal_paths as &$modal_path) { - $modal_path = preg_quote($modal_path, '/'); - $modal_path = str_replace('\*', '.*', $modal_path); + $commands = ctools_automodal_page_render($output); + drupal_alter('modal_error', $commands, $path, $page_callback_result); + + print ajax_render($commands); + exit(); } - $modal_paths_regex = '/^(' . implode('|', $modal_paths) . ')$/'; } +} - return (bool) preg_match($modal_paths_regex, $path); +/** + * Check if an internal Drupal path should be converted to a modal link. + */ +function ctools_automodal_is_path_modal($path) { + $modal_regexp = variable_get('ctools_automodal_regexp'); + $not_modal_regexp = variable_get('ctools_automodal_not_regexp'); + if (!$modal_regexp || !$not_modal_regexp) { + return FALSE; + } + return preg_match($modal_regexp, $path) && !preg_match($not_modal_regexp, $path); } /** @@ -65,7 +210,6 @@ function ctools_automodal_preprocess_link(&$variables) { static $ctools_modal_included = FALSE; if (ctools_automodal_is_path_modal($variables['path'])) { - $item = menu_get_item($variables['path']); // Only process the modal includes once per request. if (!$ctools_modal_included) { @@ -74,6 +218,13 @@ function ctools_automodal_preprocess_link(&$variables) { $ctools_modal_included = TRUE; } + $options = ctools_automodal_get_modal_options($variables['path']); + + if (!empty($options['style'])) { + ctools_automodal_include_style($options['style']); + $variables['options']['attributes']['class'][] = 'ctools-modal-' . $options['style']; + } + $variables['options']['attributes']['class'][] = 'ctools-use-modal'; if (strpos($variables['path'], 'nojs') === FALSE) { @@ -96,9 +247,135 @@ function ctools_automodal_preprocess_menu_local_action(&$variables) { } /** + * Implemenation of hook_theme(). + */ +function ctools_automodal_theme($existing, $type, $theme, $path) { + return array( + 'ctools_automodal_confirmation' => array( + 'variables' => array( + 'messages' => NULL, + 'confirmation' => NULL, + 'actions' => NULL, + ), + ), + ); +} + +/** + * Return modal configuration for given path. + * + * @param string $path + * @return array|NULL + */ +function ctools_automodal_get_modal_options($path) { + $modal_options = NULL; + $ctools_modal_paths = ctools_automodal_get_all_modal_options(); + + // @todo: Do this with a regex? + //$router_item = menu_get_item($path); + //$path = $router_item['path']; + + + + + foreach ($ctools_modal_paths as $key => $modal_options) { + $pattern = _ctools_automodal_menu_alter_regex($key); + $pattern = str_replace(array('/'), array('\/'), $pattern); + $pattern = '/^' . $pattern . '$/'; + if (preg_match($pattern, $path)) { + $modal_options += array( + 'style' => '', + 'confirm' => FALSE, + 'close' => FALSE, + 'confirm' => FALSE, + 'reload' => FALSE, + 'redirect' => '', + ); + if ($modal_options['confirm']) { + $modal_options['confirm'] += array( + 'title' => t('Confirmation'), + 'text' => t('The form was submitted.'), + 'callback' => 'ctools_automodal_confirmation_callback', + ); + } + + return $modal_options; + } + } + +} + +/** + * Return keyed array of modal paths and options returned by hook_modal_paths() implementations. + * + * @return array + */ +function ctools_automodal_get_all_modal_options() { + static $ctools_modal_paths = NULL; + + if (is_null($ctools_modal_paths)) { + $ctools_modal_paths = module_invoke_all('modal_paths'); + drupal_alter('modal_paths', $ctools_modal_paths); + } + + return $ctools_modal_paths; +} + +/** + * Return array of modal paths returned by hook_modal_paths() implementations. + * + * @return array + */ +function ctools_automodal_get_modal_paths() { + return array_keys(ctools_automodal_get_all_modal_options()); +} + +/** + * Returns CTools modal style definition. + * + * http://drupal.org/node/872072#comment-3391816 + * + * @param string $style_id + * @return array|NULL + */ +function ctools_automodal_get_style($style_id) { + static $ctools_modal_styles = NULL; + + if (is_null($ctools_modal_styles)) { + $ctools_modal_styles = module_invoke_all('modal_styles'); + drupal_alter('modal_styles', $ctools_modal_styles); + } + + return isset($ctools_modal_styles[$style_id]) ? $ctools_modal_styles[$style_id] : NULL; +} + +/** + * Includes CTools modal style in the page. + * + * @param string $style_id + * @return boolean + */ +function ctools_automodal_include_style($style_id) { + static $ctools_modal_styles = array(); + + if (!isset($ctools_modal_styles[$style_id])) { + $style = ctools_automodal_get_style($style_id); + if ($style) { + drupal_add_js(array($style_id => $style), 'setting'); + $ctools_modal_styles[$style_id] = TRUE; + } + else { + $ctools_modal_styles[$style_id] = FALSE; + } + } + + return $ctools_modal_styles[$style_id]; +} + +/** * Dirty, dirty function to fix the 'current path' global on modal pages. */ -function ctools_automodal_fix_get_q() { +function _ctools_automodal_fix_get_q() { $path = current_path(); // Pop off the /js or /nojs suffix to the path. $path = substr($path, 0, strrpos($path, '/')); @@ -106,19 +383,113 @@ function ctools_automodal_fix_get_q() { $_GET['q'] = $path; } + +/** + * Returns redirect path if found. + * + * Search for the redirect path in the following order: + * 1. destination query string, + * 2. modal redirect option + * 3. form state redirect property + * + * @param $modal_options + * @param $form_state + * + * @return array + * + * @see ctools_automodal_get_form() + */ +function _ctools_automodal_get_form_redirect_path($modal_options, $form_state) { + $path = NULL; + $options = array(); + + if ($modal_options['redirect'] !== FALSE && ($modal_options['redirect'] || $form_state['redirect'] || !empty($_GET['destination']))) { + if (isset($_GET['destination']) && !url_is_external($_GET['destination'])) { + $options = drupal_parse_url($_GET['destination']); + $path = $options['path']; + } + elseif (is_array($modal_options['redirect'])) { + list($path, $options) = $modal_options['redirect'] + array(NULL, array()); + } + elseif (is_string($modal_options['redirect'])) { + $path = $modal_options['redirect']; + } + elseif (is_array($form_state['redirect'])) { + list($path, $options) = $form_state['redirect'] + array(NULL, array()); + } + elseif (is_string($form_state['redirect'])) { + $path = $form_state['redirect']; + } + } + return array($path, $options); +} + +/** + * Renders form confirm page. + * + * @param $modal_options + * @return array + * + * @see ctools_automodal_get_form() + */ +function _ctools_automodal_get_form_confirm_page($modal_options) { + $confirmation = call_user_func($modal_options['confirm']['callback'], $modal_options['confirm']); + $rendered_confirmation = theme('ctools_automodal_confirmation', $confirmation); + return array($modal_options['confirm']['title'], $rendered_confirmation); +} + +/** + * A wrapper to make node_add pages work as a form. + */ +function ctools_automodal_node_add() { + $args = func_get_args(); + + global $user; + $type = $args[0]; + + $node = (object) array( + 'uid' => $user->uid, + 'name' => (isset($user->name) ? $user->name : ''), + 'type' => $type, + 'language' => LANGUAGE_NONE, + ); + + $output = ctools_automodal_get_form($type . '_node_form', $node, $args[1]); + + return $output; +} + +/** + * A wrapper to make node_edit pages work as a form. + */ +function ctools_automodal_node_edit() { + $args = func_get_args(); + + $node = $args[0]; + $output = ctools_automodal_get_form($node->type . '_node_form', $node, $args[1]); + + return $output; +} + + + /** * Display a Drupal form using CTools modal or normal page display. */ function ctools_automodal_get_form() { $args = func_get_args(); $form_id = array_shift($args); - $js = $ajax = array_pop($args); + $ajax = array_pop($args); - ctools_automodal_fix_get_q(); + _ctools_automodal_fix_get_q(); + + // Load modal options. + $modal_options = ctools_automodal_get_modal_options(current_path()); if ($ajax) { ctools_include('modal'); ctools_include('ajax'); + ctools_add_js('ajax-responder'); $form_state = array( 'ajax' => $ajax, @@ -126,12 +497,46 @@ function ctools_automodal_get_form() { ); $commands = ctools_modal_form_wrapper($form_id, $form_state); - if (empty($commands)) { + // Handle submitted form. + if (!empty($form_state['executed']) && empty($form_state['rebuild'])) { + // Overwrite the form wrapper output. + $commands = array(); + + // Add custom commands + if ($modal_options['commands_callback']) { + $commands = call_user_func_array($modal_options['commands_callback'], array($form_state)); + print ajax_render($commands); + exit(); + } + $commands[] = ctools_modal_command_loading(); - if (!empty($_GET['destination'])) { - $commands[] = ctools_ajax_command_redirect($_GET['destination']); + + // Close the form or display the confirmation page. + if ($modal_options['close']) { + $commands[] = ctools_modal_command_dismiss(); + } + elseif ($modal_options['confirm']) { + list($title, $confirm_page) = _ctools_automodal_get_form_confirm_page($modal_options); + $commands[] = ctools_modal_command_display($title, $confirm_page); + } + + // Redirect or reload current page. + list($path, $options) = _ctools_automodal_get_form_redirect_path($modal_options, $form_state); + if (!empty($path) && $modal_options['redirect'] !== FALSE) { + if ($modal_options['redirect'] === 'modal') { + // Open the redirect path in a modal + $commands = _ctools_automodal_redirect($path, $options); + } + else { + // Issue a generic page redirect + $commands[] = ctools_ajax_command_redirect($path, 0, $options); + } + } + elseif ($modal_options['reload']) { + $commands[] = ctools_ajax_command_reload(); } } + print ajax_render($commands); exit(); } @@ -142,6 +547,66 @@ function ctools_automodal_get_form() { } /** + * Hijack a redirect so it stays in the modal. + * A lot of code copied from menu_execute_active_handler(). + * @param [type] $path [description] + * @param [type] $options [description] + * @return [type] [description] + */ +function _ctools_automodal_redirect($path, $options) { + if ($router_item = menu_get_item($path)) { + if ($router_item['access']) { + + if ($router_item['include_file']) { + require_once DRUPAL_ROOT . '/' . $router_item['include_file']; + } + + // Alter response ala the hook_menu_item call above. + if ($router_item['page_callback'] == 'node_page_edit') { + $args = $router_item['page_arguments']; + $router_item['page_callback'] = 'drupal_get_form'; + $router_item['page_arguments'] = array($args[0]->type . '_node_form', $args[0], $args[1]); + } + if ($router_item['page_callback'] == 'drupal_get_form') { + + // @todo + // Some modules (like multistep) depend on vars passed via the querystring + + // This logic taken from ctools_automodal_get_form() above + $args = $router_item['page_arguments']; + $form_id = array_shift($args); + $form_state = array( + 'ajax' => TRUE, + 'build_info' => array('args' => $args), + ); + // @todo? $form = drupal_rebuild_form($form_id, $form_state); + + $commands = ctools_modal_form_wrapper($form_id, $form_state); + } + // TODO: + //elseif ($item['page callback'] == 'node_add') { + // $router_item['page callback'] = 'ctools_automodal_node_add'; + //} + else { + $output = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']); + $commands = ctools_automodal_page_render($output); + } + } + else { + // TODO: + $page_callback_result = ENU_ACCESS_DENIED; + } + } + else { + // TODO: + $page_callback_result = ENU_NOT_FOUND; + } + + return $commands; +} + + +/** * Display a normal Drupal page using CTools modal. */ function ctools_automodal_get_page() { @@ -149,7 +614,7 @@ function ctools_automodal_get_page() { $callback = array_shift($args); $ajax = array_pop($args); - ctools_automodal_fix_get_q(); + _ctools_automodal_fix_get_q(); if (function_exists($callback)) { $output = call_user_func_array($callback, $args); @@ -186,14 +651,42 @@ function ctools_automodal_page_render($output) { $output = drupal_render($output); } - $title = drupal_get_title(); - // If there are messages for the form, render them. if ($messages = theme('status_messages')) { $output = '
' . $messages . '
' . $output; } $commands = array(); + $title = drupal_get_title(); $commands[] = ctools_modal_command_display($title, $output); + return $commands; } + +/** + * Default confirmation callback. + * + * @param array $options + */ +function ctools_automodal_confirmation_callback($options) { + $confirmation = array(); + $confirmation['messages']['#markup'] = theme('status_messages'); + $confirmation['confirmation']['#markup'] = $options['text']; + $confirmation['actions']['#markup'] = '' . t('Dismiss') . ''; + return $confirmation; +} + +/** + * Theme modal confirmation page. + */ +function theme_ctools_automodal_confirmation($variables) { + $output = ''; + $output .= '
'; + $output .= render($variables['messages']); + $output .= '
'; + $output .= render($variables['confirmation']); + $output .= '
'; + $output .= render($variables['actions']); + $output .= '
'; + return $output; +} diff --git a/ctools_automodal_example/ctools_automodal_example.info b/ctools_automodal_example/ctools_automodal_example.info new file mode 100755 index 0000000..9e33bee --- /dev/null +++ b/ctools_automodal_example/ctools_automodal_example.info @@ -0,0 +1,4 @@ +name = CTools Automodal Example +description = Example of automatic modal page API. +core = 7.x +dependencies[] = ctools_automodal diff --git a/ctools_automodal_example/ctools_automodal_example.module b/ctools_automodal_example/ctools_automodal_example.module new file mode 100755 index 0000000..87c680e --- /dev/null +++ b/ctools_automodal_example/ctools_automodal_example.module @@ -0,0 +1,120 @@ + 'Contact Us', + 'description' => 'Contact Us', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('ctools_automodal_example_contact_us_form'), + 'access arguments' => array('access content'), + ); + + return $items; +} + +/** + * Implements hook_modal_paths(). + */ +function ctools_automodal_example_modal_paths() { + $paths = array(); + + $paths['user/register'] = array( + 'style' => 'example-signup', + 'redirect' => 'user', + 'close' => TRUE, + ); + + $paths['contact-us'] = array( + 'style' => 'example-contact', + 'confirm' => array( + 'title' => t('Thank you'), + 'text' => t('Your message has been sent.'), + ), + ); + + return $paths; +} + +/** + * Implements hook_modal_styles(). + */ +function ctools_automodal_example_modal_styles() { + $styles = array(); + + $styles['example-contact'] = array( + 'modalSize' => array( + 'type' => 'fixed', + 'width' => 500, + 'height' => 300, + ), + ); + + $styles['example-signup'] = array( + 'modalSize' => array( + 'type' => 'fixed', + 'width' => 500, + 'height' => 500, + ), + ); + + return $styles; +} + +/** + * Implements hook_modal_error_alter(). + */ +function ctools_automodal_example_modal_error_alter(&$commands, $path, $error) { + if ($error == ENU_ACCESS_DENIED) { + if (strpos($path, 'user/') !== FALSE) { + $commands[0]['output'] = '' . t('You are already signed in.') . ''; + } + else { + $commands[0]['output'] = '' . $commands[0]['output'] . ''; + } + } +} + +/** + * Contact Us form. + */ +function ctools_automodal_example_contact_us_form($form, &$form_state) { + global $user; + + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Your name'), + '#default_value' => $user->name, + '#maxlength' => 40, + '#size' => 20, + '#required' => TRUE, + ); + + $form['message'] = array( + '#type' => 'textarea', + '#title' => t('Your message'), + '#default_value' => '', + '#rows' => 4, + '#maxlength' => 1000, + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Send message'), + ); + + return $form; +} + +/** + * Contact Us form submit handler. + */ +function ctools_automodal_example_contact_us_form_submit($form, &$form_state) { + drupal_set_message(t('Your message has been sent.')); + drupal_set_message(t('@user is saying: %message', array('@name' => $form_state['values']['name'], '%message' => $form_state['values']['message']))); +}