block.module 24.9 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 16 17 18
      $output = '<p>'. t('Blocks are the boxes of related/grouped data that are visible in the sidebar(s) of your web site. These are usually generated automatically by modules (e.g. recent forum topics), but administrators can also create their own defined blocks.') .'</p>';
      $output .= '<p>'. t('The sidebar each block appears in depends on both which theme you are using (some are left-only, some right, some both), and on the settings in block management.') .'</p>';
      $output .= '<p>'. t('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>';
      $output .= t('<p>A block\'s visibility depends on:</p>
19 20 21
<ul>
<li>Its enabled checkbox. Disabled blocks are never shown.</li>
<li>Its throttle checkbox. Throttled blocks are hidden during high server loads.</li>
22
<li>Its path options. Blocks can be configured to only show/hide on certain pages.</li>
23
<li>User settings. Administrators can choose to let your users decide whether to show/hide certain blocks.</li>
24 25
<li>Its function. Dynamic blocks (such as those defined by modules) may be empty on certain pages and will not be shown.</li>
</ul>
26 27 28 29 30 31 32 33 34 35 36 37 38
');
      $output .= '<h3>'. t('Module blocks') .'</h3>';
      $output .= '<p>'. t('Module blocks are available when modules are enabled.  These blocks can be administered in block administration.') .'</p>';
      $output .= '<h3>'. t('Administrator defined blocks') .'</h3>';
      $output .= '<p>'. t('An administrator defined block contains content supplied by the administrator. 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>';
      $output .= t('<p>You can</p>
<ul>
<li>enable throttle and configure blocks at <a href="%admin-block">administer &gt;&gt; block</a>.</li>
<li>add a block at <a href="%admin-block-add">administer &gt;&gt; block &gt;&gt; add block</a>.</li>
</ul>
', array('%admin-block' => url('admin/block'), '%admin-block-add' => url('admin/block/add')));
      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%block">Block page</a>.', array('%block' => 'http://www.drupal.org/handbook/modules/block/')) .'</p>';
      return $output;
Dries's avatar
 
Dries committed
39
    case 'admin/modules#description':
Dries's avatar
 
Dries committed
40
      return t('Controls the boxes that are displayed around the main content.');
Dries's avatar
 
Dries committed
41
    case 'admin/block':
42
      return t("
43 44
<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>
45
<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>
46
", array('%throttle' => url('admin/settings/throttle')));
Dries's avatar
 
Dries committed
47
    case 'admin/block/add':
48
      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
49
  }
Dries's avatar
 
Dries committed
50 51
}

Dries's avatar
 
Dries committed
52 53 54
/**
 * Implementation of hook_perm().
 */
Dries's avatar
 
Dries committed
55
function block_perm() {
Dries's avatar
 
Dries committed
56
  return array('administer blocks');
Dries's avatar
 
Dries committed
57 58
}

Dries's avatar
 
Dries committed
59
/**
Dries's avatar
 
Dries committed
60
 * Implementation of hook_menu().
Dries's avatar
 
Dries committed
61
 */
Dries's avatar
 
Dries committed
62
function block_menu($may_cache) {
Dries's avatar
 
Dries committed
63
  $items = array();
Dries's avatar
 
Dries committed
64 65 66 67 68 69 70

  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);
71
    $items[] = array('path' => 'admin/block/configure', 'title' => t('configure block'),
Dries's avatar
 
Dries committed
72
      'access' => user_access('administer blocks'),
73 74 75 76 77
      '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
78
      'type' => MENU_CALLBACK);
Dries's avatar
 
Dries committed
79
    $items[] = array('path' => 'admin/block/add', 'title' => t('add block'),
Dries's avatar
 
Dries committed
80
      'access' => user_access('administer blocks'),
81
      'callback' => 'block_box_add',
Dries's avatar
 
Dries committed
82
      'type' => MENU_LOCAL_TASK);
83 84 85 86 87 88 89 90 91 92 93 94
    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
95 96
  }

Dries's avatar
 
Dries committed
97
  return $items;
Dries's avatar
 
Dries committed
98 99
}

Dries's avatar
 
Dries committed
100 101 102 103 104
/**
 * Implementation of hook_block().
 *
 * Generates the administrator-defined blocks for display.
 */
105 106 107
function block_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
108 109
      $blocks = array();

110 111
      $result = db_query('SELECT bid, title, info FROM {boxes} ORDER BY title');
      while ($block = db_fetch_object($result)) {
112
        $blocks[$block->bid]['info'] = $block->info ? check_plain($block->info) : check_plain($block->title);
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
      }
      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));
129
      $data['subject'] = check_plain($block->title);
130
      $data['content'] = check_markup($block->body, $block->format, FALSE);
131
      return $data;
132 133 134
  }
}

Dries's avatar
 
Dries committed
135
function block_admin_save($edit) {
Dries's avatar
 
Dries committed
136 137
  foreach ($edit as $module => $blocks) {
    foreach ($blocks as $delta => $block) {
138 139
      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
140
    }
Dries's avatar
 
Dries committed
141 142 143
  }
}

Dries's avatar
 
Dries committed
144
/**
Dries's avatar
 
Dries committed
145
 * Update the 'blocks' DB table with the blocks currently exported by modules.
Dries's avatar
 
Dries committed
146
 *
Dries's avatar
 
Dries committed
147 148 149
 * @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.
150
 *
Dries's avatar
 
Dries committed
151 152
 * @return
 *   Blocks currently exported by modules, sorted by $order_by.
Dries's avatar
 
Dries committed
153
 */
Dries's avatar
 
Dries committed
154
function _block_rehash($order_by = array('weight')) {
155 156 157 158 159 160 161
  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
162 163 164 165
  while ($old_block = db_fetch_object($result)) {
    $old_blocks[$old_block->module][$old_block->delta] = $old_block;
  }

166
  db_query("DELETE FROM {blocks} WHERE theme = '%s'", $theme_key);
Dries's avatar
 
Dries committed
167 168

  foreach (module_list() as $module) {
Dries's avatar
 
Dries committed
169
    $module_blocks = module_invoke($module, 'block', 'list');
Dries's avatar
 
Dries committed
170 171
    if ($module_blocks) {
      foreach ($module_blocks as $delta => $block) {
Dries's avatar
 
Dries committed
172 173
        $block['module'] = $module;
        $block['delta']  = $delta;
174
        // If previously written to database, load values.
Dries's avatar
 
Dries committed
175
        if ($old_blocks[$module][$delta]) {
Dries's avatar
 
Dries committed
176 177 178
          $block['status'] = $old_blocks[$module][$delta]->status;
          $block['weight'] = $old_blocks[$module][$delta]->weight;
          $block['region'] = $old_blocks[$module][$delta]->region;
179 180
          $block['visibility'] = $old_blocks[$module][$delta]->visibility;
          $block['pages'] = $old_blocks[$module][$delta]->pages;
Dries's avatar
 
Dries committed
181 182
          $block['custom'] = $old_blocks[$module][$delta]->custom;
          $block['throttle'] = $old_blocks[$module][$delta]->throttle;
Dries's avatar
 
Dries committed
183
        }
184
        // Otherwise, use any set values, or else substitute defaults.
Dries's avatar
 
Dries committed
185
        else {
186 187 188 189 190 191
          $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
192 193 194
        }

        // reinsert blocks into table
195 196
        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
197
        $blocks[] = $block;
Dries's avatar
 
Dries committed
198

Dries's avatar
 
Dries committed
199 200
        // build array to sort on
        $order[$order_by[0]][] = $block[$order_by[0]];
Dries's avatar
 
Dries committed
201 202 203 204
      }
    }
  }

Dries's avatar
 
Dries committed
205 206 207
  // 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
208 209
  return $blocks;
}
Dries's avatar
 
Dries committed
210

Dries's avatar
 
Dries committed
211 212 213
/**
 * Prepare the main block administration form.
 */
Dries's avatar
 
Dries committed
214
function block_admin_display() {
215
  global $theme_key, $custom_theme;
216 217
  $throttle = module_exist('throttle');

218 219 220 221 222 223 224 225 226
  // If non-default theme configuration has been selected, set the custom theme.
  if (arg(3)) {
    $custom_theme = arg(3);
  }
  else {
    $custom_theme = variable_get('theme_default', 'bluemarine');
  }
  init_theme();

227 228 229
  $blocks = _block_rehash();
  $block_regions = system_region_list($theme_key);

230 231
  $form['#action'] = arg(3) ? url('admin/block/list/' . $theme_key) : url('admin/block');
  $form['#tree'] = TRUE;
232
  foreach ($blocks as $block) {
233 234 235 236 237
    $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);
238

239
    if ($throttle) {
240
      $form[$block['module']][$block['delta']]['throttle'] = array('#type' => 'checkbox', '#default_value' => $block['throttle']);
241
    }
242
    $form[$block['module']][$block['delta']]['configure'] = array('#type' => 'markup', '#value' => l(t('configure'), 'admin/block/configure/'. $block['module'] .'/'. $block['delta']));
243
    if ($block['module'] == 'block') {
244
      $form[$block['module']][$block['delta']]['delete'] = array('#type' => 'markup', '#value' => l(t('delete'), 'admin/block/delete/'. $block['delta']));
245 246
    }
  }
247
  $form['submit'] = array('#type' => 'submit', '#value' => t('Save blocks'));
248 249 250 251 252

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

function theme_block_admin_display($form) {
253
  global $theme_key;
254
  $throttle = module_exist('throttle');
255 256

  $block_regions = system_region_list($theme_key);
257

258 259 260 261 262
  // 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();
263
  $disabled = array();
264 265 266 267 268 269 270 271 272 273 274 275 276
  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']) : '';
277 278
          if ($block['status']['#default_value']) {
            $regions[$block['region']['#default_value']][] = $row;
279
          }
280
          else if ($block['region']['#default_value'] <= 1) {
281 282
            $disabled[] = $row;
          }
283
        }
284 285
      }
    }
Dries's avatar
 
Dries committed
286
  }
287

288
  $rows = array();
289 290 291
  if (count($regions)) {
    foreach ($regions as $region => $row) {
      $region_title = t('%region', array ('%region' => ucfirst($block_regions[$region])));
292
      $rows[] = array(array('data' => $region_title, 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
293 294
      $rows = array_merge($rows, $row);
    }
295 296
  }
  if (count($disabled)) {
297
    $rows[] = array(array('data' => t('Disabled'), 'class' => 'region', 'colspan' => ($throttle ? 7 : 6)));
298 299
    $rows = array_merge($rows, $disabled);
  }
300 301 302 303 304
  $header = array(t('Block'), t('Enabled'), t('Weight'), t('Placement'));
  if ($throttle) {
    $header[] = t('Throttle');
  }
  $header[] = array('data' => t('Operations'), 'colspan' => 2);
305
  $output = theme('table', $header, $rows, array('id' => 'blocks'));
306 307
  $output .= form_render($form['submit']);
  return $output;
Dries's avatar
 
Dries committed
308 309
}

310
function block_box_get($bid) {
Dries's avatar
 
Dries committed
311 312 313 314
  return db_fetch_array(db_query('SELECT * FROM {boxes} WHERE bid = %d', $bid));
}

/**
315
 * Menu callback; displays the block configuration form.
Dries's avatar
 
Dries committed
316
 */
317
function block_admin_configure($module = NULL, $delta = 0) {
318

319 320
  $form['module'] = array('#type' => 'value', '#value' => $module);
  $form['delta'] = array('#type' => 'value', '#value' => $delta);
321

322
  $edit = db_fetch_array(db_query("SELECT pages, visibility, custom FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta));
323

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

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

338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 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 379 380
  // 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'])));

  // Standard block configurations.

  $form['user_vis_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('User specific visibility settings'),
    '#collapsible' => true,
    '#weight' => 0,
  );
  $form['user_vis_settings']['custom'] = array(
    '#type' => 'radios',
    '#title' => t('Custom visibility settings'),
    '#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'],
  );
  $form['page_vis_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Page specific visibility settings'),
    '#collapsible' => true,
    '#weight' => 0,
  );
  $form['page_vis_settings']['visibility'] = array(
    '#type' => 'radios',
    '#title' => t('Show block on specific pages'),
    '#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'],
    '#description' => t("Enter one page per line as Drupal paths. 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. 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'), '%blog-wildcard' =>  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_admin_configure', $form);
}
381

382 383 384 385 386
function block_admin_configure_validate($form_id, $form_values) {
  if (empty($form_values['info']) || db_num_rows(db_query("SELECT bid FROM {boxes} WHERE bid != %d AND info = '%s'", $form_values['delta'], $form_values['info']))) {
    form_set_error('info', t('Please ensure that each block description is unique.'));
  }
}
387

388 389 390 391 392 393 394
function block_admin_configure_execute($form_id, $form_values) {
  if (!form_get_errors()) {
    db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d WHERE module = '%s' AND delta = '%s'", $form_values['visibility'], $form_values['pages'], $form_values['custom'], $form_values['module'], $form_values['delta']);
    module_invoke($form_values['module'], 'block', 'save', $form_values['delta'], $form_values);
    drupal_set_message(t('The block configuration has been saved.'));
    cache_clear_all();
    drupal_goto('admin/block');
395 396 397 398 399 400 401
  }
}

/**
 * Menu callback; displays the block creation form.
 */
function block_box_add() {
402 403
  $form = block_box_form();
  $form['submit'] = array('#type' => 'submit', '#value' => t('Save block'));
404

405 406 407 408 409 410
  return drupal_get_form('block_box_add', $form);
}

function block_box_add_validate($form_id, $form_values) {
  if (empty($form_values['info']) || db_num_rows(db_query("SELECT info FROM {boxes} WHERE info = '%s'", $form_values['info']))) {
    form_set_error('info', t('Please ensure that each block description is unique.'));
411
  }
412
}
413

414 415 416 417 418 419 420
function block_box_add_execute($form_id, $form_values) {
  if (!form_get_errors()) {
    if (block_box_save($form_values)) {
      drupal_set_message(t('The block has been created.'));
      drupal_goto('admin/block');
    }
  }
421 422 423
}

/**
424
 * Menu callback; confirm deletion of custom blocks.
425 426 427
 */
function block_box_delete($bid = 0) {
  $box = block_box_get($bid);
428 429
  $form['info'] = array('#type' => 'hidden', '#value' => $box['info'] ? $box['info'] : $box['title']);
  $form['bid'] = array('#type' => 'hidden', '#value' => $bid);
Dries's avatar
 
Dries committed
430

431
  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'));
432 433
}

434 435 436
/**
 * Deletion of custom blocks.
 */
437 438 439
function block_box_delete_confirm_execute($form_id, $form_values) {
  db_query('DELETE FROM {boxes} WHERE bid = %d', $form_values['bid']);
  drupal_set_message(t('The block %name has been removed.', array('%name' => theme('placeholder', $form_values['info']))));
440 441 442 443 444
  cache_clear_all();
  drupal_goto('admin/block');
};


445
function block_box_form($edit = array()) {
446
  $form['title'] = array('#type' => 'textfield', '#title' => t('Block title'), '#default_value' => $edit['title'], '#maxlength' => 64, '#description' => t('The title of the block as shown to the user.'));
447
  $form['format'] = filter_form($edit['format']);
448 449
  $form['body'] = array('#type' => 'textarea', '#title' => t('Block body'), '#default_value' => $edit['body'], '#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'], '#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);
450

451
  return $form;
452 453
}

454
function block_box_save($edit, $delta = NULL) {
455 456
  if (!filter_access($edit['format'])) {
    $edit['format'] = FILTER_FORMAT_DEFAULT;
Dries's avatar
 
Dries committed
457 458
  }

459 460
  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);
461 462
  }
  else {
463
    db_query("INSERT INTO {boxes} (title, body, info, format) VALUES  ('%s', '%s', '%s', %d)", $edit['title'], $edit['body'], $edit['info'], $edit['format']);
464
  }
Dries's avatar
 
Dries committed
465
  return true;
466 467
}

Dries's avatar
 
Dries committed
468
/**
Dries's avatar
Dries committed
469
 * Menu callback; displays the block overview page.
Dries's avatar
 
Dries committed
470
 */
Dries's avatar
 
Dries committed
471
function block_admin() {
472 473
  $edit = isset($_POST['edit']) ? $_POST['edit'] : '';
  $op = isset($_POST['op']) ? $_POST['op'] : '';
Dries's avatar
 
Dries committed
474

Dries's avatar
 
Dries committed
475
  if ($op == t('Save blocks')) {
476 477
    block_admin_save($edit);
    drupal_set_message(t('The blocks have been saved.'));
Dries's avatar
 
Dries committed
478
    cache_clear_all();
479
    drupal_goto($_GET['q']);
Dries's avatar
 
Dries committed
480
  }
Dries's avatar
 
Dries committed
481
  return block_admin_display();
Dries's avatar
 
Dries committed
482
}
Dries's avatar
 
Dries committed
483

Dries's avatar
 
Dries committed
484 485 486 487 488 489
/**
 * Implementation of hook_user().
 *
 * Allow users to decide which custom blocks to display when they visit
 * the site.
 */
490
function block_user($type, $edit, &$user, $category = NULL) {
491
  switch ($type) {
492
    case 'form':
493
      if ($category == 'account') {
494
        $result = db_query('SELECT * FROM {blocks} WHERE status = 1 AND custom != 0 ORDER BY weight, module, delta');
495
        $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE);
496 497 498
        while ($block = db_fetch_object($result)) {
          $data = module_invoke($block->module, 'block', 'list');
          if ($data[$block->delta]['info']) {
499
            $return = TRUE;
500
            $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));
501
          }
Kjartan's avatar
Kjartan committed
502 503
        }

504 505
        if ($return) {
          return $form;
506
        }
507
      }
Dries's avatar
 
Dries committed
508 509

      break;
Dries's avatar
 
Dries committed
510 511 512
    case 'validate':
      if (!$edit['block']) {
        $edit['block'] = array();
513 514
      }
      return $edit;
515 516 517
  }
}

518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
/**
 * 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;

538 539
  static $blocks = array();

540 541
  if (!count($blocks)) {
    $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s' AND status = 1 ORDER BY region, weight, module", $theme_key);
542
    while ($block = db_fetch_object($result)) {
543
      if (!isset($blocks[$block->region])) {
544 545
        $blocks[$block->region] = array();
      }
546
      // Use the user's block visibility setting, if necessary
547 548 549
      if ($block->custom != 0) {
        if ($user->uid && isset($user->block[$block->module][$block->delta])) {
          $enabled = $user->block[$block->module][$block->delta];
550 551
        }
        else {
552
          $enabled = ($block->custom == 1);
553 554 555 556
        }
      }
      else {
        $enabled = TRUE;
557
      }
558 559

      // Match path if necessary
560 561
      if ($block->pages) {
        if ($block->visibility < 2) {
562
          $path = drupal_get_path_alias($_GET['q']);
563 564
          $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));
565 566
        }
        else {
567
          $page_match = drupal_eval($block->pages);
568
        }
569 570
      }
      else {
571
        $page_match = TRUE;
572
      }
573

574
      if ($enabled && $page_match) {
575 576
        // Check the current throttle status and see if block should be displayed
        // based on server load.
577 578 579 580 581
        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;
            }
582
          }
Dries's avatar
 
Dries committed
583
        }
584 585
        if (isset($block->content) && $block->content) {
          $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block;
586 587 588 589
        }
      }
    }
  }
590
  // Create an empty array if there were no entries
591
  if (!isset($blocks[$region])) {
592 593
    $blocks[$region] = array();
  }
594 595 596
  return $blocks[$region];
}

597