block.module 22.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
/**
 * Implementation of hook_help().
 */
function block_help($section) {
Dries's avatar
   
Dries committed
8
  switch ($section) {
Dries's avatar
   
Dries committed
9
    case 'admin/help#block':
Dries's avatar
   
Dries committed
10
      return t("
Dries's avatar
   
Dries committed
11
<p>Blocks are the boxes visible in the sidebar(s) of your web site. These are usually generated automatically by modules (e.g. recent forum topics), but you can also create your own blocks using either static HTML or dynamic PHP content.</p>
Dries's avatar
   
Dries committed
12
13
<p>The sidebar each block appears in depends on both which theme you're using (some are left-only, some right, some both), and on the settings in block management.</p><p>Whether a block is visible in the first place depends on four things:</p><ul><li>It must have its \"enabled\" box checked in block management.</li><li>If it has its \"custom\" box checked in block management, the user must have chosen to display it in their user preferences.</li><li>If the \"path\" field in block management is set, the visitor must be on a page that matches the path specification (more on this later).</li><li>If the block has its throttle box checked, the user will only see the block if the site throttle level is low.</li></ul>
<p>The block management screen also lets you specify the vertical sort-order of the blocks within a sidebar. You do this by assigning a <strong>weight</strong> to each block. Lighter blocks (smaller weight) \"float up\" towards the top of the sidebar. Heavier ones \"sink down\" towards the bottom of it. Once you've positioned things just so, you can preview what the layout will look like in different types of themes by clicking the preview placement link in the menu to the left.</p>
Dries's avatar
   
Dries committed
14
<p>The path setting lets you define the pages on which a specific block is visible. If you leave the path blank it will appear on all pages. The path uses a regular expression syntax so remember to escape special characters! The path expression is matched against the relative URL of a Drupal page, e.g. <code>book</code>, <code>node/12</code>, <code>admin</code>.</p>
Dries's avatar
   
Dries committed
15
16
<p>In case you do not know what a regular expression is, you should read about them in the PHP manual. The chapter to look at is the one on <a href=\"%pcre\">Perl-Compatible Regular Expressions (PCRE)</a>.</p>
<p>However, for basic tasks it is sufficient to look at the following examples:</p>
Dries's avatar
   
Dries committed
17
<p>If the block should only show up on blog pages, use &lt;^blog&gt;.  To display on all node views use &lt;^node&gt;.  The angular brackets are used as delimiters of the regular expression.  To show up on either forum or book pages use &lt;^(forum|book)&gt;.  The round brackets form a group of expressions, divided by the | character. It matches if any of the expressions in it match.  A more complicated example is &lt;^node/add/(story|blog|image)&gt;. Blocks which have their paths set to this expression will show up on story, block, or image composition pages.  If you want to show a block an all pages, but not the search page, use &lt;^(?!search)&gt;.</p>
Dries's avatar
   
Dries committed
18
19
20
21
22
<h3>Administrator Defined Blocks</h3>
<p>An administrator defined block contains HTML, text or PHP 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 containing text, HTML, or PHP code which can be as long as you wish. The Drupal engine will 'render' the content of the block.</p>
<h4>PHP in admin-defined blocks</h4>
<p>If you know how to script in PHP, Drupal gives you the power to embed any script you like inside a block. It will be executed when the page is viewed and dynamically embedded into the page. This gives you amazing flexibility and power, but of course with that comes danger and insecurity if you don't write good code. If you are not familiar with PHP, SQL or with the site engine, avoid experimenting with PHP blocks because you can corrupt your database or render your site insecure or even unusable! If you don't plan to do fancy stuff with your blocks then you're probably better off with straight HTML.</p>
<p>Remember that the code within each PHP block must be valid PHP code - including things like correctly terminating statements with a semicolon so that the parser won't die. It is highly recommended that you develop your blocks separately using a simple test script on top of a test database before migrating to your production environment.</p>
23
<p>Notes:</p><ul><li>You can use global variables, such as configuration parameters, within the scope of a PHP box but remember that variables which have been given values in a PHP box will retain these values in the engine or module afterwards.</li><li>register_globals is now set to <strong>off</strong> by default. If you need form information you need to get it from the \"superglobals\" \$_POST, \$_GET, etc.</li><li>You should use the <code>return</code> statement to return the actual content for your block.</li></ul>
Dries's avatar
   
Dries committed
24
25
26
<p>A basic example:</p>
<blockquote><p>You want to have a box with the title \"Welcome\" that you use to greet your visitors. The content for this box could be created by going:</p>
<pre>
Dries's avatar
   
Dries committed
27
  return t(\"Welcome visitor, ... welcome message goes here ...\");
Dries's avatar
   
Dries committed
28
29
30
</pre>
<p>If we are however dealing with a registered user, we can customize the message by using:</p>
<pre>
Dries's avatar
   
Dries committed
31
32
33
34
35
  if (\$user->uid) {
    return t(\"Welcome \$user->name, ... welcome message goes here ...\");
  }
  else {
    return t(\"Welcome visitor, ... welcome message goes here ...\");
Dries's avatar
   
Dries committed
36
37
  }
</pre></blockquote>
Dries's avatar
   
Dries committed
38
<p>For more in-depth examples, we recommend that you check the existing boxes and use them as a starting point.</p>", array('%pcre' => 'http://php.net/pcre/'));
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
42
43
    case 'admin/block':
      return t("Blocks are the boxes in the left- and right- side bars of the web site, depending on the chosen theme.  They are created by <strong>active</strong> Drupal modules. The \"enabled\" checkbox sets the default status of the block. Only enabled blocks are shown. When the \"custom\" checkbox is checked, your users can show or hide the block using their account settings. In that case, the 'enabled' checkbox signifies the block's default status. You can assign the block's placement by giving it a region and a weight. The region specifies which side of the page the block is on, and the weight sorts blocks within a region. Lighter (smaller weight value) blocks \"float up\" towards the top of the page. The path setting lets you define which pages you want a block to be shown on. You can also create your own blocks, where you specify the content of the block rather than its being generated by a module (you can even use PHP in these). You can create one of these by clicking the <a href=\"%createblock\">add block</a> tab in the menu to the left. Edit and delete links will become active below for these admin-defined blocks.  Blocks can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by checking throttle.  The auto-throttle functionality must be enabled on the <a href=\"%throttle\">throttle configuration page</a> after having enabled the throttle module.", array('%createblock' => url('admin/block/add'), '%throttle' => url('admin/settings/throttle')));
    case 'admin/block/add':
44
      return t("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. If you are going to place PHP code in the block, and you have the <em>create php content</em> permission (see the <a href=\"%permission\">permissions</a> page), you <em>must</em> change the type to PHP to make your code active.", array('%overview' => url('admin/block'), '%permission' => url('admin/user/configure/permission')));
Dries's avatar
   
Dries committed
45
    case 'admin/block/preview':
Dries's avatar
   
Dries committed
46
      return t('This page shows you the placement of your blocks in different theme types. The numbers are the weights of each block, which are used to sort them within the sidebars.');
Dries's avatar
   
Dries committed
47
  }
Dries's avatar
   
Dries committed
48
49
}

Dries's avatar
   
Dries committed
50
/**
Dries's avatar
Dries committed
51
 * Menu callback; presents the block-specific information from admin/help.
Dries's avatar
   
Dries committed
52
 */
Dries's avatar
   
Dries committed
53
function block_help_page() {
Dries's avatar
   
Dries committed
54
  print theme('page', block_help('admin/help#block'));
Dries's avatar
   
Dries committed
55
56
}

Dries's avatar
   
Dries committed
57
58
59
/**
 * Implementation of hook_perm().
 */
Dries's avatar
   
Dries committed
60
function block_perm() {
Dries's avatar
   
Dries committed
61
  return array('administer blocks');
Dries's avatar
   
Dries committed
62
63
}

Dries's avatar
   
Dries committed
64
/**
Dries's avatar
   
Dries committed
65
 * Implementation of hook_menu().
Dries's avatar
   
Dries committed
66
 */
Dries's avatar
   
Dries committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
function block_menu() {
  $items = array();
  $items[] = array('path' => 'admin/block', 'title' => t('blocks'),
    'access' => user_access('administer blocks'),
    'callback' => 'block_admin');
  $items[] = array('path' => 'admin/block/edit', 'title' => t('edit block'),
    'access' => user_access('administer blocks'),
    'callback' => 'block_box_edit',
    'type' => MENU_CALLBACK);
  $items[] = array('path' => 'admin/block/delete', 'title' => t('delete block'),
    'access' => user_access('administer blocks'),
    'callback' => 'block_box_delete',
    'type' => MENU_CALLBACK);
  // Tabs:
  $items[] = array('path' => 'admin/block/add', 'title' => t('add block'),
    'access' => user_access('administer blocks'),
    'callback' => 'block_box_edit',
    'type' => MENU_LOCAL_TASK);
  $items[] = array('path' => 'admin/block/preview', 'title' => t('preview'),
    'access' => user_access('administer blocks'),
    'callback' => 'block_admin_preview',
    'type' => MENU_LOCAL_TASK);
  return $items;
Dries's avatar
   
Dries committed
90
91
}

Dries's avatar
   
Dries committed
92
93
94
95
96
97
98
99
/**
 * Implementation of hook_block().
 *
 * Generates the administrator-defined blocks for display.
 */
function block_block($op = 'list', $delta = 0) {
  if ($op == 'list') {
    $result = db_query('SELECT bid, title, info FROM {boxes} ORDER BY title');
Dries's avatar
   
Dries committed
100
    while ($block = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
101
      $blocks[$block->bid]['info'] = $block->info;
Dries's avatar
   
Dries committed
102
103
104
105
    }
    return $blocks;
  }
  else {
Dries's avatar
   
Dries committed
106
107
108
    $block = db_fetch_object(db_query('SELECT * FROM {boxes} WHERE bid = %d', $delta));
    $data['subject'] = $block->title;
    $data['content'] = ($block->type == 1) ? eval($block->body) : $block->body;
Dries's avatar
   
Dries committed
109
    return $data;
110
111
112
  }
}

Dries's avatar
   
Dries committed
113
function block_admin_save($edit) {
Dries's avatar
   
Dries committed
114
115
  foreach ($edit as $module => $blocks) {
    foreach ($blocks as $delta => $block) {
Dries's avatar
   
Dries committed
116
      db_query("UPDATE {blocks} SET region = %d, status = %d, custom = %d, path = '%s', weight = %d, throttle = %d WHERE module = '%s' AND delta = '%s'",
Dries's avatar
   
Dries committed
117
                $block['region'], $block['status'], $block['custom'], $block['path'], $block['weight'], $block['throttle'], $module, $delta);
Dries's avatar
   
Dries committed
118
    }
Dries's avatar
   
Dries committed
119
  }
Dries's avatar
   
Dries committed
120

Dries's avatar
   
Dries committed
121
  return t('the block settings have been updated.');
Dries's avatar
   
Dries committed
122
123
}

Dries's avatar
   
Dries committed
124
/**
Dries's avatar
   
Dries committed
125
 * Update the 'blocks' DB table with the blocks currently exported by modules.
Dries's avatar
   
Dries committed
126
 *
Dries's avatar
   
Dries committed
127
128
129
 * @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.
130
 *
Dries's avatar
   
Dries committed
131
132
 * @return
 *   Blocks currently exported by modules, sorted by $order_by.
Dries's avatar
   
Dries committed
133
 */
Dries's avatar
   
Dries committed
134
135
function _block_rehash($order_by = array('weight')) {
  $result = db_query('SELECT * FROM {blocks} ');
Dries's avatar
   
Dries committed
136
137
138
139
  while ($old_block = db_fetch_object($result)) {
    $old_blocks[$old_block->module][$old_block->delta] = $old_block;
  }

Dries's avatar
   
Dries committed
140
  db_query('DELETE FROM {blocks} ');
Dries's avatar
   
Dries committed
141
142

  foreach (module_list() as $module) {
Dries's avatar
   
Dries committed
143
    $module_blocks = module_invoke($module, 'block', 'list');
Dries's avatar
   
Dries committed
144
145
    if ($module_blocks) {
      foreach ($module_blocks as $delta => $block) {
Dries's avatar
   
Dries committed
146
147
        $block['module'] = $module;
        $block['delta']  = $delta;
Dries's avatar
   
Dries committed
148
        if ($old_blocks[$module][$delta]) {
Dries's avatar
   
Dries committed
149
150
151
152
153
154
          $block['status'] = $old_blocks[$module][$delta]->status;
          $block['weight'] = $old_blocks[$module][$delta]->weight;
          $block['region'] = $old_blocks[$module][$delta]->region;
          $block['path']   = $old_blocks[$module][$delta]->path;
          $block['custom'] = $old_blocks[$module][$delta]->custom;
          $block['throttle'] = $old_blocks[$module][$delta]->throttle;
Dries's avatar
   
Dries committed
155
156
        }
        else {
Dries's avatar
   
Dries committed
157
158
          $block['status'] = $block['weight'] = $block['region'] = $block['custom'] = 0;
          $block['path']   = '';
Dries's avatar
   
Dries committed
159
160
161
        }

        // reinsert blocks into table
Dries's avatar
   
Dries committed
162
        db_query("INSERT INTO {blocks} (module, delta, status, weight, region, path, custom, throttle) VALUES ('%s', '%s', %d, %d, %d, '%s', %d, %d)",
Dries's avatar
   
Dries committed
163
                  $block['module'], $block['delta'], $block['status'], $block['weight'], $block['region'], $block['path'], $block['custom'], $block['throttle']);
Dries's avatar
   
Dries committed
164
165

        $blocks[] = $block;
Dries's avatar
   
Dries committed
166

Dries's avatar
   
Dries committed
167
168
        // build array to sort on
        $order[$order_by[0]][] = $block[$order_by[0]];
Dries's avatar
   
Dries committed
169
170
171
172
      }
    }
  }

Dries's avatar
   
Dries committed
173
174
175
  // 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
176
177
  return $blocks;
}
Dries's avatar
   
Dries committed
178

Dries's avatar
   
Dries committed
179
180
181
/**
 * Prepare the main block administration form.
 */
Dries's avatar
   
Dries committed
182
function block_admin_display() {
Dries's avatar
   
Dries committed
183

Dries's avatar
   
Dries committed
184
  $blocks = _block_rehash();
Dries's avatar
   
Dries committed
185

Dries's avatar
   
Dries committed
186
  $header = array(t('block'), t('enabled'), t('custom'), t('throttle'), t('weight'), t('region'), t('path'), array('data' => t('operations'), 'colspan' => 2));
Dries's avatar
   
Dries committed
187

Dries's avatar
   
Dries committed
188
  foreach ($blocks as $block) {
Dries's avatar
   
Dries committed
189
    if ($block['module'] == 'block') {
190
191
      $edit = l(t('edit block'), 'admin/block/edit/'. $block['delta']);
      $delete = l(t('delete block'), 'admin/block/delete/'. $block['delta']);
192
    }
Dries's avatar
   
Dries committed
193
    else {
Dries's avatar
   
Dries committed
194
195
      $edit = '';
      $delete = '';
Dries's avatar
   
Dries committed
196
    }
Dries's avatar
   
Dries committed
197

Dries's avatar
   
Dries committed
198
    $rows[] = array($block['info'], array('data' => form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][status', 1, $block['status']), 'align' => 'center'), array('data' => form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][custom', 1, $block['custom']), 'align' => 'center'), array('data' => form_checkbox(NULL, $block['module'] .']['. $block['delta'] .'][throttle', 1, $block['throttle'], NULL, module_exist('throttle') ? NULL : array('disabled' => 'disabled')), 'align' => 'center'), form_weight(NULL, $block['module'] .']['. $block['delta'] .'][weight', $block['weight']), form_radios(NULL, $block['module'] .']['. $block['delta'] .'][region', $block['region'], array(t('left'), t('right'))), form_textfield(NULL, $block['module'] .']['. $block['delta'] .'][path', $block['path'], 10, 255),
Dries's avatar
   
Dries committed
199
    $edit, $delete);
Dries's avatar
   
Dries committed
200
  }
Dries's avatar
   
Dries committed
201

Dries's avatar
   
Dries committed
202
203
  $output = theme('table', $header, $rows);
  $output .= form_submit(t('Save blocks'));
Dries's avatar
   
Dries committed
204

Dries's avatar
   
Dries committed
205
  return form($output, 'post', url('admin/block'));
Dries's avatar
   
Dries committed
206
207
}

Dries's avatar
   
Dries committed
208
/**
Dries's avatar
Dries committed
209
 * Menu callback; displays the block layout as it will appear when themed.
Dries's avatar
   
Dries committed
210
 */
Dries's avatar
   
Dries committed
211
function block_admin_preview() {
Dries's avatar
   
Dries committed
212
  $result = db_query('SELECT * FROM {blocks} WHERE status > 0 AND region = 0 ORDER BY weight');
Dries's avatar
   
Dries committed
213
  $lblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
214
  while ($block = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
215
216
217
    $block_data = module_invoke($block->module, 'block', 'list');
    $name = $block_data[$block->delta]['info'];
    $lblocks .= ' <tr><td>'. ($block->status == 2 ? "<strong>$name</strong>" : $name) ."</td><td>$block->weight</td></tr>\n";
Dries's avatar
   
Dries committed
218
  }
Dries's avatar
   
Dries committed
219
  $lblocks .= "</table>\n";
Dries's avatar
   
Dries committed
220

Dries's avatar
   
Dries committed
221
  $result = db_query('SELECT * FROM {blocks} WHERE status > 0 AND region = 1 ORDER BY weight');
Dries's avatar
   
Dries committed
222
  $rblocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
223
  while ($block = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
224
225
226
    $block_data = module_invoke($block->module, 'block', 'list');
    $name = $block_data[$block->delta]['info'];
    $rblocks .= ' <tr><td>'. ($block->status == 2 ? "<strong>$name</strong>" : $name) ."</td><td>$block->weight</td></tr>\n";
Dries's avatar
   
Dries committed
227
  }
Dries's avatar
   
Dries committed
228
  $rblocks .= "</table>\n";
Dries's avatar
   
Dries committed
229

Dries's avatar
   
Dries committed
230
  $output .= '<h3>'. t('Themes with both left and right sidebars') .":</h3>\n";
Dries's avatar
   
Dries committed
231
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
232
233
234
  $output .= ' <tr><td colspan="3" style="text-align: center;">'. t('header') ."</td></tr>\n";
  $output .= " <tr><td>\n". ($lblocks ? $lblocks : '&nbsp;') ."</td><td style=\"width: 300px;\">&nbsp;</td><td>\n". ($rblocks ? $rblocks : '&nbsp;') ."</td></tr>\n";
  $output .= ' <tr><td colspan="3" style="text-align: center;">'. t('footer') ."</td></tr>\n";
Dries's avatar
   
Dries committed
235
  $output .= "</table>\n";
Dries's avatar
   
Dries committed
236

Dries's avatar
   
Dries committed
237
  $result = db_query('SELECT * FROM {blocks} WHERE status > 0 ORDER BY weight');
Dries's avatar
   
Dries committed
238
  $blocks .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
239
  while ($block = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
240
241
242
    $block_data = module_invoke($block->module, 'block', 'list');
    $name = $block_data[$block->delta]['info'];
    $blocks .= ' <tr><td>'. ($block->status == 2 ? "<strong>$name</strong>" : $name) ."</td><td>$block->weight</td></tr>\n";
Dries's avatar
   
Dries committed
243
  }
Dries's avatar
   
Dries committed
244
245
  $blocks .= "</table>\n";

Dries's avatar
   
Dries committed
246
  $output .= '<h3>'. t('Themes with right sidebar only') .":</h3>\n";
Dries's avatar
   
Dries committed
247
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
248
249
250
  $output .= ' <tr><td colspan="2" style="text-align: center;">'. t('header') ."</td></tr>\n";
  $output .= " <tr><td style=\"width: 400px;\">&nbsp;</td><td>\n". ($blocks ? $blocks : '&nbsp;') ."</td></tr>\n";
  $output .= ' <tr><td colspan="2" style="text-align: center;">'. t('footer') ."</td></tr>\n";
Dries's avatar
   
Dries committed
251
252
  $output .= "</table>\n";

Dries's avatar
   
Dries committed
253
  $output .= '<h3>'. t('Themes with left sidebar only') .":</h3>\n";
Dries's avatar
   
Dries committed
254
  $output .= "<table border=\"1\" cellpadding=\"2\" cellspacing=\"2\">\n";
Dries's avatar
   
Dries committed
255
256
257
  $output .= ' <tr><td colspan="2" style="text-align: center;">'. t('header') ."</td></tr>\n";
  $output .= " <tr><td>\n". ($blocks ? $blocks : '&nbsp;') ."</td><td style=\"width: 400px;\">&nbsp;</td></tr>\n";
  $output .= ' <tr><td colspan="2" style="text-align: center;">'. t('footer') ."</td></tr>\n";
Dries's avatar
   
Dries committed
258
  $output .= "</table>\n";
Dries's avatar
   
Dries committed
259

Dries's avatar
   
Dries committed
260
  print theme('page', $output);
Dries's avatar
   
Dries committed
261
262
}

263
function block_box_get($bid) {
Dries's avatar
   
Dries committed
264
265
266
267
  return db_fetch_array(db_query('SELECT * FROM {boxes} WHERE bid = %d', $bid));
}

/**
Dries's avatar
Dries committed
268
269
270
 * Menu callback; displays the block editing form.
 *
 * On edit, saves changes and displays the block overview.
Dries's avatar
   
Dries committed
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
 */
function block_box_edit($bid = 0) {
  $edit = $_POST['edit'];
  $op = $_POST['op'];

  if ($op == t('Save block')) {
    drupal_set_message(block_box_save($edit));
    cache_clear_all();
    $output = block_admin_display();
  }
  else {
    if ($bid) {
      $output = block_box_form(block_box_get($bid));
    }
    else {
      $output = block_box_form();
    }
  }

  print theme('page', $output);
291
292
293
}

function block_box_form($edit = array()) {
Dries's avatar
   
Dries committed
294
  $type = array(0 => 'HTML', 1 => 'PHP');
295

296
297
298
  $group = form_textfield(t('Block title'), 'title', $edit['title'], 50, 64, t('The title of the block as shown to the user.'));
  $group .= form_textarea(t('Block body'), 'body', $edit['body'], 70, 10, t('The content of the block as shown to the user.'));
  $group .= form_textfield(t('Block description'), 'info', $edit['info'], 50, 64, t('A brief description of your block.  Used on the <a href="%overview">block overview page</a>.', array('%overview' => url('admin/block'))));
Dries's avatar
   
Dries committed
299
  if (user_access('create php content')) {
300
    $group .= form_radios(t('Block type'), 'type', $edit['type'], $type, t("If you would like to use PHP code inside your block, set the above option to 'PHP' instead of 'HTML'."));
Dries's avatar
   
Dries committed
301
  }
302

Dries's avatar
   
Dries committed
303
  if ($edit['bid']) {
304
    $group .= form_hidden('bid', $edit['bid']);
305
306
  }

307
  $group .= form_submit(t('Save block'));
308

309
310
  $output = form_group(t('Add a new block'), $group);
  return form($output);
311
312
313
}

function block_box_save($edit) {
Dries's avatar
   
Dries committed
314
315
  if (!user_access('create php content')) {
    $edit['type'] = 0;
Dries's avatar
   
Dries committed
316
317
  }

Dries's avatar
   
Dries committed
318
319
320
  if ($edit['bid']) {
    db_query("UPDATE {boxes} SET title = '%s', body = '%s', info = '%s', type = %d WHERE bid = %d", $edit['title'], $edit['body'], $edit['info'], $edit['type'], $edit['bid']);
    return t('the block has been updated.');
321
322
  }
  else {
Dries's avatar
   
Dries committed
323
324
    db_query("INSERT INTO {boxes} (title, body, info, type) VALUES  ('%s', '%s', '%s', %d)", $edit['title'], $edit['body'], $edit['info'], $edit['type']);
    return t('the new block has been added.');
325
326
327
  }
}

Dries's avatar
   
Dries committed
328
/**
Dries's avatar
Dries committed
329
 * Menu callback; deletes a custom box, then displays the overview page.
Dries's avatar
   
Dries committed
330
331
 */
function block_box_delete($bid = 0) {
332
  if ($bid) {
Dries's avatar
   
Dries committed
333
334
335
    db_query('DELETE FROM {boxes} WHERE bid = %d', $bid);
    drupal_set_message(t('the block has been deleted.'));
    cache_clear_all();
336
  }
Dries's avatar
   
Dries committed
337
  print theme('page', block_admin_display());
338
339
}

Dries's avatar
   
Dries committed
340
/**
Dries's avatar
Dries committed
341
 * Menu callback; displays the block overview page.
Dries's avatar
   
Dries committed
342
 */
Dries's avatar
   
Dries committed
343
function block_admin() {
Dries's avatar
   
Dries committed
344
345
  $edit = $_POST['edit'];
  $op = $_POST['op'];
Dries's avatar
   
Dries committed
346

Dries's avatar
   
Dries committed
347
348
349
  if ($op == t('Save blocks')) {
    drupal_set_message(block_admin_save($edit));
    cache_clear_all();
Dries's avatar
   
Dries committed
350
  }
Dries's avatar
   
Dries committed
351
  print theme('page', block_admin_display());
Dries's avatar
   
Dries committed
352
}
Dries's avatar
   
Dries committed
353

Dries's avatar
   
Dries committed
354
355
356
357
358
359
/**
 * Implementation of hook_user().
 *
 * Allow users to decide which custom blocks to display when they visit
 * the site.
 */
Dries's avatar
   
Dries committed
360
function block_user($type, $edit, &$user) {
361
  switch ($type) {
362
    case 'form':
Dries's avatar
   
Dries committed
363
      $result = db_query('SELECT * FROM {blocks} WHERE custom = %d ORDER BY module, delta', 1);
364
365

      while ($block = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
366
367
        $data = module_invoke($block->module, 'block', 'list');
        if ($data[$block->delta]['info']) {
368
          $form .= form_checkbox($data[$block->delta]['info'], "block][$block->module][$block->delta", 1, isset($user->block[$block->module][$block->delta]) ? $user->block[$block->module][$block->delta] : $block->status);
Kjartan's avatar
Kjartan committed
369
370
371
372
        }
      }

      if (isset($form)) {
373
        return array(t('Block configuration') => $form);
374
      }
Dries's avatar
   
Dries committed
375
376

      break;
Dries's avatar
   
Dries committed
377
378
379
    case 'validate':
      if (!$edit['block']) {
        $edit['block'] = array();
380
381
      }
      return $edit;
382
383
384
  }
}

385
386
387
/**
 * Return blocks available for current $user at $region.
 *
Dries's avatar
   
Dries committed
388
 * @param $region main|left|right
389
 *
Dries's avatar
   
Dries committed
390
 * @return array of block objects, indexed with <i>module</i>_<i>delta</i>
391
 *
Dries's avatar
   
Dries committed
392
 * @see <a href="http://drupal.org/node/1042" target="_top">[feature]
393
 *   Generic template design difficult w/o block region "look-ahead"</a>
Dries's avatar
   
Dries committed
394
 * @todo add a proper primary key (bid) to the blocks table so we don't have
395
396
397
398
 *   to mess around with this <i>module</i>_<i>delta</i> construct. currently,
 *   "blocks" has no primary key defined (bad)!
 */
function block_list($region) {
399
  global $user, $base_url;
400
401
402
403
  static $blocks = array();

  if (!isset($blocks[$region])) {
    $blocks[$region] = array();
Dries's avatar
   
Dries committed
404
    $result = db_query('SELECT * FROM {blocks} WHERE (status = 1 OR custom = 1) '. ($region != 'all' ? 'AND region = %d ' : '') .'ORDER BY weight, module', $region == 'left' ? 0 : 1);
405
406

    while ($result && ($block = db_fetch_array($result))) {
407
408
409
410
      // When the user's account setting is empty, we use the block's regular 'status' (which is the default)
      if ($block['custom'] && $user->uid && !isset($user->block[$block['module']][$block['delta']])) {
        $user->block[$block['module']][$block['delta']] = $block['status'];
      }
411
412
      $base = parse_url($base_url);
      if ((($block['status'] && (!$user->uid || !$block['custom'])) || ($block['custom'] && $user->block[$block['module']][$block['delta']])) && (!$block['path'] || preg_match($block['path'], ereg_replace('^/(\?q=)?', '', str_replace($base['path'], '', request_uri()))))) {
Dries's avatar
   
Dries committed
413
414

        /*
415
416
        ** Check the current throttle status and see if block should be displayed
        ** based on server load.
Dries's avatar
   
Dries committed
417
        */
Dries's avatar
   
Dries committed
418
        if (!($block['throttle'] && (module_invoke('throttle', 'status') > 4))) {
Dries's avatar
   
Dries committed
419
420
          $block = array_merge($block, module_invoke($block['module'], 'block', 'view', $block['delta']));
        }
Dries's avatar
   
Dries committed
421
        if (isset($block['content']) && $block['content']) {
422
423
424
425
426
427
428
429
          $blocks[$region]["$block[module]_$block[delta]"] = (object) $block;
        }
      }
    }
  }
  return $blocks[$region];
}

430
?>