View source
<?php
define('BLOCKREFERENCE_AC_REGEX', '#\\[([\\w\\-]+):([\\w\\-]+)\\]$#');
include_once __DIR__ . '/blockreference.field.inc';
function blockreference_menu() {
$items = array();
$items['blockreference/autocomplete/%/%/%/%'] = array(
'title' => 'blockreference autocomplete',
'page callback' => 'blockreference_autocomplete',
'page arguments' => array(
2,
3,
4,
5,
),
'access callback' => 'blockreference_autocomplete_access',
'access arguments' => array(
2,
3,
4,
5,
),
'type' => MENU_CALLBACK,
);
return $items;
}
function blockreference_autocomplete_access($entity_type, $bundle, $field_name, $eid) {
if ($eid == 0) {
$entity_info = entity_get_info($entity_type);
$entity_dummy = entity_create($entity_type, array(
$entity_info['entity keys']['bundle'] => $bundle,
));
$entity_access = entity_access('create', $entity_type, $entity_dummy);
}
else {
$entity = entity_load($entity_type, array(
$eid,
));
$entity = reset($entity) ?: FALSE;
$entity_access = entity_access('update', $entity_type, $entity);
}
return user_access('access content') && $entity_access;
}
function blockreference_autocomplete($entity_type, $bundle, $field_name, $entity_id, $search_string) {
$search_string = trim(implode('/', array_slice(func_get_args(), 4)), '/');
$entity = FALSE;
if ($entity_id) {
$entity_load = entity_load($entity_type, array(
$entity_id,
));
if ($entity_load) {
$entity = reset($entity_load);
}
}
$instance = field_info_instance($entity_type, $field_name, $bundle);
$context = array(
'type' => 'autocomplete',
'entity' => $entity,
);
$blocks = _blockreference_find_blocks($instance, $search_string, $context);
$options = _blockreference_options($blocks, TRUE);
drupal_json_output($options);
}
function blockreference_autocomplete_value($element, $input = FALSE, $form_state) {
$ac_string = $input !== FALSE ? $input : (isset($element['#value']) ? $element['#value'] : (string) @$element['#default_value']);
$module = $delta = '';
if (is_string($ac_string)) {
$block_arr = _blockreference_block_from_ac_string($ac_string);
if ($block_arr) {
list($module, $delta) = array_values($block_arr);
}
}
if ($module && $delta) {
$infos = module_invoke($module, 'block_info');
if (isset($infos[$delta])) {
$block = _blockreference_block($module, $delta, $infos[$delta]);
$value = trim($block->info) . ' [' . $block->module . ':' . $block->delta . ']';
return $value;
}
}
return '';
}
function blockreference_autocomplete_validate($element, &$form_state, $form) {
$instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
$value = $element['#value'];
if (!$value) {
form_set_value($element, '', $form_state);
return;
}
$block_arr = _blockreference_block_from_ac_string($value);
if (!$block_arr) {
return form_error($element, t('%name: Title mismatch. Please check your selection.', array(
'%name' => $instance['label'],
)));
}
$allowed_blocks = _blockreference_find_blocks($instance, '', array(
'entity' => $element['#entity'],
'type' => 'autocomplete',
));
$moddelta = implode(':', $block_arr);
if (!isset($allowed_blocks[$moddelta])) {
return form_error($element, t('This block is not allowed in this field/context.'));
}
form_set_value($element, $moddelta, $form_state);
}
function blockreference_theme() {
return array(
'blockreference_formatter_default' => array(
'variables' => array(
'element' => NULL,
),
),
'blockreference_formatter_without_title' => array(
'variables' => array(
'element' => NULL,
),
),
'blockreference_formatter_title' => array(
'variables' => array(
'element' => NULL,
),
),
'blockreference_formatter_plain' => array(
'variables' => array(
'element' => NULL,
),
),
'blockreference_formatter_config_link' => array(
'variables' => array(
'element' => NULL,
),
),
);
}
function theme_blockreference_formatter_default($variables) {
$element = $variables['element'];
$block = _blockreference_formatter_get_block($element);
if ($block) {
$bid = $block->module . '_' . $block->delta;
if (!isset($block->title)) {
$block->title = '';
}
if (!isset($block->region)) {
$block->region = 'none';
}
$block_content = _block_render_blocks(array(
$block,
));
$build = _block_get_renderable_array($block_content);
$build[$bid]['#blockreference_element'] = $element;
return drupal_render($build);
}
return '';
}
function theme_blockreference_formatter_without_title($variables) {
$element = $variables['element'];
$block = _blockreference_formatter_get_block($element);
if ($block) {
$bid = $block->module . '_' . $block->delta;
if (!isset($block->title)) {
$block->title = '';
}
if (!isset($block->region)) {
$block->region = 'none';
}
$block_content = _block_render_blocks(array(
$block,
));
if ($block_content) {
reset($block_content)->subject = '';
$build = _block_get_renderable_array($block_content);
$build[$bid]['#blockreference_element'] = $element;
return drupal_render($build);
}
}
return '';
}
function theme_blockreference_formatter_plain($variables) {
$element = $variables['element'];
$block = _blockreference_formatter_get_block($element);
if ($block) {
$info = module_invoke($block->module, 'block_info');
return $info[$block->delta]['info'];
}
return '';
}
function theme_blockreference_formatter_title($variables) {
$element = $variables['element'];
$block = _blockreference_formatter_get_block($element);
if ($block) {
$block_content = _block_render_blocks(array(
$block,
));
if ($block_content) {
return reset($block_content)->subject;
}
}
return '';
}
function theme_blockreference_formatter_config_link($variables) {
$element = $variables['element'];
$item = $element['item'];
if (@$item['moddelta']) {
list($module, $delta) = explode(':', $item['moddelta']);
$settings = $element['display']['settings'];
$label = '';
switch ($settings['label']) {
case 'custom':
$label = t($settings['custom_label']);
break;
case 'info':
$label = theme_blockreference_formatter_plain($variables);
break;
case 'config':
$label = db_query('
SELECT title
FROM {block}
WHERE module = ? AND delta = ?
', array(
$module,
$delta,
))
->fetchField();
break;
case 'rendered':
$label = theme_blockreference_formatter_title($variables);
break;
}
if (!$label) {
$label = t('configure block');
}
return l($label, 'admin/structure/block/manage/' . $module . '/' . $delta . '/configure');
}
return '';
}
function _blockreference_get_block_modules_from_field($instance, $field = NULL) {
$modules = @$instance['settings']['blockreference_modules'];
if (!$modules) {
$field or $field = field_info_field($instance['field_name']);
$modules = @$field['settings']['referenceable_modules'];
}
$modules = drupal_map_assoc(array_keys(array_filter($modules)));
return (array) $modules;
}
function _blockreference_get_ac_match_method_from_field($instance, $field = NULL) {
$method = @$instance['widget']['settings']['blockreference_ac_match_method'];
return $method ?: 'contains';
}
function _blockreference_get_block_modules() {
$modules =& drupal_static(__FUNCTION__);
if (!$modules) {
$modules = module_implements('block_info');
$modules = array_flip($modules);
$all_modules = system_list('module_enabled');
foreach ($modules as $machine_name => $foo) {
$modules[$machine_name] = @$all_modules[$machine_name]->info['name'] ?: $machine_name;
}
natcasesort($modules);
}
return $modules;
}
function _blockreference_block_string($block) {
if (!$block) {
return '';
}
$moddelta = $block->module . ':' . $block->delta;
$label = $block->info;
return $label . ' [' . $moddelta . ']';
}
function _blockreference_block_from_ac_string($ac_string) {
if (preg_match(BLOCKREFERENCE_AC_REGEX, $ac_string, $match)) {
$module = $match[1];
$delta = $match[2];
return compact('module', 'delta');
}
}
function _blockreference_block($module, $delta, $info = NULL) {
if (!$info) {
$infos = module_invoke($module, 'block_info');
$info = @$infos[$delta];
}
if ($info) {
$info = compact('module', 'delta') + $info;
$info['info'] = trim($info['info']);
return (object) $info;
}
}
function _blockreference_find_blocks($instance, $search_string = '', $context = array()) {
$all_block_infos =& drupal_static(__FUNCTION__, array());
$iid = $instance['id'];
if (!isset($all_block_infos[$iid])) {
$referenceable_modules = _blockreference_get_block_modules_from_field($instance);
$all_block_infos[$iid] = array();
foreach (module_implements('block_info') as $module) {
if (!$referenceable_modules || isset($referenceable_modules[$module])) {
if ($blocks = module_invoke($module, 'block_info')) {
foreach ($blocks as $delta => $info) {
$moddelta = $module . ':' . $delta;
$all_block_infos[$iid][$moddelta] = _blockreference_block($module, $delta, $info);
}
}
}
}
}
$blocks = $all_block_infos[$iid];
$context['instance'] = $instance;
drupal_alter('blockreference_blocks_pre', $blocks, $context);
if ($search_string) {
$check_string = drupal_strtolower($search_string);
foreach ($blocks as $moddelta => $block) {
if (strpos(drupal_strtolower($block->info), $check_string) === FALSE) {
unset($blocks[$moddelta]);
}
}
}
uasort($blocks, function ($a, $b) {
return strnatcasecmp($a->info, $b->info);
});
drupal_alter('blockreference_blocks_post', $blocks, $context);
return $blocks;
}
function _blockreference_options($blocks, $ac_style = FALSE) {
$options = array();
foreach ($blocks as $block) {
$moddelta = $block->module . ':' . $block->delta;
$label = $block->info;
$value = $ac_style ? _blockreference_block_string($block) : $moddelta;
$options[$value] = $label;
}
return $options;
}
function blockreference_options_list($field, $instance, $entity_type, $entity) {
$context = array(
'type' => 'options_list',
'entity' => $entity,
);
$blocks = _blockreference_find_blocks($instance, '', $context);
return _blockreference_options($blocks);
}
function _blockreference_formatter_get_block($element) {
$item = $element['item'];
if (@$item['moddelta']) {
list($module, $delta) = explode(':', $item['moddelta']);
$block = _blockreference_block($module, $delta);
if ($block) {
$query = db_select('block', 'b')
->fields('b')
->condition('module', $module)
->condition('delta', $delta)
->execute();
$result = $query
->fetchAssoc();
if ($result) {
foreach ($result as $column => $value) {
if (!isset($block->{$column}) && !in_array($column, array(
'bid',
'theme',
))) {
$block->{$column} = $value;
}
}
}
$block->region = 'none';
return $block;
}
}
return FALSE;
}
function blockreference_entity_view($entity, $entity_type, $view_mode, $langcode) {
if (empty($entity->content)) {
return;
}
foreach (element_children($entity->content) as $field_name) {
$field = $entity->content[$field_name];
if (isset($field['#field_type']) && $field['#field_type'] == 'blockreference') {
foreach (element_children($field) as $n) {
unset($entity->content[$field_name][$n]);
}
$html = render($field);
$keep_meta = array_flip(array(
'#weight',
'#title',
'#access',
'#label_display',
'#field_name',
'#entity_type',
'#bundle',
));
$entity->content[$field_name] = array(
'#markup' => $html,
) + array_intersect_key($field, $keep_meta);
}
}
}
function blockreference_migrate_api() {
return array(
'api' => 2,
'field handlers' => array(
'MigrateBlockReferenceFieldHandler',
),
);
}
function blockreference_block_usage($module, $delta) {
$moddelta = $module . ':' . $delta;
$fields = field_info_field_map();
$entity_loads = $loads_by_field_name = array();
foreach ($fields as $field_name => $field) {
if ($field['type'] == 'blockreference') {
$table_name = 'field_data_' . $field_name;
$column_name = $field_name . '_moddelta';
$items = db_query("SELECT entity_type, entity_id FROM {$table_name} WHERE {$column_name} = :moddelta", array(
':moddelta' => $moddelta,
));
foreach ($items as $item) {
$entity_loads[$item->entity_type][] = $item->entity_id;
$loads_by_field_name[$item->entity_type][$item->entity_id][] = $field_name;
}
}
}
$matches = array();
foreach ($entity_loads as $entity_type => $ids) {
$entities = entity_load($entity_type, $ids);
foreach ($entities as $id => $entity) {
$uri = entity_uri($entity_type, $entity);
$path = $uri['path'];
$options = @$uri['options'] ?: array();
$fields = $loads_by_field_name[$entity_type][$id];
$matches[] = l($entity_type . ' # ' . $id, $path, $options) . ' (' . implode(', ', $fields) . ')';
}
}
return $matches;
}
function blockreference_entityreference_link_config() {
return array(
'blockreference' => array(
'value_column' => 'moddelta',
'links_callback' => '_blockreference_entityreference_link_links',
),
);
}
function _blockreference_entityreference_link_links($entity_type, $moddeltas, $options, $context, $element) {
$links = array();
foreach ($moddeltas as $moddelta) {
list($module, $delta) = explode(':', $moddelta);
$block = _blockreference_block($module, $delta);
if ($block) {
$links[] = l($block->info, 'admin/structure/block/manage/' . $module . '/' . $delta . '/configure', $options);
}
}
return $links;
}