block.module 23.6 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
 
Dries committed
4 5 6 7 8
/**
 * @file
 * Controls the boxes that are displayed around the main content.
 */

Dries's avatar
 
Dries committed
9 10 11 12
/**
 * Implementation of hook_help().
 */
function block_help($section) {
Dries's avatar
 
Dries committed
13
  switch ($section) {
Dries's avatar
 
Dries committed
14
    case 'admin/help#block':
15
      return t('
16 17
<p>Blocks are the boxes visible in the sidebar(s) of your web site and other regions. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks.</p>
<p>The region each block appears in depends on both which theme you are using (some are left-only, some right, some both, and some may offer other regions), and on the settings in block management.</p>
18 19 20 21 22
<p>The block management screen lets you specify the vertical sort-order of the blocks within a sidebar. You do this by assigning a weight to each block. Lighter blocks (smaller weight) "float up" towards the top of the sidebar. Heavier ones "sink down" towards the bottom of it.</p>
<p>A block\'s visibility depends on:</p>
<ul>
<li>Its enabled checkbox. Disabled blocks are never shown.</li>
<li>Its throttle checkbox. Throttled blocks are hidden during high server loads.</li>
23
<li>Its path options. Blocks can be configured to only show/hide on certain pages.</li>
24 25 26 27 28 29
<li>User settings. You can choose to let your users decide whether to show/hide certain blocks.</li>
<li>Its function. Dynamic blocks (such as those defined by modules) may be empty on certain pages and will not be shown.</li>
</ul>

<h3>Administrator defined blocks</h3>
<p>An administrator defined block contains content supplied by you (as opposed to being generated automatically by a module). Each admin-defined block consists of a title, a description, and a body which can be as long as you wish. The Drupal engine will render the content of the block.</p>');
Dries's avatar
 
Dries committed
30
    case 'admin/modules#description':
Dries's avatar
 
Dries committed
31
      return t('Controls the boxes that are displayed around the main content.');
Dries's avatar
 
Dries committed
32
    case 'admin/block':
33
      return t("
34 35
<p>Blocks are content rendered into regions, often boxes in the left and right side bars of the web site. They are made available by modules or created manually.</p>
<p>Only enabled blocks are shown. You can position the blocks by deciding which area of the page they will show up on (e.g., a sidebar) and in which order they appear (weight).  Highlighting on this page shows the regions where content will be rendered.</p>
36
<p>If you want certain blocks to disable themselves temporarily during high server loads, check the 'Throttle' box. You can configure the auto-throttle on the <a href=\"%throttle\">throttle configuration page</a> after having enabled the throttle module.</p>
37
", array('%throttle' => url('admin/settings/throttle')));
Dries's avatar
 
Dries committed
38
    case 'admin/block/add':
39
      return t('<p>Here you can create a new block. Once you have created this block you must make it active and give it a place on the page using <a href="%overview">blocks</a>. The title is used when displaying the block. The description is used in the "block" column on the <a href="%overview">blocks</a> page.</p>', array('%overview' => url('admin/block')));
Dries's avatar
 
Dries committed
40
  }
Dries's avatar
 
Dries committed
41 42
}

Dries's avatar
 
Dries committed
43 44 45
/**
 * Implementation of hook_perm().
 */
Dries's avatar
 
Dries committed
46
function block_perm() {
Dries's avatar
 
Dries committed
47
  return array('administer blocks');
Dries's avatar
 
Dries committed
48 49
}

Dries's avatar
 
Dries committed
50
/**
Dries's avatar
 
Dries committed
51
 * Implementation of hook_menu().
Dries's avatar
 
Dries committed
52
 */
Dries's avatar
 
Dries committed
53
function block_menu($may_cache) {
Dries's avatar
 
Dries committed
54
  $items = array();
Dries's avatar
 
Dries committed
55 56 57 58 59 60 61

  if ($may_cache) {
    $items[] = array('path' => 'admin/block', 'title' => t('blocks'),
      'access' => user_access('administer blocks'),
      'callback' => 'block_admin');
    $items[] = array('path' => 'admin/block/list', 'title' => t('list'),
      'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
62
    $items[] = array('path' => 'admin/block/configure', 'title' => t('configure block'),
Dries's avatar
 
Dries committed
63
      'access' => user_access('administer blocks'),
64 65 66 67 68
      'callback' => 'block_admin_configure',
      'type' => MENU_CALLBACK);
    $items[] = array('path' => 'admin/block/delete', 'title' => t('delete block'),
      'access' => user_access('administer blocks'),
      'callback' => 'block_box_delete',
Dries's avatar
 
Dries committed
69
      'type' => MENU_CALLBACK);
Dries's avatar
 
Dries committed
70
    $items[] = array('path' => 'admin/block/add', 'title' => t('add block'),
Dries's avatar
 
Dries committed
71
      'access' => user_access('administer blocks'),
72
      'callback' => 'block_box_add',
Dries's avatar
 
Dries committed
73
      'type' => MENU_LOCAL_TASK);
74 75 76 77 78 79 80 81 82 83 84 85
    foreach (list_themes() as $key => $theme) {
      if ($theme->status) {
        if ($key == variable_get('theme_default', 'bluemarine')) {
          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
            'access' => user_access('administer blocks'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
        }
        else {
          $items[] = array('path' => 'admin/block/list/' . $key, 'title' => t('%key settings', array('%key' => $key)),
            'access' => user_access('administer blocks'), 'type' => MENU_LOCAL_TASK);
        }
      }
    }
Dries's avatar
 
Dries committed
86 87
  }

Dries's avatar
 
Dries committed
88
  return $items;
Dries's avatar
 
Dries committed
89 90
}

Dries's avatar
 
Dries committed
91 92 93 94 95
/**
 * Implementation of hook_block().
 *
 * Generates the administrator-defined blocks for display.
 */
96 97 98 99 100
function block_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $result = db_query('SELECT bid, title, info FROM {boxes} ORDER BY title');
      while ($block = db_fetch_object($result)) {
101
        $blocks[$block->bid]['info'] = $block->info ? check_plain($block->info) : check_plain($block->title);
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
      }
      return $blocks;

    case 'configure':
      $box = block_box_get($delta);
      if (filter_access($box['format'])) {
        return block_box_form($box);
      }
      break;

    case 'save':
      block_box_save($edit, $delta);
      break;

    case 'view':
      $block = db_fetch_object(db_query('SELECT * FROM {boxes} WHERE bid = %d', $delta));
118
      $data['subject'] = check_plain($block->title);
119
      $data['content'] = check_markup($block->body, $block->format, FALSE);
120
      return $data;
121 122 123
  }
}

Dries's avatar
 
Dries committed
124
function block_admin_save($edit) {
Dries's avatar
 
Dries committed
125 126
  foreach ($edit as $module => $blocks) {
    foreach ($blocks as $delta => $block) {
127 128
      db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'",
                $block['status'], $block['weight'], $block['region'], $block['throttle'], $module, $delta, $block['theme']);
Dries's avatar
 
Dries committed
129
    }
Dries's avatar
 
Dries committed
130 131 132
  }
}

Dries's avatar
 
Dries committed
133
/**
Dries's avatar
 
Dries committed
134
 * Update the 'blocks' DB table with the blocks currently exported by modules.
Dries's avatar
 
Dries committed
135
 *
Dries's avatar
 
Dries committed
136 137 138
 * @param $order_by php <a
 *   href="http://www.php.net/manual/en/function.array-multisort.php">array_multisort()</a>
 *   style sort ordering, eg. "weight", SORT_ASC, SORT_STRING.
139
 *
Dries's avatar
 
Dries committed
140 141
 * @return
 *   Blocks currently exported by modules, sorted by $order_by.
Dries's avatar
 
Dries committed
142
 */
Dries's avatar
 
Dries committed
143
function _block_rehash($order_by = array('weight')) {
144 145 146 147 148 149 150
  global $theme_key;

  if (empty($theme_key)) {
    init_theme();
  }

  $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key);
Dries's avatar
 
Dries committed
151 152 153 154
  while ($old_block = db_fetch_object($result)) {
    $old_blocks[$old_block->module][$old_block->delta] = $old_block;
  }

155
  db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
Dries's avatar
 
Dries committed
156 157

  foreach (module_list() as $module) {
Dries's avatar
 
Dries committed
158
    $module_blocks = module_invoke($module, 'block', 'list');
Dries's avatar
 
Dries committed
159 160
    if ($module_blocks) {
      foreach ($module_blocks as $delta => $block) {
Dries's avatar
 
Dries committed
161 162
        $block['module'] = $module;
        $block['delta']  = $delta;
163
        // If previously written to database, load values.
Dries's avatar
 
Dries committed
164
        if ($old_blocks[$module][$delta]) {
Dries's avatar
 
Dries committed
165 166 167
          $block['status'] = $old_blocks[$module][$delta]->status;
          $block['weight'] = $old_blocks[$module][$delta]->weight;
          $block['region'] = $old_blocks[$module][$delta]->region;
168 169
          $block['visibility'] = $old_blocks[$module][$delta]->visibility;
          $block['pages'] = $old_blocks[$module][$delta]->pages;
Dries's avatar
 
Dries committed
170 171
          $block['custom'] = $old_blocks[$module][$delta]->custom;
          $block['throttle'] = $old_blocks[$module][$delta]->throttle;
Dries's avatar
 
Dries committed
172
        }
173
        // Otherwise, use any set values, or else substitute defaults.
Dries's avatar
 
Dries committed
174
        else {
175 176 177 178 179 180
          $properties = array ('status' => 0, 'weight' => 0, 'region' => 'left', 'pages' => '', 'custom' => 0);
          foreach ($properties as $property => $default) {
            if (!isset ($block[$property])) {
              $block[$property] = $default;
            }
          }
Dries's avatar
 
Dries committed
181 182 183
        }

        // reinsert blocks into table
184 185
        db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
          $block['module'], $block['delta'], $theme_key, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
Dries's avatar
 
Dries committed
186
        $blocks[] = $block;
Dries's avatar
 
Dries committed
187

Dries's avatar
 
Dries committed
188 189
        // build array to sort on
        $order[$order_by[0]][] = $block[$order_by[0]];
Dries's avatar
 
Dries committed
190 191 192 193
      }
    }
  }

Dries's avatar
 
Dries committed
194 195 196
  // sort
  array_multisort($order[$order_by[0]], $order_by[1] ? $order_by[1] : SORT_ASC, $order_by[2] ? $order_by[2] : SORT_REGULAR, $blocks);

Dries's avatar
 
Dries committed
197 198
  return $blocks;
}
Dries's avatar
 
Dries committed
199

Dries's avatar
 
Dries committed
200 201 202
/**
 * Prepare the main block administration form.
 */
Dries's avatar
 
Dries committed
203
function block_admin_display() {
204 205 206 207 208 209 210 211 212 213 214 215 216 217
  global $theme_key;
  $throttle = module_exist('throttle');

  $blocks = _block_rehash();
  $block_regions = system_region_list($theme_key);

  $form[action] = arg(3) ? url('admin/block/list/' . $theme_key) : url('admin/block');
  $form[tree] = TRUE;
  foreach ($blocks as $block) {
    $form[$block['module']][$block['delta']]['info'] = array(type => 'markup', value => $block['info']);
    $form[$block['module']][$block['delta']]['status'] = array(type => 'checkbox', default_value => $block['status']);
    $form[$block['module']][$block['delta']]['theme'] = array(type => 'hidden', value => $theme_key);
    $form[$block['module']][$block['delta']]['weight'] = array(type => 'weight', default_value => $block['weight']);
    $form[$block['module']][$block['delta']]['region'] = array(type => 'select', default_value => isset($block['region']) ? $block['region'] : system_default_region(), options => $block_regions);
218

219 220 221 222 223 224 225 226 227 228 229 230 231 232
    if ($throttle) {
      $form[$block['module']][$block['delta']]['throttle'] = array(type => 'checkbox', default_value => $block['throttle']);
    }
    $form[$block['module']][$block['delta']]['configure'] = array(type => 'markup', value => l(t('configure'), 'admin/block/configure/'. $block['module'] .'/'. $block['delta']));
    if ($block['module'] == 'block') {
      $form[$block['module']][$block['delta']]['delete'] = array(type => 'markup', value => l(t('delete'), 'admin/block/delete/'. $block['delta']));
    }
  }
  $form['submit'] = array(type => 'submit', value => t('Save blocks'));

  return drupal_get_form('block_admin_display', $form);
}

function theme_block_admin_display($form) {
233

234
  global $theme_key, $custom_theme;
235
  $throttle = module_exist('throttle');
236 237 238 239 240 241 242

  // If non-default theme configuration has been selected, set the custom theme.
  if (arg(3)) {
    $custom_theme = arg(3);
    init_theme();
  }
  $block_regions = system_region_list($theme_key);
243

244 245 246 247 248
  // Highlight regions on page, to provide visual reference.
  foreach ($block_regions as $key => $value) {
    drupal_set_content($key, '<div class="block-region">' . $value . '</div>');
  }
  $regions = array();
249
  $disabled = array();
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
  foreach (element_children($form) as $module) {
    // Don't take form control structures
    if (is_array($form[$module])) {
      foreach ($form[$module] as $delta => $element) {
        // Only take form elements that are blocks
        if (is_array($form[$module][$delta]['info'])) {
          $block = $form[$module][$delta];
          $row = array(array('data' => form_render($block['info']), 'class' => 'block'), form_render($block['status']) . form_render($block['theme']), form_render($block['weight']), form_render($block['region']));
          if ($throttle) {
            $row[] = form_render($block['throttle']);
          }
          $row[] = form_render($block['configure']);
          $row[] = $block['delete'] ? form_render($block['delete']) : '';
          if ($block['status'][default_value]) {
            $regions[$block['region'][default_value]][] = $row;
          }
          else if ($block['region'][default_value] <= 1) {
            $disabled[] = $row;
          }
269
        }
270 271
      }
    }
Dries's avatar
 
Dries committed
272
  }
273

274
  $rows = array();
275 276 277
  if (count($regions)) {
    foreach ($regions as $region => $row) {
      $region_title = t('%region', array ('%region' => ucfirst($block_regions[$region])));
278
      $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
279 280
      $rows = array_merge($rows, $row);
    }
281 282
  }
  if (count($disabled)) {
283
    $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
284 285
    $rows = array_merge($rows, $disabled);
  }
286 287 288 289 290
  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Placement'));
  if ($throttle) {
    $header[] = t('Throttle');
  }
  $header[] = array('data' => t('Operations'), 'colspan' => 2);
291
  $output = theme('table', $header, $rows, array('id' => 'blocks'));
292 293
  $output .= form_render($form['submit']);
  return $output;
Dries's avatar
 
Dries committed
294 295
}

296
function block_box_get($bid) {
Dries's avatar
 
Dries committed
297 298 299 300
  return db_fetch_array(db_query('SELECT * FROM {boxes} WHERE bid = %d', $bid));
}

/**
301
 * Menu callback; displays the block configuration form.
Dries's avatar
 
Dries committed
302
 */
303
function block_admin_configure($module = NULL, $delta = 0) {
Dries's avatar
 
Dries committed
304 305 306
  $edit = $_POST['edit'];
  $op = $_POST['op'];

307 308
  switch ($op) {
    case t('Save block'):
309
      db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d WHERE module = '%s' AND delta = '%s'", $edit['visibility'], $edit['pages'], $edit['custom'], $module, $delta);
310
      module_invoke($module, 'block', 'save', $delta, $edit);
311
      drupal_set_message(t('The block configuration has been saved.'));
312 313 314
      cache_clear_all();
      drupal_goto('admin/block');

315 316 317
    default:
      // Always evaluates to TRUE, but a validation step may be added later.
      if (!$edit) {
318
        $edit = db_fetch_array(db_query("SELECT pages, visibility, custom FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta));
319 320 321 322
      }

      // Module-specific block configurations.
      if ($settings = module_invoke($module, 'block', 'configure', $delta)) {
323
          $form['block_settings'] = array(type => 'fieldset',
324 325 326 327 328 329 330 331
            title => t('Block specific settings'),
            collapsible => true,
            collapsed => false,
            weight => 0);

          foreach ($settings as $k => $v) {
            $form['block_settings'][$k] = $v;
          }
332 333 334 335 336
      }

      // Get the block subject for the page title.
      $info = module_invoke($module, 'block', 'list');
      drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])));
337

338
      // Standard block configurations.
339

340 341 342 343 344 345 346 347 348 349 350 351 352
      $form['user_vis_settings'] = array(type => 'fieldset',
        title => t('User specific visibility settings'),
        collapsible => true,
        collapsed => false,
        weight => 0);

      $form['user_vis_settings']['custom'] = array(
        type => 'radios',
        title => t('Custom visibility settings'),
        default_value => $edit['custom'],
        options => array(t('Users cannot control whether or not they see this block.'), t('Show this block by default, but let individual users hide it.'), t('Hide this block by default but let individual users show it.')), t('Allow individual users to customize the visibility of this block in their account settings.'),
        default_value => $edit['custom']);

353

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
      $form['page_vis_settings'] = array(type => 'fieldset',
        title => t('Page specific visibility settings'),
        collapsible => true,
        collapsed => false,
        weight => 0);


      $form['page_vis_settings']['visibility'] = array(
        type => 'radios',
        title => t('Show block on specific pages'),
        default_value => $edit['visibility'],
        options => array(t('Show on every page except the listed pages.'), t('Show on only the listed pages.'), t('Show if the following PHP code returns <code>TRUE</code> (PHP-mode, experts only).')),
        default_value => $edit['visibility']);

      $form['page_vis_settings']['pages'] = array(
        type => 'textarea',
        title => t('Pages'),
        default_value => $edit['pages'],
        cols => 60,
        rows => 5,
        description => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are '%blog' for the blog page and %blog1 for every personal blog. %front is the front page. If the PHP-mode is chosen, enter PHP code between %php.  Note that executing incorrect PHP-code can break your Drupal site.", array('%blog' => theme('placeholder', 'blog'), '%blog1' =>  theme('placeholder', 'blog/*'), '%front' => theme('placeholder', '<front>'), '%php' => theme('placeholder', '<?php ?>'))));

      $form['submit'] = array(type => 'submit', value => t('Save block'));

      return drupal_get_form('block_config', $form);
379 380 381 382 383 384 385 386 387 388 389 390
  }
}

/**
 * Menu callback; displays the block creation form.
 */
function block_box_add() {
  $edit = $_POST['edit'];
  $op = $_POST['op'];

  switch ($op) {
    case t('Save block'):
Dries's avatar
 
Dries committed
391
      if (block_box_save($edit)) {
392
        drupal_set_message(t('The block has been created.'));
Dries's avatar
 
Dries committed
393 394 395
        drupal_goto('admin/block');
      }
      // deliberate no break
396
    default:
Dries's avatar
 
Dries committed
397
      $form = block_box_form($edit);
398
      $form['submit'] = array(type => 'submit', value => t('Save block'));
399 400
  }

401
  return drupal_get_form('block_box_add', $form);
402 403 404
}

/**
405
 * Menu callback; confirm deletion of custom blocks.
406 407 408
 */
function block_box_delete($bid = 0) {
  $box = block_box_get($bid);
409 410
  $form['info'] = array(type => 'hidden', value => $box['info'] ? $box['info'] : $box['title']);
  $form['bid'] = array(type => 'hidden', value => $bid);
Dries's avatar
 
Dries committed
411

412
  return confirm_form('block_box_delete_confirm', $form, t('Are you sure you want to delete the block %name?', array('%name' => theme('placeholder', $info))), 'admin/block', '', t('Delete'), t('Cancel'));
413 414
}

415 416 417 418 419 420 421 422 423 424 425 426
/**
 * Deletion of custom blocks.
 */
function block_box_delete_confirm_execute($form_id, $edit) {
  $form = $GLOBALS['form_values'];
  db_query('DELETE FROM {boxes} WHERE bid = %d', $form['bid']);
  drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form['info']))));
  cache_clear_all();
  drupal_goto('admin/block');
};


427
function block_box_form($edit = array()) {
428 429 430 431
  $form['title'] = array(type => 'textfield', title => t('Block title'), default_value => $edit['title'], size => 60, maxlength => 64, description => t('The title of the block as shown to the user.'));
  $form['format'] = filter_form($edit['format']);
  $form['body'] = array(type => 'textarea', title => t('Block body'), default_value => $edit['body'], cols => 60, rows => 15, description => t('The content of the block as shown to the user.'));
  $form['info'] = array(type => 'textfield', title => t('Block description'), default_value => $edit['info'], size => 60, maxlength => 64, description => t('A brief description of your block. Used on the <a href="%overview">block overview page</a>.', array('%overview' => url('admin/block'))), required => TRUE);
432

433
  return $form;
434 435
}

436
function block_box_save($edit, $delta = NULL) {
437 438
  if (!filter_access($edit['format'])) {
    $edit['format'] = FILTER_FORMAT_DEFAULT;
Dries's avatar
 
Dries committed
439 440
  }

441 442
  if (isset($delta)) {
    db_query("UPDATE {boxes} SET title = '%s', body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['title'], $edit['body'], $edit['info'], $edit['format'], $delta);
443 444
  }
  else {
Dries's avatar
 
Dries committed
445
    if (empty($edit['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $edit['info']))) {
446
      form_set_error('info', t('Please ensure that each block description is unique.'));
Dries's avatar
 
Dries committed
447 448
      return false;
    }
449
    db_query("INSERT INTO {boxes} (title, body, info, format) VALUES  ('%s', '%s', '%s', %d)", $edit['title'], $edit['body'], $edit['info'], $edit['format']);
450
  }
Dries's avatar
 
Dries committed
451
  return true;
452 453
}

Dries's avatar
 
Dries committed
454
/**
Dries's avatar
Dries committed
455
 * Menu callback; displays the block overview page.
Dries's avatar
 
Dries committed
456
 */
Dries's avatar
 
Dries committed
457
function block_admin() {
Dries's avatar
 
Dries committed
458 459
  $edit = $_POST['edit'];
  $op = $_POST['op'];
Dries's avatar
 
Dries committed
460

Dries's avatar
 
Dries committed
461
  if ($op == t('Save blocks')) {
462 463
    block_admin_save($edit);
    drupal_set_message(t('The blocks have been saved.'));
Dries's avatar
 
Dries committed
464
    cache_clear_all();
465
    drupal_goto($_GET['q']);
Dries's avatar
 
Dries committed
466
  }
Dries's avatar
 
Dries committed
467
  return block_admin_display();
Dries's avatar
 
Dries committed
468
}
Dries's avatar
 
Dries committed
469

Dries's avatar
 
Dries committed
470 471 472 473 474 475
/**
 * Implementation of hook_user().
 *
 * Allow users to decide which custom blocks to display when they visit
 * the site.
 */
476
function block_user($type, $edit, &$user, $category = NULL) {
477
  switch ($type) {
478
    case 'form':
479
      if ($category == 'account') {
480
        $result = db_query('SELECT * FROM {blocks} WHERE status = 1 AND custom != 0 ORDER BY weight, module, delta');
481
        $form['block'] = array(type => 'fieldset', title => t('Block configuration'), weight => 3, collapsible => TRUE, collapsed => FALSE, tree => TRUE);
482 483 484
        while ($block = db_fetch_object($result)) {
          $data = module_invoke($block->module, 'block', 'list');
          if ($data[$block->delta]['info']) {
485 486
            $return = TRUE;
            $form['block'][$block->module][$block->delta] = array(type => 'checkbox', title => $data[$block->delta]['info'], default_value => isset($user->block[$block->module][$block->delta]) ? $user->block[$block->module][$block->delta] : ($block->custom == 1));
487
          }
Kjartan's avatar
Kjartan committed
488 489
        }

490 491
        if ($return) {
          return $form;
492
        }
493
      }
Dries's avatar
 
Dries committed
494 495

      break;
Dries's avatar
 
Dries committed
496 497 498
    case 'validate':
      if (!$edit['block']) {
        $edit['block'] = array();
499 500
      }
      return $edit;
501 502 503
  }
}

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
/**
 * Return 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 <i>module</i>_<i>delta</i>.
 *   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
 *   Add a proper primary key (bid) to the blocks table so we don't have
 *   to mess around with this <i>module</i>_<i>delta</i> construct.
 *   Currently, the blocks table has no primary key defined!
 */
function block_list($region) {
  global $user, $theme_key;

524 525
  static $blocks = array();

526 527
  if (!count($blocks)) {
    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s' AND status = 1 ORDER BY region, weight, module", $theme_key);
528
    while ($block = db_fetch_object($result)) {
529 530 531
      if(!isset($blocks[$block->region])) {
        $blocks[$block->region] = array();
      }
532
      // Use the user's block visibility setting, if necessary
533 534 535
      if ($block->custom != 0) {
        if ($user->uid && isset($user->block[$block->module][$block->delta])) {
          $enabled = $user->block[$block->module][$block->delta];
536 537
        }
        else {
538
          $enabled = ($block->custom == 1);
539 540 541 542
        }
      }
      else {
        $enabled = TRUE;
543
      }
544 545

      // Match path if necessary
546 547
      if ($block->pages) {
        if ($block->visibility < 2) {
548
          $path = drupal_get_path_alias($_GET['q']);
549 550
          $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($block->pages, '/')) .')$/';
          $page_match = !($block->visibility xor preg_match($regexp, $path));
551 552
        }
        else {
553
          $page_match = drupal_eval($block->pages);
554
        }
555 556
      }
      else {
557
        $page_match = TRUE;
558
      }
559

560
      if ($enabled && $page_match) {
561 562
        // Check the current throttle status and see if block should be displayed
        // based on server load.
563 564 565 566 567
        if (!($block->throttle && (module_invoke('throttle', 'status') > 0))) {
          if (is_array($array = module_invoke($block->module, 'block', 'view', $block->delta))) {
            foreach ($array as $k => $v) {
              $block->$k = $v;
            }
568
          }
Dries's avatar
 
Dries committed
569
        }
570 571
        if (isset($block->content) && $block->content) {
          $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block;
572 573 574 575
        }
      }
    }
  }
576 577 578 579
  // Create an empty array if there were no entries
  if(!isset($blocks[$region])) {
    $blocks[$region] = array();
  }
580 581 582
  return $blocks[$region];
}

583