'file', 'weight' => 10)); $js_settings = array( 'width' => variable_get('colorbox_node_width', '600px'), 'height' => variable_get('colorbox_node_height', '600px'), ); // Allow other modules to add or change the default settings. drupal_alter('colorbox_node_settings', $js_settings); drupal_add_js(array('colorbox_node' => $js_settings), array('type' => 'setting', 'scope' => JS_DEFAULT)); } /** * Implements hook_menu(). */ function colorbox_node_menu() { $items['colorbox/%colorbox_node_url'] = array( 'page callback' => 'colorbox_node_output', 'page arguments' => array(1), 'access callback' => 'colorbox_node_check_access', 'access arguments' => array(1), 'load arguments' => array('%map'), 'delivery callback' => 'ajax_deliver', 'theme callback' => 'ajax_base_page_theme', 'type' => MENU_CALLBACK, ); return $items; } /** * Checks the access of the path for the current user * based on the menu system access * @param $path * @return bool */ function colorbox_node_check_access($path) { $menu_item = menu_get_item($path); return (isset($menu_item['access']) && $menu_item['access']); } /** * Implements hook_form_alter(). */ function colorbox_node_form_alter(&$form, &$form_state, $form_id) { switch ($form_id) { case 'colorbox_admin_settings': $form['colorbox_node'] = array( '#type' => 'fieldset', '#title' => t('Colorbox Node Integration'), ); $form['colorbox_node']['colorbox_node_regions'] = array( '#type' => 'checkbox', '#title' => module_exists('context') ? t('Enable Regions') : t('Enable Regions Missing Context Module'), '#description' => t('This enables regions to be rendered inside the colorbox modal. The context module can further target a colorbox modal. Experimental'), '#default_value' => variable_get('colorbox_node_regions', FALSE), '#disabled' => !module_exists('context') ? TRUE : FALSE, ); $form['colorbox_node']['colorbox_node_width'] = array( '#type' => 'textfield', '#title' => t('Default Width'), '#description' => t('Default width of the colorbox loaded window. You must include the \'px\' or \'%\' suffix with your numeric value.'), '#default_value' => variable_get('colorbox_node_width', '600px'), ); $form['colorbox_node']['colorbox_node_height'] = array( '#type' => 'textfield', '#title' => t('Default Height'), '#description' => t('Default height of the colorbox loaded window. You must include the \'px\' or \'%\' suffix with your numeric value.'), '#default_value' => variable_get('colorbox_node_height', '600px'), ); break; } } /** * Adds AJAX support to the registration form inside a colorbox modal. */ function colorbox_node_form_user_register_form_alter(&$form, &$form_state) { colorbox_node_form_ajax_support($form, $form_state, 'register'); } /** * Adds AJAX support to the login form inside a colorbox modal. */ function colorbox_node_form_user_login_alter(&$form, &$form_state) { colorbox_node_form_ajax_support($form, $form_state, 'login'); } /** * Adds AJAX support to the user pass reset form inside a colorbox modal. */ function colorbox_node_form_user_pass_alter(&$form, &$form_state) { colorbox_node_form_ajax_support($form, $form_state, 'pass'); } /** * Adds AJAX support to the node edit form inside a colorbox modal. */ function colorbox_node_form_node_form_alter(&$form, &$form_state) { colorbox_node_form_ajax_support($form, $form_state, 'node'); } /** * Adds AJAX support to the user edit form inside a colorbox modal. */ function colorbox_node_form_user_profile_form_alter(&$form, &$form_state) { colorbox_node_form_ajax_support($form, $form_state, 'user', 'redirect', 'user'); } /** * @param $form * @param $form_state * @param $form_id * @param string $action * The action to take when the form is completed. * close = Closes the colorbox modal. * redirect = Closes the colorbox modal and redirects the user to the $destination url * reload = Reloads the current page. This is good for the login form. * replace = Replaces the form/ajax data with the provided $destination. * @param string $destination */ function colorbox_node_form_ajax_support(&$form, &$form_state, $form_id, $action='close', $destination='') { // Check to see if we are inside an active colorbox if (colorbox_node_is_active() || isset($form_state['#colorboxNode'])) { // Set our form to be active as AJAX upload fields will be in a // different context and this code will never be called again and will fail out. $form_state['#colorboxNode'] = TRUE; $form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['actions']['submit']['#id'] = 'colorboxNode-' . $form_id . '-Submit'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'colorbox_node_ajax_submit', 'wrapper' => 'colorboxNode-' . $form_id . '-Wrapper', 'method' => 'replace', 'effect' => 'fade', ); if ($action == 'reload') { $form['#cbox_reload'] = TRUE; } elseif ($action == 'redirect') { $form['#cbox_redirect'] = $destination; } elseif ($action == 'replace') { $form['#cbox_replace'] = $destination; } } } /** * Handles all the ajax forms and runs them through this * central function to either return the form with error * messages, or to close the colorbox and populate our * messages div container. * * @param $form * @param $form_state * @return array * @throws Exception */ function colorbox_node_ajax_submit($form, &$form_state) { if (!form_get_errors()) { // Set our commands for the return to just display status messages. $commands = array(); // Replace the content area with the provided destination if (isset($form['#cbox_replace'])) { return colorbox_node_output($form['#cbox_replace']); } // Close the colorbox modal. // This is the default behavior. $commands[] = ajax_command_invoke('#cboxClose', 'click'); // Reload the main window if required. if (isset($form['#cbox_reload'])) { // @TODO: What happens to our messages if the page is reloaded? $commands[] = array('command' => 'colorboxNodeReload'); } else // Redirect the user to the passed in destination. // @TODO: Add support for dynamic redirects based on newly created content if (isset($form['#cbox_redirect'])) { $url = url($form['#cbox_redirect']); $commands[] = array('command' => 'colorboxNodeRedirect', 'data' => $url); } else { if (isset($form_state['redirect']) && !empty($form_state['redirect'])) { // Lets see if we can find the natural redirect from the form. // @TODO: I think the redirect key can also be an array. Add checks for that. if (is_array($form_state['redirect']) && isset($form_state['redirect'][0])) { $path = $form_state['redirect'][0]; $options = array(); if (isset($form_state['redirect'][1])) { foreach ($form_state['redirect'][1] as $key => $value) { $options[$key] = $value; } } $data = url($path, $options); } else { $data = url($form_state['redirect']); } $commands[] = array('command' => 'colorboxNodeRedirect', 'data' => $data); } else { // Set message. // @TODO: How not to make this theme specific? // @TODO: Maybe a variable on the admin settings page? $commands[] = ajax_command_before('#main-content', theme('status_messages')); } } return array('#type' => 'ajax', '#commands' => $commands); } return $form; } /** * Displays a node view without the page template. * Takes the path as our argument and from that we * will determine the internal path and node id. */ function colorbox_node_output($path) { // Tell others our modal window is active drupal_static('colorbox_node_is_active', TRUE); // Setup our return destination. if (!isset($_GET['destination'])) { $_GET['destination'] = $path; } // Change our super global for the rest of the // bootstrap process. $_GET['q'] = $path; // Fetch our callback based on our path. $page_callback_result = menu_execute_active_handler($path, FALSE); // Lets include our context execution. if (module_exists('context')) { if ($plugin = context_get_plugin('condition', 'colorbox_node')) { $plugin->execute('view'); } } $commands = array(); // Is we have an array, lets assume we need to render it out. if (is_array($page_callback_result)) { if (isset($page_callback_result['nodes'])) { foreach ($page_callback_result['nodes'] as $nid => $tmp_node) { if (isset($tmp_node['#view_mode'])) { $node_view = $tmp_node['#node']; $node_view_array = node_view($node_view, 'colorbox'); if (module_exists('comment')) { $node_view_array['comments'] = comment_node_page_additions($node_view); } $rendered_node = drupal_render($node_view_array); $page_callback_result['nodes'][$nid] = array('#markup' => $rendered_node); } } } } // Load up our regions if enabled. if (variable_get('colorbox_node_regions', FALSE) == TRUE) { drupal_set_page_content($page_callback_result); $page_callback_result = element_info('ajax'); // Modules can add elements to $page as needed in hook_page_build(). foreach (module_implements('page_build') as $module) { $function = $module . '_page_build'; $function($page_callback_result); } // Modules alter the $page as needed. Blocks are populated into regions like // 'sidebar_first', 'footer', etc. drupal_alter('page', $page_callback_result); } // Allow other modules to alter the colorbox node callback drupal_alter('colorbox_node_page_callback_result', $page_callback_result); $html = is_string($page_callback_result) ? $page_callback_result : drupal_render($page_callback_result); $commands[] = ajax_command_html('#cboxLoadedContent', $html); // Add the status messages inside the new content's wrapper element, so that // on subsequent Ajax requests, it is treated as old content. $commands[] = ajax_command_prepend('#cboxLoadedContent', theme('status_messages')); // Render our commands out to the browser. return array('#type' => 'ajax', '#commands' => $commands); } /** * Takes a path as an array of all our arguments from the * url structure. We then put that structure back together, * find our system path and then return it. */ function colorbox_node_url_load($arg, $path = array()) { // First lets remove 'colorbox' array_shift($path); // Lets determine if we have a prefix from our languages. if (module_exists('locale') && function_exists('language_url_split_prefix')) { // Get our language list to pass into our url splitter. $languages = language_list(); // Turn the path into a string so we can then remove our prefix. $path_string = implode('/', $path); $language_path = language_url_split_prefix($path_string, $languages); // Separate out the returned path and language. We should always // have two indexes, the first is the language, second is the path. $language = $language_path[0] ? $language_path[0]->language : ''; $final_path = $language_path[1]; // Lets find our path based on the current translation. return drupal_get_normal_path($final_path, $language); } // Now lets buld our path to return our system path, return drupal_get_normal_path(implode('/', $path)); } /** * Determines if the current page request is inside a modal window. */ function colorbox_node_is_active() { return drupal_static('colorbox_node_is_active', FALSE); } /** * Implements hook_entity_info_alter(). */ function colorbox_node_entity_info_alter(&$entity_info) { $entity_info['node']['view modes']['colorbox'] = array( 'label' => t('Colorbox'), 'custom settings' => FALSE, ); } /** * Implements hook_views_api(). */ function colorbox_node_views_api() { return array( 'api' => 2, 'path' => drupal_get_path('module', 'colorbox_node') . '/views', ); } /** * Implements hook_context_plugins(). */ function colorbox_node_context_plugins() { $plugins = array(); $plugins['colorbox_node_context_condition'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'colorbox_node'), 'file' => 'colorbox_node.context.inc', 'class' => 'colorbox_node_context_condition', 'parent' => 'context_condition', ), ); return $plugins; } /** * Implements hook_context_registry(). */ function colorbox_node_context_registry() { return array( 'conditions' => array( 'colorbox_node' => array( 'title' => t('Colorbox Modal'), 'description' => t('Set this context based on if you are viewing your content inside a colorbox modal.'), 'plugin' => 'colorbox_node_context_condition', ), ), ); } /** * Implement hook_ctools_plugin_api(). */ function colorbox_node_ctools_plugin_api($module, $api) { if ($module == 'page_manager') { return array('version' => 2); } } /** * Implement hook_ctools_plugin_directory(). */ function colorbox_node_ctools_plugin_directory($module, $plugin) { if ($module == 'page_manager' || $module == 'ctools') { return 'ctools/plugins/' . $plugin; } } /** * Implements hook_menu_attribute_info(). */ function colorbox_node_menu_attribute_info() { // Add a data-inner-width attribute. $attributes['data-inner-width'] = array( 'label' => t('Data-Inner-Width (px)'), 'description' => t('Specifies the inner width used by colorbox.'), 'form' => array( '#size' => 5, ), ); // Add a data-inner-width attribute. $attributes['data-inner-height'] = array( 'label' => t('Data-Inner-Height (px)'), 'description' => t('Specifies the inner height used by colorbox.'), 'form' => array( '#size' => 5, ), ); return $attributes; } /** * Implements hook_field_formatter_info_alter(). */ function colorbox_node_field_formatter_info_alter(&$info) { if (isset($info['entityreference_label']) && module_exists('field_formatter_settings')) { $info['entityreference_label']['settings'] += array( 'colorbox_node_link' => FALSE, 'colorbox_node_classes' => '', 'colorbox_node_width' => '600', 'colorbox_node_height' => '600', ); } } /** * Implements hook_field_formatter_settings_form_alter(). */ function colorbox_node_field_formatter_settings_form_alter(&$settings_form, $context) { // Integration with the entityreference module if (isset($context['instance']['display'][$context['view_mode']]['type']) && $context['instance']['display'][$context['view_mode']]['type'] == 'entityreference_label') { $display = $context['instance']['display'][$context['view_mode']]; $settings = $display['settings']; switch ($context['form']['#form_id']) { case 'field_ui_display_overview_form': $class = 'fields-field-entity-settings-edit-form-settings'; break; case 'views_ui_config_item_form': default: $class = 'options-settings'; break; } $settings_form['colorbox_node_link'] = array( '#title' => t('Open in a Colorbox'), '#type' => 'checkbox', '#default_value' => $settings['colorbox_node_link'], '#dependency' => array( 'edit-' . $class . '-link' => array(1), ), ); $settings_form['colorbox_node_width'] = array( '#type' => 'textfield', '#title' => t('Colorbox Width'), '#default_value' => !empty($settings['colorbox_node_width']) ? $settings['colorbox_node_width'] : '600', '#dependency' => array( 'edit-' . $class . '-colorbox-node-link' => array(1), ), '#dependency_count' => 1, '#weight' => 1, ); $settings_form['colorbox_node_height'] = array( '#type' => 'textfield', '#title' => t('Colorbox Height'), '#default_value' => !empty($settings['colorbox_node_height']) ? $settings['colorbox_node_height'] : '600', '#dependency' => array( 'edit-' . $class . '-colorbox-node-link' => array(1), ), '#dependency_count' => 1, '#weight' => 2, ); $settings_form['colorbox_node_classes'] = array( '#title' => t('Classes to add to the anchor tag (in addition to "colorbox-node")'), '#type' => 'textfield', '#default_value' => $settings['colorbox_node_classes'], '#dependency' => array( 'edit-' . $class . '-colorbox-node-link' => array(1), ), '#weight' => 3, ); } } /** * Implements hook_field_formatter_settings_summary_alter(). */ function colorbox_node_field_formatter_settings_summary_alter(&$summary, $context) { if ($context['instance']['display'][$context['view_mode']]['type'] == 'entityreference_label') { $display = $context['instance']['display'][$context['view_mode']]; $settings = $display['settings']; if (!empty($summary)) { $summary .= '
'; } if (isset($settings['colorbox_node_link']) && $settings['colorbox_node_link']) { $summary .= t('Open in Colorbox'); } } } /** * Implements hook_field_attach_view_alter(). */ function colorbox_node_field_attach_view_alter(&$output, $context) { foreach (element_children($output) as $field_name) { $element = &$output[$field_name]; $field = field_info_field($field_name); if (!isset($field['settings']['target_type'])) continue; // Load up the rest of our data since we have a target type. $instance = field_info_instance($element['#entity_type'], $field_name, $element['#bundle']); $entity = entity_get_info($field['settings']['target_type']); $display = $instance['display']['default']; $settings = $display['settings']; // In views, we will have a localized context for our settings. // Set them here to override the defaults. if (isset($context['display']) && isset($context['display']['settings'])) { $settings = $context['display']['settings']; } // If we are not linking as a colorbox, then just continue on. if (!isset($settings['colorbox_node_link']) || !$settings['colorbox_node_link']) { continue; } $handler = entityreference_get_selection_handler($field, $instance, $element['#entity_type'], $entity); foreach (element_children($element) as $delta) { $label = $handler->getLabel($element['#items'][$delta]['entity']); if ($uri = entity_uri($field['settings']['target_type'], $element['#items'][$delta]['entity'])) { $class = array(); if (!empty($settings['colorbox_node_classes'])) { $class = array_unique(explode(' ', trim($settings['colorbox_node_classes']))); } $class[] = 'colorbox-node'; $uri['options']['attributes'] = array( 'class' => $class, 'data-inner-width' => $settings['colorbox_node_width'], 'data-inner-height' => $settings['colorbox_node_height'], ); $element[$delta]['#markup'] = l($label, $uri['path'], $uri['options']); } } } }