summaryrefslogtreecommitdiff
path: root/kolab.org/www/drupal-7.26/modules/block
diff options
context:
space:
mode:
Diffstat (limited to 'kolab.org/www/drupal-7.26/modules/block')
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block-admin-display-form.tpl.php69
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.admin.inc700
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.api.php368
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.css36
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.info13
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.install477
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.js152
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.module1092
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.test979
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/block.tpl.php58
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/tests/block_test.info12
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/tests/block_test.module67
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/block_test_theme.info20
-rw-r--r--kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/page.tpl.php78
14 files changed, 4121 insertions, 0 deletions
diff --git a/kolab.org/www/drupal-7.26/modules/block/block-admin-display-form.tpl.php b/kolab.org/www/drupal-7.26/modules/block/block-admin-display-form.tpl.php
new file mode 100644
index 0000000..17a15e4
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block-admin-display-form.tpl.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * 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->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()
+ *
+ * @ingroup themeable
+ */
+?>
+<?php
+ // Add table javascript.
+ drupal_add_js('misc/tableheader.js');
+ drupal_add_js(drupal_get_path('module', 'block') . '/block.js');
+ 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">
+ <thead>
+ <tr>
+ <th><?php print t('Block'); ?></th>
+ <th><?php print t('Region'); ?></th>
+ <th><?php print t('Weight'); ?></th>
+ <th colspan="2"><?php print t('Operations'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php $row = 0; ?>
+ <?php foreach ($block_regions as $region => $title): ?>
+ <tr class="region-title region-title-<?php print $region?>">
+ <td colspan="5"><?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="5"><em><?php print t('No blocks in this region'); ?></em></td>
+ </tr>
+ <?php foreach ($block_listing[$region] as $delta => $data): ?>
+ <tr class="draggable <?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><?php print $data->configure_link; ?></td>
+ <td><?php print $data->delete_link; ?></td>
+ </tr>
+ <?php $row++; ?>
+ <?php endforeach; ?>
+ <?php endforeach; ?>
+ </tbody>
+</table>
+
+<?php print $form_submit; ?>
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.admin.inc b/kolab.org/www/drupal-7.26/modules/block/block.admin.inc
new file mode 100644
index 0000000..bd61790
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.admin.inc
@@ -0,0 +1,700 @@
+<?php
+
+/**
+ * @file
+ * Admin page callbacks for the block module.
+ */
+
+/**
+ * Menu callback for admin/structure/block/demo.
+ */
+function block_admin_demo($theme = NULL) {
+ drupal_add_css(drupal_get_path('module', 'block') . '/block.css');
+ return '';
+}
+
+/**
+ * Menu callback for admin/structure/block.
+ *
+ * @param $theme
+ * The theme to display the administration page for. If not provided, defaults
+ * to the currently used theme.
+ */
+function block_admin_display($theme = NULL) {
+ global $theme_key;
+
+ drupal_theme_initialize();
+
+ if (!isset($theme)) {
+ // If theme is not specifically set, rehash for the current theme.
+ $theme = $theme_key;
+ }
+
+ // Fetch and sort blocks.
+ $blocks = block_admin_display_prepare_blocks($theme);
+
+ return drupal_get_form('block_admin_display_form', $blocks, $theme);
+}
+
+/**
+ * Prepares a list of blocks for display on the blocks administration page.
+ *
+ * @param $theme
+ * The machine-readable name of the theme whose blocks should be returned.
+ *
+ * @return
+ * An array of blocks, as returned by _block_rehash(), sorted by region in
+ * preparation for display on the blocks administration page.
+ *
+ * @see block_admin_display_form()
+ */
+function block_admin_display_prepare_blocks($theme) {
+ $blocks = _block_rehash($theme);
+ $compare_theme = &drupal_static('_block_compare:theme');
+ $compare_theme = $theme;
+ usort($blocks, '_block_compare');
+ return $blocks;
+}
+
+/**
+ * Form constructor for the main block administration form.
+ *
+ * @param $blocks
+ * An array of blocks, as returned by block_admin_display_prepare_blocks().
+ * @param $theme
+ * A string representing the name of the theme to edit blocks for.
+ * @param $block_regions
+ * (optional) An array of regions in which the blocks will be allowed to be
+ * placed. Defaults to all visible regions for the theme whose blocks are
+ * being configured. In all cases, a dummy region for disabled blocks will
+ * also be displayed.
+ *
+ * @return
+ * An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see block_admin_display_form_submit()
+ */
+function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_regions = NULL) {
+
+ $form['#attached']['css'] = array(drupal_get_path('module', 'block') . '/block.css');
+
+ // Get a list of block regions if one was not provided.
+ if (!isset($block_regions)) {
+ $block_regions = system_region_list($theme, REGIONS_VISIBLE);
+ }
+
+ // 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);
+
+ // Build the form tree.
+ $form['edited_theme'] = array(
+ '#type' => 'value',
+ '#value' => $theme,
+ );
+ $form['block_regions'] = array(
+ '#type' => 'value',
+ // Add a last region for disabled blocks.
+ '#value' => $block_regions + array(BLOCK_REGION_NONE => BLOCK_REGION_NONE),
+ );
+ $form['blocks'] = array();
+ $form['#tree'] = TRUE;
+
+ foreach ($blocks as $i => $block) {
+ $key = $block['module'] . '_' . $block['delta'];
+ $form['blocks'][$key]['module'] = array(
+ '#type' => 'value',
+ '#value' => $block['module'],
+ );
+ $form['blocks'][$key]['delta'] = array(
+ '#type' => 'value',
+ '#value' => $block['delta'],
+ );
+ $form['blocks'][$key]['info'] = array(
+ '#markup' => check_plain($block['info']),
+ );
+ $form['blocks'][$key]['theme'] = array(
+ '#type' => 'hidden',
+ '#value' => $theme,
+ );
+ $form['blocks'][$key]['weight'] = array(
+ '#type' => 'weight',
+ '#default_value' => $block['weight'],
+ '#delta' => $weight_delta,
+ '#title_display' => 'invisible',
+ '#title' => t('Weight for @block block', array('@block' => $block['info'])),
+ );
+ $form['blocks'][$key]['region'] = array(
+ '#type' => 'select',
+ '#default_value' => $block['region'] != BLOCK_REGION_NONE ? $block['region'] : NULL,
+ '#empty_value' => BLOCK_REGION_NONE,
+ '#title_display' => 'invisible',
+ '#title' => t('Region for @block block', array('@block' => $block['info'])),
+ '#options' => $block_regions,
+ );
+ $form['blocks'][$key]['configure'] = array(
+ '#type' => 'link',
+ '#title' => t('configure'),
+ '#href' => 'admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure',
+ );
+ if ($block['module'] == 'block') {
+ $form['blocks'][$key]['delete'] = array(
+ '#type' => 'link',
+ '#title' => t('delete'),
+ '#href' => 'admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/delete',
+ );
+ }
+ }
+ // Do not allow disabling the main system content block when it is present.
+ if (isset($form['blocks']['system_main']['region'])) {
+ $form['blocks']['system_main']['region']['#required'] = TRUE;
+ }
+
+ $form['actions'] = array(
+ '#tree' => FALSE,
+ '#type' => 'actions',
+ );
+ $form['actions']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save blocks'),
+ );
+
+ return $form;
+}
+
+/**
+ * Form submission handler for block_admin_display_form().
+ *
+ * @see block_admin_display_form()
+ */
+function block_admin_display_form_submit($form, &$form_state) {
+ $transaction = db_transaction();
+ try {
+ foreach ($form_state['values']['blocks'] as $block) {
+ $block['status'] = (int) ($block['region'] != BLOCK_REGION_NONE);
+ $block['region'] = $block['status'] ? $block['region'] : '';
+ db_update('block')
+ ->fields(array(
+ 'status' => $block['status'],
+ 'weight' => $block['weight'],
+ 'region' => $block['region'],
+ ))
+ ->condition('module', $block['module'])
+ ->condition('delta', $block['delta'])
+ ->condition('theme', $block['theme'])
+ ->execute();
+ }
+ }
+ catch (Exception $e) {
+ $transaction->rollback();
+ watchdog_exception('block', $e);
+ throw $e;
+ }
+ drupal_set_message(t('The block settings have been updated.'));
+ cache_clear_all();
+}
+
+/**
+ * Sorts active blocks by region, then by weight; sorts inactive blocks by name.
+ *
+ * Callback for usort() in block_admin_display_prepare_blocks().
+ */
+function _block_compare($a, $b) {
+ global $theme_key;
+
+ // Theme should be set before calling this function, or the current theme
+ // is being used.
+ $theme = &drupal_static(__FUNCTION__ . ':theme');
+ if (!isset($theme)) {
+ $theme = $theme_key;
+ }
+
+ $regions = &drupal_static(__FUNCTION__ . ':regions');
+ // We need the region list to correctly order by region.
+ if (!isset($regions)) {
+ $regions = array_flip(array_keys(system_region_list($theme)));
+ $regions[BLOCK_REGION_NONE] = count($regions);
+ }
+
+ // Separate enabled from disabled.
+ $status = $b['status'] - $a['status'];
+ if ($status) {
+ return $status;
+ }
+ // Sort by region (in the order defined by theme .info file).
+ if ((!empty($a['region']) && !empty($b['region'])) && ($place = ($regions[$a['region']] - $regions[$b['region']]))) {
+ return $place;
+ }
+ // Sort by weight, unless disabled.
+ if ($a['region'] != BLOCK_REGION_NONE) {
+ $weight = $a['weight'] - $b['weight'];
+ if ($weight) {
+ return $weight;
+ }
+ }
+ // Sort by title.
+ return strcmp($a['info'], $b['info']);
+}
+
+/**
+ * Form constructor for the block configuration form.
+ *
+ * Also used by block_add_block_form() for adding a new custom block.
+ *
+ * @param $module
+ * Name of the module that implements the block to be configured.
+ * @param $delta
+ * Unique ID of the block within the context of $module.
+ *
+ * @see block_admin_configure_validate()
+ * @see block_admin_configure_submit()
+ * @ingroup forms
+ */
+function block_admin_configure($form, &$form_state, $module, $delta) {
+ $block = block_load($module, $delta);
+ $form['module'] = array(
+ '#type' => 'value',
+ '#value' => $block->module,
+ );
+ $form['delta'] = array(
+ '#type' => 'value',
+ '#value' => $block->delta,
+ );
+
+ // Get the block subject for the page title.
+ $info = module_invoke($block->module, 'block_info');
+ if (isset($info[$block->delta])) {
+ drupal_set_title(t("'%name' block", array('%name' => $info[$block->delta]['info'])), PASS_THROUGH);
+ }
+
+ $form['settings']['title'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Block title'),
+ '#maxlength' => 64,
+ '#description' => $block->module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <em>!placeholder</em> to display no title, or leave blank to use the default block title.', array('!placeholder' => '&lt;none&gt;')),
+ '#default_value' => isset($block->title) ? $block->title : '',
+ '#weight' => -19,
+ );
+
+ // Module-specific block configuration.
+ if ($settings = module_invoke($block->module, 'block_configure', $block->delta)) {
+ foreach ($settings as $k => $v) {
+ $form['settings'][$k] = $v;
+ }
+ }
+
+ // Region settings.
+ $form['regions'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Region settings'),
+ '#collapsible' => FALSE,
+ '#description' => t('Specify in which themes and regions this block is displayed.'),
+ '#tree' => TRUE,
+ );
+
+ $theme_default = variable_get('theme_default', 'bartik');
+ $admin_theme = variable_get('admin_theme');
+ foreach (list_themes() as $key => $theme) {
+ // Only display enabled themes
+ if ($theme->status) {
+ $region = db_query("SELECT region FROM {block} WHERE module = :module AND delta = :delta AND theme = :theme", array(
+ ':module' => $block->module,
+ ':delta' => $block->delta,
+ ':theme' => $key,
+ ))->fetchField();
+
+ // Use a meaningful title for the main site theme and administrative
+ // theme.
+ $theme_title = $theme->info['name'];
+ if ($key == $theme_default) {
+ $theme_title = t('!theme (default theme)', array('!theme' => $theme_title));
+ }
+ elseif ($admin_theme && $key == $admin_theme) {
+ $theme_title = t('!theme (administration theme)', array('!theme' => $theme_title));
+ }
+ $form['regions'][$key] = array(
+ '#type' => 'select',
+ '#title' => $theme_title,
+ '#default_value' => !empty($region) && $region != -1 ? $region : NULL,
+ '#empty_value' => BLOCK_REGION_NONE,
+ '#options' => system_region_list($key, REGIONS_VISIBLE),
+ '#weight' => ($key == $theme_default ? 9 : 10),
+ );
+ }
+ }
+
+ // Visibility settings.
+ $form['visibility_title'] = array(
+ '#type' => 'item',
+ '#title' => t('Visibility settings'),
+ );
+ $form['visibility'] = array(
+ '#type' => 'vertical_tabs',
+ '#attached' => array(
+ 'js' => array(drupal_get_path('module', 'block') . '/block.js'),
+ ),
+ );
+
+ // Per-path visibility.
+ $form['visibility']['path'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Pages'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ '#group' => 'visibility',
+ '#weight' => 0,
+ );
+
+ $access = user_access('use PHP for settings');
+ if (isset($block->visibility) && $block->visibility == BLOCK_VISIBILITY_PHP && !$access) {
+ $form['visibility']['path']['visibility'] = array(
+ '#type' => 'value',
+ '#value' => BLOCK_VISIBILITY_PHP,
+ );
+ $form['visibility']['path']['pages'] = array(
+ '#type' => 'value',
+ '#value' => isset($block->pages) ? $block->pages : '',
+ );
+ }
+ else {
+ $options = array(
+ BLOCK_VISIBILITY_NOTLISTED => t('All pages except those listed'),
+ BLOCK_VISIBILITY_LISTED => t('Only the listed pages'),
+ );
+ $description = t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%front' => '<front>'));
+
+ if (module_exists('php') && $access) {
+ $options += array(BLOCK_VISIBILITY_PHP => t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'));
+ $title = t('Pages or PHP code');
+ $description .= ' ' . t('If the PHP option is chosen, enter PHP code between %php. Note that executing incorrect PHP code can break your Drupal site.', array('%php' => '<?php ?>'));
+ }
+ else {
+ $title = t('Pages');
+ }
+ $form['visibility']['path']['visibility'] = array(
+ '#type' => 'radios',
+ '#title' => t('Show block on specific pages'),
+ '#options' => $options,
+ '#default_value' => isset($block->visibility) ? $block->visibility : BLOCK_VISIBILITY_NOTLISTED,
+ );
+ $form['visibility']['path']['pages'] = array(
+ '#type' => 'textarea',
+ '#title' => '<span class="element-invisible">' . $title . '</span>',
+ '#default_value' => isset($block->pages) ? $block->pages : '',
+ '#description' => $description,
+ );
+ }
+
+ // Per-role visibility.
+ $default_role_options = db_query("SELECT rid FROM {block_role} WHERE module = :module AND delta = :delta", array(
+ ':module' => $block->module,
+ ':delta' => $block->delta,
+ ))->fetchCol();
+ $role_options = array_map('check_plain', user_roles());
+ $form['visibility']['role'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Roles'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ '#group' => 'visibility',
+ '#weight' => 10,
+ );
+ $form['visibility']['role']['roles'] = array(
+ '#type' => 'checkboxes',
+ '#title' => t('Show block for specific roles'),
+ '#default_value' => $default_role_options,
+ '#options' => $role_options,
+ '#description' => t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'),
+ );
+
+ // Per-user visibility.
+ $form['visibility']['user'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Users'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ '#group' => 'visibility',
+ '#weight' => 20,
+ );
+ $form['visibility']['user']['custom'] = array(
+ '#type' => 'radios',
+ '#title' => t('Customizable per user'),
+ '#options' => array(
+ BLOCK_CUSTOM_FIXED => t('Not customizable'),
+ BLOCK_CUSTOM_ENABLED => t('Customizable, visible by default'),
+ BLOCK_CUSTOM_DISABLED => t('Customizable, hidden by default'),
+ ),
+ '#description' => t('Allow individual users to customize the visibility of this block in their account settings.'),
+ '#default_value' => isset($block->custom) ? $block->custom : BLOCK_CUSTOM_FIXED,
+ );
+
+ $form['actions'] = array('#type' => 'actions');
+ $form['actions']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save block'),
+ );
+
+ return $form;
+}
+
+/**
+ * Form validation handler for block_admin_configure().
+ *
+ * @see block_admin_configure()
+ * @see block_admin_configure_submit()
+ */
+function block_admin_configure_validate($form, &$form_state) {
+ if ($form_state['values']['module'] == 'block') {
+ $custom_block_exists = (bool) db_query_range('SELECT 1 FROM {block_custom} WHERE bid <> :bid AND info = :info', 0, 1, array(
+ ':bid' => $form_state['values']['delta'],
+ ':info' => $form_state['values']['info'],
+ ))->fetchField();
+ if (empty($form_state['values']['info']) || $custom_block_exists) {
+ form_set_error('info', t('Ensure that each block description is unique.'));
+ }
+ }
+}
+
+/**
+ * Form submission handler for block_admin_configure().
+ *
+ * @see block_admin_configure()
+ * @see block_admin_configure_validate()
+ */
+function block_admin_configure_submit($form, &$form_state) {
+ if (!form_get_errors()) {
+ $transaction = db_transaction();
+ try {
+ db_update('block')
+ ->fields(array(
+ 'visibility' => (int) $form_state['values']['visibility'],
+ 'pages' => trim($form_state['values']['pages']),
+ 'custom' => (int) $form_state['values']['custom'],
+ 'title' => $form_state['values']['title'],
+ ))
+ ->condition('module', $form_state['values']['module'])
+ ->condition('delta', $form_state['values']['delta'])
+ ->execute();
+
+ db_delete('block_role')
+ ->condition('module', $form_state['values']['module'])
+ ->condition('delta', $form_state['values']['delta'])
+ ->execute();
+ $query = db_insert('block_role')->fields(array('rid', 'module', 'delta'));
+ foreach (array_filter($form_state['values']['roles']) as $rid) {
+ $query->values(array(
+ 'rid' => $rid,
+ 'module' => $form_state['values']['module'],
+ 'delta' => $form_state['values']['delta'],
+ ));
+ }
+ $query->execute();
+
+ // Store regions per theme for this block
+ foreach ($form_state['values']['regions'] as $theme => $region) {
+ db_merge('block')
+ ->key(array('theme' => $theme, 'delta' => $form_state['values']['delta'], 'module' => $form_state['values']['module']))
+ ->fields(array(
+ 'region' => ($region == BLOCK_REGION_NONE ? '' : $region),
+ 'pages' => trim($form_state['values']['pages']),
+ 'status' => (int) ($region != BLOCK_REGION_NONE),
+ ))
+ ->execute();
+ }
+
+ module_invoke($form_state['values']['module'], 'block_save', $form_state['values']['delta'], $form_state['values']);
+ }
+ catch (Exception $e) {
+ $transaction->rollback();
+ watchdog_exception('block', $e);
+ throw $e;
+ }
+ drupal_set_message(t('The block configuration has been saved.'));
+ cache_clear_all();
+ $form_state['redirect'] = 'admin/structure/block';
+ }
+}
+
+/**
+ * Form constructor for the add block form.
+ *
+ * @see block_add_block_form_validate()
+ * @see block_add_block_form_submit()
+ * @ingroup forms
+ */
+function block_add_block_form($form, &$form_state) {
+ return block_admin_configure($form, $form_state, 'block', NULL);
+}
+
+/**
+ * Form validation handler for block_add_block_form().
+ *
+ * @see block_add_block_form()
+ * @see block_add_block_form_submit()
+ */
+function block_add_block_form_validate($form, &$form_state) {
+ $custom_block_exists = (bool) db_query_range('SELECT 1 FROM {block_custom} WHERE info = :info', 0, 1, array(':info' => $form_state['values']['info']))->fetchField();
+
+ if (empty($form_state['values']['info']) || $custom_block_exists) {
+ form_set_error('info', t('Ensure that each block description is unique.'));
+ }
+}
+
+/**
+ * Form submission handler for block_add_block_form().
+ *
+ * Saves the new custom block.
+ *
+ * @see block_add_block_form()
+ * @see block_add_block_form_validate()
+ */
+function block_add_block_form_submit($form, &$form_state) {
+ $delta = db_insert('block_custom')
+ ->fields(array(
+ 'body' => $form_state['values']['body']['value'],
+ 'info' => $form_state['values']['info'],
+ 'format' => $form_state['values']['body']['format'],
+ ))
+ ->execute();
+ // Store block delta to allow other modules to work with new block.
+ $form_state['values']['delta'] = $delta;
+
+ $query = db_insert('block')->fields(array('visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache'));
+ foreach (list_themes() as $key => $theme) {
+ if ($theme->status) {
+ $query->values(array(
+ 'visibility' => (int) $form_state['values']['visibility'],
+ 'pages' => trim($form_state['values']['pages']),
+ 'custom' => (int) $form_state['values']['custom'],
+ 'title' => $form_state['values']['title'],
+ 'module' => $form_state['values']['module'],
+ 'theme' => $theme->name,
+ 'status' => 0,
+ 'weight' => 0,
+ 'delta' => $delta,
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ }
+ $query->execute();
+
+ $query = db_insert('block_role')->fields(array('rid', 'module', 'delta'));
+ foreach (array_filter($form_state['values']['roles']) as $rid) {
+ $query->values(array(
+ 'rid' => $rid,
+ 'module' => $form_state['values']['module'],
+ 'delta' => $delta,
+ ));
+ }
+ $query->execute();
+
+ // Store regions per theme for this block
+ foreach ($form_state['values']['regions'] as $theme => $region) {
+ db_merge('block')
+ ->key(array('theme' => $theme, 'delta' => $delta, 'module' => $form_state['values']['module']))
+ ->fields(array(
+ 'region' => ($region == BLOCK_REGION_NONE ? '' : $region),
+ 'pages' => trim($form_state['values']['pages']),
+ 'status' => (int) ($region != BLOCK_REGION_NONE),
+ ))
+ ->execute();
+ }
+
+ drupal_set_message(t('The block has been created.'));
+ cache_clear_all();
+ $form_state['redirect'] = 'admin/structure/block';
+}
+
+/**
+ * Form constructor for the custom block deletion form.
+ *
+ * @param $module
+ * The name of the module that implements the block to be deleted. This should
+ * always equal 'block' since it only allows custom blocks to be deleted.
+ * @param $delta
+ * The unique ID of the block within the context of $module.
+ *
+ * @see block_custom_block_delete_submit()
+ */
+function block_custom_block_delete($form, &$form_state, $module, $delta) {
+ $block = block_load($module, $delta);
+ $custom_block = block_custom_block_get($block->delta);
+ $form['info'] = array('#type' => 'hidden', '#value' => $custom_block['info'] ? $custom_block['info'] : $custom_block['title']);
+ $form['bid'] = array('#type' => 'hidden', '#value' => $block->delta);
+
+ return confirm_form($form, t('Are you sure you want to delete the block %name?', array('%name' => $custom_block['info'])), 'admin/structure/block', '', t('Delete'), t('Cancel'));
+}
+
+/**
+ * Form submission handler for block_custom_block_delete().
+ *
+ * @see block_custom_block_delete()
+ */
+function block_custom_block_delete_submit($form, &$form_state) {
+ db_delete('block_custom')
+ ->condition('bid', $form_state['values']['bid'])
+ ->execute();
+ db_delete('block')
+ ->condition('module', 'block')
+ ->condition('delta', $form_state['values']['bid'])
+ ->execute();
+ db_delete('block_role')
+ ->condition('module', 'block')
+ ->condition('delta', $form_state['values']['bid'])
+ ->execute();
+ drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['info'])));
+ cache_clear_all();
+ $form_state['redirect'] = 'admin/structure/block';
+ return;
+}
+
+/**
+ * Processes variables for block-admin-display-form.tpl.php.
+ *
+ * The $variables array contains the following arguments:
+ * - $form
+ *
+ * @see block-admin-display.tpl.php
+ * @see theme_block_admin_display()
+ */
+function template_preprocess_block_admin_display_form(&$variables) {
+ $variables['block_regions'] = $variables['form']['block_regions']['#value'];
+ if (isset($variables['block_regions'][BLOCK_REGION_NONE])) {
+ $variables['block_regions'][BLOCK_REGION_NONE] = t('Disabled');
+ }
+
+ foreach ($variables['block_regions'] as $key => $value) {
+ // Initialize an empty array for the region.
+ $variables['block_listing'][$key] = array();
+ }
+
+ // Initialize disabled blocks array.
+ $variables['block_listing'][BLOCK_REGION_NONE] = array();
+
+ // Add each block in the form to the appropriate place in the block listing.
+ foreach (element_children($variables['form']['blocks']) as $i) {
+ $block = &$variables['form']['blocks'][$i];
+
+ // Fetch the region for the current block.
+ $region = (isset($block['region']['#default_value']) ? $block['region']['#default_value'] : BLOCK_REGION_NONE);
+
+ // Set special classes needed for table drag and drop.
+ $block['region']['#attributes']['class'] = array('block-region-select', 'block-region-' . $region);
+ $block['weight']['#attributes']['class'] = array('block-weight', 'block-weight-' . $region);
+
+ $variables['block_listing'][$region][$i] = new stdClass();
+ $variables['block_listing'][$region][$i]->row_class = !empty($block['#attributes']['class']) ? implode(' ', $block['#attributes']['class']) : '';
+ $variables['block_listing'][$region][$i]->block_modified = !empty($block['#attributes']['class']) && in_array('block-modified', $block['#attributes']['class']);
+ $variables['block_listing'][$region][$i]->block_title = drupal_render($block['info']);
+ $variables['block_listing'][$region][$i]->region_select = drupal_render($block['region']) . drupal_render($block['theme']);
+ $variables['block_listing'][$region][$i]->weight_select = drupal_render($block['weight']);
+ $variables['block_listing'][$region][$i]->configure_link = drupal_render($block['configure']);
+ $variables['block_listing'][$region][$i]->delete_link = !empty($block['delete']) ? drupal_render($block['delete']) : '';
+ $variables['block_listing'][$region][$i]->printed = FALSE;
+ }
+
+ $variables['form_submit'] = drupal_render_children($variables['form']);
+}
+
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.api.php b/kolab.org/www/drupal-7.26/modules/block/block.api.php
new file mode 100644
index 0000000..d8e129e
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.api.php
@@ -0,0 +1,368 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Block module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+/**
+ * Define all blocks provided by the module.
+ *
+ * This hook declares to Drupal what blocks are provided by your module and can
+ * optionally specify initial block configuration settings.
+ *
+ * In hook_block_info(), each block your module provides is given a unique
+ * identifier referred to as "delta" (the array key in the return value). Delta
+ * values only need to be unique within your module, and they are used in the
+ * following ways:
+ * - Passed into the other block hooks in your module as an argument to identify
+ * the block being configured or viewed.
+ * - Used to construct the default HTML ID of "block-MODULE-DELTA" applied to
+ * each block when it is rendered. This ID may then be used for CSS styling or
+ * JavaScript programming.
+ * - Used to define a theming template suggestion of block__MODULE__DELTA, for
+ * advanced theming possibilities.
+ * - Used by other modules to identify your block in hook_block_info_alter() and
+ * other alter hooks.
+ * The values of delta can be strings or numbers, but because of the uses above
+ * it is preferable to use descriptive strings whenever possible, and only use a
+ * numeric identifier if you have to (for instance if your module allows users
+ * to create several similar blocks that you identify within your module code
+ * with numeric IDs). The maximum length for delta values is 32 bytes.
+ *
+ * @return
+ * An associative array whose keys define the delta for each block and whose
+ * values contain the block descriptions. Each block description is itself an
+ * associative array, with the following key-value pairs:
+ * - info: (required) The human-readable administrative name of the block.
+ * This is used to identify the block on administration screens, and is not
+ * displayed to non-administrative users.
+ * - cache: (optional) A bitmask describing what kind of caching is
+ * appropriate for the block. Drupal provides the following bitmask
+ * constants for defining cache granularity:
+ * - DRUPAL_CACHE_PER_ROLE (default): The block can change depending on the
+ * roles the user viewing the page belongs to.
+ * - DRUPAL_CACHE_PER_USER: The block can change depending on the user
+ * viewing the page. This setting can be resource-consuming for sites with
+ * large number of users, and should only be used when
+ * DRUPAL_CACHE_PER_ROLE is not sufficient.
+ * - DRUPAL_CACHE_PER_PAGE: The block can change depending on the page being
+ * viewed.
+ * - DRUPAL_CACHE_GLOBAL: The block is the same for every user on every page
+ * where it is visible.
+ * - DRUPAL_CACHE_CUSTOM: The module implements its own caching system.
+ * - DRUPAL_NO_CACHE: The block should not get cached.
+ * - properties: (optional) Array of additional metadata to add to the block.
+ * Common properties include:
+ * - administrative: Boolean that categorizes this block as usable in an
+ * administrative context. This might include blocks that help an
+ * administrator approve/deny comments, or view recently created user
+ * accounts.
+ * - weight: (optional) Initial value for the ordering weight of this block.
+ * Most modules do not provide an initial value, and any value provided can
+ * be modified by a user on the block configuration screen.
+ * - status: (optional) Initial value for block enabled status. (1 = enabled,
+ * 0 = disabled). Most modules do not provide an initial value, and any
+ * value provided can be modified by a user on the block configuration
+ * screen.
+ * - region: (optional) Initial value for theme region within which this
+ * block is set. Most modules do not provide an initial value, and any value
+ * provided can be modified by a user on the block configuration screen.
+ * Note: If you set a region that isn't available in the currently enabled
+ * theme, the block will be disabled.
+ * - visibility: (optional) Initial value for the visibility flag, which tells
+ * how to interpret the 'pages' value. Possible values are:
+ * - BLOCK_VISIBILITY_NOTLISTED: Show on all pages except listed pages.
+ * 'pages' lists the paths where the block should not be shown.
+ * - BLOCK_VISIBILITY_LISTED: Show only on listed pages. 'pages' lists the
+ * paths where the block should be shown.
+ * - BLOCK_VISIBILITY_PHP: Use custom PHP code to determine visibility.
+ * 'pages' gives the PHP code to use.
+ * Most modules do not provide an initial value for 'visibility' or 'pages',
+ * and any value provided can be modified by a user on the block
+ * configuration screen.
+ * - pages: (optional) See 'visibility' above. A string that contains one or
+ * more page paths separated by '\n', '\r', or '\r\n' when 'visibility' is
+ * set to BLOCK_VISIBILITY_NOTLISTED or BLOCK_VISIBILITY_LISTED, or custom
+ * PHP code when 'visibility' is set to BLOCK_VISIBILITY_PHP. Paths may use
+ * '*' as a wildcard (matching any number of characters); '<front>'
+ * designates the site's front page. For BLOCK_VISIBILITY_PHP, the PHP
+ * code's return value should be TRUE if the block is to be made visible or
+ * FALSE if the block should not be visible.
+ *
+ * For a detailed usage example, see block_example.module.
+ *
+ * @see hook_block_configure()
+ * @see hook_block_save()
+ * @see hook_block_view()
+ * @see hook_block_info_alter()
+ */
+function hook_block_info() {
+ // This example comes from node.module.
+ $blocks['syndicate'] = array(
+ 'info' => t('Syndicate'),
+ 'cache' => DRUPAL_NO_CACHE
+ );
+
+ $blocks['recent'] = array(
+ 'info' => t('Recent content'),
+ // DRUPAL_CACHE_PER_ROLE will be assumed.
+ );
+
+ return $blocks;
+}
+
+/**
+ * Change block definition before saving to the database.
+ *
+ * @param $blocks
+ * A multidimensional array of blocks keyed by the defining module and delta;
+ * the values are blocks returned by hook_block_info(). This hook is fired
+ * after the blocks are collected from hook_block_info() and the database,
+ * right before saving back to the database.
+ * @param $theme
+ * The theme these blocks belong to.
+ * @param $code_blocks
+ * The blocks as defined in hook_block_info() before being overwritten by the
+ * database data.
+ *
+ * @see hook_block_info()
+ */
+function hook_block_info_alter(&$blocks, $theme, $code_blocks) {
+ // Disable the login block.
+ $blocks['user']['login']['status'] = 0;
+}
+
+/**
+ * Define a configuration form for a block.
+ *
+ * @param $delta
+ * Which block is being configured. This is a unique identifier for the block
+ * within the module, defined in hook_block_info().
+ *
+ * @return
+ * A configuration form, if one is needed for your block beyond the standard
+ * elements that the block module provides (block title, visibility, etc.).
+ *
+ * For a detailed usage example, see block_example.module.
+ *
+ * @see hook_block_info()
+ * @see hook_block_save()
+ */
+function hook_block_configure($delta = '') {
+ // This example comes from node.module.
+ $form = array();
+ if ($delta == 'recent') {
+ $form['node_recent_block_count'] = array(
+ '#type' => 'select',
+ '#title' => t('Number of recent content items to display'),
+ '#default_value' => variable_get('node_recent_block_count', 10),
+ '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
+ );
+ }
+ return $form;
+}
+
+/**
+ * Save the configuration options from hook_block_configure().
+ *
+ * This hook allows you to save the block-specific configuration settings
+ * defined within your hook_block_configure().
+ *
+ * @param $delta
+ * Which block is being configured. This is a unique identifier for the block
+ * within the module, defined in hook_block_info().
+ * @param $edit
+ * The submitted form data from the configuration form.
+ *
+ * For a detailed usage example, see block_example.module.
+ *
+ * @see hook_block_configure()
+ * @see hook_block_info()
+ */
+function hook_block_save($delta = '', $edit = array()) {
+ // This example comes from node.module.
+ if ($delta == 'recent') {
+ variable_set('node_recent_block_count', $edit['node_recent_block_count']);
+ }
+}
+
+/**
+ * Return a rendered or renderable view of a block.
+ *
+ * @param $delta
+ * Which block to render. This is a unique identifier for the block
+ * within the module, defined in hook_block_info().
+ *
+ * @return
+ * Either an empty array so the block will not be shown or an array containing
+ * the following elements:
+ * - subject: The default localized title of the block. If the block does not
+ * have a default title, this should be set to NULL.
+ * - content: The content of the block's body. This may be a renderable array
+ * (preferable) or a string containing rendered HTML content. If the content
+ * is empty the block will not be shown.
+ *
+ * For a detailed usage example, see block_example.module.
+ *
+ * @see hook_block_info()
+ * @see hook_block_view_alter()
+ * @see hook_block_view_MODULE_DELTA_alter()
+ */
+function hook_block_view($delta = '') {
+ // This example is adapted from node.module.
+ $block = array();
+
+ switch ($delta) {
+ case 'syndicate':
+ $block['subject'] = t('Syndicate');
+ $block['content'] = array(
+ '#theme' => 'feed_icon',
+ '#url' => 'rss.xml',
+ '#title' => t('Syndicate'),
+ );
+ break;
+
+ case 'recent':
+ if (user_access('access content')) {
+ $block['subject'] = t('Recent content');
+ if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
+ $block['content'] = array(
+ '#theme' => 'node_recent_block',
+ '#nodes' => $nodes,
+ );
+ } else {
+ $block['content'] = t('No content available.');
+ }
+ }
+ break;
+ }
+ return $block;
+}
+
+/**
+ * Perform alterations to the content of a block.
+ *
+ * This hook allows you to modify any data returned by hook_block_view().
+ *
+ * Note that instead of hook_block_view_alter(), which is called for all
+ * blocks, you can also use hook_block_view_MODULE_DELTA_alter() to alter a
+ * specific block.
+ *
+ * @param $data
+ * The data as returned from the hook_block_view() implementation of the
+ * module that defined the block. This could be an empty array or NULL value
+ * (if the block is empty) or an array containing:
+ * - subject: The default localized title of the block.
+ * - content: Either a string or a renderable array representing the content
+ * of the block. You should check that the content is an array before trying
+ * to modify parts of the renderable structure.
+ * @param $block
+ * The block object, as loaded from the database, having the main properties:
+ * - module: The name of the module that defined the block.
+ * - delta: The unique identifier for the block within that module, as defined
+ * in hook_block_info().
+ *
+ * @see hook_block_view_MODULE_DELTA_alter()
+ * @see hook_block_view()
+ */
+function hook_block_view_alter(&$data, $block) {
+ // Remove the contextual links on all blocks that provide them.
+ if (is_array($data['content']) && isset($data['content']['#contextual_links'])) {
+ unset($data['content']['#contextual_links']);
+ }
+ // Add a theme wrapper function defined by the current module to all blocks
+ // provided by the "somemodule" module.
+ if (is_array($data['content']) && $block->module == 'somemodule') {
+ $data['content']['#theme_wrappers'][] = 'mymodule_special_block';
+ }
+}
+
+/**
+ * Perform alterations to a specific block.
+ *
+ * Modules can implement hook_block_view_MODULE_DELTA_alter() to modify a
+ * specific block, rather than implementing hook_block_view_alter().
+ *
+ * @param $data
+ * The data as returned from the hook_block_view() implementation of the
+ * module that defined the block. This could be an empty array or NULL value
+ * (if the block is empty) or an array containing:
+ * - subject: The localized title of the block.
+ * - content: Either a string or a renderable array representing the content
+ * of the block. You should check that the content is an array before trying
+ * to modify parts of the renderable structure.
+ * @param $block
+ * The block object, as loaded from the database, having the main properties:
+ * - module: The name of the module that defined the block.
+ * - delta: The unique identifier for the block within that module, as defined
+ * in hook_block_info().
+ *
+ * @see hook_block_view_alter()
+ * @see hook_block_view()
+ */
+function hook_block_view_MODULE_DELTA_alter(&$data, $block) {
+ // This code will only run for a specific block. For example, if MODULE_DELTA
+ // in the function definition above is set to "mymodule_somedelta", the code
+ // will only run on the "somedelta" block provided by the "mymodule" module.
+
+ // Change the title of the "somedelta" block provided by the "mymodule"
+ // module.
+ $data['subject'] = t('New title of the block');
+}
+
+/**
+ * Act on blocks prior to rendering.
+ *
+ * This hook allows you to add, remove or modify blocks in the block list. The
+ * block list contains the block definitions, not the rendered blocks. The
+ * blocks are rendered after the modules have had a chance to manipulate the
+ * block list.
+ *
+ * You can also set $block->content here, which will override the content of the
+ * block and prevent hook_block_view() from running.
+ *
+ * @param $blocks
+ * An array of $blocks, keyed by the block ID.
+ */
+function hook_block_list_alter(&$blocks) {
+ global $language, $theme_key;
+
+ // This example shows how to achieve language specific visibility setting for
+ // blocks.
+
+ $result = db_query('SELECT module, delta, language FROM {my_table}');
+ $block_languages = array();
+ foreach ($result as $record) {
+ $block_languages[$record->module][$record->delta][$record->language] = TRUE;
+ }
+
+ foreach ($blocks as $key => $block) {
+ // Any module using this alter should inspect the data before changing it,
+ // to ensure it is what they expect.
+ if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {
+ // This block was added by a contrib module, leave it in the list.
+ continue;
+ }
+
+ if (!isset($block_languages[$block->module][$block->delta])) {
+ // No language setting for this block, leave it in the list.
+ continue;
+ }
+
+ if (!isset($block_languages[$block->module][$block->delta][$language->language])) {
+ // This block should not be displayed with the active language, remove
+ // from the list.
+ unset($blocks[$key]);
+ }
+ }
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.css b/kolab.org/www/drupal-7.26/modules/block/block.css
new file mode 100644
index 0000000..214c8a2
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.css
@@ -0,0 +1,36 @@
+
+#blocks tr.region-title td {
+ font-weight: bold;
+}
+#blocks tr.region-message {
+ font-weight: normal;
+ color: #999;
+}
+#blocks tr.region-populated {
+ display: none;
+}
+.block-region {
+ background-color: #ff6;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ padding: 3px;
+}
+a.block-demo-backlink,
+a.block-demo-backlink:link,
+a.block-demo-backlink:visited {
+ background-color: #B4D7F0;
+ -moz-border-radius: 0 0 10px 10px;
+ -webkit-border-radius: 0 0 10px 10px;
+ border-radius: 0 0 10px 10px;
+ color: #000;
+ font-family: "Lucida Grande", Verdana, sans-serif;
+ font-size: small;
+ line-height: 20px;
+ left: 20px; /*LTR*/
+ padding: 5px 10px;
+ position: fixed;
+ z-index: 499;
+}
+a.block-demo-backlink:hover {
+ text-decoration: underline;
+}
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.info b/kolab.org/www/drupal-7.26/modules/block/block.info
new file mode 100644
index 0000000..fd0fce0
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.info
@@ -0,0 +1,13 @@
+name = Block
+description = Controls the visual building blocks a page is constructed with. Blocks are boxes of content rendered into an area, or region, of a web page.
+package = Core
+version = VERSION
+core = 7.x
+files[] = block.test
+configure = admin/structure/block
+
+; Information added by Drupal.org packaging script on 2014-01-15
+version = "7.26"
+project = "drupal"
+datestamp = "1389815930"
+
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.install b/kolab.org/www/drupal-7.26/modules/block/block.install
new file mode 100644
index 0000000..a78c885
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.install
@@ -0,0 +1,477 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the block module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function block_schema() {
+ $schema['block'] = array(
+ 'description' => 'Stores block settings, such as region and visibility settings.',
+ 'fields' => array(
+ 'bid' => array(
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'description' => 'Primary Key: Unique block ID.',
+ ),
+ 'module' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => "The module from which the block originates; for example, 'user' for the Who's Online block, and 'block' for any custom blocks.",
+ ),
+ 'delta' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'default' => '0',
+ 'description' => 'Unique ID for block within a module.',
+ ),
+ 'theme' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The theme under which the block settings apply.',
+ ),
+ 'status' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'size' => 'tiny',
+ 'description' => 'Block enabled status. (1 = enabled, 0 = disabled)',
+ ),
+ 'weight' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'Block weight within region.',
+ ),
+ 'region' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Theme region within which the block is set.',
+ ),
+ 'custom' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'size' => 'tiny',
+ 'description' => 'Flag to indicate how users may control visibility of the block. (0 = Users cannot control, 1 = On by default, but can be hidden, 2 = Hidden by default, but can be shown)',
+ ),
+ 'visibility' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'size' => 'tiny',
+ 'description' => 'Flag to indicate how to show blocks on pages. (0 = Show on all pages except listed pages, 1 = Show only on listed pages, 2 = Use custom PHP code to determine visibility)',
+ ),
+ 'pages' => array(
+ 'type' => 'text',
+ 'not null' => TRUE,
+ 'description' => 'Contents of the "Pages" block; contains either a list of paths on which to include/exclude the block or PHP code, depending on "visibility" setting.',
+ ),
+ 'title' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Custom title for the block. (Empty string will use block default title, <none> will remove the title, text will cause block to use specified title.)',
+ 'translatable' => TRUE,
+ ),
+ 'cache' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 1,
+ 'size' => 'tiny',
+ 'description' => 'Binary flag to indicate block cache mode. (-2: Custom cache, -1: Do not cache, 1: Cache per role, 2: Cache per user, 4: Cache per page, 8: Block cache global) See DRUPAL_CACHE_* constants in ../includes/common.inc for more detailed information.',
+ ),
+ ),
+ 'primary key' => array('bid'),
+ 'unique keys' => array(
+ 'tmd' => array('theme', 'module', 'delta'),
+ ),
+ 'indexes' => array(
+ 'list' => array('theme', 'status', 'region', 'weight', 'module'),
+ ),
+ );
+
+ $schema['block_role'] = array(
+ 'description' => 'Sets up access permissions for blocks based on user roles',
+ 'fields' => array(
+ 'module' => array(
+ 'type' => 'varchar',
+ 'length' => 64,
+ 'not null' => TRUE,
+ 'description' => "The block's origin module, from {block}.module.",
+ ),
+ 'delta' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'description' => "The block's unique delta within module, from {block}.delta.",
+ ),
+ 'rid' => array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'description' => "The user's role ID from {users_roles}.rid.",
+ ),
+ ),
+ 'primary key' => array('module', 'delta', 'rid'),
+ 'indexes' => array(
+ 'rid' => array('rid'),
+ ),
+ );
+
+ $schema['block_custom'] = array(
+ 'description' => 'Stores contents of custom-made blocks.',
+ 'fields' => array(
+ 'bid' => array(
+ 'type' => 'serial',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'description' => "The block's {block}.bid.",
+ ),
+ 'body' => array(
+ 'type' => 'text',
+ 'not null' => FALSE,
+ 'size' => 'big',
+ 'description' => 'Block contents.',
+ 'translatable' => TRUE,
+ ),
+ 'info' => array(
+ 'type' => 'varchar',
+ 'length' => 128,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Block description.',
+ ),
+ 'format' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ 'description' => 'The {filter_format}.format of the block body.',
+ ),
+ ),
+ 'unique keys' => array(
+ 'info' => array('info'),
+ ),
+ 'primary key' => array('bid'),
+ );
+
+ $schema['cache_block'] = drupal_get_schema_unprocessed('system', 'cache');
+ $schema['cache_block']['description'] = 'Cache table for the Block module to store already built blocks, identified by module, delta, and various contexts which may change the block, such as theme, locale, and caching mode defined for the block.';
+
+ return $schema;
+}
+
+/**
+ * Implements hook_install().
+ */
+function block_install() {
+
+ // Block should go first so that other modules can alter its output
+ // during hook_page_alter(). Almost everything on the page is a block,
+ // so before block module runs, there will not be much to alter.
+ db_update('system')
+ ->fields(array('weight' => -5))
+ ->condition('name', 'block')
+ ->execute();
+}
+
+/**
+ * Implements hook_update_dependencies().
+ */
+function block_update_dependencies() {
+ // block_update_7005() needs to query the {filter_format} table to get a list
+ // of existing text formats, so it must run after filter_update_7000(), which
+ // creates that table.
+ $dependencies['block'][7005] = array(
+ 'filter' => 7000,
+ );
+
+ return $dependencies;
+}
+
+/**
+ * @addtogroup updates-6.x-to-7.x
+ * @{
+ */
+
+/**
+ * Set system.weight to a low value for block module.
+ *
+ * Block should go first so that other modules can alter its output
+ * during hook_page_alter(). Almost everything on the page is a block,
+ * so before block module runs, there will not be much to alter.
+ */
+function block_update_7000() {
+ db_update('system')
+ ->fields(array('weight' => '-5'))
+ ->condition('name', 'block')
+ ->execute();
+}
+
+/**
+ * Rename {blocks} table to {block}, {blocks_roles} to {block_role} and
+ * {boxes} to {block_custom}.
+ */
+function block_update_7002() {
+ db_drop_index('blocks', 'list');
+ db_rename_table('blocks', 'block');
+ db_rename_table('blocks_roles', 'block_role');
+ db_rename_table('boxes', 'block_custom');
+}
+
+/**
+ * Change the weight column to normal int.
+ */
+function block_update_7003() {
+ db_change_field('block', 'weight', 'weight', array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'Block weight within region.',
+ ), array(
+ 'indexes' => array(
+ 'list' => array('theme', 'status', 'region', 'weight', 'module'),
+ ),
+ ));
+}
+
+/**
+ * Add new blocks to new regions, migrate custom variables to blocks.
+ */
+function block_update_7004() {
+ // Collect a list of themes with blocks.
+ $themes_with_blocks = array();
+ $result = db_query("SELECT s.name FROM {system} s INNER JOIN {block} b ON s.name = b.theme WHERE s.type = 'theme' GROUP by s.name");
+
+ $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'));
+ foreach ($result as $theme) {
+ $themes_with_blocks[] = $theme->name;
+ // Add new system generated help block.
+ $insert->values(array(
+ 'module' => 'system',
+ 'delta' => 'help',
+ 'theme' => $theme->name,
+ 'status' => 1,
+ 'weight' => 0,
+ 'region' => 'help',
+ 'pages' => '',
+ 'cache' => DRUPAL_CACHE_PER_ROLE,
+ ));
+ // Add new system generated main page content block.
+ $insert->values(array(
+ 'module' => 'system',
+ 'delta' => 'main',
+ 'theme' => $theme->name,
+ 'status' => 1,
+ 'weight' => 0,
+ 'region' => 'content',
+ 'pages' => '',
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ $insert->execute();
+
+ // Migrate blocks from left/right regions to first/second regions.
+ db_update('block')
+ ->fields(array('region' => 'sidebar_first'))
+ ->condition('region', 'left')
+ ->execute();
+ db_update('block')
+ ->fields(array('region' => 'sidebar_second'))
+ ->condition('region', 'right')
+ ->execute();
+
+ // Migrate contact form information.
+ $default_format = variable_get('filter_default_format', 1);
+ if ($contact_help = variable_get('contact_form_information', '')) {
+ $bid = db_insert('block_custom')
+ ->fields(array(
+ 'body' => $contact_help,
+ 'info' => 'Contact page help',
+ 'format' => $default_format,
+ ))
+ ->execute();
+
+ $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache'));
+ foreach ($themes_with_blocks as $theme) {
+ // Add contact help block for themes, which had blocks.
+ $insert->values(array(
+ 'module' => 'block',
+ 'delta' => $bid,
+ 'theme' => $theme,
+ 'status' => 1,
+ 'weight' => 5,
+ 'region' => 'help',
+ 'visibility' => BLOCK_VISIBILITY_LISTED,
+ 'pages' => 'contact',
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ drupal_set_message('The contact form information setting was migrated to <a href="' . url('admin/structure/block/manage/block/' . $bid . '/configure') . '">a custom block</a> and set up to only show on the site-wide contact page. The block was set to use the default text format, which might differ from the HTML based format used before. Check the block and ensure that the output is right.');
+ }
+ $insert->execute();
+
+ // Migrate user help setting.
+ if ($user_help = variable_get('user_registration_help', '')) {
+ $bid = db_insert('block_custom')->fields(array('body' => $user_help, 'info' => 'User registration guidelines', 'format' => $default_format))->execute();
+
+ $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache'));
+ foreach ($themes_with_blocks as $theme) {
+ // Add user registration help block for themes, which had blocks.
+ $insert->values(array(
+ 'module' => 'block',
+ 'delta' => $bid,
+ 'theme' => $theme,
+ 'status' => 1,
+ 'weight' => 5,
+ 'region' => 'help',
+ 'visibility' => BLOCK_VISIBILITY_LISTED,
+ 'pages' => 'user/register',
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ drupal_set_message('The user registration guidelines were migrated to <a href="' . url('admin/structure/block/manage/block/' . $bid . '/configure') . '">a custom block</a> and set up to only show on the user registration page. The block was set to use the default text format, which might differ from the HTML based format used before. Check the block and ensure that the output is right.');
+ $insert->execute();
+ }
+
+ // Migrate site mission setting.
+ if ($mission = variable_get('site_mission')) {
+ $bid = db_insert('block_custom')->fields(array('body' => $mission, 'info' => 'Site mission', 'format' => $default_format))->execute();
+
+ $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'visibility', 'pages', 'cache'));
+ foreach ($themes_with_blocks as $theme) {
+ // Add mission block for themes, which had blocks.
+ $insert->values(array(
+ 'module' => 'block',
+ 'delta' => $bid,
+ 'theme' => $theme,
+ 'status' => 1,
+ 'weight' => 0,
+ 'region' => 'highlighted',
+ 'visibility' => BLOCK_VISIBILITY_LISTED,
+ 'pages' => '<front>',
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ drupal_set_message('The site mission was migrated to <a href="' . url('admin/structure/block/manage/block/' . $bid . '/configure') . '">a custom block</a> and set up to only show on the front page in the highlighted content region. The block was set to use the default text format, which might differ from the HTML based format used before. Check the block and ensure that the output is right. If your theme does not have a highlighted content region, you might need to <a href="' . url('admin/structure/block') . '">relocate the block</a>.');
+ $insert->execute();
+ // Migrate mission to RSS site description.
+ variable_set('feed_description', $mission);
+ }
+
+ // Migrate site footer message to a custom block.
+ if ($footer_message = variable_get('site_footer', '')) {
+ $bid = db_insert('block_custom')->fields(array('body' => $footer_message, 'info' => 'Footer message', 'format' => $default_format))->execute();
+
+ $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'));
+ foreach ($themes_with_blocks as $theme) {
+ // Add site footer block for themes, which had blocks.
+ // Set low weight, so the block comes early (it used to be
+ // before the other blocks).
+ $insert->values(array(
+ 'module' => 'block',
+ 'delta' => $bid,
+ 'theme' => $theme,
+ 'status' => 1,
+ 'weight' => -10,
+ 'region' => 'footer',
+ 'pages' => '',
+ 'cache' => DRUPAL_NO_CACHE,
+ ));
+ }
+ drupal_set_message('The footer message was migrated to <a href="' . url('admin/structure/block/manage/block/' . $bid . '/configure') . '">a custom block</a> and set up to appear in the footer. The block was set to use the default text format, which might differ from the HTML based format used before. Check the block and ensure that the output is right. If your theme does not have a footer region, you might need to <a href="' . url('admin/structure/block') . '">relocate the block</a>.');
+ $insert->execute();
+ }
+
+ // Remove the variables (even if they were saved empty on the admin interface),
+ // to avoid keeping clutter in the variables table.
+ variable_del('contact_form_information');
+ variable_del('user_registration_help');
+ variable_del('site_mission');
+ variable_del('site_footer');
+
+ // Rebuild theme data, so the new 'help' region is identified.
+ system_rebuild_theme_data();
+}
+
+/**
+ * Update the {block_custom}.format column.
+ */
+function block_update_7005() {
+ // For an explanation of these updates, see the code comments in
+ // user_update_7010().
+ db_change_field('block_custom', 'format', 'format', array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => FALSE,
+ 'description' => 'The {filter_format}.format of the block body.',
+ ));
+ db_update('block_custom')
+ ->fields(array('format' => NULL))
+ ->condition('body', '')
+ ->condition('format', 0)
+ ->execute();
+ $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
+ $default_format = variable_get('filter_default_format', 1);
+ db_update('block_custom')
+ ->fields(array('format' => $default_format))
+ ->isNotNull('format')
+ ->condition('format', $existing_formats, 'NOT IN')
+ ->execute();
+}
+
+/**
+ * Recreates cache_block table.
+ *
+ * Converts fields that hold serialized variables from text to blob.
+ * Removes 'headers' column.
+ */
+function block_update_7006() {
+ $schema = system_schema_cache_7054();
+
+ db_drop_table('cache_block');
+ db_create_table('cache_block', $schema);
+}
+
+/**
+ * Change {block_custom}.format into varchar.
+ */
+function block_update_7007() {
+ db_change_field('block_custom', 'format', 'format', array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ 'description' => 'The {filter_format}.format of the block body.',
+ ));
+}
+
+/**
+ * @} End of "addtogroup updates-6.x-to-7.x".
+ */
+
+/**
+ * @addtogroup updates-7.x-extra
+ * @{
+ */
+
+/**
+ * Update database to match Drupal 7 schema.
+ */
+function block_update_7008() {
+ db_drop_field('block', 'throttle');
+}
+
+/**
+ * @} End of "addtogroup updates-7.x-extra".
+ */
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.js b/kolab.org/www/drupal-7.26/modules/block/block.js
new file mode 100644
index 0000000..acd3f5a
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.js
@@ -0,0 +1,152 @@
+(function ($) {
+
+/**
+ * Provide the summary information for the block settings vertical tabs.
+ */
+Drupal.behaviors.blockSettingsSummary = {
+ attach: function (context) {
+ // The drupalSetSummary method required for this behavior is not available
+ // on the Blocks administration page, so we need to make sure this
+ // behavior is processed only if drupalSetSummary is defined.
+ if (typeof jQuery.fn.drupalSetSummary == 'undefined') {
+ return;
+ }
+
+ $('fieldset#edit-path', context).drupalSetSummary(function (context) {
+ if (!$('textarea[name="pages"]', context).val()) {
+ return Drupal.t('Not restricted');
+ }
+ else {
+ return Drupal.t('Restricted to certain pages');
+ }
+ });
+
+ $('fieldset#edit-node-type', context).drupalSetSummary(function (context) {
+ var vals = [];
+ $('input[type="checkbox"]:checked', context).each(function () {
+ vals.push($.trim($(this).next('label').text()));
+ });
+ if (!vals.length) {
+ vals.push(Drupal.t('Not restricted'));
+ }
+ return vals.join(', ');
+ });
+
+ $('fieldset#edit-role', context).drupalSetSummary(function (context) {
+ var vals = [];
+ $('input[type="checkbox"]:checked', context).each(function () {
+ vals.push($.trim($(this).next('label').text()));
+ });
+ if (!vals.length) {
+ vals.push(Drupal.t('Not restricted'));
+ }
+ return vals.join(', ');
+ });
+
+ $('fieldset#edit-user', context).drupalSetSummary(function (context) {
+ var $radio = $('input[name="custom"]:checked', context);
+ if ($radio.val() == 0) {
+ return Drupal.t('Not customizable');
+ }
+ else {
+ return $radio.next('label').text();
+ }
+ });
+ }
+};
+
+/**
+ * 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 = {
+ attach: function (context, settings) {
+ // tableDrag is required and we should be on the blocks admin page.
+ if (typeof Drupal.tableDrag == 'undefined' || typeof Drupal.tableDrag.blocks == 'undefined') {
+ return;
+ }
+
+ 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="messages warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('The changes to these blocks will not be saved until the <em>Save blocks</em> button is clicked.') + '</div>';
+ };
+
+ // Add a handler so when a row is dropped, update fields dropped into new regions.
+ tableDrag.onDrop = function () {
+ dragObject = this;
+ // Use "region-message" row instead of "region" row because
+ // "region-{region_name}-message" is less prone to regexp match errors.
+ var regionRow = $(dragObject.rowObject.element).prevAll('tr.region-message').get(0);
+ var regionName = regionRow.className.replace(/([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/, '$2');
+ var regionField = $('select.block-region-select', dragObject.rowObject.element);
+ // Check whether the newly picked region is available for this block.
+ if ($('option[value=' + regionName + ']', regionField).length == 0) {
+ // If not, alert the user and keep the block in its old region setting.
+ alert(Drupal.t('The block cannot be placed in this region.'));
+ // Simulate that there was a selected element change, so the row is put
+ // back to from where the user tried to drag it.
+ regionField.change();
+ }
+ else if ($(dragObject.rowObject.element).prev('tr').is('.region-message')) {
+ 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', context).once('block-region-select', function () {
+ $(this).change(function (event) {
+ // Make our new row and select field.
+ var row = $(this).closest('tr');
+ var select = $(this);
+ tableDrag.rowObject = new tableDrag.row(row);
+
+ // Find the correct region and insert the row as the last in the region.
+ table.find('.region-' + select[0].value + '-message').nextUntil('.region-message').last().before(row);
+
+ // Modify empty regions with added or removed fields.
+ checkEmptyRegions(table, row);
+ // Remove focus from selectbox.
+ select.get(0).blur();
+ });
+ });
+
+ 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').is(':not(.draggable)') || $(this).next('tr').length == 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');
+ }
+ });
+ };
+ }
+};
+
+})(jQuery);
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.module b/kolab.org/www/drupal-7.26/modules/block/block.module
new file mode 100644
index 0000000..2977ca8
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.module
@@ -0,0 +1,1092 @@
+<?php
+
+/**
+ * @file
+ * Controls the visual building blocks a page is constructed with.
+ */
+
+/**
+ * Denotes that a block is not enabled in any region and should not be shown.
+ */
+define('BLOCK_REGION_NONE', -1);
+
+/**
+ * Users cannot control whether or not they see this block.
+ */
+define('BLOCK_CUSTOM_FIXED', 0);
+
+/**
+ * Shows this block by default, but lets individual users hide it.
+ */
+define('BLOCK_CUSTOM_ENABLED', 1);
+
+/**
+ * Hides this block by default but lets individual users show it.
+ */
+define('BLOCK_CUSTOM_DISABLED', 2);
+
+/**
+ * Shows this block on every page except the listed pages.
+ */
+define('BLOCK_VISIBILITY_NOTLISTED', 0);
+
+/**
+ * Shows this block on only the listed pages.
+ */
+define('BLOCK_VISIBILITY_LISTED', 1);
+
+/**
+ * Shows this block if the associated PHP code returns TRUE.
+ */
+define('BLOCK_VISIBILITY_PHP', 2);
+
+/**
+ * Implements hook_help().
+ */
+function block_help($path, $arg) {
+ switch ($path) {
+ case 'admin/help#block':
+ $output = '';
+ $output .= '<h3>' . t('About') . '</h3>';
+ $output .= '<p>' . t('The Block module allows you to create boxes of content, which are rendered into an area, or region, of one or more pages of a website. The core Seven administration theme, for example, implements the regions "Content", "Help", "Dashboard main", and "Dashboard sidebar", and a block may appear in any one of these regions. The <a href="@blocks">Blocks administration page</a> provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. For more information, see the online handbook entry for <a href="@block">Block module</a>.', array('@block' => 'http://drupal.org/documentation/modules/block/', '@blocks' => url('admin/structure/block'))) . '</p>';
+ $output .= '<h3>' . t('Uses') . '</h3>';
+ $output .= '<dl>';
+ $output .= '<dt>' . t('Positioning content') . '</dt>';
+ $output .= '<dd>' . t('When working with blocks, remember that all themes do <em>not</em> implement the same regions, or display regions in the same way. Blocks are positioned on a per-theme basis. Users with the <em>Administer blocks</em> permission can disable blocks. Disabled blocks are listed on the <a href="@blocks">Blocks administration page</a>, but are not displayed in any region.', array('@block' => 'http://drupal.org/documentation/modules/block/', '@blocks' => url('admin/structure/block'))) . '</dd>';
+ $output .= '<dt>' . t('Controlling visibility') . '</dt>';
+ $output .= '<dd>' . t('Blocks can be configured to be visible only on certain pages, only to users of certain roles, or only on pages displaying certain <a href="@content-type">content types</a>. Administrators can also allow specific blocks to be enabled or disabled by users when they edit their <a href="@user">My account</a> page. Some dynamic blocks, such as those generated by modules, will be displayed only on certain pages.', array('@content-type' => url('admin/structure/types'), '@user' => url('user'))) . '</dd>';
+ $output .= '<dt>' . t('Creating custom blocks') . '</dt>';
+ $output .= '<dd>' . t('Users with the <em>Administer blocks</em> permission can <a href="@block-add">add custom blocks</a>, which are then listed on the <a href="@blocks">Blocks administration page</a>. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/add'))) . '</dd>';
+ $output .= '</dl>';
+ return $output;
+ case 'admin/structure/block/add':
+ return '<p>' . t('Use this page to create a new custom block.') . '</p>';
+ }
+ if ($arg[0] == 'admin' && $arg[1] == 'structure' && $arg['2'] == 'block' && (empty($arg[3]) || $arg[3] == 'list')) {
+ $demo_theme = !empty($arg[4]) ? $arg[4] : variable_get('theme_default', 'bartik');
+ $themes = list_themes();
+ $output = '<p>' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page. Click the <em>configure</em> link next to each block to configure its specific title and visibility settings.') . '</p>';
+ $output .= '<p>' . l(t('Demonstrate block regions (@theme)', array('@theme' => $themes[$demo_theme]->info['name'])), 'admin/structure/block/demo/' . $demo_theme) . '</p>';
+ return $output;
+ }
+}
+
+/**
+ * Implements hook_theme().
+ */
+function block_theme() {
+ return array(
+ 'block' => array(
+ 'render element' => 'elements',
+ 'template' => 'block',
+ ),
+ 'block_admin_display_form' => array(
+ 'template' => 'block-admin-display-form',
+ 'file' => 'block.admin.inc',
+ 'render element' => 'form',
+ ),
+ );
+}
+
+/**
+ * Implements hook_permission().
+ */
+function block_permission() {
+ return array(
+ 'administer blocks' => array(
+ 'title' => t('Administer blocks'),
+ ),
+ );
+}
+
+/**
+ * Implements hook_menu().
+ */
+function block_menu() {
+ $default_theme = variable_get('theme_default', 'bartik');
+ $items['admin/structure/block'] = array(
+ 'title' => 'Blocks',
+ 'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
+ 'page callback' => 'block_admin_display',
+ 'page arguments' => array($default_theme),
+ 'access arguments' => array('administer blocks'),
+ 'file' => 'block.admin.inc',
+ );
+ $items['admin/structure/block/manage/%/%'] = array(
+ 'title' => 'Configure block',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('block_admin_configure', 4, 5),
+ 'access arguments' => array('administer blocks'),
+ 'file' => 'block.admin.inc',
+ );
+ $items['admin/structure/block/manage/%/%/configure'] = array(
+ 'title' => 'Configure block',
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'context' => MENU_CONTEXT_INLINE,
+ );
+ $items['admin/structure/block/manage/%/%/delete'] = array(
+ 'title' => 'Delete block',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('block_custom_block_delete', 4, 5),
+ 'access arguments' => array('administer blocks'),
+ 'type' => MENU_LOCAL_TASK,
+ 'context' => MENU_CONTEXT_NONE,
+ 'file' => 'block.admin.inc',
+ );
+ $items['admin/structure/block/add'] = array(
+ 'title' => 'Add block',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('block_add_block_form'),
+ 'access arguments' => array('administer blocks'),
+ 'type' => MENU_LOCAL_ACTION,
+ 'file' => 'block.admin.inc',
+ );
+ foreach (list_themes() as $key => $theme) {
+ $items['admin/structure/block/list/' . $key] = array(
+ 'title' => check_plain($theme->info['name']),
+ 'page arguments' => array($key),
+ 'type' => $key == $default_theme ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
+ 'weight' => $key == $default_theme ? -10 : 0,
+ 'access callback' => '_block_themes_access',
+ 'access arguments' => array($theme),
+ 'file' => 'block.admin.inc',
+ );
+ if ($key != $default_theme) {
+ $items['admin/structure/block/list/' . $key . '/add'] = array(
+ 'title' => 'Add block',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('block_add_block_form'),
+ 'access arguments' => array('administer blocks'),
+ 'type' => MENU_LOCAL_ACTION,
+ 'file' => 'block.admin.inc',
+ );
+ }
+ $items['admin/structure/block/demo/' . $key] = array(
+ 'title' => check_plain($theme->info['name']),
+ 'page callback' => 'block_admin_demo',
+ 'page arguments' => array($key),
+ 'type' => MENU_CALLBACK,
+ 'access callback' => '_block_themes_access',
+ 'access arguments' => array($theme),
+ 'theme callback' => '_block_custom_theme',
+ 'theme arguments' => array($key),
+ 'file' => 'block.admin.inc',
+ );
+ }
+ return $items;
+}
+
+/**
+ * Menu item access callback - only admin or enabled themes can be accessed.
+ */
+function _block_themes_access($theme) {
+ return user_access('administer blocks') && drupal_theme_access($theme);
+}
+
+/**
+ * Theme callback for the block configuration pages.
+ *
+ * @param $theme
+ * The theme whose blocks are being configured. If not set, the default theme
+ * is assumed.
+ * @return
+ * The theme that should be used for the block configuration page, or NULL
+ * to indicate that the default theme should be used.
+ */
+function _block_custom_theme($theme = NULL) {
+ // We return exactly what was passed in, to guarantee that the page will
+ // always be displayed using the theme whose blocks are being configured.
+ return $theme;
+}
+
+/**
+ * Implements hook_block_info().
+ */
+function block_block_info() {
+ $blocks = array();
+
+ $result = db_query('SELECT bid, info FROM {block_custom} ORDER BY info');
+ foreach ($result as $block) {
+ $blocks[$block->bid]['info'] = $block->info;
+ // Not worth caching.
+ $blocks[$block->bid]['cache'] = DRUPAL_NO_CACHE;
+ }
+ return $blocks;
+}
+
+/**
+ * Implements hook_block_configure().
+ */
+function block_block_configure($delta = 0) {
+ if ($delta) {
+ $custom_block = block_custom_block_get($delta);
+ }
+ else {
+ $custom_block = array();
+ }
+ return block_custom_block_form($custom_block);
+}
+
+/**
+ * Implements hook_block_save().
+ */
+function block_block_save($delta = 0, $edit = array()) {
+ block_custom_block_save($edit, $delta);
+}
+
+/**
+ * Implements hook_block_view().
+ *
+ * Generates the administrator-defined blocks for display.
+ */
+function block_block_view($delta = '') {
+ $block = db_query('SELECT body, format FROM {block_custom} WHERE bid = :bid', array(':bid' => $delta))->fetchObject();
+ $data['subject'] = NULL;
+ $data['content'] = check_markup($block->body, $block->format, '', TRUE);
+ return $data;
+}
+
+/**
+ * Implements hook_page_build().
+ *
+ * Renders blocks into their regions.
+ */
+function block_page_build(&$page) {
+ global $theme;
+
+ // The theme system might not yet be initialized. We need $theme.
+ drupal_theme_initialize();
+
+ // Fetch a list of regions for the current theme.
+ $all_regions = system_region_list($theme);
+
+ $item = menu_get_item();
+ if ($item['path'] != 'admin/structure/block/demo/' . $theme) {
+ // Load all region content assigned via blocks.
+ foreach (array_keys($all_regions) as $region) {
+ // Assign blocks to region.
+ if ($blocks = block_get_blocks_by_region($region)) {
+ $page[$region] = $blocks;
+ }
+ }
+ // Once we've finished attaching all blocks to the page, clear the static
+ // cache to allow modules to alter the block list differently in different
+ // contexts. For example, any code that triggers hook_page_build() more
+ // than once in the same page request may need to alter the block list
+ // differently each time, so that only certain parts of the page are
+ // actually built. We do not clear the cache any earlier than this, though,
+ // because it is used each time block_get_blocks_by_region() gets called
+ // above.
+ drupal_static_reset('block_list');
+ }
+ else {
+ // Append region description if we are rendering the regions demo page.
+ $item = menu_get_item();
+ if ($item['path'] == 'admin/structure/block/demo/' . $theme) {
+ $visible_regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
+ foreach ($visible_regions as $region) {
+ $description = '<div class="block-region">' . $all_regions[$region] . '</div>';
+ $page[$region]['block_description'] = array(
+ '#markup' => $description,
+ '#weight' => 15,
+ );
+ }
+ $page['page_top']['backlink'] = array(
+ '#type' => 'link',
+ '#title' => t('Exit block region demonstration'),
+ '#href' => 'admin/structure/block' . (variable_get('theme_default', 'bartik') == $theme ? '' : '/list/' . $theme),
+ // Add the "overlay-restore" class to indicate this link should restore
+ // the context in which the region demonstration page was opened.
+ '#options' => array('attributes' => array('class' => array('block-demo-backlink', 'overlay-restore'))),
+ '#weight' => -10,
+ );
+ }
+ }
+}
+
+/**
+ * Gets a renderable array of a region containing all enabled blocks.
+ *
+ * @param $region
+ * The requested region.
+ *
+ * @return
+ * A renderable array of a region containing all enabled blocks.
+ */
+function block_get_blocks_by_region($region) {
+ $build = array();
+ if ($list = block_list($region)) {
+ $build = _block_get_renderable_array($list);
+ }
+ return $build;
+}
+
+/**
+ * Gets an array of blocks suitable for drupal_render().
+ *
+ * @param $list
+ * A list of blocks such as that returned by block_list().
+ *
+ * @return
+ * A renderable array.
+ */
+function _block_get_renderable_array($list = array()) {
+ $weight = 0;
+ $build = array();
+ foreach ($list as $key => $block) {
+ $build[$key] = $block->content;
+ unset($block->content);
+
+ // Add contextual links for this block; skip the main content block, since
+ // contextual links are basically output as tabs/local tasks already. Also
+ // skip the help block, since we assume that most users do not need or want
+ // to perform contextual actions on the help block, and the links needlessly
+ // draw attention on it.
+ if ($key != 'system_main' && $key != 'system_help') {
+ $build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($block->module, $block->delta));
+ }
+
+ $build[$key] += array(
+ '#block' => $block,
+ '#weight' => ++$weight,
+ );
+ $build[$key]['#theme_wrappers'][] ='block';
+ }
+ $build['#sorted'] = TRUE;
+ return $build;
+}
+
+/**
+ * Updates the 'block' DB table with the blocks currently exported by modules.
+ *
+ * @param $theme
+ * The theme to rehash blocks for. If not provided, defaults to the currently
+ * used theme.
+ *
+ * @return
+ * Blocks currently exported by modules.
+ */
+function _block_rehash($theme = NULL) {
+ global $theme_key;
+
+ drupal_theme_initialize();
+ if (!isset($theme)) {
+ // If theme is not specifically set, rehash for the current theme.
+ $theme = $theme_key;
+ }
+ $regions = system_region_list($theme);
+
+ // These are the blocks the function will return.
+ $blocks = array();
+ // These are the blocks defined by code and modified by the database.
+ $current_blocks = array();
+ // These are {block}.bid values to be kept.
+ $bids = array();
+ $or = db_or();
+ // Gather the blocks defined by modules.
+ foreach (module_implements('block_info') as $module) {
+ $module_blocks = module_invoke($module, 'block_info');
+ foreach ($module_blocks as $delta => $block) {
+ // Compile a condition to retrieve this block from the database.
+ $condition = db_and()
+ ->condition('module', $module)
+ ->condition('delta', $delta);
+ $or->condition($condition);
+ // Add identifiers.
+ $block['module'] = $module;
+ $block['delta'] = $delta;
+ $block['theme'] = $theme;
+ $current_blocks[$module][$delta] = $block;
+ }
+ }
+ // Save the blocks defined in code for alter context.
+ $code_blocks = $current_blocks;
+ $database_blocks = db_select('block', 'b', array('fetch' => PDO::FETCH_ASSOC))
+ ->fields('b')
+ ->condition($or)
+ ->condition('theme', $theme)
+ ->execute();
+ $original_database_blocks = array();
+ foreach ($database_blocks as $block) {
+ $module = $block['module'];
+ $delta = $block['delta'];
+ $original_database_blocks[$module][$delta] = $block;
+ // The cache mode can only by set from hook_block_info(), so that has
+ // precedence over the database's value.
+ if (isset($current_blocks[$module][$delta]['cache'])) {
+ $block['cache'] = $current_blocks[$module][$delta]['cache'];
+ }
+ // Preserve info which is not in the database.
+ $block['info'] = $current_blocks[$module][$delta]['info'];
+ // Blocks stored in the database override the blocks defined in code.
+ $current_blocks[$module][$delta] = $block;
+ // Preserve this block.
+ $bids[$block['bid']] = $block['bid'];
+ }
+ drupal_alter('block_info', $current_blocks, $theme, $code_blocks);
+ foreach ($current_blocks as $module => $module_blocks) {
+ foreach ($module_blocks as $delta => $block) {
+ 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'] = '';
+ }
+ // Make sure weight is set.
+ if (!isset($block['weight'])) {
+ $block['weight'] = 0;
+ }
+ if (!empty($block['region']) && $block['region'] != BLOCK_REGION_NONE && !isset($regions[$block['region']]) && $block['status'] == 1) {
+ drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block['info'], '%region' => $block['region'])), 'warning');
+ // Disabled modules are moved into the BLOCK_REGION_NONE later so no
+ // need to move the block to another region.
+ $block['status'] = 0;
+ }
+ // Set region to none if not enabled and make sure status is set.
+ if (empty($block['status'])) {
+ $block['status'] = 0;
+ $block['region'] = BLOCK_REGION_NONE;
+ }
+ // There is no point saving disabled blocks. Still, we need to save them
+ // because the 'title' attribute is saved to the {blocks} table.
+ if (isset($block['bid'])) {
+ // If the block has a bid property, it comes from the database and
+ // the record needs to be updated, so set the primary key to 'bid'
+ // before passing to drupal_write_record().
+ $primary_keys = array('bid');
+ // Remove a block from the list of blocks to keep if it became disabled.
+ unset($bids[$block['bid']]);
+ }
+ else {
+ $primary_keys = array();
+ }
+ // If the block is new or differs from the original database block, save
+ // it. To determine whether there was a change it is enough to examine
+ // the values for the keys in the original database record as that
+ // contained every database field.
+ if (!$primary_keys || array_diff_assoc($original_database_blocks[$module][$delta], $block)) {
+ drupal_write_record('block', $block, $primary_keys);
+ // Make it possible to test this.
+ $block['saved'] = TRUE;
+ }
+ // Add to the list of blocks we return.
+ $blocks[] = $block;
+ }
+ }
+ if ($bids) {
+ // Remove disabled that are no longer defined by the code from the
+ // database.
+ db_delete('block')
+ ->condition('bid', $bids, 'NOT IN')
+ ->condition('theme', $theme)
+ ->execute();
+ }
+ return $blocks;
+}
+
+/**
+ * Returns information from database about a user-created (custom) block.
+ *
+ * @param $bid
+ * ID of the block to get information for.
+ *
+ * @return
+ * Associative array of information stored in the database for this block.
+ * Array keys:
+ * - bid: Block ID.
+ * - info: Block description.
+ * - body: Block contents.
+ * - format: Filter ID of the filter format for the body.
+ */
+function block_custom_block_get($bid) {
+ return db_query("SELECT * FROM {block_custom} WHERE bid = :bid", array(':bid' => $bid))->fetchAssoc();
+}
+
+/**
+ * Form constructor for the custom block form.
+ *
+ * @param $edit
+ * (optional) An associative array of information retrieved by
+ * block_custom_get_block() if an existing block is being edited, or an empty
+ * array otherwise. Defaults to array().
+ *
+ * @ingroup forms
+ */
+function block_custom_block_form($edit = array()) {
+ $edit += array(
+ 'info' => '',
+ 'body' => '',
+ );
+ $form['info'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Block description'),
+ '#default_value' => $edit['info'],
+ '#maxlength' => 64,
+ '#description' => t('A brief description of your block. Used on the <a href="@overview">Blocks administration page</a>.', array('@overview' => url('admin/structure/block'))),
+ '#required' => TRUE,
+ '#weight' => -18,
+ );
+ $form['body_field']['#weight'] = -17;
+ $form['body_field']['body'] = array(
+ '#type' => 'text_format',
+ '#title' => t('Block body'),
+ '#default_value' => $edit['body'],
+ '#format' => isset($edit['format']) ? $edit['format'] : NULL,
+ '#rows' => 15,
+ '#description' => t('The content of the block as shown to the user.'),
+ '#required' => TRUE,
+ '#weight' => -17,
+ );
+
+ return $form;
+}
+
+/**
+ * Saves a user-created block in the database.
+ *
+ * @param $edit
+ * Associative array of fields to save. Array keys:
+ * - info: Block description.
+ * - body: Associative array of body value and format. Array keys:
+ * - value: Block contents.
+ * - format: Filter ID of the filter format for the body.
+ * @param $delta
+ * Block ID of the block to save.
+ *
+ * @return
+ * Always returns TRUE.
+ */
+function block_custom_block_save($edit, $delta) {
+ db_update('block_custom')
+ ->fields(array(
+ 'body' => $edit['body']['value'],
+ 'info' => $edit['info'],
+ 'format' => $edit['body']['format'],
+ ))
+ ->condition('bid', $delta)
+ ->execute();
+ return TRUE;
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter() for user_profile_form().
+ */
+function block_form_user_profile_form_alter(&$form, &$form_state) {
+ if ($form['#user_category'] == 'account') {
+ $account = $form['#user'];
+ $rids = array_keys($account->roles);
+ $result = db_query("SELECT DISTINCT b.* FROM {block} b LEFT JOIN {block_role} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom <> 0 AND (r.rid IN (:rids) OR r.rid IS NULL) ORDER BY b.weight, b.module", array(':rids' => $rids));
+
+ $blocks = array();
+ foreach ($result as $block) {
+ $data = module_invoke($block->module, 'block_info');
+ if ($data[$block->delta]['info']) {
+ $blocks[$block->module][$block->delta] = array(
+ '#type' => 'checkbox',
+ '#title' => check_plain($data[$block->delta]['info']),
+ '#default_value' => isset($account->data['block'][$block->module][$block->delta]) ? $account->data['block'][$block->module][$block->delta] : ($block->custom == 1),
+ );
+ }
+ }
+ // Only display the fieldset if there are any personalizable blocks.
+ if ($blocks) {
+ $form['block'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Personalize blocks'),
+ '#description' => t('Blocks consist of content or information that complements the main content of the page. Enable or disable optional blocks using the checkboxes below.'),
+ '#weight' => 3,
+ '#collapsible' => TRUE,
+ '#tree' => TRUE,
+ );
+ $form['block'] += $blocks;
+ }
+ }
+}
+
+/**
+ * Implements hook_user_presave().
+ */
+function block_user_presave(&$edit, $account, $category) {
+ if (isset($edit['block'])) {
+ $edit['data']['block'] = $edit['block'];
+ }
+}
+
+/**
+ * Initializes blocks for enabled themes.
+ *
+ * @param $theme_list
+ * An array of theme names.
+ */
+function block_themes_enabled($theme_list) {
+ foreach ($theme_list as $theme) {
+ block_theme_initialize($theme);
+ }
+}
+
+/**
+ * Assigns an initial, default set of blocks for a theme.
+ *
+ * This function is called the first time a new theme is enabled. The new theme
+ * gets a copy of the default theme's blocks, with the difference that if a
+ * particular region isn't available in the new theme, the block is assigned
+ * to the new theme's default region.
+ *
+ * @param $theme
+ * The name of a theme.
+ */
+function block_theme_initialize($theme) {
+ // Initialize theme's blocks if none already registered.
+ $has_blocks = (bool) db_query_range('SELECT 1 FROM {block} WHERE theme = :theme', 0, 1, array(':theme' => $theme))->fetchField();
+ if (!$has_blocks) {
+ $default_theme = variable_get('theme_default', 'bartik');
+ // Apply only to new theme's visible regions.
+ $regions = system_region_list($theme, REGIONS_VISIBLE);
+ $result = db_query("SELECT * FROM {block} WHERE theme = :theme", array(':theme' => $default_theme), array('fetch' => PDO::FETCH_ASSOC));
+ foreach ($result as $block) {
+ // If the region isn't supported by the theme, assign the block to the theme's default region.
+ if ($block['status'] && !isset($regions[$block['region']])) {
+ $block['region'] = system_default_region($theme);
+ }
+ $block['theme'] = $theme;
+ unset($block['bid']);
+ drupal_write_record('block', $block);
+ }
+ }
+}
+
+/**
+ * Returns all blocks in the specified region for the current user.
+ *
+ * @param $region
+ * The name of a region.
+ *
+ * @return
+ * An array of block objects, indexed with the module name and block delta
+ * concatenated with an underscore, thus: MODULE_DELTA. If you are displaying
+ * your blocks in one or two sidebars, you may check whether this array is
+ * empty to see how many columns are going to be displayed.
+ *
+ * @todo
+ * Now that the block table has a primary key, we should use that as the
+ * array key instead of MODULE_DELTA.
+ */
+function block_list($region) {
+ $blocks = &drupal_static(__FUNCTION__);
+
+ if (!isset($blocks)) {
+ $blocks = _block_load_blocks();
+ }
+
+ // Create an empty array if there are no entries.
+ if (!isset($blocks[$region])) {
+ $blocks[$region] = array();
+ }
+ else {
+ $blocks[$region] = _block_render_blocks($blocks[$region]);
+ }
+
+ return $blocks[$region];
+}
+
+/**
+ * Loads a block object from the database.
+ *
+ * @param $module
+ * Name of the module that implements the block to load.
+ * @param $delta
+ * Unique ID of the block within the context of $module. Pass NULL to return
+ * an empty block object for $module.
+ *
+ * @return
+ * A block object.
+ */
+function block_load($module, $delta) {
+ if (isset($delta)) {
+ $block = db_query('SELECT * FROM {block} WHERE module = :module AND delta = :delta', array(':module' => $module, ':delta' => $delta))->fetchObject();
+ }
+
+ // If the block does not exist in the database yet return a stub block
+ // object.
+ if (empty($block)) {
+ $block = new stdClass();
+ $block->module = $module;
+ $block->delta = $delta;
+ }
+
+ return $block;
+}
+
+/**
+ * Loads blocks' information from the database.
+ *
+ * @return
+ * An array of blocks grouped by region.
+ */
+function _block_load_blocks() {
+ global $theme_key;
+
+ $query = db_select('block', 'b');
+ $result = $query
+ ->fields('b')
+ ->condition('b.theme', $theme_key)
+ ->condition('b.status', 1)
+ ->orderBy('b.region')
+ ->orderBy('b.weight')
+ ->orderBy('b.module')
+ ->addTag('block_load')
+ ->addTag('translatable')
+ ->execute();
+
+ $block_info = $result->fetchAllAssoc('bid');
+ // Allow modules to modify the block list.
+ drupal_alter('block_list', $block_info);
+
+ $blocks = array();
+ foreach ($block_info as $block) {
+ $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block;
+ }
+ return $blocks;
+}
+
+/**
+ * Implements hook_block_list_alter().
+ *
+ * Checks the page, user role, and user-specific visibility settings.
+ * Removes the block if the visibility conditions are not met.
+ */
+function block_block_list_alter(&$blocks) {
+ global $user, $theme_key;
+
+ // Build an array of roles for each block.
+ $block_roles = array();
+ $result = db_query('SELECT module, delta, rid FROM {block_role}');
+ foreach ($result as $record) {
+ $block_roles[$record->module][$record->delta][] = $record->rid;
+ }
+
+ foreach ($blocks as $key => $block) {
+ if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {
+ // This block was added by a contrib module, leave it in the list.
+ continue;
+ }
+
+ // If a block has no roles associated, it is displayed for every role.
+ // For blocks with roles associated, if none of the user's roles matches
+ // the settings from this block, remove it from the block list.
+ if (isset($block_roles[$block->module][$block->delta]) && !array_intersect($block_roles[$block->module][$block->delta], array_keys($user->roles))) {
+ // No match.
+ unset($blocks[$key]);
+ continue;
+ }
+
+ // Use the user's block visibility setting, if necessary.
+ if ($block->custom != BLOCK_CUSTOM_FIXED) {
+ if ($user->uid && isset($user->data['block'][$block->module][$block->delta])) {
+ $enabled = $user->data['block'][$block->module][$block->delta];
+ }
+ else {
+ $enabled = ($block->custom == BLOCK_CUSTOM_ENABLED);
+ }
+ }
+ else {
+ $enabled = TRUE;
+ }
+
+ // Limited visibility blocks must list at least one page.
+ if ($block->visibility == BLOCK_VISIBILITY_LISTED && empty($block->pages)) {
+ $enabled = FALSE;
+ }
+
+ if (!$enabled) {
+ unset($blocks[$key]);
+ continue;
+ }
+
+ // Match path if necessary.
+ if ($block->pages) {
+ // Convert path to lowercase. This allows comparison of the same path
+ // with different case. Ex: /Page, /page, /PAGE.
+ $pages = drupal_strtolower($block->pages);
+ if ($block->visibility < BLOCK_VISIBILITY_PHP) {
+ // Convert the Drupal path to lowercase
+ $path = drupal_strtolower(drupal_get_path_alias($_GET['q']));
+ // Compare the lowercase internal and lowercase path alias (if any).
+ $page_match = drupal_match_path($path, $pages);
+ if ($path != $_GET['q']) {
+ $page_match = $page_match || drupal_match_path($_GET['q'], $pages);
+ }
+ // When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED),
+ // the block is displayed on all pages except those listed in $block->pages.
+ // When set to 1 (BLOCK_VISIBILITY_LISTED), it is displayed only on those
+ // pages listed in $block->pages.
+ $page_match = !($block->visibility xor $page_match);
+ }
+ elseif (module_exists('php')) {
+ $page_match = php_eval($block->pages);
+ }
+ else {
+ $page_match = FALSE;
+ }
+ }
+ else {
+ $page_match = TRUE;
+ }
+ if (!$page_match) {
+ unset($blocks[$key]);
+ }
+ }
+}
+
+/**
+ * Render the content and subject for a set of blocks.
+ *
+ * @param $region_blocks
+ * An array of block objects such as returned for one region by _block_load_blocks().
+ *
+ * @return
+ * An array of visible blocks as expected by drupal_render().
+ */
+function _block_render_blocks($region_blocks) {
+ // Block caching is not compatible with node access modules. We also
+ // preserve the submission of forms in blocks, by fetching from cache only
+ // if the request method is 'GET' (or 'HEAD').
+ $cacheable = !count(module_implements('node_grants')) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD');
+
+ // Proceed to loop over all blocks in order to compute their respective cache
+ // identifiers; this allows us to do one single cache_get_multiple() call
+ // instead of doing one cache_get() call per block.
+ $cached_blocks = array();
+ $cids = array();
+
+ if ($cacheable) {
+ foreach ($region_blocks as $key => $block) {
+ if (!isset($block->content)) {
+ if (($cid = _block_get_cache_id($block))) {
+ $cids[$key] = $cid;
+ }
+ }
+ }
+
+ if ($cids) {
+ // We cannot pass $cids in directly because cache_get_multiple() will
+ // modify it, and we need to use it later on in this function.
+ $cid_values = array_values($cids);
+ $cached_blocks = cache_get_multiple($cid_values, 'cache_block');
+ }
+ }
+
+ foreach ($region_blocks as $key => $block) {
+ // Render the block content if it has not been created already.
+ if (!isset($block->content)) {
+ // Erase the block from the static array - we'll put it back if it has
+ // content.
+ unset($region_blocks[$key]);
+
+ $cid = empty($cids[$key]) ? NULL : $cids[$key];
+
+ // Try fetching the block from the previously loaded cache entries.
+ if (isset($cached_blocks[$cid])) {
+ $array = $cached_blocks[$cid]->data;
+ }
+ else {
+ $array = module_invoke($block->module, 'block_view', $block->delta);
+
+ // Valid PHP function names cannot contain hyphens.
+ $delta = str_replace('-', '_', $block->delta);
+ // Allow modules to modify the block before it is viewed, via either
+ // hook_block_view_alter() or hook_block_view_MODULE_DELTA_alter().
+ drupal_alter(array('block_view', "block_view_{$block->module}_{$delta}"), $array, $block);
+
+ if (isset($cid)) {
+ cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY);
+ }
+ }
+
+ if (isset($array) && is_array($array)) {
+ foreach ($array as $k => $v) {
+ $block->$k = $v;
+ }
+ }
+ if (isset($block->content) && $block->content) {
+ // Normalize to the drupal_render() structure.
+ if (is_string($block->content)) {
+ $block->content = array('#markup' => $block->content);
+ }
+ // Override default block title if a custom display title is present.
+ if ($block->title) {
+ // Check plain here to allow module generated titles to keep any
+ // markup.
+ $block->subject = $block->title == '<none>' ? '' : check_plain($block->title);
+ }
+ if (!isset($block->subject)) {
+ $block->subject = '';
+ }
+ $region_blocks["{$block->module}_{$block->delta}"] = $block;
+ }
+ }
+ }
+ return $region_blocks;
+}
+
+/**
+ * Assemble the cache_id to use for a given block.
+ *
+ * The cache_id string reflects the viewing context for the current block
+ * instance, obtained by concatenating the relevant context information
+ * (user, page, ...) according to the block's cache settings (BLOCK_CACHE_*
+ * constants). Two block instances can use the same cached content when
+ * they share the same cache_id.
+ *
+ * Theme and language contexts are automatically differentiated.
+ *
+ * @param $block
+ * @return
+ * The string used as cache_id for the block.
+ */
+function _block_get_cache_id($block) {
+ global $user;
+
+ // User 1 being out of the regular 'roles define permissions' schema,
+ // it brings too many chances of having unwanted output get in the cache
+ // and later be served to other users. We therefore exclude user 1 from
+ // block caching.
+ if (variable_get('block_cache', FALSE) && !in_array($block->cache, array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM)) && $user->uid != 1) {
+ // Start with common sub-patterns: block identification, theme, language.
+ $cid_parts[] = $block->module;
+ $cid_parts[] = $block->delta;
+ $cid_parts = array_merge($cid_parts, drupal_render_cid_parts($block->cache));
+
+ return implode(':', $cid_parts);
+ }
+}
+
+/**
+ * Implements hook_flush_caches().
+ */
+function block_flush_caches() {
+ // Rehash blocks for active themes. We don't use list_themes() here,
+ // because if MAINTENANCE_MODE is defined it skips reading the database,
+ // and we can't tell which themes are active.
+ $themes = db_query("SELECT name FROM {system} WHERE type = 'theme' AND status = 1");
+ foreach ($themes as $theme) {
+ _block_rehash($theme->name);
+ }
+
+ return array('cache_block');
+}
+
+/**
+ * Processes variables for block.tpl.php.
+ *
+ * Prepares the values passed to the theme_block function to be passed
+ * into a pluggable template engine. Uses block properties to generate a
+ * series of template file suggestions. If none are found, the default
+ * block.tpl.php is used.
+ *
+ * Most themes utilize their own copy of block.tpl.php. The default is located
+ * inside "modules/block/block.tpl.php". Look in there for the full list of
+ * variables.
+ *
+ * The $variables array contains the following arguments:
+ * - $block
+ *
+ * @see block.tpl.php
+ */
+function template_preprocess_block(&$variables) {
+ $block_counter = &drupal_static(__FUNCTION__, array());
+ $variables['block'] = $variables['elements']['#block'];
+ // All blocks get an independent counter for each region.
+ if (!isset($block_counter[$variables['block']->region])) {
+ $block_counter[$variables['block']->region] = 1;
+ }
+ // Same with zebra striping.
+ $variables['block_zebra'] = ($block_counter[$variables['block']->region] % 2) ? 'odd' : 'even';
+ $variables['block_id'] = $block_counter[$variables['block']->region]++;
+
+ // Create the $content variable that templates expect.
+ $variables['content'] = $variables['elements']['#children'];
+
+ $variables['classes_array'][] = drupal_html_class('block-' . $variables['block']->module);
+
+ $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
+ $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
+ // Hyphens (-) and underscores (_) play a special role in theme suggestions.
+ // Theme suggestions should only contain underscores, because within
+ // drupal_find_theme_templates(), underscores are converted to hyphens to
+ // match template file names, and then converted back to underscores to match
+ // pre-processing and other function names. So if your theme suggestion
+ // contains a hyphen, it will end up as an underscore after this conversion,
+ // and your function names won't be recognized. So, we need to convert
+ // hyphens to underscores in block deltas for the theme suggestions.
+ $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . strtr($variables['block']->delta, '-', '_');
+
+ // Create a valid HTML ID and make sure it is unique.
+ $variables['block_html_id'] = drupal_html_id('block-' . $variables['block']->module . '-' . $variables['block']->delta);
+}
+
+/**
+ * Implements hook_user_role_delete().
+ *
+ * Removes deleted role from blocks that use it.
+ */
+function block_user_role_delete($role) {
+ db_delete('block_role')
+ ->condition('rid', $role->rid)
+ ->execute();
+}
+
+/**
+ * Implements hook_menu_delete().
+ */
+function block_menu_delete($menu) {
+ db_delete('block')
+ ->condition('module', 'menu')
+ ->condition('delta', $menu['menu_name'])
+ ->execute();
+ db_delete('block_role')
+ ->condition('module', 'menu')
+ ->condition('delta', $menu['menu_name'])
+ ->execute();
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function block_form_system_performance_settings_alter(&$form, &$form_state) {
+ $disabled = count(module_implements('node_grants'));
+ $form['caching']['block_cache'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Cache blocks'),
+ '#default_value' => variable_get('block_cache', FALSE),
+ '#disabled' => $disabled,
+ '#description' => $disabled ? t('Block caching is inactive because you have enabled modules defining content access restrictions.') : NULL,
+ '#weight' => -1,
+ );
+}
+
+/**
+ * Implements hook_admin_paths().
+ */
+function block_admin_paths() {
+ $paths = array(
+ // Exclude the block demonstration page from admin (overlay) treatment.
+ // This allows us to present this page in its true form, full page.
+ 'admin/structure/block/demo/*' => FALSE,
+ );
+ return $paths;
+}
+
+/**
+ * Implements hook_modules_uninstalled().
+ *
+ * Cleans up {block} and {block_role} tables from modules' blocks.
+ */
+function block_modules_uninstalled($modules) {
+ db_delete('block')
+ ->condition('module', $modules, 'IN')
+ ->execute();
+ db_delete('block_role')
+ ->condition('module', $modules, 'IN')
+ ->execute();
+}
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.test b/kolab.org/www/drupal-7.26/modules/block/block.test
new file mode 100644
index 0000000..99c81dc
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.test
@@ -0,0 +1,979 @@
+<?php
+
+/**
+ * @file
+ * Tests for block.module.
+ */
+
+class BlockTestCase extends DrupalWebTestCase {
+ protected $regions;
+ protected $admin_user;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block functionality',
+ 'description' => 'Add, edit and delete custom block. Configure and move a module-defined block.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp();
+
+ // Create and log in an administrative user having access to the Full HTML
+ // text format.
+ $full_html_format = filter_format_load('full_html');
+ $this->admin_user = $this->drupalCreateUser(array(
+ 'administer blocks',
+ filter_permission_name($full_html_format),
+ 'access administration pages',
+ ));
+ $this->drupalLogin($this->admin_user);
+
+ // Define the existing regions
+ $this->regions = array();
+ $this->regions[] = 'header';
+ $this->regions[] = 'sidebar_first';
+ $this->regions[] = 'content';
+ $this->regions[] = 'sidebar_second';
+ $this->regions[] = 'footer';
+ }
+
+ /**
+ * Test creating custom block, moving it to a specific region and then deleting it.
+ */
+ function testCustomBlock() {
+ // Confirm that the add block link appears on block overview pages.
+ $this->drupalGet('admin/structure/block');
+ $this->assertRaw(l('Add block', 'admin/structure/block/add'), 'Add block link is present on block overview page for default theme.');
+ $this->drupalGet('admin/structure/block/list/seven');
+ $this->assertRaw(l('Add block', 'admin/structure/block/list/seven/add'), 'Add block link is present on block overview page for non-default theme.');
+
+ // Confirm that hidden regions are not shown as options for block placement
+ // when adding a new block.
+ theme_enable(array('stark'));
+ $themes = list_themes();
+ $this->drupalGet('admin/structure/block/add');
+ foreach ($themes as $key => $theme) {
+ if ($theme->status) {
+ foreach ($theme->info['regions_hidden'] as $hidden_region) {
+ $elements = $this->xpath('//select[@id=:id]//option[@value=:value]', array(':id' => 'edit-regions-' . $key, ':value' => $hidden_region));
+ $this->assertFalse(isset($elements[0]), format_string('The hidden region @region is not available for @theme.', array('@region' => $hidden_region, '@theme' => $key)));
+ }
+ }
+ }
+
+ // Add a new custom block by filling out the input form on the admin/structure/block/add page.
+ $custom_block = array();
+ $custom_block['info'] = $this->randomName(8);
+ $custom_block['title'] = $this->randomName(8);
+ $custom_block['body[value]'] = $this->randomName(32);
+ $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
+
+ // Confirm that the custom block has been created, and then query the created bid.
+ $this->assertText(t('The block has been created.'), 'Custom block successfully created.');
+ $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
+
+ // Check to see if the custom block was created by checking that it's in the database.
+ $this->assertNotNull($bid, 'Custom block found in database');
+
+ // Check that block_block_view() returns the correct title and content.
+ $data = block_block_view($bid);
+ $format = db_query("SELECT format FROM {block_custom} WHERE bid = :bid", array(':bid' => $bid))->fetchField();
+ $this->assertTrue(array_key_exists('subject', $data) && empty($data['subject']), 'block_block_view() provides an empty block subject, since custom blocks do not have default titles.');
+ $this->assertEqual(check_markup($custom_block['body[value]'], $format), $data['content'], 'block_block_view() provides correct block content.');
+
+ // Check whether the block can be moved to all available regions.
+ $custom_block['module'] = 'block';
+ $custom_block['delta'] = $bid;
+ foreach ($this->regions as $region) {
+ $this->moveBlockToRegion($custom_block, $region);
+ }
+
+ // Verify presence of configure and delete links for custom block.
+ $this->drupalGet('admin/structure/block');
+ $this->assertLinkByHref('admin/structure/block/manage/block/' . $bid . '/configure', 0, 'Custom block configure link found.');
+ $this->assertLinkByHref('admin/structure/block/manage/block/' . $bid . '/delete', 0, 'Custom block delete link found.');
+
+ // Set visibility only for authenticated users, to verify delete functionality.
+ $edit = array();
+ $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
+ $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', $edit, t('Save block'));
+
+ // Delete the created custom block & verify that it's been deleted and no longer appearing on the page.
+ $this->clickLink(t('delete'));
+ $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
+ $this->assertRaw(t('The block %title has been removed.', array('%title' => $custom_block['info'])), 'Custom block successfully deleted.');
+ $this->assertNoText(t($custom_block['title']), 'Custom block no longer appears on page.');
+ $count = db_query("SELECT 1 FROM {block_role} WHERE module = :module AND delta = :delta", array(':module' => $custom_block['module'], ':delta' => $custom_block['delta']))->fetchField();
+ $this->assertFalse($count, 'Table block_role being cleaned.');
+ }
+
+ /**
+ * Test creating custom block using Full HTML.
+ */
+ function testCustomBlockFormat() {
+ // Add a new custom block by filling out the input form on the admin/structure/block/add page.
+ $custom_block = array();
+ $custom_block['info'] = $this->randomName(8);
+ $custom_block['title'] = $this->randomName(8);
+ $custom_block['body[value]'] = '<h1>Full HTML</h1>';
+ $full_html_format = filter_format_load('full_html');
+ $custom_block['body[format]'] = $full_html_format->format;
+ $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
+
+ // Set the created custom block to a specific region.
+ $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
+ $edit = array();
+ $edit['blocks[block_' . $bid . '][region]'] = $this->regions[1];
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+
+ // Confirm that the custom block is being displayed using configured text format.
+ $this->drupalGet('node');
+ $this->assertRaw('<h1>Full HTML</h1>', 'Custom block successfully being displayed using Full HTML.');
+
+ // Confirm that a user without access to Full HTML can not see the body field,
+ // but can still submit the form without errors.
+ $block_admin = $this->drupalCreateUser(array('administer blocks'));
+ $this->drupalLogin($block_admin);
+ $this->drupalGet('admin/structure/block/manage/block/' . $bid . '/configure');
+ $this->assertFieldByXPath("//textarea[@name='body[value]' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Body field contains denied message');
+ $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', array(), t('Save block'));
+ $this->assertNoText(t('Ensure that each block description is unique.'));
+
+ // Confirm that the custom block is still being displayed using configured text format.
+ $this->drupalGet('node');
+ $this->assertRaw('<h1>Full HTML</h1>', 'Custom block successfully being displayed using Full HTML.');
+ }
+
+ /**
+ * Test block visibility.
+ */
+ function testBlockVisibility() {
+ $block = array();
+
+ // Create a random title for the block
+ $title = $this->randomName(8);
+
+ // Create the custom block
+ $custom_block = array();
+ $custom_block['info'] = $this->randomName(8);
+ $custom_block['title'] = $title;
+ $custom_block['body[value]'] = $this->randomName(32);
+ $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
+
+ $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
+ $block['module'] = 'block';
+ $block['delta'] = $bid;
+ $block['title'] = $title;
+
+ // Set the block to be hidden on any user path, and to be shown only to
+ // authenticated users.
+ $edit = array();
+ $edit['pages'] = 'user*';
+ $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
+
+ // Move block to the first sidebar.
+ $this->moveBlockToRegion($block, $this->regions[1]);
+
+ $this->drupalGet('');
+ $this->assertText($title, 'Block was displayed on the front page.');
+
+ $this->drupalGet('user');
+ $this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
+
+ $this->drupalGet('USER/' . $this->admin_user->uid);
+ $this->assertNoText($title, 'Block was not displayed according to block visibility rules regardless of path case.');
+
+ // Confirm that the block is not displayed to anonymous users.
+ $this->drupalLogout();
+ $this->drupalGet('');
+ $this->assertNoText($title, 'Block was not displayed to anonymous users.');
+ }
+
+ /**
+ * Test block visibility when using "pages" restriction but leaving
+ * "pages" textarea empty
+ */
+ function testBlockVisibilityListedEmpty() {
+ $block = array();
+
+ // Create a random title for the block
+ $title = $this->randomName(8);
+
+ // Create the custom block
+ $custom_block = array();
+ $custom_block['info'] = $this->randomName(8);
+ $custom_block['title'] = $title;
+ $custom_block['body[value]'] = $this->randomName(32);
+ $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
+
+ $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
+ $block['module'] = 'block';
+ $block['delta'] = $bid;
+ $block['title'] = $title;
+
+ // Move block to the first sidebar.
+ $this->moveBlockToRegion($block, $this->regions[1]);
+
+ // Set the block to be hidden on any user path, and to be shown only to
+ // authenticated users.
+ $edit = array();
+ $edit['visibility'] = BLOCK_VISIBILITY_LISTED;
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
+
+ $this->drupalGet('');
+ $this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
+
+ $this->drupalGet('user');
+ $this->assertNoText($title, 'Block was not displayed according to block visibility rules regardless of path case.');
+
+ // Confirm that the block is not displayed to anonymous users.
+ $this->drupalLogout();
+ $this->drupalGet('');
+ $this->assertNoText($title, 'Block was not displayed to anonymous users.');
+ }
+
+ /**
+ * Test user customization of block visibility.
+ */
+ function testBlockVisibilityPerUser() {
+ $block = array();
+
+ // Create a random title for the block.
+ $title = $this->randomName(8);
+
+ // Create our custom test block.
+ $custom_block = array();
+ $custom_block['info'] = $this->randomName(8);
+ $custom_block['title'] = $title;
+ $custom_block['body[value]'] = $this->randomName(32);
+ $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
+
+ $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
+ $block['module'] = 'block';
+ $block['delta'] = $bid;
+ $block['title'] = $title;
+
+ // Move block to the first sidebar.
+ $this->moveBlockToRegion($block, $this->regions[1]);
+
+ // Set the block to be customizable per user, visible by default.
+ $edit = array();
+ $edit['custom'] = BLOCK_CUSTOM_ENABLED;
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
+
+ // Disable block visibility for the admin user.
+ $edit = array();
+ $edit['block[' . $block['module'] . '][' . $block['delta'] . ']'] = FALSE;
+ $this->drupalPost('user/' . $this->admin_user->uid . '/edit', $edit, t('Save'));
+
+ $this->drupalGet('');
+ $this->assertNoText($block['title'], 'Block was not displayed according to per user block visibility setting.');
+
+ // Set the block to be customizable per user, hidden by default.
+ $edit = array();
+ $edit['custom'] = BLOCK_CUSTOM_DISABLED;
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
+
+ // Enable block visibility for the admin user.
+ $edit = array();
+ $edit['block[' . $block['module'] . '][' . $block['delta'] . ']'] = TRUE;
+ $this->drupalPost('user/' . $this->admin_user->uid . '/edit', $edit, t('Save'));
+
+ $this->drupalGet('');
+ $this->assertText($block['title'], 'Block was displayed according to per user block visibility setting.');
+ }
+
+ /**
+ * Test configuring and moving a module-define block to specific regions.
+ */
+ function testBlock() {
+ // Select the Navigation block to be configured and moved.
+ $block = array();
+ $block['module'] = 'system';
+ $block['delta'] = 'management';
+ $block['title'] = $this->randomName(8);
+
+ // Set block title to confirm that interface works and override any custom titles.
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => $block['title']), t('Save block'));
+ $this->assertText(t('The block configuration has been saved.'), 'Block title set.');
+ $bid = db_query("SELECT bid FROM {block} WHERE module = :module AND delta = :delta", array(
+ ':module' => $block['module'],
+ ':delta' => $block['delta'],
+ ))->fetchField();
+
+ // Check to see if the block was created by checking that it's in the database.
+ $this->assertNotNull($bid, 'Block found in database');
+
+ // Check whether the block can be moved to all available regions.
+ foreach ($this->regions as $region) {
+ $this->moveBlockToRegion($block, $region);
+ }
+
+ // Set the block to the disabled region.
+ $edit = array();
+ $edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = '-1';
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+
+ // Confirm that the block was moved to the proper region.
+ $this->assertText(t('The block settings have been updated.'), 'Block successfully move to disabled region.');
+ $this->assertNoText(t($block['title']), 'Block no longer appears on page.');
+
+ // Confirm that the region's xpath is not available.
+ $xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-block-' . $bid));
+ $this->assertNoFieldByXPath($xpath, FALSE, 'Custom block found in no regions.');
+
+ // For convenience of developers, put the navigation block back.
+ $edit = array();
+ $edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $this->regions[1];
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+ $this->assertText(t('The block settings have been updated.'), 'Block successfully move to first sidebar region.');
+
+ $this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => 'Navigation'), t('Save block'));
+ $this->assertText(t('The block configuration has been saved.'), 'Block title set.');
+ }
+
+ function moveBlockToRegion($block, $region) {
+ // Set the created block to a specific region.
+ $edit = array();
+ $edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+
+ // Confirm that the block was moved to the proper region.
+ $this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
+
+ // Confirm that the block is being displayed.
+ $this->drupalGet('node');
+ $this->assertText(t($block['title']), 'Block successfully being displayed on the page.');
+
+ // Confirm that the custom block was found at the proper region.
+ $xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
+ ':region-class' => 'region region-' . str_replace('_', '-', $region),
+ ':block-id' => 'block-' . $block['module'] . '-' . $block['delta'],
+ ));
+ $this->assertFieldByXPath($xpath, NULL, format_string('Custom block found in %region_name region.', array('%region_name' => $region)));
+ }
+
+ /**
+ * Test _block_rehash().
+ */
+ function testBlockRehash() {
+ module_enable(array('block_test'));
+ $this->assertTrue(module_exists('block_test'), 'Test block module enabled.');
+
+ // Our new block should be inserted in the database when we visit the
+ // block management page.
+ $this->drupalGet('admin/structure/block');
+ // Our test block's caching should default to DRUPAL_CACHE_PER_ROLE.
+ $current_caching = db_query("SELECT cache FROM {block} WHERE module = 'block_test' AND delta = 'test_cache'")->fetchField();
+ $this->assertEqual($current_caching, DRUPAL_CACHE_PER_ROLE, 'Test block cache mode defaults to DRUPAL_CACHE_PER_ROLE.');
+
+ // Disable caching for this block.
+ variable_set('block_test_caching', DRUPAL_NO_CACHE);
+ // Flushing all caches should call _block_rehash().
+ drupal_flush_all_caches();
+ // Verify that the database is updated with the new caching mode.
+ $current_caching = db_query("SELECT cache FROM {block} WHERE module = 'block_test' AND delta = 'test_cache'")->fetchField();
+ $this->assertEqual($current_caching, DRUPAL_NO_CACHE, "Test block's database entry updated to DRUPAL_NO_CACHE.");
+ }
+}
+
+class NonDefaultBlockAdmin extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Non default theme admin',
+ 'description' => 'Check the administer page for non default theme.',
+ 'group' => 'Block',
+ );
+ }
+
+ /**
+ * Test non-default theme admin.
+ */
+ function testNonDefaultBlockAdmin() {
+ $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
+ $this->drupalLogin($admin_user);
+ theme_enable(array('stark'));
+ $this->drupalGet('admin/structure/block/list/stark');
+ }
+}
+
+/**
+ * Test blocks correctly initialized when picking a new default theme.
+ */
+class NewDefaultThemeBlocks extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'New default theme blocks',
+ 'description' => 'Checks that the new default theme gets blocks.',
+ 'group' => 'Block',
+ );
+ }
+
+ /**
+ * Check the enabled Bartik blocks are correctly copied over.
+ */
+ function testNewDefaultThemeBlocks() {
+ // Create administrative user.
+ $admin_user = $this->drupalCreateUser(array('administer themes'));
+ $this->drupalLogin($admin_user);
+
+ // Ensure no other theme's blocks are in the block table yet.
+ $themes = array();
+ $themes['default'] = variable_get('theme_default', 'bartik');
+ if ($admin_theme = variable_get('admin_theme')) {
+ $themes['admin'] = $admin_theme;
+ }
+ $count = db_query_range('SELECT 1 FROM {block} WHERE theme NOT IN (:themes)', 0, 1, array(':themes' => $themes))->fetchField();
+ $this->assertFalse($count, 'Only the default theme and the admin theme have blocks.');
+
+ // Populate list of all blocks for matching against new theme.
+ $blocks = array();
+ $result = db_query('SELECT * FROM {block} WHERE theme = :theme', array(':theme' => $themes['default']));
+ foreach ($result as $block) {
+ // $block->theme and $block->bid will not match, so remove them.
+ unset($block->theme, $block->bid);
+ $blocks[$block->module][$block->delta] = $block;
+ }
+
+ // Turn on the Stark theme and ensure that it contains all of the blocks
+ // the default theme had.
+ theme_enable(array('stark'));
+ variable_set('theme_default', 'stark');
+ $result = db_query('SELECT * FROM {block} WHERE theme = :theme', array(':theme' => 'stark'));
+ foreach ($result as $block) {
+ unset($block->theme, $block->bid);
+ $this->assertEqual($blocks[$block->module][$block->delta], $block, format_string('Block %name matched', array('%name' => $block->module . '-' . $block->delta)));
+ }
+ }
+}
+
+/**
+ * Test the block system with admin themes.
+ */
+class BlockAdminThemeTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Admin theme block admin accessibility',
+ 'description' => "Check whether the block administer page for a disabled theme accessible if and only if it's the admin theme.",
+ 'group' => 'Block',
+ );
+ }
+
+ /**
+ * Check for the accessibility of the admin theme on the block admin page.
+ */
+ function testAdminTheme() {
+ // Create administrative user.
+ $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
+ $this->drupalLogin($admin_user);
+
+ // Ensure that access to block admin page is denied when theme is disabled.
+ $this->drupalGet('admin/structure/block/list/stark');
+ $this->assertResponse(403, 'The block admin page for a disabled theme can not be accessed');
+
+ // Enable admin theme and confirm that tab is accessible.
+ $edit['admin_theme'] = 'stark';
+ $this->drupalPost('admin/appearance', $edit, t('Save configuration'));
+ $this->drupalGet('admin/structure/block/list/stark');
+ $this->assertResponse(200, 'The block admin page for the admin theme can be accessed');
+ }
+}
+
+/**
+ * Test block caching.
+ */
+class BlockCacheTestCase extends DrupalWebTestCase {
+ protected $admin_user;
+ protected $normal_user;
+ protected $normal_user_alt;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block caching',
+ 'description' => 'Test block caching.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('block_test');
+
+ // Create an admin user, log in and enable test blocks.
+ $this->admin_user = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
+ $this->drupalLogin($this->admin_user);
+
+ // Create additional users to test caching modes.
+ $this->normal_user = $this->drupalCreateUser();
+ $this->normal_user_alt = $this->drupalCreateUser();
+ // Sync the roles, since drupalCreateUser() creates separate roles for
+ // the same permission sets.
+ user_save($this->normal_user_alt, array('roles' => $this->normal_user->roles));
+ $this->normal_user_alt->roles = $this->normal_user->roles;
+
+ // Enable block caching.
+ variable_set('block_cache', TRUE);
+
+ // Enable our test block.
+ $edit['blocks[block_test_test_cache][region]'] = 'sidebar_first';
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+ }
+
+ /**
+ * Test DRUPAL_CACHE_PER_ROLE.
+ */
+ function testCachePerRole() {
+ $this->setCacheMode(DRUPAL_CACHE_PER_ROLE);
+
+ // Enable our test block. Set some content for it to display.
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ $this->drupalLogin($this->normal_user);
+ $this->drupalGet('');
+ $this->assertText($current_content, 'Block content displays.');
+
+ // Change the content, but the cached copy should still be served.
+ $old_content = $current_content;
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ $this->drupalGet('');
+ $this->assertText($old_content, 'Block is served from the cache.');
+
+ // Clear the cache and verify that the stale data is no longer there.
+ cache_clear_all();
+ $this->drupalGet('');
+ $this->assertNoText($old_content, 'Block cache clear removes stale cache data.');
+ $this->assertText($current_content, 'Fresh block content is displayed after clearing the cache.');
+
+ // Test whether the cached data is served for the correct users.
+ $old_content = $current_content;
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ $this->drupalLogout();
+ $this->drupalGet('');
+ $this->assertNoText($old_content, 'Anonymous user does not see content cached per-role for normal user.');
+
+ $this->drupalLogin($this->normal_user_alt);
+ $this->drupalGet('');
+ $this->assertText($old_content, 'User with the same roles sees per-role cached content.');
+
+ $this->drupalLogin($this->admin_user);
+ $this->drupalGet('');
+ $this->assertNoText($old_content, 'Admin user does not see content cached per-role for normal user.');
+
+ $this->drupalLogin($this->normal_user);
+ $this->drupalGet('');
+ $this->assertText($old_content, 'Block is served from the per-role cache.');
+ }
+
+ /**
+ * Test DRUPAL_CACHE_GLOBAL.
+ */
+ function testCacheGlobal() {
+ $this->setCacheMode(DRUPAL_CACHE_GLOBAL);
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ $this->drupalGet('');
+ $this->assertText($current_content, 'Block content displays.');
+
+ $old_content = $current_content;
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ $this->drupalLogout();
+ $this->drupalGet('user');
+ $this->assertText($old_content, 'Block content served from global cache.');
+ }
+
+ /**
+ * Test DRUPAL_NO_CACHE.
+ */
+ function testNoCache() {
+ $this->setCacheMode(DRUPAL_NO_CACHE);
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ // If DRUPAL_NO_CACHE has no effect, the next request would be cached.
+ $this->drupalGet('');
+ $this->assertText($current_content, 'Block content displays.');
+
+ // A cached copy should not be served.
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ $this->drupalGet('');
+ $this->assertText($current_content, 'DRUPAL_NO_CACHE prevents blocks from being cached.');
+ }
+
+ /**
+ * Test DRUPAL_CACHE_PER_USER.
+ */
+ function testCachePerUser() {
+ $this->setCacheMode(DRUPAL_CACHE_PER_USER);
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ $this->drupalLogin($this->normal_user);
+
+ $this->drupalGet('');
+ $this->assertText($current_content, 'Block content displays.');
+
+ $old_content = $current_content;
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ $this->drupalGet('');
+ $this->assertText($old_content, 'Block is served from per-user cache.');
+
+ $this->drupalLogin($this->normal_user_alt);
+ $this->drupalGet('');
+ $this->assertText($current_content, 'Per-user block cache is not served for other users.');
+
+ $this->drupalLogin($this->normal_user);
+ $this->drupalGet('');
+ $this->assertText($old_content, 'Per-user block cache is persistent.');
+ }
+
+ /**
+ * Test DRUPAL_CACHE_PER_PAGE.
+ */
+ function testCachePerPage() {
+ $this->setCacheMode(DRUPAL_CACHE_PER_PAGE);
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ $this->drupalGet('node');
+ $this->assertText($current_content, 'Block content displays on the node page.');
+
+ $old_content = $current_content;
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+
+ $this->drupalGet('user');
+ $this->assertNoText($old_content, 'Block content cached for the node page does not show up for the user page.');
+ $this->drupalGet('node');
+ $this->assertText($old_content, 'Block content cached for the node page.');
+ }
+
+ /**
+ * Private helper method to set the test block's cache mode.
+ */
+ private function setCacheMode($cache_mode) {
+ db_update('block')
+ ->fields(array('cache' => $cache_mode))
+ ->condition('module', 'block_test')
+ ->execute();
+
+ $current_mode = db_query("SELECT cache FROM {block} WHERE module = 'block_test'")->fetchField();
+ if ($current_mode != $cache_mode) {
+ $this->fail(t('Unable to set cache mode to %mode. Current mode: %current_mode', array('%mode' => $cache_mode, '%current_mode' => $current_mode)));
+ }
+ }
+}
+
+/**
+ * Test block HTML id validity.
+ */
+class BlockHTMLIdTestCase extends DrupalWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block HTML id',
+ 'description' => 'Test block HTML id validity.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('block_test');
+
+ // Create an admin user, log in and enable test blocks.
+ $this->admin_user = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
+ $this->drupalLogin($this->admin_user);
+
+ // Enable our test block.
+ $edit['blocks[block_test_test_html_id][region]'] = 'sidebar_first';
+ $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
+
+ // Make sure the block has some content so it will appear
+ $current_content = $this->randomName();
+ variable_set('block_test_content', $current_content);
+ }
+
+ /**
+ * Test valid HTML id.
+ */
+ function testHTMLId() {
+ $this->drupalGet('');
+ $this->assertRaw('block-block-test-test-html-id', 'HTML id for test block is valid.');
+ }
+}
+
+
+/**
+ * Unit tests for template_preprocess_block().
+ */
+class BlockTemplateSuggestionsUnitTest extends DrupalUnitTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block template suggestions',
+ 'description' => 'Test the template_preprocess_block() function.',
+ 'group' => 'Block',
+ );
+ }
+
+ /**
+ * Test if template_preprocess_block() handles the suggestions right.
+ */
+ function testBlockThemeHookSuggestions() {
+ // Define block delta with underscore to be preprocessed
+ $block1 = new stdClass();
+ $block1->module = 'block';
+ $block1->delta = 'underscore_test';
+ $block1->region = 'footer';
+ $variables1 = array();
+ $variables1['elements']['#block'] = $block1;
+ $variables1['elements']['#children'] = '';
+ template_preprocess_block($variables1);
+ $this->assertEqual($variables1['theme_hook_suggestions'], array('block__footer', 'block__block', 'block__block__underscore_test'), 'Found expected block suggestions for delta with underscore');
+
+ // Define block delta with hyphens to be preprocessed. Hyphens should be
+ // replaced with underscores.
+ $block2 = new stdClass();
+ $block2->module = 'block';
+ $block2->delta = 'hyphen-test';
+ $block2->region = 'footer';
+ $variables2 = array();
+ $variables2['elements']['#block'] = $block2;
+ $variables2['elements']['#children'] = '';
+ template_preprocess_block($variables2);
+ $this->assertEqual($variables2['theme_hook_suggestions'], array('block__footer', 'block__block', 'block__block__hyphen_test'), 'Hyphens (-) in block delta were replaced by underscore (_)');
+ }
+}
+
+/**
+ * Tests for hook_block_view_MODULE_DELTA_alter().
+ */
+class BlockViewModuleDeltaAlterWebTest extends DrupalWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block view module delta alter',
+ 'description' => 'Test the hook_block_view_MODULE_DELTA_alter() hook.',
+ 'group' => 'Block',
+ );
+ }
+
+ public function setUp() {
+ parent::setUp(array('block_test'));
+ }
+
+ /**
+ * Tests that the alter hook is called, even if the delta contains a hyphen.
+ */
+ public function testBlockViewModuleDeltaAlter() {
+ $block = new stdClass;
+ $block->module = 'block_test';
+ $block->delta = 'test_underscore';
+ $block->title = '';
+ $render_array = _block_render_blocks(array('region' => $block));
+ $render = array_pop($render_array);
+ $test_underscore = $render->content['#markup'];
+ $this->assertEqual($test_underscore, 'hook_block_view_MODULE_DELTA_alter', 'Found expected altered block content for delta with underscore');
+
+ $block = new stdClass;
+ $block->module = 'block_test';
+ $block->delta = 'test-hyphen';
+ $block->title = '';
+ $render_array = _block_render_blocks(array('region' => $block));
+ $render = array_pop($render_array);
+ $test_hyphen = $render->content['#markup'];
+ $this->assertEqual($test_hyphen, 'hook_block_view_MODULE_DELTA_alter', 'Hyphens (-) in block delta were replaced by underscore (_)');
+ }
+
+}
+
+/**
+ * Tests that hidden regions do not inherit blocks when a theme is enabled.
+ */
+class BlockHiddenRegionTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Blocks not in hidden region',
+ 'description' => 'Checks that a newly enabled theme does not inherit blocks to its hidden regions.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp(array('block_test'));
+ }
+
+ /**
+ * Tests that hidden regions do not inherit blocks when a theme is enabled.
+ */
+ function testBlockNotInHiddenRegion() {
+ // Create administrative user.
+ $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes', 'search content'));
+ $this->drupalLogin($admin_user);
+
+ // Enable "block_test_theme" and set it as the default theme.
+ $theme = 'block_test_theme';
+ theme_enable(array($theme));
+ variable_set('theme_default', $theme);
+ menu_rebuild();
+
+ // Ensure that "block_test_theme" is set as the default theme.
+ $this->drupalGet('admin/structure/block');
+ $this->assertText('Block test theme(' . t('active tab') . ')', 'Default local task on blocks admin page is the block test theme.');
+
+ // Ensure that the search form block is displayed.
+ $this->drupalGet('');
+ $this->assertText('Search form', 'Block was displayed on the front page.');
+ }
+}
+
+/**
+ * Tests that a block assigned to an invalid region triggers the warning.
+ */
+class BlockInvalidRegionTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Blocks in invalid regions',
+ 'description' => 'Checks that an active block assigned to a non-existing region triggers the warning message and is disabled.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp(array('block', 'block_test'));
+ // Create an admin user.
+ $admin_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages'));
+ $this->drupalLogin($admin_user);
+ }
+
+ /**
+ * Tests that blocks assigned to invalid regions work correctly.
+ */
+ function testBlockInInvalidRegion() {
+ // Enable a test block in the default theme and place it in an invalid region.
+ db_merge('block')
+ ->key(array(
+ 'module' => 'block_test',
+ 'delta' => 'test_html_id',
+ 'theme' => variable_get('theme_default', 'stark'),
+ ))
+ ->fields(array(
+ 'status' => 1,
+ 'region' => 'invalid_region',
+ 'cache' => DRUPAL_NO_CACHE,
+ ))
+ ->execute();
+
+ $warning_message = t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => t('Test block html id'), '%region' => 'invalid_region'));
+
+ // Clearing the cache should disable the test block placed in the invalid region.
+ $this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
+ $this->assertRaw($warning_message, 'Enabled block was in the invalid region and has been disabled.');
+
+ // Clear the cache to check if the warning message is not triggered.
+ $this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
+ $this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
+
+ // Place disabled test block in the invalid region of the default theme.
+ db_merge('block')
+ ->key(array(
+ 'module' => 'block_test',
+ 'delta' => 'test_html_id',
+ 'theme' => variable_get('theme_default', 'stark'),
+ ))
+ ->fields(array(
+ 'region' => 'invalid_region',
+ 'cache' => DRUPAL_NO_CACHE,
+ ))
+ ->execute();
+
+ // Clear the cache to check if the warning message is not triggered.
+ $this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
+ $this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
+ }
+}
+
+/**
+ * Tests that block rehashing works correctly.
+ */
+class BlockHashTestCase extends DrupalWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Block rehash',
+ 'description' => 'Checks _block_rehash() functionality.',
+ 'group' => 'Block',
+ );
+ }
+
+ function setUp() {
+ parent::setUp(array('block'));
+ }
+
+ /**
+ * Tests that block rehashing does not write to the database too often.
+ */
+ function testBlockRehash() {
+ // No hook_block_info_alter(), no save.
+ $this->doRehash();
+ module_enable(array('block_test'), FALSE);
+ // Save the new blocks, check that the new blocks exist by checking weight.
+ _block_rehash();
+ $this->assertWeight(0);
+ // Now hook_block_info_alter() exists but no blocks are saved on a second
+ // rehash.
+ $this->doRehash();
+ $this->assertWeight(0);
+ // Now hook_block_info_alter() exists and is changing one block which
+ // should be saved.
+ $GLOBALS['conf']['block_test_info_alter'] = 1;
+ $this->doRehash(TRUE);
+ $this->assertWeight(10000);
+ // Now hook_block_info_alter() exists but already changed the block's
+ // weight before, so it should not be saved again.
+ $this->doRehash();
+ $this->assertWeight(10000);
+ }
+
+ /**
+ * Performs a block rehash and checks several related assertions.
+ *
+ * @param $alter_active
+ * Set to TRUE if the block_test module's hook_block_info_alter()
+ * implementation is expected to make a change that results in an existing
+ * block needing to be resaved to the database. Defaults to FALSE.
+ */
+ function doRehash($alter_active = FALSE) {
+ $saves = 0;
+ foreach (_block_rehash() as $block) {
+ $module = $block['module'];
+ $delta = $block['delta'];
+ if ($alter_active && $module == 'block_test' && $delta == 'test_html_id') {
+ $this->assertFalse(empty($block['saved']), "$module $delta saved");
+ $saves++;
+ }
+ else {
+ $this->assertTrue(empty($block['saved']), "$module $delta not saved");
+ }
+ }
+ $this->assertEqual($alter_active, $saves);
+ }
+
+ /**
+ * Asserts that the block_test module's block has a given weight.
+ *
+ * @param $weight
+ * The expected weight.
+ */
+ function assertWeight($weight) {
+ $db_weight = db_query('SELECT weight FROM {block} WHERE module = :module AND delta = :delta', array(':module' => 'block_test', ':delta' => 'test_html_id'))->fetchField();
+ // By casting to string the assert fails on FALSE.
+ $this->assertIdentical((string) $db_weight, (string) $weight);
+ }
+}
diff --git a/kolab.org/www/drupal-7.26/modules/block/block.tpl.php b/kolab.org/www/drupal-7.26/modules/block/block.tpl.php
new file mode 100644
index 0000000..f0bfa5c
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/block.tpl.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Default theme implementation to display a block.
+ *
+ * Available variables:
+ * - $block->subject: Block title.
+ * - $content: Block content.
+ * - $block->module: Module that generated the block.
+ * - $block->delta: An ID for the block, unique within each module.
+ * - $block->region: The block region embedding the current block.
+ * - $classes: String of classes that can be used to style contextually through
+ * CSS. It can be manipulated through the variable $classes_array from
+ * preprocess functions. The default values can be one or more of the
+ * following:
+ * - block: The current template type, i.e., "theming hook".
+ * - block-[module]: The module generating the block. For example, the user
+ * module is responsible for handling the default user navigation block. In
+ * that case the class would be 'block-user'.
+ * - $title_prefix (array): An array containing additional output populated by
+ * modules, intended to be displayed in front of the main title tag that
+ * appears in the template.
+ * - $title_suffix (array): An array containing additional output populated by
+ * modules, intended to be displayed after the main title tag that appears in
+ * the template.
+ *
+ * Helper variables:
+ * - $classes_array: Array of html class attribute values. It is flattened
+ * into a string within the variable $classes.
+ * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
+ * - $zebra: Same output as $block_zebra but independent of any block region.
+ * - $block_id: Counter dependent on each block region.
+ * - $id: Same output as $block_id but independent of any block region.
+ * - $is_front: Flags true when presented in the front page.
+ * - $logged_in: Flags true when the current user is a logged-in member.
+ * - $is_admin: Flags true when the current user is an administrator.
+ * - $block_html_id: A valid HTML ID and guaranteed unique.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_block()
+ * @see template_process()
+ *
+ * @ingroup themeable
+ */
+?>
+<div id="<?php print $block_html_id; ?>" class="<?php print $classes; ?>"<?php print $attributes; ?>>
+
+ <?php print render($title_prefix); ?>
+<?php if ($block->subject): ?>
+ <h2<?php print $title_attributes; ?>><?php print $block->subject ?></h2>
+<?php endif;?>
+ <?php print render($title_suffix); ?>
+
+ <div class="content"<?php print $content_attributes; ?>>
+ <?php print $content ?>
+ </div>
+</div>
diff --git a/kolab.org/www/drupal-7.26/modules/block/tests/block_test.info b/kolab.org/www/drupal-7.26/modules/block/tests/block_test.info
new file mode 100644
index 0000000..846e067
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/tests/block_test.info
@@ -0,0 +1,12 @@
+name = Block test
+description = Provides test blocks.
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
+
+; Information added by Drupal.org packaging script on 2014-01-15
+version = "7.26"
+project = "drupal"
+datestamp = "1389815930"
+
diff --git a/kolab.org/www/drupal-7.26/modules/block/tests/block_test.module b/kolab.org/www/drupal-7.26/modules/block/tests/block_test.module
new file mode 100644
index 0000000..e7ed09b
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/tests/block_test.module
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Provide test blocks.
+ */
+
+/**
+ * Implements hook_system_theme_info().
+ */
+function block_test_system_theme_info() {
+ $themes['block_test_theme'] = drupal_get_path('module', 'block_test') . '/themes/block_test_theme/block_test_theme.info';
+ return $themes;
+}
+
+/**
+ * Implements hook_block_info().
+ */
+function block_test_block_info() {
+ $blocks['test_cache'] = array(
+ 'info' => t('Test block caching'),
+ 'cache' => variable_get('block_test_caching', DRUPAL_CACHE_PER_ROLE),
+ );
+
+ $blocks['test_underscore'] = array(
+ 'info' => t('Test underscore'),
+ );
+
+ $blocks['test-hyphen'] = array(
+ 'info' => t('Test hyphen'),
+ );
+
+ $blocks['test_html_id'] = array(
+ 'info' => t('Test block html id'),
+ );
+ return $blocks;
+}
+
+/**
+ * Implements hook_block_view().
+ */
+function block_test_block_view($delta = 0) {
+ return array('content' => variable_get('block_test_content', ''));
+}
+
+/**
+ * Implements hook_block_view_MODULE_DELTA_alter().
+ */
+function block_test_block_view_block_test_test_underscore_alter(&$data, $block) {
+ $data['content'] = 'hook_block_view_MODULE_DELTA_alter';
+}
+
+/**
+ * Implements hook_block_view_MODULE_DELTA_alter().
+ */
+function block_test_block_view_block_test_test_hyphen_alter(&$data, $block) {
+ $data['content'] = 'hook_block_view_MODULE_DELTA_alter';
+}
+
+/**
+ * Implements hook_block_info_alter().
+ */
+function block_test_block_info_alter(&$blocks) {
+ if (variable_get('block_test_info_alter')) {
+ $blocks['block_test']['test_html_id']['weight'] = 10000;
+ }
+}
diff --git a/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/block_test_theme.info b/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/block_test_theme.info
new file mode 100644
index 0000000..3da86d0
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/block_test_theme.info
@@ -0,0 +1,20 @@
+name = Block test theme
+description = Theme for testing the block system
+core = 7.x
+hidden = TRUE
+
+regions[sidebar_first] = Left sidebar
+regions_hidden[] = sidebar_first
+regions[sidebar_second] = Right sidebar
+regions_hidden[] = sidebar_second
+regions[content] = Content
+regions[header] = Header
+regions[footer] = Footer
+regions[highlighted] = Highlighted
+regions[help] = Help
+
+; Information added by Drupal.org packaging script on 2014-01-15
+version = "7.26"
+project = "drupal"
+datestamp = "1389815930"
+
diff --git a/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/page.tpl.php b/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/page.tpl.php
new file mode 100644
index 0000000..ba72882
--- /dev/null
+++ b/kolab.org/www/drupal-7.26/modules/block/tests/themes/block_test_theme/page.tpl.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * @file
+ * Custom theme implementation to display a single Drupal page without
+ * sidebars. The sidebars are hidden by regions_hidden for this theme, so
+ * the default page.tpl.php will not work without throwing exceptions.
+ */
+?>
+
+ <div id="page-wrapper"><div id="page">
+
+ <div id="header"><div class="section clearfix">
+
+ <?php if ($logo): ?>
+ <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo">
+ <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" />
+ </a>
+ <?php endif; ?>
+
+ <?php if ($site_name || $site_slogan): ?>
+ <div id="name-and-slogan">
+ <?php if ($site_name): ?>
+ <?php if ($title): ?>
+ <div id="site-name"><strong>
+ <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
+ </strong></div>
+ <?php else: /* Use h1 when the content title is empty */ ?>
+ <h1 id="site-name">
+ <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
+ </h1>
+ <?php endif; ?>
+ <?php endif; ?>
+
+ <?php if ($site_slogan): ?>
+ <div id="site-slogan"><?php print $site_slogan; ?></div>
+ <?php endif; ?>
+ </div> <!-- /#name-and-slogan -->
+ <?php endif; ?>
+
+ <?php print render($page['header']); ?>
+
+ </div></div> <!-- /.section, /#header -->
+
+ <?php if ($main_menu || $secondary_menu): ?>
+ <div id="navigation"><div class="section">
+ <?php print theme('links__system_main_menu', array('links' => $main_menu, 'attributes' => array('id' => 'main-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Main menu'))); ?>
+ <?php print theme('links__system_secondary_menu', array('links' => $secondary_menu, 'attributes' => array('id' => 'secondary-menu', 'class' => array('links', 'inline', 'clearfix')), 'heading' => t('Secondary menu'))); ?>
+ </div></div> <!-- /.section, /#navigation -->
+ <?php endif; ?>
+
+ <?php if ($breadcrumb): ?>
+ <div id="breadcrumb"><?php print $breadcrumb; ?></div>
+ <?php endif; ?>
+
+ <?php print $messages; ?>
+
+ <div id="main-wrapper"><div id="main" class="clearfix">
+
+ <div id="content" class="column"><div class="section">
+ <?php if ($page['highlighted']): ?><div id="highlighted"><?php print render($page['highlighted']); ?></div><?php endif; ?>
+ <a id="main-content"></a>
+ <?php print render($title_prefix); ?>
+ <?php if ($title): ?><h1 class="title" id="page-title"><?php print $title; ?></h1><?php endif; ?>
+ <?php print render($title_suffix); ?>
+ <?php if ($tabs = render($tabs)): ?><div class="tabs"><?php print $tabs; ?></div><?php endif; ?>
+ <?php print render($page['help']); ?>
+ <?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
+ <?php print render($page['content']); ?>
+ <?php print $feed_icons; ?>
+ </div></div> <!-- /.section, /#content -->
+ </div></div> <!-- /#main, /#main-wrapper -->
+
+ <div id="footer"><div class="section">
+ <?php print render($page['footer']); ?>
+ </div></div> <!-- /.section, /#footer -->
+
+ </div></div> <!-- /#page, /#page-wrapper -->