summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Sansbury2009-05-12 15:56:50 (GMT)
committerJames Sansbury2009-05-12 15:56:50 (GMT)
commit81be80a5785e49a92de56c769dbf773c7c31ee9f (patch)
treeba77523d86eb9342bee35f9b3b8fc1247e770346
Initial commit.6.x-1.0-alpha1
-rw-r--r--README.txt15
-rw-r--r--region-manager-manage-form.tpl.php61
-rw-r--r--region_manager.admin.inc238
-rw-r--r--region_manager.admin.js59
-rw-r--r--region_manager.css33
-rw-r--r--region_manager.info5
-rw-r--r--region_manager.install59
-rw-r--r--region_manager.js147
-rw-r--r--region_manager.module501
-rw-r--r--region_manager.pages.inc374
10 files changed, 1492 insertions, 0 deletions
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..2be07a0
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,15 @@
+$Id$
+
+********************************************************************************
+Region Manager provides a simple interface to manage blocks, and combined with
+the nodeblock module, add new blocks to regions. You can specify which regions
+for each theme can be managed. After clicking the link to configure a region,
+an interface is provided for managing which blocks are visible ON THE PAGE from
+which the link was clicked.
+
+The list of which blocks are available can be configured per theme, per region,
+per module, or even per block. For example, you can specify that menu module
+blocks are only available in the header, or that the navigation menu block is
+not available for any region.
+
+Recommended additional modules are nodeblock, and region_visibility. \ No newline at end of file
diff --git a/region-manager-manage-form.tpl.php b/region-manager-manage-form.tpl.php
new file mode 100644
index 0000000..ddbd1f7
--- /dev/null
+++ b/region-manager-manage-form.tpl.php
@@ -0,0 +1,61 @@
+<?php
+// $Id$
+
+/**
+ * @file block-admin-display-form.tpl.php
+ * Default theme implementation to configure blocks.
+ *
+ * Available variables:
+ * - $block_regions: An array of regions. Keyed by name with the title as value.
+ * - $block_listing: An array of blocks keyed by region and then delta.
+ * - $form_submit: Form submit button.
+ *
+ * Each $block_listing[$region] contains an array of blocks for that region.
+ *
+ * Each $data in $block_listing[$region] contains:
+ * - $data->region_title: Region title for the listed block.
+ * - $data->block_title: Block title.
+ * - $data->region_select: Drop-down menu for assigning a region.
+ * - $data->weight_select: Drop-down menu for setting weights.
+ * - $data->throttle_check: Checkbox to enable throttling.
+ * - $data->configure_link: Block configuration link.
+ * - $data->delete_link: For deleting user added blocks.
+ *
+ * @see template_preprocess_block_admin_display_form()
+ * @see theme_block_admin_display()
+ */
+?>
+<?php
+ // Add table javascript.
+ drupal_add_js('misc/tableheader.js');
+ drupal_add_js(drupal_get_path('module', 'region_manager') .'/region_manager.js');
+ drupal_add_js(array('block_name' => _region_manager_block_name()), 'setting');
+ foreach ($block_regions as $region => $title) {
+ drupal_add_tabledrag('blocks', 'match', 'sibling', 'block-region-select', 'block-region-'. $region, NULL, FALSE);
+ drupal_add_tabledrag('blocks', 'order', 'sibling', 'block-weight', 'block-weight-'. $region);
+ }
+?>
+<table id="blocks" class="sticky-enabled">
+ <tbody>
+ <?php $row = 0; ?>
+ <?php foreach ($block_regions as $region => $title): ?>
+ <tr class="region region-<?php print $region?>">
+ <td colspan="4" class="region"><?php print $title; ?></td>
+ </tr>
+ <tr class="region-message region-<?php print $region?>-message <?php print empty($block_listing[$region]) ? 'region-empty' : 'region-populated'; ?>">
+ <td colspan="4"><em><?php print t('No @blocks', array('@block' => _region_manager_block_name())); ?></em></td>
+ </tr>
+ <?php foreach ($block_listing[$region] as $delta => $data): ?>
+ <tr class="<?php print $row % 2 == 0 ? 'odd' : 'even'; ?><?php print $data->row_class ? ' '. $data->row_class : ''; ?>">
+ <td class="block"><?php print $data->block_title; ?></td>
+ <td><?php print $data->region_select; ?></td>
+ <td><?php print $data->weight_select; ?></td>
+ <td class="title-link"><?php print $data->title_link; ?></td>
+ </tr>
+ <?php $row++; ?>
+ <?php endforeach; ?>
+ <?php endforeach; ?>
+ </tbody>
+</table>
+
+<?php print $form_submit; ?>
diff --git a/region_manager.admin.inc b/region_manager.admin.inc
new file mode 100644
index 0000000..13f2ca0
--- /dev/null
+++ b/region_manager.admin.inc
@@ -0,0 +1,238 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Holds all administration forms for region_manager.
+ */
+
+/**
+ * Configuration settings form.
+ */
+function region_manager_settings_form() {
+ $form = array();
+
+ $form['region_manager_block_name'] = array(
+ '#type' => 'textfield',
+ '#title' => t('What should a "Block" be called?'),
+ '#description' => t('Please note: this only changes the name "Block" within the region manager UI, not throughout your Drupal site.'),
+ '#default_value' => variable_get('region_manager_block_name', 'Block'),
+ );
+
+ $form = system_settings_form($form);
+
+ // Uncomment and update the callback to override the default system settings submit handler.
+ // $form['#submit'] = array('_settings_form_submit');
+
+ return $form;
+}
+
+/**
+ * Region settings form.
+ */
+function region_manager_regions_form() {
+ $form = array();
+
+ drupal_clear_css_cache();
+ $themes = system_theme_data();
+ $settings = variable_get('region_manager_regions', array());
+
+ module_load_include('inc', 'system', 'system.admin');
+ uasort($themes, 'system_sort_modules_by_info_name');
+
+ $form['region_manager_regions']['#tree'] = TRUE;
+
+ foreach($themes as $theme) {
+ if ($theme->status) {
+ $form['region_manager_regions'][$theme->name] = array(
+ '#type' => 'fieldset',
+ '#title' => $theme->info['name'],
+ '#tree' => TRUE,
+ );
+
+ foreach (system_region_list($theme->name) as $region => $title) {
+ $form['region_manager_regions'][$theme->name][$region] = array(
+ '#type' => 'checkbox',
+ '#title' => $title,
+ '#default_value' => $settings[$theme->name][$region],
+ );
+ }
+ }
+ }
+
+ $form = system_settings_form($form);
+
+ // Uncomment and update the callback to override the default system settings submit handler.
+ // $form['submit'] = array('region_manager_regions_form_submit');
+
+ return $form;
+}
+
+/**
+ * Block settings form.
+ */
+function region_manager_blocks_form(&$form_state, $theme_key) {
+ $form = array();
+
+ $roles = user_roles();
+ $regions = region_manager_region_list($theme_key);
+ $records = region_manager_regions_load($theme_key);
+
+ if (empty($regions)) {
+ drupal_set_message(t('You must first enable some regions for this theme <a href="!href">here</a>.', array('!href' => 'admin/settings/region_manager')), 'error');
+ return array();
+ }
+
+ $form['#theme_key'] = $theme_key;
+ $form['blocked_blocks']['#tree'] = TRUE;
+
+ $form['regions']['#tree'] = TRUE;
+
+ foreach(array_keys($regions) as $region) {
+ // rid is the theme key and region delimited by a colon.
+ $rid = $theme_key .':'. $region;
+
+ // Now build each module form.
+ foreach(_region_manager_block_rehash($theme_key) as $module => $blocks) {
+
+ // Add the label for this module to the block_names column.
+ $form['regions']['block_names']['modules'][$module] = array(
+ '#type' => 'markup',
+ '#value' => t('all @module blocks', array('@module' => $module)),
+ );
+
+ // The select box for the module.
+ $form['regions'][$region]['modules'][$module] = array(
+ '#type' => 'select',
+ '#default_value' => isset($records[$rid]['modules'][$module]) ? $records[$rid]['modules'][$module] : REGION_MANAGER_ALL_ENABLED,
+ '#options' => array(
+ REGION_MANAGER_ALL_ENABLED => t('All enabled'),
+ REGION_MANAGER_ALL_DISABLED => t('All disabled'),
+ REGION_MANAGER_CUSTOM => t('Custom per block'),
+ ),
+ );
+
+ // Now, build the checkboxes for each blocks.
+ foreach($blocks as $delta => $block) {
+ // Add the label for this block to the block_names column.
+ $key = $module .':'. $delta;
+ $form['regions']['block_names']['blocked_blocks'][$module][$delta] = array(
+ '#type' => 'markup',
+ '#value' => $block['info'],
+ );
+
+ // The checkbox for the block.
+ $form['regions'][$region]['blocked_blocks'][$module][$delta] = array(
+ '#type' => 'checkbox',
+ '#default_value' => !in_array($key, (array) $records[$rid]['blocked_blocks']),
+ );
+
+ // Set tree to TRUE.
+ $form['regions'][$region]['blocked_blocks'][$module]['#tree'] = $form['regions'][$region]['blocked_blocks'][$module][$delta]['#tree'] = TRUE;
+ }
+ }
+ // Set tree to true for these arrays.
+ $form['regions'][$region]['#tree'] = $form['regions'][$region]['modules']['#tree'] = TRUE;
+ }
+
+ $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
+
+ return $form;
+}
+
+
+/**
+ * Submit handler for region_manager_blocks_form
+ */
+function region_manager_blocks_form_submit($form, &$form_state) {
+ $regions = $form_state['values']['regions'];
+ $theme_key = $form['#theme_key'];
+
+ foreach($regions as $region => $record) {
+ // Set the rid for this record.
+ $record['rid'] = $theme_key .':'. $region;
+
+ // Now go through the modules.
+ foreach($record['modules'] as $module => $module_val) {
+ foreach($record['blocked_blocks'][$module] as $delta => $block_val) {
+ // We were using the [module][delta] structure to ease in theming, but we
+ // need it to be set with just a module:delta key, so let's do that now.
+ $key = $module .':'. $delta;
+ $record['blocked_blocks'][$key] = $block_val;
+
+ // Now we switch through the $module_val to determine what needs to be done.
+ switch($module_val) {
+ case REGION_MANAGER_ALL_ENABLED:
+ // All are enabled, so unset all.
+ unset($record['blocked_blocks'][$key]);
+ break;
+
+ case REGION_MANAGER_CUSTOM:
+ // We don't want to save the checked blocks, only unchecked blocks.
+ if ($block_val) {
+ unset($record['blocked_blocks'][$key]);
+ }
+ break;
+
+ case REGION_MANAGER_ALL_DISABLED:
+ // Nothing to do here, since we want all of them.
+ break;
+ }
+ }
+ // Unset this module's array since we resaved using the module:delta format.
+ unset($record['blocked_blocks'][$module]);
+ }
+ // Flip the array, as all we need are the keys at this point.
+ $record['blocked_blocks'] = implode(', ', array_keys($record['blocked_blocks']));
+ region_manager_region_save($record);
+ }
+
+ drupal_set_message(t('The changes have been saved.'));
+}
+
+/**
+ * Theme the region_manager_blocks_form.
+ *
+ * @ingroup themeable
+ */
+function theme_region_manager_blocks_form($form) {
+ if (empty($form['blocked_blocks'])) {
+ return;
+ }
+
+ drupal_add_js(drupal_get_path('module', 'region_manager') .'/region_manager.admin.js');
+ $output = '';
+
+ $regions = region_manager_region_list($form['#theme_key']);
+
+ $header = array();
+ $header[] = (t('Block'));
+ foreach($regions as $region => $title) {
+ $header[] = $title;
+ }
+
+ foreach(element_children($form['regions']) as $region) {
+ foreach(element_children($form['regions'][$region]['modules']) as $module) {
+ $data = drupal_render($form['regions'][$region]['modules'][$module]);
+ $classes = 'region_manager_module-'. $module .' region_manager_region-'. $region;
+ $rows[$module]['data'][$region] = array('data' => $data, 'class' => $classes);
+ if (!isset($rows[$module]['class'])) {
+ $rows[$module]['class'] = $module .' module';
+ }
+ foreach(element_children($form['regions'][$region]['blocked_blocks'][$module]) as $delta) {
+ $key = $module .':'. $delta;
+ $data = drupal_render($form['regions'][$region]['blocked_blocks'][$module][$delta]);
+ $classes = 'region_manager_module-'. $module .' region_manager_region-'. $region;
+ $rows[$key]['data'][$region] = array('data' => $data, 'class' => $classes);
+ if (!isset($rows[$key]['class'])) {
+ $rows[$key]['class'] = $module .'-child block';
+ }
+ }
+ }
+ }
+
+ $output .= theme('table', $header, $rows, array('id' => 'regionmanager-regions'));
+ $output .= drupal_render($form);
+
+ return $output;
+} \ No newline at end of file
diff --git a/region_manager.admin.js b/region_manager.admin.js
new file mode 100644
index 0000000..22cf62f
--- /dev/null
+++ b/region_manager.admin.js
@@ -0,0 +1,59 @@
+// $Id$
+
+$(function() {
+ // Block administration page.
+ var selects = $('#region-manager-blocks-form tr.module select');
+ selects.change(function() {
+ var module = $(this).parents('tr').getClassNames().slice(0, 1);
+ showHideRows(module);
+
+ var classes = $(this).parents('td').getClassNames();
+ // build our selector from the classes
+ var selector = 'td.' + classes.join('.');
+ blockCheckboxes(this.value, selector);
+
+ });
+ selects.change();
+});
+
+showHideRows = function(module) {
+ var show = 0;
+ $('#region-manager-blocks-form tr.module.' + module + ' select').each(function(i) {
+ if (this.value == 2) {
+ show = 1;
+ }
+ });
+ if (show) {
+ $('#region-manager-blocks-form tr[class^=' + module + ']').not('tr.' + module).show();
+ }
+ else {
+ $('#region-manager-blocks-form tr[class^=' + module + ']').not('tr.' + module).hide();
+ }
+}
+
+blockCheckboxes = function(value, selector) {
+ switch(value) {
+ case '0':
+ $(selector + ' input').not('[id*=all-blocks]').attr('checked', 1);
+ $(selector + ' input').not('[id*=all-blocks]').attr('disabled', 1);
+ break;
+
+ case '1':
+ $(selector + ' input').not('[id*=all-blocks]').attr('checked', 0);
+ $(selector + ' input').not('[id*=all-blocks]').attr('disabled', 1);
+ break;
+
+ case '2':
+ $(selector + ' input').not('[id*=all-blocks]').attr('disabled', 0);
+ break;
+ }
+}
+
+$.fn.getClassNames = function() {
+ if (name = this.attr("class")) {
+ return name.split(" ");
+ }
+ else {
+ return [];
+ }
+} \ No newline at end of file
diff --git a/region_manager.css b/region_manager.css
new file mode 100644
index 0000000..5aef2fd
--- /dev/null
+++ b/region_manager.css
@@ -0,0 +1,33 @@
+/* $Id$ */
+
+#region-manager-blocks-form tr.module td {
+ border-top: 1.5em solid #fff;
+ border-bottom: 1px solid #b4d7f0;
+ background-color: #d4e7f3;
+ color: #455067;
+ font-weight: bold;
+}
+
+html.js #region-manager-manage-form select.block-region-select,
+html.js #region-manager-manage-form div.region-manager-block-title-wrapper,
+#region-manager-manage-form div.region-manager-block-title-wrapper div.form-radios,
+#region-manager-manage-form td.title-link a {
+ display: none;
+}
+
+html.js #region-manager-manage-form td.title-link a {
+ display: inline;
+}
+
+html.js #region-manager-manage-form div.region-manager-block-title-wrapper div.form-radios {
+ display: block;
+}
+
+#region-manager-manage-form td.title-link {
+ text-align: right;
+ vertical-align: top;
+}
+
+#region-manager-manage-form .draggable a.tabledrag-handle {
+ height: 100%;
+} \ No newline at end of file
diff --git a/region_manager.info b/region_manager.info
new file mode 100644
index 0000000..39f5ad4
--- /dev/null
+++ b/region_manager.info
@@ -0,0 +1,5 @@
+; $Id$
+name = Region Manager
+description = Implements 'add new' block controls to select regions.
+; dependencies[] =
+core = 6.x \ No newline at end of file
diff --git a/region_manager.install b/region_manager.install
new file mode 100644
index 0000000..ec4b862
--- /dev/null
+++ b/region_manager.install
@@ -0,0 +1,59 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Install file for database schema
+ */
+
+/**
+ * Implementation of hook_install().
+ */
+function region_manager_install() {
+ drupal_install_schema('region_manager');
+}
+
+/**
+ * Implementation of hook_schema().
+ */
+function region_manager_schema() {
+ $schema = array();
+
+ $schema['region_manager_regions'] = array(
+ 'description' => 'Describes {blocks} access per region.',
+ 'fields' => array(
+ 'rid' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '0',
+ 'description' => 'A region ID, defined by the theme key and region.',
+ ),
+ 'blocked_blocks' => array(
+ 'type' => 'text',
+ 'not null' => FALSE,
+ 'size' => 'big',
+ 'description' => "List of blocks that are disallowed for this region.",
+ ),
+ 'modules' => array(
+ 'type' => 'text',
+ 'size' => 'big',
+ 'description' => 'A serialized array of module settings for this region.',
+ 'serialize' => TRUE,
+ 'serialized default' => 'a:0:{}',
+ ),
+ ),
+ 'primary key' => array('rid'),
+ );
+
+ return $schema;
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function region_manager_uninstall() {
+ drupal_uninstall_schema('region_manager');
+ variable_del('region_manager_block_name');
+ variable_del('region_manager_regions');
+}
diff --git a/region_manager.js b/region_manager.js
new file mode 100644
index 0000000..c7b99e4
--- /dev/null
+++ b/region_manager.js
@@ -0,0 +1,147 @@
+// $Id$
+
+$(function() {
+ // Move the textfields next to the label for the Use custom title radio.
+ /*
+ $('td.block div.region-manager-block-title-wrapper input.form-text').each(function () {
+ var title = $(this).parent();
+ $('input.form-radio', title.prev().children()).each(function () {
+ if ($(this).val() == 1) {
+ $(this).parent().parent().append(title);
+ }
+ });
+ });
+ */
+
+ $('input.region-manager-manage-form-title-status').change(function() {
+ if (this.checked) {
+ var id = $(this).attr('id');
+ var textfield = $('input.form-text', $(this).parents('td.block'));
+ switch (this.value) {
+ case '0':
+ textfield.val('').hide('fast');
+ break;
+
+ case '1':
+ textfield.val('<none>').hide();
+ break;
+
+ case '2':
+ if (textfield.val() == '<none>') {
+ textfield.val('');
+ }
+ textfield.show('fast');
+ break;
+ }
+ }
+ });
+
+ // Simulate a change so we can disable the title field if need be.
+ $('input.region-manager-manage-form-title-status').change();
+
+ $('td.title-link a').click(function() {
+ var class = $(this).attr('class');
+ var wrapper = $('div.' + class);
+ if (wrapper.is(':hidden')) {
+ wrapper.show('fast');
+ }
+ else {
+ wrapper.hide('fast');
+ }
+ return false;
+ });
+});
+
+/**
+ * Move a block in the blocks table from one region to another via select list.
+ *
+ * This behavior is dependent on the tableDrag behavior, since it uses the
+ * objects initialized in that behavior to update the row.
+ */
+Drupal.behaviors.blockDrag = function(context) {
+ var table = $('table#blocks');
+ var tableDrag = Drupal.tableDrag.blocks; // Get the blocks tableDrag object.
+
+ // Add a handler for when a row is swapped, update empty regions.
+ tableDrag.row.prototype.onSwap = function(swappedRow) {
+ checkEmptyRegions(table, this);
+ };
+
+ // A custom message for the blocks page specifically.
+ Drupal.theme.tableDragChangedWarning = function () {
+ return '<div class="warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t("The changes to these @blocks will not be saved until the <em>@save</em> button is clicked.", { '@block' : Drupal.settings.block_name, '@save' : "Save " + Drupal.settings.block_name }) + '</div>';
+ };
+
+ // Add a handler so when a row is dropped, update fields dropped into new regions.
+ tableDrag.onDrop = function() {
+ dragObject = this;
+ if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
+ var regionRow = $(dragObject.rowObject.element).prev('tr').get(0);
+ var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+ var regionField = $('select.block-region-select', dragObject.rowObject.element);
+ var weightField = $('select.block-weight', dragObject.rowObject.element);
+ var oldRegionName = weightField[0].className.replace(/([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/, '$2');
+
+ if (!regionField.is('.block-region-'+ regionName)) {
+ regionField.removeClass('block-region-' + oldRegionName).addClass('block-region-' + regionName);
+ weightField.removeClass('block-weight-' + oldRegionName).addClass('block-weight-' + regionName);
+ regionField.val(regionName);
+ }
+ }
+ };
+
+ // Add the behavior to each region select list.
+ $('select.block-region-select:not(.blockregionselect-processed)', context).each(function() {
+ $(this).change(function(event) {
+ // Make our new row and select field.
+ var row = $(this).parents('tr:first');
+ var select = $(this);
+ tableDrag.rowObject = new tableDrag.row(row);
+
+ // Find the correct region and insert the row as the first in the region.
+ $('tr.region-message', table).each(function() {
+ if ($(this).is('.region-' + select[0].value + '-message')) {
+ // Add the new row and remove the old one.
+ $(this).after(row);
+ // Manually update weights and restripe.
+ tableDrag.updateFields(row.get(0));
+ tableDrag.rowObject.changed = true;
+ if (tableDrag.oldRowElement) {
+ $(tableDrag.oldRowElement).removeClass('drag-previous');
+ }
+ tableDrag.oldRowElement = row.get(0);
+ tableDrag.restripeTable();
+ tableDrag.rowObject.markChanged();
+ tableDrag.oldRowElement = row;
+ $(row).addClass('drag-previous');
+ }
+ });
+
+ // Modify empty regions with added or removed fields.
+ checkEmptyRegions(table, row);
+ // Remove focus from selectbox.
+ select.get(0).blur();
+ });
+ $(this).addClass('blockregionselect-processed');
+ });
+
+ var checkEmptyRegions = function(table, rowObject) {
+ $('tr.region-message', table).each(function() {
+ // If the dragged row is in this region, but above the message row, swap it down one space.
+ if ($(this).prev('tr').get(0) == rowObject.element) {
+ // Prevent a recursion problem when using the keyboard to move rows up.
+ if ((rowObject.method != 'keyboard' || rowObject.direction == 'down')) {
+ rowObject.swap('after', this);
+ }
+ }
+ // This region has become empty
+ if ($(this).next('tr').not('.locked').is(':not(.draggable)') || $(this).next('tr').size() == 0) {
+ $(this).removeClass('region-populated').addClass('region-empty');
+ }
+ // This region has become populated.
+ else if ($(this).is('.region-empty')) {
+ $(this).removeClass('region-empty').addClass('region-populated');
+ }
+ });
+ };
+}; \ No newline at end of file
diff --git a/region_manager.module b/region_manager.module
new file mode 100644
index 0000000..ac6de97
--- /dev/null
+++ b/region_manager.module
@@ -0,0 +1,501 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Adds add/remove block controls to select regions.
+ */
+
+/**
+ * Define constant module permission states.
+ */
+define('REGION_MANAGER_ALL_ENABLED', 0);
+define('REGION_MANAGER_ALL_DISABLED', 1);
+define('REGION_MANAGER_CUSTOM', 2);
+
+/**
+ * Implementation of hook_help().
+ */
+function region_manager_help($path, $arg) {
+ switch ($path) {
+ case 'admin/settings/region_manager':
+ return t('Please select for each theme which regions you would like to have region manager available on.');
+ }
+}
+
+/**
+ * Implementation of hook_init().
+ */
+function region_manager_init() {
+ if (user_access('manage regions')) {
+ global $theme_key;
+
+ init_theme();
+
+ // Add css and js.
+ $path = drupal_get_path('module', 'region_manager');
+ drupal_add_css($path .'/region_manager.css');
+
+ // Add the menus.
+ $regions = variable_get('region_manager_regions', array());
+ if (is_array($regions[$theme_key])) {
+ foreach($regions[$theme_key] as $region => $value) {
+ if ($value) {
+ $menu = theme('region_manager_region_menu', $theme_key, $region);
+ drupal_set_content($region, $menu);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function region_manager_menu() {
+ $items = array();
+
+ $items['admin/settings/region_manager'] = array(
+ 'title' => 'Region Manager regions',
+ 'description' => 'Configure region manager settings',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('region_manager_settings_form'),
+ 'access arguments' => array('administer region manager'),
+ 'file' => 'region_manager.admin.inc',
+ );
+ $items['admin/settings/region_manager/settings'] = array(
+ 'title' => 'Settings',
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ );
+
+ $items['admin/settings/region_manager/regions'] = array(
+ 'title' => 'Region Manager regions',
+ 'description' => 'Configure region manager settings',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('region_manager_regions_form'),
+ 'access arguments' => array('administer region manager'),
+ 'file' => 'region_manager.admin.inc',
+ 'type' => MENU_LOCAL_TASK,
+ );
+ $items['admin/settings/region_manager/regions/list'] = array(
+ 'title' => 'List',
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ );
+
+ foreach(list_themes() as $theme) {
+ if ($theme->status) {
+ $items['admin/settings/region_manager/regions/'. $theme->name] = array(
+ 'title' => $theme->info['name'],
+ 'description' => 'Configure region manager settings',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('region_manager_blocks_form', 4),
+ 'access arguments' => array('administer region manager'),
+ 'file' => 'region_manager.admin.inc',
+ 'type' => MENU_LOCAL_TASK,
+ );
+ }
+ }
+
+ $items['admin/build/region_manager/%/%'] = array(
+ 'title callback' => 'region_manager_region_title',
+ 'title arguments' => array(3, 4),
+ 'description' => 'Configure Region',
+ 'page callback' => 'region_manager_manage',
+ 'page arguments' => array(3, 4),
+ 'access arguments' => array('manage regions'),
+ 'file' => 'region_manager.pages.inc',
+ 'type' => MENU_CALLBACK,
+ );
+
+ return $items;
+}
+
+/**
+ * Title callback for a region manager.
+ */
+function region_manager_region_title($theme_key, $region) {
+ static $list = array();
+
+ if (!array_key_exists($theme_key, $list)) {
+ $info = unserialize(db_result(db_query("SELECT info FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key)));
+ $list[$theme_key] = array_map('t', $info['regions']);
+ }
+
+ return $list[$theme_key][$region];
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function region_manager_perm() {
+ return array('administer region manager', 'manage regions');
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function region_manager_theme() {
+ $items = array();
+
+ $items['region_manager_blocks_form'] = array(
+ 'arguments' => array('form' => array()),
+ );
+ $items['region_manager_region_menu'] = array(
+ 'arguments' => array('theme_key' => NULL, 'region' => NULL),
+ );
+ $items['region_manager_nodeblock_menu'] = array(
+ 'arguments' => array('links' => NULL),
+ );
+ $items['region_manager_manage_form'] = array(
+ 'template' => 'region-manager-manage-form',
+ 'file' => 'region_manager.pages.inc',
+ 'arguments' => array('form' => NULL),
+ );
+
+ return $items;
+}
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function region_manager_form_alter(&$form, $form_state, $form_id) {
+ if (function_exists('nodeblock_block') && $form['#id'] == 'node-form' && variable_get('nodeblock_'. $form['type']['#value'], 0) && !$form['nid']['#value']) {
+ if (($theme_key = arg(3)) && ($region = arg(4)) && ($path = $_REQUEST['destination'])) {
+ $frontpage = variable_get('site_frontpage', 'node');
+ $path = ($path == $frontpage) ? '<front>' : $path;
+
+ $form['region_manager'] = array(
+ '#tree' => TRUE,
+ );
+ $form['region_manager']['theme_key'] = array(
+ '#type' => 'hidden',
+ '#value' => $theme_key,
+ );
+ $form['region_manager']['region'] = array(
+ '#type' => 'hidden',
+ '#value' => $region,
+ );
+ $form['region_manager']['path'] = array(
+ '#type' => 'hidden',
+ '#value' => $path,
+ );
+ }
+ }
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ */
+function region_manager_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
+ if ($op == 'insert' && function_exists('nodeblock_block') && $node->region_manager) {
+ _block_rehash();
+ db_query("UPDATE {blocks} SET status = 1, region = '%s', visibility = 1, pages = '%s' WHERE module = 'nodeblock' AND delta = '%s' AND theme = '%s'", $node->region_manager['region'], $node->region_manager['path'], $node->nid, $node->region_manager['theme_key']);
+ }
+}
+
+/**
+ * Get a list of available regions from a specified theme.
+ *
+ * @param $theme_key
+ * The name of a theme.
+ * @return
+ * An array of regions in the form $region['name'] = 'description'.
+ */
+function region_manager_region_list($theme_key) {
+ $settings = variable_get('region_manager_regions', array());
+ $regions = system_region_list($theme_key);
+ if (!empty($settings)) {
+ return array_intersect_key($regions, (array) array_filter($settings[$theme_key]));
+ }
+}
+
+/**
+ * Theme function that builds the menu from a set of links.
+ *
+ * @param $theme_key
+ * A string containing the key for the active theme.
+ * @param $region
+ * A string containing the region to be managed.
+ *
+ * @return
+ * A string containing the link wrapped in a div.
+ *
+ * @ingroup themable
+ */
+function theme_region_manager_region_menu($theme_key, $region) {
+ $dest = $_REQUEST['destination'] ? array('destination' => $_REQUEST['destination']) : drupal_get_destination();
+
+ $link = l(t('Configure'), "admin/build/region_manager/$theme_key/$region", array('query' => $dest));
+
+ return "<div class='region-manager-menu'>$link</div>\n";
+}
+
+/**
+ * Loader function for regions by theme or rid.
+ *
+ * @param $theme_key
+ * A string containing either a theme key only, or theme key and region name
+ * delimited by ':'.
+ * @return
+ * A single record in array format, or FALSE if none matched the incoming ID.
+ */
+function region_manager_regions_load($rid) {
+ $regions = array();
+
+ $sql = "SELECT * FROM {region_manager_regions} WHERE rid LIKE '%s%%'";
+ $result = db_query($sql, $rid);
+ while ($region = db_fetch_array($result)) {
+ $region['modules'] = unserialize($region['modules']);
+ $region['blocked_blocks'] = explode(', ', $region['blocked_blocks']);
+ $regions[$region['rid']] = $region;
+ }
+
+ return $regions;
+}
+
+/**
+ * Public loader function for the full collection of records.
+ *
+ * In situations where the module's data rarely changes, or is being used
+ * frequently (for example, loaded and processed on every page load), this
+ * is a prime candidate for caching. See The Beginner's Guide to Caching at
+ * http://www.lullabot.com/articles/a_beginners_guide_to_caching_data for more
+ * details.
+ *
+ * This function assumes that results should be sorted by 'weight' -- if your
+ * module doesn't store a weight column on its records, or if you need to sort
+ * on some other property, this function's SQL should be updated as well.
+ *
+ * @return
+ * An array of all records, keyed by id.
+ */
+function region_manager_regions_load_all() {
+ $sql = 'SELECT * FROM {region_manager_blocks} ORDER BY theme ASC';
+ $result = db_query($sql);
+
+ $regions = array();
+ while ($region = db_fetch_array($result)) {
+ $region['modules'] = unserialize($region['modules']);
+ $regions[$region['rid']] = $region;
+ }
+ return $regions;
+}
+
+/**
+ * Inserts a new record, or updates an existing one.
+ *
+ * @param $region
+ * A record to be saved.
+ * @return
+ * The saved record.
+ */
+function region_manager_region_save($region) {
+ region_manager_region_delete($region['rid']);
+ drupal_write_record('region_manager_regions', $region);
+ return $region;
+}
+
+/**
+ * Deletes a record, given its unique ID.
+ *
+ * @param $rid
+ * A string containing the ID of a record.
+ */
+function region_manager_region_delete($rid) {
+ $sql = "DELETE FROM {region_manager_regions} WHERE rid = '%s'";
+ db_query($sql, $rid);
+}
+
+/**
+ * Loads all available blocks organized by region.
+ */
+function region_manager_blocks_load_all($theme_key, $region = NULL) {
+ static $all_blocks = NULL;
+ static $records = NULL;
+
+ $blocks = array();
+
+ // Load the blocks and regions if we haven't yet.
+ if (is_null($all_blocks)) {
+ $all_blocks = _region_manager_block_rehash($theme_key);
+ }
+ if (is_null($records)) {
+ // Load all regions for this theme, so we don't have to reload for each region.
+ $records = region_manager_regions_load($theme_key);
+ }
+
+ // Might as well quit if we don't have any blocks.
+ if (empty($all_blocks)) {
+ return;
+ }
+
+ if (is_null($region)) {
+ foreach(array_keys(region_manager_region_list($theme_key)) as $region) {
+ $rid = $theme_key .':'. $region;
+ $blocks[$region] = _region_manager_blocks_filter($region, $all_blocks, $records[$rid]);
+ }
+ }
+ else {
+ $rid = $theme_key .':'. $region;
+ $blocks = _region_manager_blocks_filter($region, $all_blocks, $records[$rid]);
+ }
+
+ return $blocks;
+}
+
+/**
+ * Helper function to filter all enabled and (available) disabled
+ * blocks for a particular region.
+ */
+function _region_manager_blocks_filter($region, $blocks = array(), $record = array()) {
+ $output = array();
+
+ foreach($blocks as $module => $modblocks) {
+ if (is_array($modblocks)) {
+
+ // If they're all disabled for this module, go on to the next module.
+ if ($record['modules'][$module] == REGION_MANAGER_ALL_DISABLED) {
+ continue;
+ }
+
+ // Otherwise, let's parse through each block.
+ else {
+ foreach($modblocks as $delta => $block) {
+ if ($block['status']) {
+ // Only add it to active if it's a part of this region.
+ if ($block['region'] == $region) {
+ $output[] = $block;
+ }
+ }
+ else {
+ // Check to see if we're using custom availability for this module.
+ if ($record['modules'][$module] == REGION_MANAGER_CUSTOM) {
+ $key = $module .':'. $delta;
+ // Is this block 'blocked'?
+ if (!in_array($key, $record['blocked_blocks'])) {
+ $output[] = $block;
+ }
+ }
+ // Otherwise add all blocks for this module.
+ else {
+ $output[] = $block;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return $output;
+}
+
+/**
+ * Helper function to assemble the blocks
+ */
+function _region_manager_block_rehash($theme_key) {
+ $blocks = array();
+
+ $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key);
+ $old_blocks = array();
+ while ($old_block = db_fetch_array($result)) {
+ $old_blocks[$old_block['module']][$old_block['delta']] = $old_block;
+ }
+
+ $blocks = array();
+ // Valid region names for the theme.
+ $regions = system_region_list($theme_key);
+
+ foreach (module_list() as $module) {
+ $module_blocks = module_invoke($module, 'block', 'list');
+ if ($module_blocks) {
+ foreach ($module_blocks as $delta => $block) {
+ if (empty($old_blocks[$module][$delta])) {
+ // If it's a new block, add identifiers.
+ $block['module'] = $module;
+ $block['delta'] = $delta;
+ $block['theme'] = $theme_key;
+ if (!isset($block['pages'])) {
+ // {block}.pages is type 'text', so it cannot have a
+ // default value, and not null, so we need to provide
+ // value if the module did not.
+ $block['pages'] = '';
+ }
+ // Add defaults and save it into the database.
+ drupal_write_record('blocks', $block);
+ // Set region to none if not enabled.
+ $block['region'] = $block['status'] ? $block['region'] : BLOCK_REGION_NONE;
+ // Add to the list of blocks we return.
+ $blocks[$module][$delta] = $block;
+ }
+ else {
+ // If it's an existing block, database settings should overwrite
+ // the code. But aside from 'info' everything that's definable in
+ // code is stored in the database and we do not store 'info', so we
+ // do not need to update the database here.
+ // Add 'info' to this block.
+ $old_blocks[$module][$delta]['info'] = $block['info'];
+ // If the region name does not exist, disable the block and assign it to none.
+ if (!empty($old_blocks[$module][$delta]['region']) && !isset($regions[$old_blocks[$module][$delta]['region']])) {
+ drupal_set_message(t('The @block %info was assigned to the invalid region %region and has been disabled.', array('@block' => _region_manager_block_name(), '%info' => $old_blocks[$module][$delta]['info'], '%region' => $old_blocks[$module][$delta]['region'])), 'warning');
+ $old_blocks[$module][$delta]['status'] = 0;
+ $old_blocks[$module][$delta]['region'] = BLOCK_REGION_NONE;
+ }
+ else {
+ $old_blocks[$module][$delta]['region'] = $old_blocks[$module][$delta]['status'] ? $old_blocks[$module][$delta]['region'] : BLOCK_REGION_NONE;
+ }
+ // Add this block to the list of blocks we return.
+ $blocks[$module][$delta] = $old_blocks[$module][$delta];
+ // Remove this block from the list of blocks to be deleted.
+ unset($old_blocks[$module][$delta]);
+ }
+ }
+ }
+ }
+
+ // Remove blocks that are no longer defined by the code from the database.
+ foreach ($old_blocks as $module => $old_module_blocks) {
+ foreach ($old_module_blocks as $delta => $block) {
+ db_query("DELETE FROM {blocks} WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $module, $delta, $theme_key);
+ }
+ }
+ return $blocks;
+}
+
+/**
+ * Helper function to determine if the block is visible for a certain path.
+ *
+ * @return
+ * Boolean FALSE if it's not visible, otherwise a string of the path.
+ */
+function _region_manager_block_check_visibility($block, $path = NULL) {
+ if ($block['visibility'] == 1) {
+ $path = is_null($path) ? drupal_get_path_alias($_GET['q']) : $path;
+ // Compare with the internal and path alias (if any).
+ $page_match = drupal_match_path($path, $block['pages']);
+ if ($path != $_GET['q']) {
+ $page_match = $page_match || drupal_match_path($_GET['q'], $block['pages']);
+ }
+ }
+ return $page_match ? $path : FALSE;
+}
+
+/**
+ * Helper function to display the custom block name.
+ *
+ * @param $name
+ * String designating upper or lower case.
+ */
+function _region_manager_block_name($case = 'lower') {
+ static $name;
+
+ if (empty($name)) {
+ $name = variable_get('region_manager_block_name', 'Block');
+ }
+
+ if ($case == 'lower') {
+ return strtolower($name);
+ }
+ return ucfirst($name);
+} \ No newline at end of file
diff --git a/region_manager.pages.inc b/region_manager.pages.inc
new file mode 100644
index 0000000..0587802
--- /dev/null
+++ b/region_manager.pages.inc
@@ -0,0 +1,374 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Page callbacks for managing regions.
+ */
+
+/**
+ * Menu callback to prepare the manage form for viewing.
+ *
+ * @param $theme_key
+ * A string containing the key of the active theme.
+ * @param $region
+ * A string containing the region to be managed.
+ *
+ * @return
+ * The HTML output of the page.
+ */
+function region_manager_manage($theme_key, $region) {
+ $output = '';
+
+ // Output the available content blocks to be added, if nodeblock is enabled.
+ if (function_exists('nodeblock_block')) {
+ $output .= theme('region_manager_nodeblock_menu', _region_manager_nodeblock_links($theme_key, $region));
+ }
+
+ // Fetch and sort blocks
+ $blocks = region_manager_blocks_load_all($theme_key, $region);
+
+ module_load_include('inc', 'block', 'block.admin');
+ usort($blocks, '_block_compare');
+
+ $output .= drupal_get_form('region_manager_manage_form', $blocks, $theme_key, $region);
+
+ return $output;
+}
+
+/**
+ * Generate main blocks administration form.
+ *
+ * @param $form_state
+ * A keyed array containing the current state of the form.
+ * @param $blocks
+ * An array of active and available blocks for this region.
+ * @param $theme_key
+ * A string containing the key of the active theme.
+ * @param $region
+ * A string containing the region to be managed.
+ *
+ * @return
+ * The form structure.
+ */
+function region_manager_manage_form(&$form_state, $blocks, $theme_key, $region) {
+ // Add CSS
+ drupal_add_css(drupal_get_path('module', 'block') .'/block.css', 'module', 'all', FALSE);
+
+ // Build form tree
+ $form = array(
+ // '#action' => arg(4) ? url('admin/build/block/list/'. $theme_key) : url('admin/build/block'),
+ '#tree' => TRUE,
+ );
+
+ $block_regions = array();
+
+ // If we're coming from a page, set that up as the top row label.
+ if ($path = $_REQUEST['destination']) {
+ $frontpage = variable_get('site_frontpage', 'node');
+ $alias = ($path == $frontpage) ? t('home page') : drupal_get_path_alias($path);
+
+ $block_regions['active_path'] = t('Active on %path', array('%path' => $alias));
+ }
+
+ // Now add the Active and Disabled row labels.
+ $block_regions[$region] = t('Active');
+ $block_regions[BLOCK_REGION_NONE] = t('Disabled');
+
+ $form['#block_regions'] = $block_regions;
+ $form['#region_manager'] = compact('theme_key', 'region', 'path');
+
+ // Weights range from -delta to +delta, so delta should be at least half
+ // of the amount of blocks present. This makes sure all blocks in the same
+ // region get an unique weight.
+ $weight_delta = round(count($blocks) / 2);
+
+ // Prepare the form for each block.
+ foreach ($blocks as $i => $block) {
+ $key = $block['module'] .'_'. $block['delta'];
+
+ $form[$key]['theme'] = array(
+ '#type' => 'hidden',
+ '#value' => $theme_key
+ );
+ $form[$key]['module'] = array(
+ '#type' => 'value',
+ '#value' => $block['module'],
+ );
+ $form[$key]['delta'] = array(
+ '#type' => 'value',
+ '#value' => $block['delta'],
+ );
+
+ // Block name.
+ $form[$key]['info'] = array(
+ '#value' => check_plain($block['info']),
+ );
+
+ // Set up the javascript link to display the title edit form.
+ $link_title = t('Edit/Configure @block Title', array('@block' => _region_manager_block_name('upper')));
+ $link_path = 'admin/build/block/configure/'. $block['module'] .'/'. $block['delta'];
+ $link_options = array(
+ 'attributes' => array('class' => 'region-manager-title-'. $key),
+ 'query' => drupal_get_destination()
+ );
+ $form[$key]['title_link'] = array(
+ '#type' => 'markup',
+ '#value' => l($link_title, $link_path, $link_options),
+ );
+
+ // Set up the radios for the title status.
+ $form[$key]['title_status'] = array(
+ '#attributes' => array('class' => 'region-manager-manage-form-title-status'),
+ '#type' => 'radios',
+ '#default_value' => _region_manager_block_title_status($block['title']),
+ '#options' => array(t('Use Default Title'), t('Disable Title'), t('Use Custom Title')),
+ );
+
+ $form[$key]['title'] = array(
+ '#attributes' => array('class' => 'region-manager-manage-form-title'),
+ '#type' => 'textfield',
+ '#size' => 40,
+ '#default_value' => $block['title'],
+ );
+ $form[$key]['weight'] = array(
+ '#type' => 'weight',
+ '#default_value' => $block['weight'],
+ '#delta' => $weight_delta,
+ );
+ $form[$key]['region'] = array(
+ '#type' => 'select',
+ '#default_value' => $block['region'],
+ '#options' => $block_regions,
+ );
+
+ $form[$key]['visibility'] = array(
+ '#type' => 'value',
+ '#value' => $block['visibility'],
+ );
+ $form[$key]['pages'] = array(
+ '#type' => 'value',
+ '#value' => $block['pages'],
+ );
+
+ // Now we customize this block depending on its status.
+ if (_region_manager_block_check_visibility($block, $path)) {
+ $form[$key]['region']['#default_value'] = 'active_path';
+ }
+ $form[$key]['#attributes']['class'] = 'draggable';
+
+ if ($block['visibility'] != 1) {
+ // We can't allow dragging of items if the block visibility isn't 1 and the block is active.
+ if ($block['status']) {
+ $form[$key]['#attributes']['class'] = 'locked';
+ $form[$key]['info']['#value'] .= ' '. t('(Locked)');
+ }
+ // Otherwise we flag this block as being disabled, to aid in processing the form after submission.
+ else {
+ $form[$key]['disabled'] = array('#type' => 'hidden', '#value' => TRUE);
+ }
+ }
+ }
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save @blocks', array('@block' => _region_manager_block_name())),
+ );
+
+ return $form;
+}
+
+/**
+ * Process main blocks administration form submission.
+ */
+function region_manager_manage_form_submit($form, &$form_state) {
+ $theme_key = $form['#region_manager']['theme_key'];
+ $region = $form['#region_manager']['region'];
+ $path = $form['#region_manager']['path'];
+
+ $frontpage = variable_get('site_frontpage', 'node');
+ $path = ($path == $frontpage) ? '<front>' : $path;
+
+ foreach ($form_state['values'] as $key => $block) {
+ // Set the block status.
+ $block['status'] = $block['region'] != BLOCK_REGION_NONE;
+ $block['title'] = trim($block['title']);
+
+ // Now let's go through our different scenarios for enabled blocks.
+ if ($block['status']) {
+ // If the block is enabled for this path, we have to set the region and
+ // add the path to $block['pages'].
+ if ($path && ($block['region'] == 'active_path')) {
+ // Set the region.
+ $block['region'] = $region;
+ // Add the path to pages, if it's not already there.
+ if (!preg_match('/^'. preg_quote($path, '/') .'$/im', $block['pages'])) {
+ $block['pages'] .= empty($block['pages']) ? $path : "\n". $path;
+ }
+ }
+ // Otherwise, if it's active, but not enabled for this path, make sure
+ // we remove the path from $block['pages']
+ elseif ($block['region'] == $region) {
+ // Remove path from the pages.
+ if (_region_manager_block_check_visibility($block, $path)) {
+ $block['pages'] = preg_replace('/^'. preg_quote($path, '/') .'$/im', '', $block['pages']);
+ }
+ }
+
+ // If the block was originally disabled, we need to set it up for our usage.
+ if ($block['disabled']) {
+ $block['visibility'] = 1;
+ $block['pages'] = $path;
+ }
+ }
+ // If the block is disabled, clean up region and pages.
+ else {
+ $block['region'] = '';
+ if ($block['visibility'] == 1) {
+ $block['pages'] = '';
+ }
+ }
+ db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', visibility = %d, pages = '%s', title = '%s' WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['title'], $block['module'], $block['delta'], $block['theme']);
+ }
+ drupal_set_message(t('The @block settings have been updated.', array('@block' => _region_manager_block_name())));
+ cache_clear_all();
+}
+
+/**
+ * Process variables for region-manager-manage-form.tpl.php.
+ *
+ * The $vars array contains the following arguments:
+ * - $form
+ *
+ * @see region-manager-manage-form.tpl.php
+ * @see theme_region_manager_manage_form()
+ */
+function template_preprocess_region_manager_manage_form(&$vars) {
+ global $theme_key;
+
+ $block_regions = $vars['form']['#block_regions'];
+ $vars['block_regions'] = $block_regions + array(BLOCK_REGION_NONE => t('Disabled'));
+
+ foreach ($block_regions as $key => $value) {
+ // Highlight regions on page to provide visual reference.
+ drupal_set_content($key, '<div class="block-region">'. $value .'</div>');
+ // Initialize an empty array for the region.
+ $vars['block_listing'][$key] = array();
+ }
+
+ // Initialize disabled blocks array.
+ $vars['block_listing'][BLOCK_REGION_NONE] = array();
+
+ // Set up to track previous region in loop.
+ $last_region = '';
+ foreach (element_children($vars['form']) as $i) {
+ $block = &$vars['form'][$i];
+
+ // Only take form elements that are blocks.
+ if (isset($block['info'])) {
+ // Fetch region for current block.
+ $region = $block['region']['#default_value'];
+
+ // Set special classes needed for table drag and drop.
+ $vars['form'][$i]['region']['#attributes']['class'] = 'block-region-select block-region-'. $region;
+ $vars['form'][$i]['weight']['#attributes']['class'] = 'block-weight block-weight-'. $region;
+
+ $vars['block_listing'][$region][$i]->row_class = isset($block['#attributes']['class']) ? $block['#attributes']['class'] : '';
+ $vars['block_listing'][$region][$i]->block_modified = isset($block['#attributes']['class']) && strpos($block['#attributes']['class'], 'block-modified') !== FALSE ? TRUE : FALSE;
+
+ $vars['block_listing'][$region][$i]->block_title = '<strong class="block-info">'. drupal_render($block['info']) .'</strong>';
+ $vars['block_listing'][$region][$i]->block_title .= '<div class="region-manager-block-title-wrapper region-manager-title-'. $i .'">';
+ $vars['block_listing'][$region][$i]->block_title .= drupal_render($block['title_status']) . drupal_render($block['title']);
+ $vars['block_listing'][$region][$i]->block_title .= '</div>';
+ $vars['block_listing'][$region][$i]->title_link = drupal_render($block['title_link']);
+
+ $vars['block_listing'][$region][$i]->region_select = drupal_render($block['region']) . drupal_render($block['theme']);
+ $vars['block_listing'][$region][$i]->weight_select = drupal_render($block['weight']);
+ $vars['block_listing'][$region][$i]->throttle_check = $vars['throttle'] ? drupal_render($block['throttle']) : '';
+ $vars['block_listing'][$region][$i]->configure_link = drupal_render($block['configure']);
+ $vars['block_listing'][$region][$i]->delete_link = !empty($block['delete']) ? drupal_render($block['delete']) : '';
+ $vars['block_listing'][$region][$i]->printed = FALSE;
+
+ $last_region = $region;
+ }
+ }
+
+ $vars['form_submit'] = drupal_render($vars['form']);
+}
+
+/**
+ * Theme function to output a list of nodeblock content types to add.
+ *
+ * @param $links
+ * An array containing the available content types to add.
+ *
+ * @return
+ * The HTML list of links.
+ */
+function theme_region_manager_nodeblock_menu($links) {
+ if (empty($links)) {
+ return;
+ }
+ $output = '<div class="region-manager-nodeblock-menu">';
+ $output .= '<h4>'. t('Add new:') .'</h4>';
+
+ $output .= theme('item_list', $links);
+ $output .= '</div>';
+
+ return $output;
+}
+
+/**
+ * Loads a list of links to add new nodeblock content types.
+ *
+ * @param $theme_key
+ * A string containing the key of the active theme.
+ * @param $region
+ * A string containing the region to be managed.
+ *
+ * @return
+ * An array containing the available content types to add.
+ */
+function _region_manager_nodeblock_links($theme_key, $region) {
+ $types = node_get_types();
+
+ foreach ($types as $type) {
+ if (nodeblock_type_enabled($type)) {
+ if (node_access('create', $type)) {
+ $options = array();
+ if ($path = $_REQUEST['destination']) {
+ $options['query'] = array('destination' => $path);
+ }
+ $type_url_str = str_replace('_', '-', $type->type);
+ $links[] = l(t('@type @block', array('@type' => $type->name, '@block' => _region_manager_block_name())), "node/add/$type_url_str/$theme_key/$region", $options);
+ }
+ }
+ }
+}
+
+/**
+ * Helper function to determine the status of a title.
+ *
+ * Title states:
+ * 0 = Using the default block title.
+ * 1 = The title is disabled.
+ * 2 = A custom title is being used.
+ *
+ * @param $title
+ * A string containing the current title.
+ *
+ * @return
+ * An integer containing the title state.
+ */
+function _region_manager_block_title_status($title) {
+ $title_status = 0; // Default title.
+
+ if ($title) {
+ $title_status++; // Disabled title.
+ if ($title != '<none>') {
+ $title_status++; // Custom title.
+ }
+ }
+
+ return $title_status;
+} \ No newline at end of file