1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306 |
- <?php
- /**
- * @file
- * Provide features components for exporting core blocks and settings.
- */
- /**
- * Version number for the current fe_block export definition.
- */
- define('FE_BLOCK_VERSION', '2.0');
- /**
- * Implements hook_features_api().
- */
- function fe_block_features_api() {
- $info = array();
- $key = 'fe_block_settings';
- $info[$key] = array(
- 'name' => t('Block settings'),
- 'feature_source' => TRUE,
- 'default_hook' => 'default_' . $key,
- 'default_file' => FEATURES_DEFAULTS_INCLUDED,
- );
- $key = 'fe_block_boxes';
- $info[$key] = array(
- 'name' => t('Block contents (boxes)'),
- 'feature_source' => TRUE,
- 'default_hook' => 'default_' . $key,
- 'default_file' => FEATURES_DEFAULTS_INCLUDED,
- );
- return $info;
- }
- /**
- * Implements hook_features_export_options().
- */
- function fe_block_settings_features_export_options() {
- $options = array();
- $blocks = _fe_block_get_blocks();
- usort($blocks, '_fe_block_compare');
- foreach ($blocks as $block) {
- // @see features.block.inc
- if (strpos($block['module'], '-') !== FALSE) {
- continue;
- }
- $block_id = _fe_block_build_id($block);
- if (empty($block_id)) {
- continue;
- }
- $options[$block_id] = '[' . $block_id . '] ' . $block['info'];
- }
- return $options;
- }
- /**
- * Implements hook_features_export().
- */
- function fe_block_settings_features_export($data, &$export, $module_name = '') {
- $pipe = array();
- $export['dependencies']['fe_block'] = 'fe_block';
- $component = 'fe_block_settings';
- // Add the components.
- foreach ($data as $object_name) {
- $export['features'][$component][$object_name] = $object_name;
- // Boxes.
- if (strpos($object_name, 'block-') === 0) {
- $machine_name = substr($object_name, strlen('block-'));
- $pipe['fe_block_boxes'][$machine_name] = $machine_name;
- }
- // @todo Export menu blocks.
- // Others.
- else {
- $pipe['block'][$object_name] = $object_name;
- }
- }
- return $pipe;
- }
- /**
- * Implements hook_features_export_render().
- */
- function fe_block_settings_features_export_render($module_name = '', $data) {
- $code = array();
- $code[] = ' $export = array();';
- $code[] = '';
- // The way the blocks are exported has changed throughout the history of the
- // module. We provide an export format version string to provide backwards
- // compatibility. Note that it is ok to use the array key "version" here.
- // Block ids always have a '-' in their string.
- $code[] = ' $export[\'version\'] = \'' . FE_BLOCK_VERSION . '\';';
- $code[] = '';
- // Get a list of all active themes to cycle through.
- $themes = _fe_block_get_active_themes();
- // Retrieve block settings for all blocks in all active themes.
- $blocks = array();
- foreach ($themes as $theme) {
- $blocks[$theme] = _fe_block_info_by_theme($theme);
- }
- // We use the first theme's block settings as master settings. Some settings
- // are specific to each theme, but these are processed later in the loop.
- $default_theme = reset($themes);
- // We try to build an export for each defined data element.
- foreach ($data as $name) {
- // Check if the block still exists in the block definitions.
- if (!empty($blocks[$default_theme][$name])) {
- $block = $blocks[$default_theme][$name];
- // We start to build the export object for this block.
- // First we retrieve data that is valid for any theme.
- $export_block = _fe_block_get_global_settings($block);
- // Ensure core custom block export keys are transformed.
- $export_block = _fe_block_prepare_custom_blocks_for_export($export_block);
- // Add node type settings.
- $export_block['node_types'] = _fe_block_get_block_node_types($block);
- // Add role visibility settings.
- $export_block['roles'] = _fe_block_get_block_roles($block);
- // Add block_class support.
- if (module_exists('block_class')) {
- $export_block['css_class'] = _fe_block_get_block_css_class($block);
- }
- // Add i18n_block support.
- if (module_exists('i18n_block')) {
- $export_block['i18n_block_language'] = _fe_block_get_block_i18n_block_language($block);
- }
- // Add theme specific settings for every active theme.
- $export_block['themes'] = array();
- foreach ($themes as $theme) {
- $export_block['themes'][$theme] = _fe_block_get_theme_specific_settings($blocks[$theme][$name]);
- }
- // Sort export array keys.
- ksort($export_block);
- // Export to code.
- $code[] = ' $export[\'' . $name . '\'] = ' . features_var_export($export_block, ' ') . ';';
- // Add an empty line.
- $code[] = '';
- }
- }
- $code[] = ' return $export;';
- $code = implode("\n", $code);
- return array('default_fe_block_settings' => $code);
- }
- /**
- * Returns the block definitions for a specific theme.
- *
- * @param string $theme
- * Machine name of the theme.
- *
- * @return array
- * Array of block definitions.
- */
- function _fe_block_info_by_theme($theme) {
- $blocks = array();
- foreach (_fe_block_get_blocks($theme) as $block) {
- // Blocks are only valid for export if we got a machine name for them.
- if ($id = _fe_block_build_id($block)) {
- $blocks[$id] = $block;
- }
- }
- // Sort blocks by keys to get a consistent order.
- ksort($blocks);
- return $blocks;
- }
- /**
- * Retrieve the global (non-theme-specific) part of a block definition.
- *
- * @param array $block
- * A block definition.
- *
- * @return array
- * The block definition filtered on non-theme-specific settings.
- */
- function _fe_block_get_global_settings($block) {
- $theme_specific_defaults = _fe_block_theme_specific_defaults();
- // Filter on any keys other than the theme specific ones.
- $return = array_diff_key($block, $theme_specific_defaults);
- // Remove the serial.
- if (isset($return['bid'])) {
- unset($return['bid']);
- }
- // Remove the info from hook_block_info().
- if (isset($return['info'])) {
- unset($return['info']);
- }
- return $return;
- }
- /**
- * Helper to prepare a core custom block for export.
- *
- * Replaces the block delta that is used by the core block module with a unique
- * machine name.
- *
- * @param array $block
- * Block definition - can be only part of the original definition.
- *
- * @return array
- * Altered block array.
- */
- function _fe_block_prepare_custom_blocks_for_export($block) {
- if ($block['module'] == 'block') {
- $block['machine_name'] = fe_block_get_machine_name($block['delta']);
- unset($block['delta']);
- }
- return $block;
- }
- /**
- * Helper function. Prepares an exported core custom block for import.
- *
- * @param array $block
- * Block definition from the import code.
- *
- * @return array
- * Altered array with machine_name replaced by delta.
- */
- function _fe_block_prepare_custom_blocks_for_import($block) {
- if ($block['module'] == 'block') {
- $block['delta'] = fe_block_get_bid($block['machine_name'], TRUE);
- unset($block['machine_name']);
- }
- return $block;
- }
- /**
- * Helper function to get the theme specific settings for a block.
- *
- * @param array $block
- * A single block definition.
- *
- * @return array
- * A filtered block definition with only theme-specific settings.
- */
- function _fe_block_get_theme_specific_settings($block) {
- $defaults = _fe_block_theme_specific_defaults();
- $settings = array_intersect_key($block, $defaults);
- // Region.
- if ($settings['region'] == BLOCK_REGION_NONE) {
- $settings['status'] = 0;
- $settings['region'] = '';
- }
- ksort($settings);
- return $settings;
- }
- /**
- * Helper function for filtering theme specific settings.
- *
- * @see _fe_block_get_global_settings()
- * @see _fe_block_get_theme_specific_settings()
- *
- * @return array
- * An array of default settings, keyed by name.
- */
- function _fe_block_theme_specific_defaults() {
- return array(
- 'theme' => '',
- 'status' => '',
- 'weight' => 0,
- 'region' => '',
- );
- }
- /**
- * Get node type visibility settings for the specified block.
- *
- * @param array $block
- * Block definition array.
- *
- * @return array
- * Array of node types associated with the block.
- */
- function _fe_block_get_block_node_types($block) {
- $query = db_select('block_node_type', 'bnt')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->fields('bnt', array('type'))
- ->orderBy('bnt.type', 'ASC');
- return $query->execute()->fetchCol();
- }
- /**
- * Returns the blocks currently exported by modules.
- *
- * This is derived from _block_rehash().
- *
- * @param string $theme
- * The theme to retrieve blocks for. If not provided, defaults to the
- * currently used theme.
- *
- * @return array
- * Blocks currently exported by modules.
- */
- function _fe_block_get_blocks($theme = NULL) {
- global $theme_key;
- $blocks = array();
- drupal_theme_initialize();
- if (!isset($theme)) {
- // If theme is not specifically set, rehash for the current theme.
- $theme = $theme_key;
- }
- $regions = system_region_list($theme);
- // These are the blocks defined by code and modified by the database.
- $current_blocks = array();
- // These are {block}.bid values to be kept.
- $bids = array();
- $or = db_or();
- // Gather the blocks defined by modules.
- foreach (module_implements('block_info') as $module) {
- $module_blocks = module_invoke($module, 'block_info');
- foreach ($module_blocks as $delta => $block) {
- // Compile a condition to retrieve this block from the database.
- $condition = db_and()
- ->condition('module', $module)
- ->condition('delta', $delta);
- $or->condition($condition);
- // Add identifiers.
- $block['module'] = $module;
- $block['delta'] = $delta;
- $block['theme'] = $theme;
- $current_blocks[$module][$delta] = $block;
- }
- }
- // Retrieve database settings for all blocks that are defined by modules.
- $code_blocks = $current_blocks;
- $database_blocks = db_select('block', 'b')
- ->fields('b')
- ->condition($or)
- ->condition('theme', $theme)
- ->execute();
- foreach ($database_blocks as $block) {
- // Preserve info which is not in the database.
- $block->info = $current_blocks[$block->module][$block->delta]['info'];
- // The cache mode can only by set from hook_block_info(), so that has
- // precedence over the database's value.
- if (isset($current_blocks[$block->module][$block->delta]['cache'])) {
- $block->cache = $current_blocks[$block->module][$block->delta]['cache'];
- }
- // Blocks stored in the database override the blocks defined in code.
- $current_blocks[$block->module][$block->delta] = get_object_vars($block);
- // Preserve this block.
- $bids[$block->bid] = $block->bid;
- }
- drupal_alter('block_info', $current_blocks, $theme, $code_blocks);
- foreach ($current_blocks as $module => $module_blocks) {
- foreach ($module_blocks as $delta => $block) {
- if (!isset($block['pages'])) {
- // {block}.pages is type 'text', so it cannot have a
- // default value, and not null, so we need to provide
- // value if the module did not.
- $block['pages'] = '';
- }
- // Make sure weight is set.
- if (!isset($block['weight'])) {
- $block['weight'] = 0;
- }
- // Disable blocks that are not assigned to a region in the theme.
- if (!empty($block['region']) && $block['region'] != BLOCK_REGION_NONE && !isset($regions[$block['region']]) && $block['status'] == 1) {
- // Disabled modules are moved into the BLOCK_REGION_NONE later so no
- // need to move the block to another region.
- $block['status'] = 0;
- }
- // Set region to none if not enabled and make sure status is set.
- if (empty($block['status'])) {
- $block['status'] = 0;
- $block['region'] = BLOCK_REGION_NONE;
- }
- // Add to the list of blocks we return.
- $blocks[] = $block;
- }
- }
- return $blocks;
- }
- /**
- * Returns a list of machine names of active themes.
- *
- * @return array
- * An array of theme machine names.
- */
- function _fe_block_get_active_themes() {
- $theme_names = array();
- foreach (system_list('theme') as $machine_name => $theme) {
- if (!empty($theme->status)) {
- $theme_names[] = $machine_name;
- }
- }
- sort($theme_names);
- return $theme_names;
- }
- /**
- * Implements hook_features_revert().
- */
- function fe_block_settings_features_revert($module_name = NULL) {
- $component = 'fe_block_settings';
- $defaults = features_get_default($component, $module_name);
- if (empty($defaults)) {
- return;
- }
- // We remove the version, as we now want to deal with actual block settings.
- unset($defaults['version']);
- $themes_rehashed = array();
- $active_themes = _fe_block_get_active_themes();
- // The fallback theme for theme specific settings.
- $theme_default = variable_get('theme_default', 'bartik');
- foreach ($defaults as $block) {
- // Core custom blocks are prepared with a delta value.
- $block = _fe_block_prepare_custom_blocks_for_import($block);
- // Remove the additional settings from the block array, to process them
- // later. We explicitely set NULL, if no setting was given in the defaults.
- $block_themes = $block['themes'];
- $block_node_types = isset($block['node_types']) ? $block['node_types'] : NULL;
- $block_roles = isset($block['roles']) ? $block['roles'] : NULL;
- $block_css_class = isset($block['css_class']) ? $block['css_class'] : NULL;
- $block_i18n_block_language = isset($block['i18n_block_language']) ? $block['i18n_block_language'] : NULL;
- unset($block['themes']);
- unset($block['node_types']);
- unset($block['roles']);
- unset($block['css_class']);
- unset($block['i18n_block_language']);
- // Restore theme specific settings for every active theme.
- foreach ($active_themes as $theme) {
- // Rehash if we did not yet.
- if (empty($themes_rehashed[$theme])) {
- _block_rehash($theme);
- $themes_rehashed[$theme] = TRUE;
- }
- // Get the theme specific setting for the active theme.
- if (isset($block_themes[$theme])) {
- $key = $theme;
- }
- // Or fallback on the default theme.
- elseif (isset($block_themes[$theme_default])) {
- $key = $theme_default;
- }
- // Or fallback on the first available theme spec.
- else {
- $key = key($block_themes);
- }
- // Write block settings.
- $write = array_merge($block, $block_themes[$key]);
- drupal_write_record('block', $write, array('module', 'delta', 'theme'));
- }
- // Ensure global settings.
- _fe_block_settings_update_global_settings($block);
- // Set node type settings
- // (only if there were some defined, to avoid overwriting not yet exported
- // data).
- if (isset($block_node_types)) {
- _fe_block_settings_update_block_node_type_settings($block, $block_node_types);
- }
- // Apply role visibility settings.
- if (isset($block_roles)) {
- _fe_block_settings_update_block_roles($block, $block_roles);
- }
- // Update block CSS classes.
- if (isset($block_css_class) && module_exists('block_class')) {
- _fe_block_settings_update_block_css_class($block, $block_css_class);
- }
- // Set i18n_block languages.
- if (module_exists('i18n_block') && isset($block_i18n_block_language)) {
- _fe_block_settings_update_i18n_block_language($block, $block_i18n_block_language);
- }
- // Apply blockcache_alter settings.
- if (module_exists('blockcache_alter')) {
- _fe_block_settings_update_block_cache_alter($block);
- }
- }
- // Clear block cache.
- cache_clear_all(NULL, 'cache_block');
- return TRUE;
- }
- /**
- * Helper to update global block settings for a specific block.
- *
- * @param array $block
- * Block definition.
- */
- function _fe_block_settings_update_global_settings($block) {
- $globals = _fe_block_get_global_settings($block);
- // Filter out any keys that do not correspond to fields in the block table.
- $fields = drupal_schema_fields_sql('block');
- $globals = array_intersect_key($globals, array_flip($fields));
- db_update('block')
- ->fields($globals)
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- }
- /**
- * Helper to update node type settings for a given block.
- *
- * @param array $block
- * Block definition.
- * @param array $node_types
- * Array of node types.
- */
- function _fe_block_settings_update_block_node_type_settings($block, $node_types) {
- // First delete the old node type settings.
- db_delete('block_node_type')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- if (!empty($node_types)) {
- $insert = db_insert('block_node_type')
- ->fields(array('module', 'delta', 'type'));
- foreach ($node_types as $type) {
- $insert->values(array(
- 'module' => $block['module'],
- 'delta' => $block['delta'],
- 'type' => $type,
- ));
- }
- $insert->execute();
- }
- }
- /**
- * Helper to update the block role settings for a given block.
- *
- * @param array $block
- * Block definition.
- * @param array $block_roles
- * Associative array of roles.
- * - key: role name.
- * - value: (foreign) role id.
- */
- function _fe_block_settings_update_block_roles($block, $block_roles) {
- static $roles;
- // First get the current set of roles, so we can match role names to rids.
- if (!isset($roles)) {
- $roles = db_select('role', 'r')
- ->fields('r', array('rid', 'name'))
- ->execute()
- ->fetchAllKeyed(1, 0);
- }
- // First delete the old block role settings.
- db_delete('block_role')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- // Then write the new settings, if any are present.
- if (!empty($block_roles)) {
- $insert = db_insert('block_role')
- ->fields(array('module', 'delta', 'rid'));
- // We use a found flag, to avoid empty inserts if no role names match.
- $found = FALSE;
- foreach ($block_roles as $name => $rid) {
- // We only write for roles, matching the given role name.
- if (isset($roles[$name])) {
- $insert->values(array(
- 'module' => $block['module'],
- 'delta' => $block['delta'],
- 'rid' => $roles[$name],
- ));
- $found = TRUE;
- }
- }
- if ($found) {
- $insert->execute();
- }
- }
- }
- /**
- * Helper to update the block class settings for a given block.
- *
- * @param array $block
- * Block definition of the block to update.
- * @param string $block_css_class
- * List of CSS classes to apply to the block.
- */
- function _fe_block_settings_update_block_css_class($block, $block_css_class) {
- // This functionality is provided by the Block Class module.
- if (module_exists('block_class')) {
- // Block Class 1.x maintained its own table.
- if (db_table_exists('block_class')) {
- // First delete the old block_class settings, if any.
- db_delete('block_class')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- // Then write the new settings, if any are present.
- if (!empty($block_css_class)) {
- db_insert('block_class')
- ->fields(array('module', 'delta', 'css_class'))
- ->values(array(
- 'module' => $block['module'],
- 'delta' => $block['delta'],
- 'css_class' => $block_css_class,
- ))
- ->execute();
- }
- }
- // Block Class 2.x extends the core Block table.
- elseif (db_field_exists('block', 'css_class')) {
- db_update('block')
- ->fields(array('css_class' => $block_css_class))
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- }
- }
- }
- /**
- * Helper to update the i18n block language settings for a specific block.
- *
- * @param array $block
- * Block definition.
- * @param array $block_languages
- * Array of associated languages.
- */
- function _fe_block_settings_update_i18n_block_language($block, $block_languages) {
- // First remove the old settings.
- db_delete('i18n_block_language')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute();
- // Then write the new settings.
- if (!empty($block_languages)) {
- $insert = db_insert('i18n_block_language')
- ->fields(array('module', 'delta', 'language'));
- foreach ($block_languages as $langcode) {
- $insert->values(array(
- 'module' => $block['module'],
- 'delta' => $block['delta'],
- 'language' => $langcode,
- ));
- }
- $insert->execute();
- }
- }
- /**
- * Helper to update the blockcache_alter settings for a specific block.
- *
- * @param array $block
- * Block definition.
- */
- function _fe_block_settings_update_block_cache_alter($block){
- $bids = db_select('block', 'b')
- ->fields('b', array('bid'))
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute()
- ->fetchCol();
- $blockcache_alter = db_select('blockcache_alter', 'b')
- ->fields('b', array('bid'))
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute()
- ->fetchCol();
- foreach ($bids as $bid) {
- $block['bid'] = $bid;
- if (in_array($bid, $blockcache_alter)) {
- drupal_write_record('blockcache_alter', $block, array('bid'));
- }
- else {
- drupal_write_record('blockcache_alter', $block);
- }
- }
- }
- /**
- * Implements hook_features_disable_feature().
- */
- function fe_block_settings_features_disable_feature($module) {
- }
- /**
- * Implements hook_features_enable_feature().
- */
- function fe_block_settings_features_enable_feature($module) {
- fe_block_settings_features_revert($module);
- }
- /**
- * Implements hook_features_rebuild().
- */
- function fe_block_settings_features_rebuild($module) {
- fe_block_settings_features_revert($module);
- }
- /**
- * Implements hook_features_export_options().
- */
- function fe_block_boxes_features_export_options() {
- $table = 'fe_block_boxes';
- $options = array();
- // Defaults.
- $schema = ctools_export_get_schema($table);
- $export = $schema['export'];
- $defaults = _ctools_export_get_defaults($table, $export);
- foreach ($defaults as $obj) {
- $options[$obj->machine_name] = t('@name [@machine_name]', array('@name' => $obj->info, '@machine_name' => $obj->machine_name));
- }
- // Normals.
- $query = "SELECT * FROM {{$table}} {$table} INNER JOIN {block_custom} b ON b.bid = {$table}.bid ORDER BY b.bid ASC";
- $result = db_query($query);
- foreach ($result as $obj) {
- $options[$obj->machine_name] = t('@name [@machine_name]', array('@name' => $obj->info, '@machine_name' => $obj->machine_name));
- }
- ksort($options);
- return $options;
- }
- /**
- * Implements hook_features_export().
- */
- function fe_block_boxes_features_export($data, &$export, $module_name = '') {
- $pipe = array();
- $export['dependencies']['fe_block'] = 'fe_block';
- $table = 'fe_block_boxes';
- // Add the components.
- foreach ($data as $object_name) {
- $export['features'][$table][$object_name] = $object_name;
- }
- return $pipe;
- }
- /**
- * Implements hook_features_export_render().
- */
- function fe_block_boxes_features_export_render($module_name = '', $data) {
- ctools_include('export');
- $component = 'fe_block_boxes';
- $schema = ctools_export_get_schema($component);
- $objects = ctools_export_load_object($component);
- $code = array();
- $code[] = ' $export = array();';
- $code[] = '';
- foreach ($data as $machine_name) {
- // The object to be exported.
- if (isset($objects[$machine_name]) && $object = $objects[$machine_name]) {
- $additions = array();
- // Load box.
- if (!empty($object->bid) && $box = block_custom_block_get($object->bid)) {
- $additions = (array) $box;
- unset($additions['bid'], $additions['body']);
- // Code.
- $identifier = $schema['export']['identifier'];
- $code[] = ctools_export_object($component, $object, ' ', $identifier, $additions) . ' $' . $identifier . '->body = ' . features_var_export($box['body']) . ';';
- $code[] = '';
- $code[] = ' $export[\'' . $machine_name . '\'] = $' . $identifier . ';';
- $code[] = '';
- }
- }
- }
- $code[] = ' return $export;';
- $code = implode("\n", $code);
- return array($schema['export']['default hook'] => $code);
- }
- /**
- * Implements hook_features_revert().
- */
- function fe_block_boxes_features_revert($module_name = NULL) {
- $defaults = features_get_default('fe_block_boxes', $module_name);
- if (empty($defaults)) {
- return;
- }
- // Revert.
- foreach ($defaults as $object) {
- if (empty($object->machine_name)) {
- continue;
- }
- $bid = fe_block_get_bid($object->machine_name);
- if (empty($bid) || !($box = block_custom_block_get($bid))) {
- $result = _fe_block_save_box((array) $object);
- if (!empty($result['bid'])) {
- $or = db_or()
- ->condition('bid', $result['bid'])
- ->condition('machine_name', $object->machine_name);
- db_delete('fe_block_boxes')
- ->condition($or)
- ->execute();
- db_insert('fe_block_boxes')
- ->fields(array(
- 'bid' => $result['bid'],
- 'machine_name' => $object->machine_name,
- ))
- ->execute();
- }
- }
- else {
- $object->bid = $bid;
- $result = _fe_block_save_box((array) $object);
- }
- }
- // Clear block cache.
- cache_clear_all(NULL, 'cache_block');
- return TRUE;
- }
- /**
- * Implements hook_features_disable_feature().
- */
- function fe_block_boxes_features_disable_feature($module) {
- }
- /**
- * Implements hook_features_enable_feature().
- */
- function fe_block_boxes_features_enable_feature($module) {
- fe_block_boxes_features_revert($module);
- }
- /**
- * Implements hook_features_rebuild().
- */
- function fe_block_boxes_features_rebuild($module) {
- fe_block_boxes_features_revert($module);
- }
- /**
- * Implements hook_form_alter().
- */
- function fe_block_form_alter(&$form, $form_state, $form_id) {
- $default_values = array();
- if ($form_id == 'block_add_block_form' && $form['module']['#value'] == 'block' && user_access('administer features')) {
- $default_values['machine_name'] = '';
- $default_values['bid'] = 0;
- }
- elseif ($form_id == 'block_admin_configure' && $form['module']['#value'] == 'block' && user_access('administer features')) {
- $bid = $form['delta']['#value'];
- $machine_name = fe_block_get_machine_name($bid);
- $default_values['machine_name'] = empty($machine_name) ? '' : $machine_name;
- $default_values['bid'] = $bid;
- }
- // Delete a block.
- elseif ($form_id == 'block_box_delete') {
- $form['#submit'][] = 'fe_block_machine_name_delete';
- }
- // Add & edit.
- if (!empty($default_values)) {
- $form['settings']['machine_name'] = array(
- '#type' => 'textfield',
- '#title' => t('Machine name'),
- '#default_value' => $default_values['machine_name'],
- '#maxlength' => 32,
- '#description' => t('Give the block a machine name to make it exportable with "!features" module.', array('!features' => l('Features', 'http://drupal.org/project/features'))),
- '#weight' => -50,
- );
- $form['bid'] = array(
- '#type' => 'value',
- '#value' => $default_values['bid'],
- );
- // Validate & submit.
- $form['#validate'][] = 'fe_block_machine_name_validate';
- $form['#submit'][] = 'fe_block_machine_name_submit';
- }
- }
- /**
- * Validate machine name.
- */
- function fe_block_machine_name_validate($form, &$form_state) {
- if (empty($form_state['values']['machine_name'])) {
- return;
- }
- $table = 'fe_block_boxes';
- $query = db_select($table)
- ->condition('bid', $form_state['values']['bid'], '<>')
- ->condition('machine_name', $form_state['values']['machine_name']);
- $count = $query->countQuery()->execute()->fetchField();
- if (!preg_match('!^[a-z0-9_]+$!', $form_state['values']['machine_name'])) {
- form_set_error('machine_name', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
- }
- elseif ($count > 0) {
- form_set_error('machine_name', t('The machine-readable name has been taken. Please pick another one.'));
- }
- }
- /**
- * Save machine name.
- */
- function fe_block_machine_name_submit($form, &$form_state) {
- // If a block id is not given, retrieve it from the database.
- if (empty($form_state['values']['bid'])) {
- $form_state['values']['bid'] = db_select('block_custom')
- ->fields('block_custom', array('bid'))
- ->condition('info', $form_state['values']['info'])
- ->execute()->fetch()->bid;
- }
- if (empty($form_state['values']['bid'])) {
- return;
- }
- $table = 'fe_block_boxes';
- db_delete($table)
- ->condition('bid', $form_state['values']['bid'])
- ->execute();
- if (!empty($form_state['values']['machine_name'])) {
- drupal_write_record($table, $form_state['values']);
- }
- }
- /**
- * Delete machine name.
- */
- function fe_block_machine_name_delete($form, &$form_state) {
- $table = 'fe_block_boxes';
- db_delete($table)->condition('bid', $form_state['values']['bid']);
- }
- /**
- * Callback for usort(). Sorts blocks on "module" and "delta".
- */
- function _fe_block_compare($a, $b) {
- $module_cmp = strcmp($a['module'], $b['module']);
- if (!empty($module_cmp)) {
- return $module_cmp;
- }
- return strcmp($a['delta'], $b['delta']);
- }
- /**
- * Provided for backwards compatibility. Use fe_block_get_machine_name().
- */
- function _fe_block_get_machine_name($bid) {
- debug(t('The function @function is deprecated.', array('@function' => __FUNCTION__ . '()')));
- return fe_block_get_machine_name($bid);
- }
- /**
- * Returns the machine name that corresponds to a given block id.
- *
- * @param int $bid
- * The block id for which to retrieve the machine name.
- *
- * @return string | FALSE
- * The machine name, or FALSE if it could not be found.
- */
- function fe_block_get_machine_name($bid) {
- $machine_names = &drupal_static(__FUNCTION__);
- if (!isset($machine_names[$bid])) {
- $result = db_select('fe_block_boxes')
- ->fields('fe_block_boxes', array('machine_name'))
- ->condition('bid', $bid)
- ->execute()
- ->fetch();
- if (empty($result)) {
- return FALSE;
- }
- $machine_names[$bid] = $result->machine_name;
- }
- return $machine_names[$bid];
- }
- /**
- * Provided for backwards compatibility. Use fe_block_get_bid() instead.
- */
- function _fe_block_get_bid($machine_name, $reset = FALSE) {
- debug(t('The function @function is deprecated.', array('@function' => __FUNCTION__ . '()')));
- return fe_block_get_bid($machine_name, $reset);
- }
- /**
- * Returns the block id that corresponds to a given machine name.
- *
- * @param string $machine_name
- * The machine name of a block for which to retrieve the block id.
- *
- * @return int | FALSE
- * The block id, or FALSE if the machine name was not found.
- */
- function fe_block_get_bid($machine_name, $reset = FALSE) {
- $bids = &drupal_static(__FUNCTION__);
- if (!isset($bids[$machine_name]) || $reset) {
- $result = db_select('fe_block_boxes')
- ->fields('fe_block_boxes', array('bid'))
- ->condition('machine_name', $machine_name)
- ->execute()
- ->fetch();
- if (empty($result)) {
- return FALSE;
- }
- $bids[$machine_name] = (int) $result->bid;
- }
- return $bids[$machine_name];
- }
- /**
- * Generate block ID.
- */
- function _fe_block_build_id($block) {
- if (empty($block['module']) || (empty($block['delta']) && !is_numeric($block['delta']))) {
- return NULL;
- }
- if ($block['module'] == 'block') {
- $machine_name = fe_block_get_machine_name($block['delta']);
- if (empty($machine_name)) {
- return NULL;
- }
- return $block['module'] . '-' . $machine_name;
- }
- else {
- return $block['module'] . '-' . $block['delta'];
- }
- }
- /**
- * Save a box.
- *
- * @param array $settings
- * A box settings array.
- *
- * @return array
- * Updated settings array.
- */
- function _fe_block_save_box($settings = array()) {
- if (empty($settings['info'])) {
- return FALSE;
- }
- // 'info' must be unique.
- if (empty($settings['bid'])) {
- $conflict = db_query("SELECT COUNT(*) as count FROM {block_custom} WHERE info = :info", array('info' => $settings['info']));
- }
- else {
- $conflict = db_query("SELECT COUNT(*) as count FROM {block_custom} WHERE info = :info AND bid <> :bid", array('info' => $settings['info'], ':bid' => $settings['bid']));
- }
- if (!empty($conflict->fetch()->count)) {
- return FALSE;
- }
- // Provide some default settings.
- $default_settings = array(
- 'info' => '',
- 'body' => '',
- 'format' => 'FILTER_FORMAT_DEFAULT',
- );
- $settings = array_merge($default_settings, $settings);
- // Save the block settings.
- if (empty($settings['bid'])) {
- drupal_write_record('block_custom', $settings);
- }
- else {
- drupal_write_record('block_custom', $settings, 'bid');
- }
- return $settings;
- }
- /**
- * Implements hook_module_implements_alter().
- */
- function fe_block_module_implements_alter(&$implementations, $hook) {
- if ($hook == 'default_fe_block_settings_alter') {
- // Ensure fe_block is the first imlementation to be called, so we can
- // convert to the newest format.
- $group = $implementations['fe_block'];
- unset($implementations['fe_block']);
- $rest = array_reverse($implementations, TRUE);
- $rest['fe_block'] = $group;
- $implementations = array_reverse($rest, TRUE);
- }
- }
- /**
- * Implements hook_default_fe_block_settings_alter().
- */
- function fe_block_default_fe_block_settings_alter(&$defaults) {
- // Convert the settings in the newest format.
- $defaults = _fe_block_settings_convert($defaults);
- }
- /**
- * Helper function to get the block roles visibility settings.
- *
- * @param array $block
- * the block definition array
- *
- * @return array
- * associated role settings for the block
- * - key: role name
- * - value: role id
- */
- function _fe_block_get_block_roles($block) {
- $query = db_select('block_role', 'br')
- ->condition('br.module', $block['module'])
- ->condition('br.delta', $block['delta']);
- $query->innerJoin('role', 'r', 'r.rid = br.rid');
- $query->fields('r', array('name', 'rid'))
- ->orderBy('r.name', 'ASC');
- $roles = $query->execute()->fetchAllKeyed(0, 1);
- return $roles;
- }
- /**
- * Helper function to get block class settings.
- *
- * @param array $block
- * The block definition.
- *
- * @return string
- * Class name(s) for the block.
- */
- function _fe_block_get_block_css_class($block) {
- // This functionality depends on the Block Class module.
- if (module_exists('block_class')) {
- // Block Class 2.x extends the core Block table, so we have the data.
- if (!empty($block['css_class'])) {
- return $block['css_class'];
- }
- // Block Class 1.x maintains its own table.
- if (db_table_exists('block_class')) {
- $css_class = db_select('block_class', 'b')
- ->fields('b', array('css_class'))
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->execute()
- ->fetchField();
- }
- }
- return !empty($css_class) ? $css_class : '';
- }
- /**
- * Get i18n block language from i18n_block.
- *
- * @param array $block
- * Block definition array.
- *
- * @return array
- * Array of language codes for the specified block.
- */
- function _fe_block_get_block_i18n_block_language($block) {
- $query = db_select('i18n_block_language', 'bl')
- ->condition('module', $block['module'])
- ->condition('delta', $block['delta'])
- ->fields('bl', array('language'))
- ->orderBy('bl.language');
- return $query->execute()->fetchCol();
- }
- /**
- * Helper function to convert an older export into the new format.
- *
- * @param array $defaults
- * array of fe_block_settings definition.
- *
- * @return array
- * array of current fe_block_settings definition
- */
- function _fe_block_settings_convert($defaults) {
- $version = (isset($defaults['version'])) ? $defaults['version'] : 0;
- // Directly return if the version is the current one.
- if ($version == FE_BLOCK_VERSION) {
- return $defaults;
- }
- elseif ($version == '1.0') {
- // We try to get the default theme for the global definitions, else we take
- // the first.
- $theme_default = variable_get('theme_default', 'bartik');
- if (!isset($defaults['theme'][$theme_default])) {
- $theme_default = key($defaults['theme']);
- }
- $blocks = array();
- // We get the basic blocks from the visibility array.
- foreach ($defaults['visibility'] as $block_id => $base) {
- $node_types = array();
- if (isset($base['node_type'])) {
- // Node types were specified in node_type => TRUE/FALSE. Now we simply
- // list the selected node types.
- $node_types = array_keys(array_filter($base));
- unset($base['node_type']);
- }
- $block = $base;
- $block['node_types'] = $node_types;
- // Global settings.
- $globals = _fe_block_get_global_settings($defaults['theme'][$theme_default][$block_id]);
- $block = array_merge($globals, $block);
- // Build theme specific array.
- $block['themes'] = array();
- foreach ($defaults['theme'] as $theme => $items) {
- $block['themes'][$theme] = _fe_block_get_theme_specific_settings($items[$block_id]);
- }
- $blocks[$block_id] = $block;
- }
- // Set current version so we can compare it with current version defaults.
- $blocks['version'] = FE_BLOCK_VERSION;
- return $blocks;
- }
- // The oldest version.
- // There we got an array of themes that holded the block settings.
- elseif ($version == 0) {
- // We try to get the default theme for the global definitions, else we take
- // the first.
- $theme_default = variable_get('theme_default', 'bartik');
- if (!isset($defaults[$theme_default])) {
- $theme_default = key($defaults);
- }
- $blocks = array();
- foreach ($defaults as $theme => $items) {
- foreach ($items as $block_id => $item) {
- // Avoid php notices.
- if (!isset($blocks[$block_id])) {
- $blocks[$block_id] = array(
- 'themes' => array(),
- );
- }
- // Set theme specific settings.
- $blocks[$block_id]['themes'][$theme] = _fe_block_get_theme_specific_settings($item);
- // We add the global settings for the default theme.
- if ($theme == $theme_default) {
- $globals = _fe_block_get_global_settings($item);
- $blocks[$block_id] = array_merge($blocks[$block_id], $globals);
- }
- }
- }
- // Set current version so we can compare it with current version defaults.
- $blocks['version'] = FE_BLOCK_VERSION;
- return $blocks;
- }
- }
|