| 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;  }}
 |