mongodb_block.module in MongoDB 7
Controls the visual building blocks a page is constructed with.
Resembles very closely the core block module but without an UI. The best way to read this code is to compare it with block.module.
File
mongodb_block/mongodb_block.moduleView source
<?php
/**
* @file
* Controls the visual building blocks a page is constructed with.
*
* Resembles very closely the core block module but without an UI. The best way
* to read this code is to compare it with block.module.
*/
// Denotes that a block is not enabled in any region and should not be shown.
define('MONGODB_BLOCK_REGION_NONE', -1);
/**
* Create indexes for mongo blocks.
*
* @param array $theme_list
* Array of themes to create indexes for.
*
* @throws \MongoConnectionException
*/
function _mongodb_block_ensure_indexes(array $theme_list) {
foreach ($theme_list as $theme) {
$index = [
'_id.module' => 1,
'_id.delta' => 1,
];
mongodb_collection('block', $theme)
->ensureIndex($index);
mongodb_collection('block_customized', $theme)
->ensureIndex($index);
}
}
/**
* Implements hook_menu().
*/
function mongodb_block_menu() {
return [
'admin/structure/block-rebuild' => [
'title' => 'Block rebuild',
'description' => 'Rebuilds blocks in MongoDB',
'page callback' => 'mongodb_block_rehash',
'access arguments' => [
'administer site configuration',
],
],
];
}
/**
* Implements hook_flush_caches().
*/
function mongodb_block_flush_caches() {
return [
'cache_block',
];
}
/**
* Implements hook_theme().
*
* @see \block_theme()
*/
function mongodb_block_theme() {
return [
'block' => [
'render element' => 'elements',
'template' => 'block',
'path' => drupal_get_path('module', 'block'),
],
];
}
/**
* Implements hook_form_system_modules_alter().
*
* Hides block, dashboard module.
*/
function mongodb_block_form_system_modules_alter(&$form) {
unset($form['modules']['Core']['block']);
unset($form['modules']['Core']['dashboard']);
}
/**
* Implements hook_page_build().
*
* Renders blocks into their regions.
*
* @see \block_page_build()
*/
function mongodb_block_page_build(&$page) {
global $theme;
// The theme system might not yet be initialized. We need $theme.
drupal_theme_initialize();
// Fetch a list of regions for the current theme.
$all_regions = system_region_list($theme);
$collection = mongodb_collection('block', $theme);
// Fastest way to check if collection is not empty, per #2072135.
if (!$collection
->find()
->limit(1)
->hasNext()) {
_mongodb_block_rehash($theme);
}
$query = [];
if ($node = menu_get_object()) {
$query['node_type']['$in'] = [
'*',
$node->type,
];
}
$parts = array_slice(arg(), 0, MENU_MAX_PARTS);
$ancestors = menu_get_ancestors($parts);
if ($_GET['q'] != request_path()) {
$request_parts = array_slice(explode('/', request_path()), 0, MENU_MAX_PARTS);
$ancestors = array_merge($ancestors, menu_get_ancestors($request_parts));
}
$ancestors[] = '%';
if (drupal_is_front_page()) {
$ancestors[] = '<front>';
}
$query['pages']['$in'] = $ancestors;
$query['pages_exclude']['$nin'] = $ancestors;
$query['region']['$in'] = array_keys($all_regions);
$blocks_result = $collection
->find($query)
->sort(array(
'weight' => 1,
));
$regions_blocks = array();
foreach ($blocks_result as $block) {
if (!isset($regions_blocks[$block['region']])) {
$regions_blocks[$block['region']] = array();
}
$regions_blocks[$block['region']][] = $block;
}
foreach ($regions_blocks as $region => $region_blocks) {
$region_blocks = mongodb_block_render_blocks($region_blocks);
if (isset($page[$region])) {
$page[$region] = array_merge($page[$region], mongodb_block_get_renderable_array($region_blocks));
}
else {
$page[$region] = mongodb_block_get_renderable_array($region_blocks);
}
}
}
/**
* Render the content and subject for a set of blocks.
*
* @param array $blocks_result
* An array of block objects such as returned for one region by
* _block_load_blocks()
*
* @return array
* A render array for the blocks.
*/
function mongodb_block_render_blocks(array $blocks_result) {
$return = [];
foreach ($blocks_result as $block) {
// Copy module and delta out of the _id.
if (is_array($block) && isset($block['_id'])) {
$block += $block['_id'];
}
$block = (object) $block;
// Render the block content if it has not been created already.
if (!isset($block->content)) {
// Try fetching the block from cache. Block caching is not compatible
// with node_access modules. We also preserve the submission of forms in
// blocks, by fetching from cache only if the request method is 'GET'
// (or 'HEAD').
if (($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && ($cid = mongodb_block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) {
$array = $cache->data;
}
else {
$array = module_invoke($block->module, 'block_view', $block->delta);
// Allow modules to modify the block before it is viewed, via either
// hook_block_view_MODULE_DELTA_alter() or hook_block_view_alter().
drupal_alter("block_view_{$block->module}_{$block->delta}", $array, $block);
drupal_alter('block_view', $array, $block);
if (isset($cid)) {
cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY);
}
}
if (isset($array) && is_array($array)) {
foreach ($array as $k => $v) {
$block->{$k} = $v;
}
}
}
if (isset($block->content) && $block->content) {
// Normalize to the drupal_render() structure.
if (is_string($block->content)) {
$block->content = [
'#markup' => $block->content,
];
}
// Override default block title if a custom display title is present.
if (!empty($block->title)) {
// Check plain here to allow module generated titles to keep any
// markup.
$block->subject = $block->title == '<none>' ? '' : check_plain($block->title);
}
if (!isset($block->subject)) {
$block->subject = '';
}
$return["{$block->module}_{$block->delta}"] = $block;
}
}
return $return;
}
/**
* Assemble the cache_id to use for a given block.
*
* The cache_id string reflects the viewing context for the current block
* instance, obtained by concatenating the relevant context information
* (user, page, ...) according to the block's cache settings (BLOCK_CACHE_*
* constants). Two block instances can use the same cached content when
* they share the same cache_id.
*
* Theme and language contexts are automatically differentiated.
*
* @param object $block
* The block object.
*
* @return string
* The string used as cache_id for the block.
*/
function mongodb_block_get_cache_id($block) {
global $user;
// Not all block definitions define caching.
if (!isset($block->cache)) {
$block->cache = DRUPAL_NO_CACHE;
}
// User 1 being out of the regular 'roles define permissions' schema,
// it brings too many chances of having unwanted output get in the cache
// and later be served to other users. We therefore exclude user 1 from
// block caching.
if (variable_get('block_cache', 0) && !in_array($block->cache, [
DRUPAL_NO_CACHE,
DRUPAL_CACHE_CUSTOM,
]) && $user->uid != 1) {
// Start with common sub-patterns: block identification, theme, language.
$cid_parts[] = $block->module;
$cid_parts[] = $block->delta;
$cid_parts = array_merge($cid_parts, drupal_render_cid_parts($block->cache));
return implode(':', $cid_parts);
}
}
/**
* Gets an array of blocks suitable for drupal_render().
*
* @param array $list
* A list of blocks such as that returned by block_list().
*
* @return array
* A renderable array.
*
* @see _block_get_renderable_array()
*/
function mongodb_block_get_renderable_array(array $list = []) {
global $theme;
$weight = 0;
$build = [];
foreach ($list as $key => $block) {
$build[$key] = $block->content;
unset($block->content);
// Add contextual links for this block; skip the main content block, since
// contextual links are basically output as tabs/local tasks already. Also
// skip the help block, since we assume that most users do not need or want
// to perform contextual actions on the help block, and the links needlessly
// draw attention on it.
if (module_exists('mongodb_block_ui') && $key != 'system_main' && $key != 'system_help') {
$build[$key]['#contextual_links']['mongodb_block_ui'] = [
'admin/structure/mongodb_block/manage',
[
$theme,
$block->module,
$block->delta,
],
];
}
$build[$key] += [
'#block' => $block,
'#weight' => ++$weight,
];
$build[$key]['#theme_wrappers'][] = 'block';
}
$build['#sorted'] = TRUE;
return $build;
}
/**
* Implements hook_mongodb_block_info_alter().
*/
function mongodb_block_mongodb_block_info_alter(&$blocks) {
// Enable the main content block if it is not already enabled.
if (empty($blocks['system_main']['status'])) {
$blocks['system_main']['region'] = 'content';
$blocks['system_main']['weight'] = 0;
$blocks['system_main']['status'] = 1;
}
}
/**
* Run _mongodb_block_rehash and go to admin/structure.
*/
function mongodb_block_rehash() {
_mongodb_block_rehash(variable_get('theme_default', 'garland'));
drupal_set_message(t('Blocks rebuild done.'));
drupal_goto('admin/structure');
}
/**
* Updates the block collection with the blocks currently exported by modules.
*
* @param string $theme
* The theme to rehash blocks for. If not provided, defaults to the currently
* used theme.
*
* @return mixed
* Blocks currently exported by modules.
*
* @throws \MongoConnectionException
* @throws \MongoCursorException
* @throws \MongoCursorTimeoutException
*/
function _mongodb_block_rehash($theme) {
$collection = mongodb_collection('block', $theme);
$regions = system_region_list($theme);
$ids = [];
foreach (module_implements('block_info') as $module) {
if ($blocks_current = module_invoke($module, 'block_info')) {
foreach ($blocks_current as $delta => $block) {
$block = [
'_id' => [
'module' => $module,
'delta' => $delta,
],
'module' => $module,
'delta' => $delta,
] + $block + [
'weight' => 0,
'pages' => [
'%',
],
'pages_exclude' => [],
'status' => 0,
'region' => MONGODB_BLOCK_REGION_NONE,
];
if (isset($block['node_type']) && $block['pages'] == [
'%',
]) {
$block['pages'] = [
'node/%',
];
}
else {
if (!isset($block['node_type'])) {
$block['node_type'] = [
'*',
];
}
}
$blocks[$module . '_' . $delta] = $block;
}
}
}
drupal_alter('mongodb_block_info', $blocks, $theme);
// Only store the block in MongoDB if the status is enabled.
foreach ($blocks as $key => $block) {
if ($block['region'] != MONGODB_BLOCK_REGION_NONE && !isset($regions[$block['region']])) {
$blocks[$key]['status'] = 0;
$blocks[$key]['region'] = MONGODB_BLOCK_REGION_NONE;
$block = $blocks[$key];
}
if (!empty($block['status'])) {
$ids[] = $block['_id'];
mongodb_block_save_block($collection, $block);
}
else {
$blocks[$key]['status'] = 0;
$blocks[$key]['region'] = MONGODB_BLOCK_REGION_NONE;
}
}
$collection
->remove([
'_id' => [
'$nin' => $ids,
],
], mongodb_default_write_options());
return $blocks;
}
/**
* Unset block data and save the block collection.
*
* @param object $collection
* MongoDB collection to use.
* @param array $block
* The block array.
*/
function mongodb_block_save_block($collection, array $block) {
unset($block['module'], $block['delta'], $block['status']);
$collection
->save($block, mongodb_default_write_options());
}
/**
* Processes variables for block.tpl.php.
*
* Prepares the values passed to the theme_block function to be passed
* into a pluggable template engine. Uses block properties to generate a
* series of template file suggestions. If none are found, the default
* block.tpl.php is used.
*
* Most themes utilize their own copy of block.tpl.php. The default is located
* inside "modules/block/block.tpl.php". Look in there for the full list of
* variables.
*
* The $variables array contains the following arguments:
* - $block
*
* @see block.tpl.php
*/
function mongodb_block_preprocess_block(&$variables) {
$block_counter =& drupal_static(__FUNCTION__, []);
$variables['block'] = $variables['elements']['#block'];
// All blocks get an independent counter for each region.
if (!isset($block_counter[$variables['block']->region])) {
$block_counter[$variables['block']->region] = 1;
}
// Same with zebra striping.
$variables['block_zebra'] = $block_counter[$variables['block']->region] % 2 ? 'odd' : 'even';
$variables['block_id'] = $block_counter[$variables['block']->region]++;
// Create the $content variable that templates expect.
$variables['content'] = $variables['elements']['#children'];
$variables['classes_array'][] = drupal_html_class('block-' . $variables['block']->module);
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
// Hyphens (-) and underscores (_) play a special role in theme suggestions.
// Theme suggestions should only contain underscores, because within
// drupal_find_theme_templates(), underscores are converted to hyphens to
// match template file names, and then converted back to underscores to match
// pre-processing and other function names. So if your theme suggestion
// contains a hyphen, it will end up as an underscore after this conversion,
// and your function names won't be recognized. So, we need to convert
// hyphens to underscores in block deltas for the theme suggestions.
$variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . strtr($variables['block']->delta, '-', '_');
// Create a valid HTML ID and make sure it is unique.
$variables['block_html_id'] = drupal_html_id('block-' . $variables['block']->module . '-' . $variables['block']->delta);
}
/**
* Implements hook_themes_enabled().
*/
function mongodb_block_themes_enabled($theme_list) {
_mongodb_block_ensure_indexes($theme_list);
}
Functions
Name | Description |
---|---|
mongodb_block_flush_caches | Implements hook_flush_caches(). |
mongodb_block_form_system_modules_alter | Implements hook_form_system_modules_alter(). |
mongodb_block_get_cache_id | Assemble the cache_id to use for a given block. |
mongodb_block_get_renderable_array | Gets an array of blocks suitable for drupal_render(). |
mongodb_block_menu | Implements hook_menu(). |
mongodb_block_mongodb_block_info_alter | Implements hook_mongodb_block_info_alter(). |
mongodb_block_page_build | Implements hook_page_build(). |
mongodb_block_preprocess_block | Processes variables for block.tpl.php. |
mongodb_block_rehash | Run _mongodb_block_rehash and go to admin/structure. |
mongodb_block_render_blocks | Render the content and subject for a set of blocks. |
mongodb_block_save_block | Unset block data and save the block collection. |
mongodb_block_theme | Implements hook_theme(). |
mongodb_block_themes_enabled | Implements hook_themes_enabled(). |
_mongodb_block_ensure_indexes | Create indexes for mongo blocks. |
_mongodb_block_rehash | Updates the block collection with the blocks currently exported by modules. |
Constants
Name | Description |
---|---|
MONGODB_BLOCK_REGION_NONE |