123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- <?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 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 $theme
- * The theme to retrieve blocks for. If not provided, defaults to the
- * currently used theme.
- *
- * @return
- * 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 (list_themes() 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;
- unset($block['themes']);
- unset($block['node_types']);
- unset($block['roles']);
- // 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);
- }
- }
- // 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);
- 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 definiton
- * @param array $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();
- }
- }
- }
- /**
- * 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) {
- // Insert
- 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']);
- }
- /**
- * Public APIs.
- *
- * TODO
- */
- /**
- * Internal functions.
- */
- /**
- * Sort blocks with "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 $settings
- * @return 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;
- }
- // Defaults
- $default_settings = array(
- 'info' => '',
- 'body' => '',
- 'format' => 'FILTER_FORMAT_DEFAULT',
- );
- $settings = array_merge($default_settings, $settings);
- // Save
- 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 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;
- }
- }
|