'Sections', 'description' => 'Define sections of your site and apply themes to them.', 'page callback' => 'drupal_get_form', 'page arguments' => array('sections_admin_display_form'), 'access arguments' => $access, 'file' => 'sections.admin.inc', 'type' => MENU_NORMAL_ITEM ); $items['admin/build/sections/list'] = array( 'title' => 'List', 'page callback' => 'drupal_get_form', 'page arguments' => array('sections_admin_display_form'), 'access arguments' => $access, 'weight' => -10, 'file' => 'sections.admin.inc', 'type' => MENU_DEFAULT_LOCAL_TASK ); $items['admin/build/sections/add'] = array( 'title' => 'Add section', 'page callback' => 'drupal_get_form', 'page arguments' => array('sections_admin_settings_form'), 'access arguments' => $access, 'file' => 'sections.admin.inc', 'type' => MENU_LOCAL_TASK ); $items['admin/build/sections/edit/%section'] = array( 'title' => 'Edit section', 'page callback' => 'drupal_get_form', 'page arguments' => array('sections_admin_settings_form', 4), 'access arguments' => $access, 'file' => 'sections.admin.inc', 'type' => MENU_CALLBACK ); $items['admin/build/sections/delete/%section'] = array( 'title' => 'Delete section', 'page callback' => 'drupal_get_form', 'page arguments' => array('sections_delete_form', 4), 'access arguments' => $access, 'file' => 'sections.admin.inc', 'type' => MENU_CALLBACK ); return $items; } /** * Implementation of hook_form_alter(). */ function sections_form_alter(&$form, $form_state, $form_id) { // Add theme selection option to node forms. if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id && user_access('assign node theme')) { $node = $form['#node']; $form['sections'] = array( '#type' => 'fieldset', '#title' => t('Theme configuration'), '#collapsible' => TRUE, '#collapsed' => !$node->sections['theme'], '#tree' => TRUE, '#weight' => 30, '#description' => t('This setting allows you to create a section per node. A node section will get the highest weight and take precedence about all other inheriting sections.') ); $form['sections']['theme'] = array( '#type' => 'select', '#title' => t('Select theme'), '#default_value' => $node->sections['theme'], '#options' => _sections_theme_select(), '#description' => t('Select the theme you want to use for this node. Disabled themes are not used until they are enabled on themes page.', array('@url' => url('admin/build/themes'))) ); } // Disable core Administration theme. if ($form_id == 'system_admin_theme_settings') { // TODO: If other modules like theme_settings add form items, these items are not disabled. $form['admin_theme']['#disabled'] = TRUE; $form['node_admin_theme']['#disabled'] = TRUE; drupal_set_message(t('The configuration options have been disabled for compatibility reasons with the sections module. Configure the administration theme via sections.', array('@sections-admin' => url('admin/build/sections'))), 'warning', FALSE); } } /** * Implementation of hook_nodeapi(). * * Manages section information for nodes. */ function sections_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { switch ($op) { case 'delete': // Node has been deleted. Remove node theme reference. db_query('DELETE FROM {sections_nodes} WHERE nid = %d', $node->nid); break; case 'insert': // Save new node with configured theme setting. if (!empty($node->sections['theme'])) { db_query("INSERT INTO {sections_nodes} (nid, theme) VALUES (%d, '%s')", $node->nid, $node->sections['theme']); } break; case 'load': $node->sections['theme'] = db_result(db_query("SELECT theme FROM {sections_nodes} WHERE nid = %d", $node->nid)); break; case 'update': $theme = db_result(db_query("SELECT theme FROM {sections_nodes} WHERE nid = %d", $node->nid)); // Update existing node theme setting. if ($theme && !empty($node->sections['theme'])) { db_query("UPDATE {sections_nodes} SET theme = '%s' WHERE nid = %d", $node->sections['theme'], $node->nid); } // Insert new node theme setting, if node already exists. elseif (!empty($node->sections['theme'])) { db_query("INSERT INTO {sections_nodes} (nid, theme) VALUES (%d, '%s')", $node->nid, $node->sections['theme']); } // Node theme has been disabled. Remove from sections_nodes table. elseif ($theme && empty($node->sections['theme'])) { db_query('DELETE FROM {sections_nodes} WHERE nid = %d', $node->nid); } break; case 'view': // TODO: Only switch the theme if the node is viewed as page and not in teaser mode. // If node specific theme is configured, switch to node theme. if (!empty($node->sections['theme'])) { _sections_switch_theme($node->sections['theme']); } break; } } /** * Implementation of hook_theme() */ function sections_theme() { return array( 'sections_admin_display_form' => array( 'file' => 'sections.admin.inc', 'arguments' => array('form' => NULL), ), ); } /** * Implementation of hook_init(). */ function sections_init() { if ($section = _sections_in_section()) { _sections_switch_theme($section->theme); } } /** * Menu helper function to verify if section exists. */ function section_load($section) { return db_fetch_object(db_query("SELECT * FROM {sections_data} WHERE sid = %d", $section)); } /** * Loads the options for the themes select form element. */ function _sections_theme_select() { $options = array(); $options[0] = '<'. t('System default') .'>'; foreach (list_themes() as $key => $theme) { $options[$theme->name] = t('@name (@status)', array('@name' => $theme->name, '@status' => ($theme->status ? t('Enabled') : t('Disabled')))); } return $options; } /** * Change the current theme to a custom theme. * * @param $theme * The theme_key of the custom theme that should be used. */ function _sections_switch_theme($theme_key = NULL) { if (!empty($theme_key)) { // Only switch to custom theme if theme is active, to prohibit a destroyed site. foreach (list_themes() as $key => $theme) { if ($theme->status == 1 && $theme->name == $theme_key) { global $custom_theme; $custom_theme = $theme_key; init_theme(); } } } } /** * An API for modules that want to know about sections. * * This API is a function that lets you find out about settings. * * @param * Optional $setting a string containing the section you what to test against. * * @return * Depends on the parameter. * If you do not give $section, it will return the section object, if found. * If you give $section, it will return TRUE if you are in that section * Otherwise it will return FALSE */ function _sections_in_section($section = NULL) { global $user; if (is_string($section)) { // Caller wants to know if shes in the section she provided. if ($section == _sections_in_section()) { return TRUE; } } else { // Caller wants to know in which section she is. $rids = array_keys($user->roles); $res = db_query(db_rewrite_sql('SELECT DISTINCT s.* FROM {sections_data} s LEFT JOIN {sections_roles} r ON s.sid = r.sid WHERE s.status = 1 AND (r.rid IN ('. db_placeholders($rids) .') OR r.rid IS NULL) ORDER BY s.weight', 's', 'sid'), $rids); while ($row = db_fetch_object($res)) { if ($row->visibility < 2) { $path = drupal_get_path_alias($_GET['q']); // Compare with the internal and path alias (if any). $page_match = drupal_match_path($path, $row->path); if ($path != $_GET['q']) { $page_match = $page_match || drupal_match_path($_GET['q'], $row->path); } // When $row->visibility has a value of 0, the block is displayed on // all pages except those listed in $row->path. When set to 1, it // is displayed only on those pages listed in $row->path. if ($page_match = !($row->visibility xor $page_match)) { return $row; } } else { if (drupal_eval($row->path)) { return $row; } } } } // No section has been found, return FALSE. return FALSE; } /** * Implementation of hook_preprocess(). */ function sections_preprocess(&$variables, $hook) { // Are we in a section? if ($section = _sections_in_section()) { // Clean up the section names for template file names. $filter = '![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s'; $name_clean = preg_replace($filter, '-', drupal_strtolower($section->name)); // Add some section information to all preprocess hooks. $variables['section'] = array( 'sid' => $section->sid, 'theme' => $section->theme, 'name_clean' => $name_clean, ); switch ($hook) { case 'page': // Add template suggestions for page templates. $variables['template_files'][] = 'page-sections'; $variables['template_files'][] = 'page-sections-'. $section->sid; $variables['template_files'][] = 'page-sections-'. $name_clean; break; case 'node': // Add template suggestions for node templates. $variables['template_files'][] = 'node-sections'; $variables['template_files'][] = 'node-sections-'. $section->sid; $variables['template_files'][] = 'node-sections-'. $name_clean; break; case 'block': // Add template suggestions for block templates. $variables['template_files'][] = 'block-sections'; $variables['template_files'][] = 'block-sections-'. $section->sid; $variables['template_files'][] = 'block-sections-'. $name_clean; break; } } }