00001 <?php
00002
00003
00004
00005
00006 class context_reaction_block extends context_reaction {
00007
00008
00009
00010 function options_form($context) {
00011
00012 $this->get_blocks(NULL, NULL, $this->rebuild_needed());
00013 $this->rebuild_needed(FALSE);
00014
00015 $theme_key = variable_get('theme_default', 'garland');
00016 $weight_delta = $this->max_block_weight();
00017
00018 $form = array(
00019 '#tree' => TRUE,
00020 '#theme' => 'context_block_form',
00021 'max_block_weight' => array(
00022 '#value' => $weight_delta,
00023 '#type' => 'value',
00024 ),
00025 'state' => array(
00026 '#type' => 'hidden',
00027 '#attributes' => array('class' => 'context-blockform-state'),
00028 ),
00029 );
00030
00031
00032
00033
00034 $modules = module_list();
00035 $form['selector'] = array(
00036 '#type' => 'item',
00037 '#tree' => TRUE,
00038 '#prefix' => '<div class="context-blockform-selector">',
00039 '#suffix' => '</div>',
00040 );
00041 foreach ($this->get_blocks() as $block) {
00042 $group = isset($block->context_group) ? $block->context_group : $block->module;
00043 if (!isset($form['selector'][$group])) {
00044 $form['selector'][$group] = array(
00045 '#type' => 'checkboxes',
00046 '#title' => isset($block->context_group) ? $block->context_group : $modules[$block->module],
00047 '#options' => array(),
00048 );
00049 }
00050 $form['selector'][$group]['#options'][$block->bid] = check_plain($block->info);
00051 }
00052 ksort($form['selector']);
00053
00054
00055
00056
00057 $form['blocks'] = array(
00058 '#tree' => TRUE,
00059 '#theme' => 'context_block_regions_form',
00060 );
00061 foreach (system_region_list($theme_key, REGIONS_VISIBLE) as $region => $label) {
00062 $form['blocks'][$region] = array(
00063 '#type' => 'item',
00064 '#title' => $label,
00065 '#tree' => TRUE,
00066 );
00067 foreach ($this->get_blocks($region, $context) as $block) {
00068 if (!empty($block->context)) {
00069 $form['blocks'][$region][$block->bid] = array(
00070 '#value' => check_plain($block->info),
00071 '#weight' => $block->weight,
00072 '#type' => 'markup',
00073 '#tree' => TRUE,
00074 'weight' => array('#type' => 'weight', '#delta' => $weight_delta, '#default_value' => $block->weight),
00075 );
00076 }
00077 }
00078 }
00079 return $form;
00080 }
00081
00082
00083
00084
00085 function options_form_submit($values) {
00086 $blocks = array();
00087 $block_info = $this->get_blocks();
00088
00089
00090 if (!empty($values['state'])) {
00091 $edited = $this->json_decode($values['state']);
00092 }
00093 else {
00094 $edited = array();
00095 }
00096
00097 foreach ($edited as $region => $block_data) {
00098 foreach ($block_data as $position => $data) {
00099 if (isset($block_info[$data->bid])) {
00100 $blocks[$data->bid] = array(
00101 'module' => $block_info[$data->bid]->module,
00102 'delta' => $block_info[$data->bid]->delta,
00103 'region' => $region,
00104 'weight' => $data->weight,
00105 );
00106 }
00107 }
00108 }
00109 return array('blocks' => $blocks);
00110 }
00111
00112
00113
00114
00115 function editor_form($context) {
00116 $form = array();
00117 drupal_add_library('system', 'ui.droppable');
00118 drupal_add_library('system', 'ui.sortable');
00119 drupal_add_js(drupal_get_path('module', 'context_ui') . '/json2.js');
00120 drupal_add_js(drupal_get_path('module', 'context_ui') . '/theme/filter.js');
00121 drupal_add_js(drupal_get_path('module', 'context') . '/plugins/context_reaction_block.js');
00122 drupal_add_css(drupal_get_path('module', 'context') . '/plugins/context_reaction_block.css');
00123
00124
00125 static $once;
00126 if (!isset($once)) {
00127 $settings = array(
00128 'path' => drupal_is_front_page() ? base_path() : url($_GET['q']),
00129 'params' => (object) array_diff_key($_GET, array('q' => '')),
00130 'scriptPlaceholder' => theme('context_block_script_placeholder', array('text' => '')),
00131 );
00132 drupal_add_js(array('contextBlockEditor' => $settings), 'setting');
00133 $once = TRUE;
00134 }
00135
00136 $form['state'] = array(
00137 '#type' => 'hidden',
00138 '#attributes' => array('class' => array('context-block-editor-state')),
00139 );
00140 $form['browser'] = array(
00141 '#markup' => theme('context_block_browser', array(
00142 'blocks' => $this->get_blocks(NULL, NULL, $this->rebuild_needed()),
00143 'context' => $context
00144 )),
00145 );
00146 $this->rebuild_needed(FALSE);
00147 return $form;
00148 }
00149
00150
00151
00152
00153 function editor_form_submit(&$context, $values) {
00154 $edited = !empty($values['state']) ? (array) $this->json_decode($values['state']) : array();
00155
00156 $options = array();
00157
00158
00159 $affected_regions = array_keys($edited);
00160 if (!empty($context->reactions['block']['blocks'])) {
00161 $options = $context->reactions['block'];
00162 foreach ($options['blocks'] as $key => $block) {
00163 if (in_array($block['region'], $affected_regions)) {
00164 unset($options['blocks'][$key]);
00165 }
00166 }
00167 }
00168
00169
00170 foreach ($edited as $region => $blocks) {
00171 foreach ($blocks as $weight => $block) {
00172 if ($block->context === $context->name) {
00173 $split = explode('-', $block->bid);
00174 $options['blocks'][$block->bid] = array(
00175 'module' => array_shift($split),
00176 'delta' => implode('-', $split),
00177 'region' => $region,
00178 'weight' => $weight,
00179 );
00180 }
00181 }
00182 }
00183
00184 return $options;
00185 }
00186
00187
00188
00189
00190 function settings_form() {
00191 $form = array();
00192 $form['context_reaction_block_all_regions'] = array(
00193 '#title' => t('Show all regions'),
00194 '#type' => 'checkbox',
00195 '#default_value' => variable_get('context_reaction_block_all_regions', FALSE),
00196 '#description' => t('Show all regions including those that are empty. Enable if you are administering your site using the inline editor.')
00197 );
00198 return $form;
00199 }
00200
00201
00202
00203
00204 function execute(&$page) {
00205 global $theme;
00206
00207
00208 drupal_theme_initialize();
00209
00210
00211
00212
00213 if (isset($_GET['context_block']) && !ob_get_contents()) {
00214 return $this->render_ajax($_GET['context_block']);
00215 }
00216
00217
00218 $all_regions = system_region_list($theme);
00219
00220
00221 foreach (array_keys($all_regions) as $region) {
00222 if ($this->is_enabled_region($region)) {
00223 if ($blocks = $this->block_get_blocks_by_region($region)) {
00224
00225
00226 $blocks_sorted = TRUE;
00227
00228
00229
00230 if (isset($page[$region])) {
00231 $page[$region] = array_merge($page[$region], $blocks);
00232
00233
00234
00235 foreach ($page[$region] as &$block) {
00236 if (isset($block['#block']->weight)) {
00237 $block['#weight'] = $block['#block']->weight;
00238 $blocks_sorted = FALSE;
00239 }
00240 }
00241 }
00242 else {
00243 $page[$region] = $blocks;
00244 }
00245
00246 $page[$region]['#sorted'] = $blocks_sorted;
00247 }
00248 }
00249 }
00250 }
00251
00252
00253
00254
00255
00256 protected function is_enabled_region($region) {
00257 global $theme;
00258 $regions = array_keys(system_region_list($theme));
00259 return in_array($region, $regions, TRUE);
00260 }
00261
00262
00263
00264
00265
00266 protected function is_editable_region($region, $reset = FALSE) {
00267
00268
00269
00270
00271
00272 static $requirements;
00273 if (!isset($requirements) || $reset) {
00274 global $user;
00275 if ($user->uid && variable_get('context_ui_dialog_enabled', FALSE)) {
00276 $requirements = TRUE;
00277 drupal_add_library('system', 'ui.droppable');
00278 drupal_add_library('system', 'ui.sortable');
00279 drupal_add_js(drupal_get_path('module', 'context') . '/plugins/context_reaction_block.js');
00280 drupal_add_css(drupal_get_path('module', 'context') . '/plugins/context_reaction_block.css');
00281 }
00282 else {
00283 $requirements = FALSE;
00284 }
00285 }
00286
00287 global $theme;
00288 $info = system_get_info('theme', $theme);
00289 if ($info && isset($info['regions_locked']) && in_array($region, $info['regions_locked'])) {
00290 return FALSE;
00291 }
00292
00293 $visible = system_region_list($theme, REGIONS_VISIBLE);
00294 return $requirements && $this->is_enabled_region($region) && isset($visible[$region]);
00295 }
00296
00297
00298
00299
00300 protected function editable_block($block) {
00301 if (!empty($block->content)) {
00302 $block->content = array(
00303 'content' => $block->content,
00304 'context' => array('#markup' => "<a id='context-block-{$block->module}-{$block->delta}' class='context-block editable edit-{$block->context}'></a>"),
00305 );
00306
00307 if (isset($block->content['content']['#contextual_links'])) {
00308 $block->content['#contextual_links'] = $block->content['content']['#contextual_links'];
00309 unset($block->content['content']['#contextual_links']);
00310 }
00311 }
00312 else {
00313
00314
00315
00316 drupal_set_message(t('The block with delta @delta from module @module is not compatible with the inline editor and will be dropped from the context containing it if you edit contexts here', array('@delta' => $block->delta, '@module' => $block->module)), 'warning');
00317 }
00318 return $block;
00319 }
00320
00321
00322
00323
00324 protected function editable_region($region, $build) {
00325 if ($this->is_editable_region($region) &&
00326 (!empty($build) ||
00327 variable_get('context_reaction_block_all_regions', FALSE) ||
00328 context_isset('context_ui', 'context_ui_editor_present'))
00329 ) {
00330 global $theme;
00331 $regions = system_region_list($theme);
00332 $name = isset($regions[$region]) ? $regions[$region] : $region;
00333
00334 $build['context'] = array(
00335 '#prefix' => "<div class='context-block-region' id='context-block-region-{$region}'>",
00336 '#markup' => "<span class='region-name'>{$name}</span>" .
00337 "<a class='context-ui-add-link'>" . t('Add a block here.') . '</a>',
00338 '#suffix' => '</div>',
00339 '#weight' => -100,
00340 );
00341 $build['#sorted'] = FALSE;
00342 }
00343
00344 return $build;
00345 }
00346
00347
00348
00349
00350 function block_get_blocks_by_region($region) {
00351 module_load_include('module', 'block', 'block');
00352
00353 $build = array();
00354 if ($list = $this->block_list($region)) {
00355 $build = _block_get_renderable_array($list);
00356 }
00357 if ($this->is_editable_region($region)) {
00358 $build = $this->editable_region($region, $build);
00359 }
00360 return $build;
00361 }
00362
00363
00364
00365
00366 function block_list($region) {
00367 module_load_include('module', 'block', 'block');
00368
00369 $context_blocks = &drupal_static('context_reaction_block_list');;
00370 $contexts = context_active_contexts();
00371 if (!isset($context_blocks)) {
00372 $info = $this->get_blocks();
00373 $context_blocks = array();
00374 foreach ($contexts as $context) {
00375 $options = $this->fetch_from_context($context);
00376 if (!empty($options['blocks'])) {
00377 foreach ($options['blocks'] as $context_block) {
00378 $bid = "{$context_block['module']}-{$context_block['delta']}";
00379 if (isset($info[$bid])) {
00380 $block = (object) array_merge((array) $info[$bid], $context_block);
00381 $block->context = $context->name;
00382 $block->title = isset($info[$block->bid]->title) ? $info[$block->bid]->title : NULL;
00383 $block->cache = isset($info[$block->bid]->cache) ? $info[$block->bid]->cache : DRUPAL_NO_CACHE;
00384 $context_blocks[$block->region][$block->bid] = $block;
00385 }
00386 }
00387 }
00388 }
00389
00390 $this->is_editable_check($context_blocks);
00391 foreach ($context_blocks as $r => $blocks) {
00392 $context_blocks[$r] = _block_render_blocks($blocks);
00393
00394
00395 if ($this->is_editable_region($r)) {
00396 foreach ($context_blocks[$r] as $key => $block) {
00397 $context_blocks[$r][$key] = $this->editable_block($block);
00398 }
00399 }
00400
00401
00402 uasort($context_blocks[$r], array('context_reaction_block', 'block_sort'));
00403 }
00404 }
00405 return isset($context_blocks[$region]) ? $context_blocks[$region] : array();
00406 }
00407
00408
00409
00410
00411
00412
00413 function is_editable_check($context_blocks) {
00414 foreach ($context_blocks as $r => $blocks) {
00415 if (isset($blocks['context_ui-editor'])) {
00416 $block = $blocks['context_ui-editor'];
00417
00418 if (!count(module_implements('node_grants')) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && ($cid = _block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) {
00419 $array = $cache->data;
00420 }
00421 else {
00422 $array = module_invoke($block->module, 'block_view', $block->delta);
00423 drupal_alter(array('block_view', "block_view_{$block->module}_{$block->delta}"), $array, $block);
00424 }
00425 if(!empty($array['content'])) {
00426 context_set('context_ui', 'context_ui_editor_present', TRUE);
00427 }
00428 break;
00429 }
00430 }
00431 }
00432
00433
00434
00435
00436
00437 protected function max_block_weight() {
00438 $blocks = $this->get_blocks();
00439 $block_count = 0;
00440 foreach ($blocks as $region => $block_list) {
00441 $block_count += count($block_list);
00442 }
00443
00444 return round(($block_count + 2) / 2);
00445 }
00446
00447
00448
00449
00450 function rebuild_needed($set = NULL) {
00451 if (isset($set) && $set != variable_get('context_block_rebuild_needed', FALSE)) {
00452 variable_set('context_block_rebuild_needed', $set);
00453 }
00454 return (bool) variable_get('context_block_rebuild_needed', FALSE);
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 function get_blocks($region = NULL, $context = NULL, $reset = FALSE) {
00471 static $block_info;
00472 $theme_key = variable_get('theme_default', 'garland');
00473
00474 if (!isset($block_info) || $reset) {
00475 $block_info = array();
00476 if (!$reset) {
00477 $block_info = context_cache_get('block_info');
00478 }
00479 if (empty($block_info)) {
00480 if (module_exists('block')) {
00481 $block_blocks = _block_rehash($theme_key);
00482 $block_info = array();
00483
00484 foreach ($block_blocks as $block) {
00485 $block = (object) $block;
00486 unset($block->theme, $block->status, $block->weight, $block->region, $block->custom, $block->visibility, $block->pages);
00487 $block->bid = "{$block->module}-{$block->delta}";
00488 $block_info[$block->bid] = $block;
00489 }
00490 }
00491 else {
00492 $block_info = array();
00493 foreach (module_implements('block_info') as $module) {
00494 $module_blocks = module_invoke($module, 'block_info');
00495 if (!empty($module_blocks)) {
00496 foreach ($module_blocks as $delta => $block) {
00497 $block = (object) $block;
00498 $block->module = $module;
00499 $block->delta = $delta;
00500 $block->bid = "{$block->module}-{$block->delta}";
00501 $block_info[$block->bid] = $block;
00502 }
00503 }
00504 }
00505 }
00506 context_cache_set('block_info', $block_info);
00507 }
00508
00509
00510 drupal_alter('context_block_info', $block_info);
00511
00512
00513 if (module_exists('block')) {
00514 $result = db_select('block')
00515 ->fields('block')
00516 ->condition('theme', $theme_key)
00517 ->execute();
00518 foreach ($result as $row) {
00519 if (isset($block_info["{$row->module}-{$row->delta}"])) {
00520 $block_info["{$row->module}-{$row->delta}"] = (object) array_merge((array) $row, (array) $block_info["{$row->module}-{$row->delta}"]);
00521 unset($block_info["{$row->module}-{$row->delta}"]->status);
00522 unset($block_info["{$row->module}-{$row->delta}"]->visibility);
00523 unset($block_info["{$row->module}-{$row->delta}"]->cache);
00524 }
00525 }
00526 }
00527 }
00528
00529 $blocks = array();
00530
00531
00532 if (!isset($region)) {
00533 $blocks = $block_info;
00534 }
00535
00536 else {
00537 foreach ($block_info as $bid => $block) {
00538 if (isset($block->region) && $block->region == $region) {
00539 $blocks[$bid] = $block;
00540 }
00541 }
00542 }
00543
00544
00545 if (is_object($context) && $options = $this->fetch_from_context($context)) {
00546 if (!empty($options['blocks'])) {
00547 foreach ($options['blocks'] as $block) {
00548 if (
00549 isset($block_info["{$block['module']}-{$block['delta']}"]) &&
00550 (!isset($region) || (!empty($region) && $block['region'] == $region))
00551 ) {
00552 $context_block = $block_info["{$block['module']}-{$block['delta']}"];
00553 $context_block->weight = $block['weight'];
00554 $context_block->region = $block['region'];
00555 $context_block->context = !empty($context->name) ? $context->name : 'tempname';
00556 $blocks[$context_block->bid] = $context_block;
00557 }
00558 }
00559 }
00560 uasort($blocks, array('context_reaction_block', 'block_sort'));
00561 }
00562 return $blocks;
00563 }
00564
00565
00566
00567
00568 static function block_sort($a, $b) {
00569 return ($a->weight - $b->weight);
00570 }
00571
00572
00573
00574
00575 protected function json_decode($json, $assoc = FALSE) {
00576
00577 if (function_exists('json_decode')) {
00578 return json_decode($json, $assoc);
00579 }
00580 return context_reaction_block::_json_decode($json);
00581 }
00582
00583
00584
00585
00586
00587
00588
00589 static function _json_decode($json) {
00590 $comment = FALSE;
00591 $out = '$x = ';
00592 for ($i=0; $i < strlen($json); $i++) {
00593 if (!$comment) {
00594 switch ($json[$i]) {
00595 case '{':
00596 $out .= ' (object) array(';
00597 break;
00598 case '}':
00599 $out .= ')';
00600 break;
00601 case '[':
00602 $out .= ' array(';
00603 break;
00604 case ']':
00605 $out .= ')';
00606 break;
00607 case ':';
00608 $out .= '=>';
00609 break;
00610 default:
00611 $out .= $json[$i];
00612 break;
00613 }
00614 }
00615 else {
00616 $out .= $json[$i];
00617 }
00618 if ($json[$i] == '"') {
00619 $comment = !$comment;
00620 }
00621 }
00622 eval($out . ';');
00623 return $x;
00624 }
00625
00626
00627
00628
00629
00630 function render_ajax($param) {
00631
00632 $headers = drupal_get_http_header();
00633 if (array_key_exists('status', $headers) && ($headers['status'] == "404 Not Found" || $headers['status'] == "403 Forbidden")) {
00634 return;
00635 }
00636
00637
00638 drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8');
00639
00640 if (strpos($param, ',') !== FALSE) {
00641 list($bid, $context) = explode(',', $param);
00642 list($module, $delta) = explode('-', $bid, 2);
00643
00644 if (empty($_GET['context_token']) || $_GET['context_token'] != drupal_get_token($bid)) {
00645 echo drupal_json_encode(array('status' => 0));
00646 exit;
00647 }
00648
00649
00650 $info = $this->get_blocks();
00651 if (isset($info[$bid])) {
00652 module_load_include('module', 'block', 'block');
00653 $block = $info[$bid];
00654 $block->title = isset($block->title) ? $block->title : '';
00655 $block->context = $context;
00656 $block->region = '';
00657 $rendered_blocks = _block_render_blocks(array($block));
00658 $block = array_shift($rendered_blocks);
00659 if (empty($block->content['#markup'])) {
00660 $block->content['#markup'] = "<div class='context-block-empty'>" . t('This block appears empty when displayed on this page.') . "</div>";
00661 }
00662 $block = $this->editable_block($block);
00663 $renderable_block = _block_get_renderable_array(array($block));
00664 echo drupal_json_encode(array(
00665 'status' => 1,
00666 'block' => drupal_render($renderable_block),
00667 ));
00668 drupal_exit();
00669 }
00670 }
00671 echo drupal_json_encode(array('status' => 0));
00672 drupal_exit();
00673 }
00674 }