diff --git a/core/lib/Drupal/Core/Annotation/Evaluate.php b/core/lib/Drupal/Core/Annotation/Evaluate.php new file mode 100644 index 0000000..a2dfd25 --- /dev/null +++ b/core/lib/Drupal/Core/Annotation/Evaluate.php @@ -0,0 +1,28 @@ +code = $values['value']; + } + + /** + * Implements AnnotationInterface::get(). + */ + public function get() { + return eval($this->code); + } +} diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module index 047026a..ceecd3f 100644 --- a/core/modules/aggregator/aggregator.module +++ b/core/modules/aggregator/aggregator.module @@ -347,95 +347,6 @@ function aggregator_queue_info() { } /** - * Implements hook_block_info(). - */ -function aggregator_block_info() { - $blocks = array(); - $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title'); - foreach ($result as $category) { - $blocks['category-' . $category->cid]['info'] = t('!title category latest items', array('!title' => $category->title)); - } - $result = db_query('SELECT fid, title FROM {aggregator_feed} WHERE block <> 0 ORDER BY fid'); - foreach ($result as $feed) { - $blocks['feed-' . $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); - } - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function aggregator_block_configure($delta = '') { - list($type, $id) = explode('-', $delta); - if ($type == 'category') { - $value = db_query('SELECT block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchField(); - $form['block'] = array( - '#type' => 'select', - '#title' => t('Number of news items in block'), - '#default_value' => $value, - '#options' => drupal_map_assoc(range(2, 20)), - ); - return $form; - } -} - -/** - * Implements hook_block_save(). - */ -function aggregator_block_save($delta = '', $edit = array()) { - list($type, $id) = explode('-', $delta); - if ($type == 'category') { - db_update('aggregator_category') - ->fields(array('block' => $edit['block'])) - ->condition('cid', $id) - ->execute(); - } -} - -/** - * Implements hook_block_view(). - * - * Generates blocks for the latest news items in each category and feed. - */ -function aggregator_block_view($delta = '') { - if (user_access('access news feeds')) { - $block = array(); - list($type, $id) = explode('-', $delta); - $result = FALSE; - switch ($type) { - case 'feed': - if ($feed = db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE block <> 0 AND fid = :fid', array(':fid' => $id))->fetchObject()) { - $block['subject'] = check_plain($feed->title); - $result = db_query_range("SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC", 0, $feed->block, array(':fid' => $id)); - $read_more = theme('more_link', array('url' => 'aggregator/sources/' . $feed->fid, 'title' => t("View this feed's recent news."))); - } - break; - - case 'category': - if ($category = db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchObject()) { - $block['subject'] = check_plain($category->title); - $result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = :cid ORDER BY i.timestamp DESC, i.iid DESC', 0, $category->block, array(':cid' => $category->cid)); - $read_more = theme('more_link', array('url' => 'aggregator/categories/' . $category->cid, 'title' => t("View this category's recent news."))); - } - break; - } - - $items = array(); - if (!empty($result)) { - foreach ($result as $item) { - $items[] = theme('aggregator_block_item', array('item' => $item)); - } - } - - // Only display the block if there are items to show. - if (count($items) > 0) { - $block['content'] = theme('item_list', array('items' => $items)) . $read_more; - } - return $block; - } -} - -/** * Adds/edits/deletes aggregator categories. * * @param $edit diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/CategoryBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/CategoryBlock.php new file mode 100644 index 0000000..c6b2e9a --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/CategoryBlock.php @@ -0,0 +1,36 @@ +derivatives) && !empty($this->derivatives[$derivative_id])) { + return $this->derivatives[$derivative_id]; + } + $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title WHERE cid = :cid', array(':cid' => $derivative_id))->fetchObject(); + $this->derivatives[$derivative_id] = $base_plugin_definition; + $this->derivatives[$derivative_id]['delta'] = $result->cid; + $this->derivatives[$derivative_id]['subject'] = t('@title category latest items', array('@title' => $result->title)); + return $this->derivatives[$derivative_id]; + } + + /** + * Implements DerivativeInterface::getDerivativeDefinitions(). + */ + public function getDerivativeDefinitions(array $base_plugin_definition) { + $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title'); + foreach ($result as $category) { + $this->derivatives[$category->cid] = $this->config; + $this->derivatives[$category->cid]['delta'] = $category->cid; + $this->derivatives[$category->cid]['subject'] = t('@title category latest items', array('@title' => $category->title)); + } + return $this->derivatives; + } +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/FeedBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/FeedBlock.php new file mode 100644 index 0000000..456535d --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Derivative/FeedBlock.php @@ -0,0 +1,36 @@ +derivatives) && !empty($this->derivatives[$derivative_id])) { + return $this->derivatives[$derivative_id]; + } + $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title WHERE cid = :cid', array(':cid' => $derivative_id))->fetchObject(); + $this->derivatives[$derivative_id] = $base_plugin_definition; + $this->derivatives[$derivative_id]['delta'] = $result->cid; + $this->derivatives[$derivative_id]['subject'] = t('@title feed latest items', array('@title' => $result->title)); + return $this->derivatives[$derivative_id]; + } + + /** + * Implements DerivativeInterface::getDerivativeDefinitions(). + */ + public function getDerivativeDefinitions(array $base_plugin_definition) { + $result = db_query('SELECT fid, title FROM {aggregator_feed} WHERE block <> 0 ORDER BY fid'); + foreach ($result as $feed) { + $this->derivatives[$feed->fid] = $this->config; + $this->derivatives[$feed->fid]['delta'] = $feed->fid; + $this->derivatives[$feed->fid]['subject'] = t('@title feed latest items', array('@title' => $feed->title)); + } + return $this->derivatives; + } +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/CategoryBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/CategoryBlock.php new file mode 100644 index 0000000..970f6ce --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/CategoryBlock.php @@ -0,0 +1,84 @@ +derivatives = array(); + } + + /** + * Implements AccessInterface::access(). + */ + public function access() { + return user_access('access news feeds'); + } + + /** + * Implements BlockInterface::configure(). + */ + public function configure($form, &$form_state) { + $form = parent::configure($form, $form_state); + $form['block_count'] = array( + '#type' => 'select', + '#title' => t('Number of news items in block'), + '#default_value' => $this->config['settings']['block_count'], + '#options' => drupal_map_assoc(range(2, 20)), + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->config['settings']['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + $id = $this->derivative; + if ($category = db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = :cid', array(':cid' => $id))->fetchObject()) { + $result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = :cid ORDER BY i.timestamp DESC, i.iid DESC', 0, $this->config['settings']['block_count'], array(':cid' => $category->cid)); + $read_more = theme('more_link', array('url' => 'aggregator/categories/' . $category->cid, 'title' => t("View this category's recent news."))); + + $items = array(); + foreach ($result as $item) { + $items[] = theme('aggregator_block_item', array('item' => $item)); + } + + // Only display the block if there are items to show. + if (count($items) > 0) { + return array( + '#block' => $this->derivatives[$this->derivative], + '#children' => theme('item_list', array('items' => $items)) . $read_more, + ); + } + return array(); + } + } +} diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/FeedBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/FeedBlock.php new file mode 100644 index 0000000..6becb5b --- /dev/null +++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/block/block/FeedBlock.php @@ -0,0 +1,82 @@ +derivatives = array(); + } + + /** + * Implements AccessInterface::access(). + */ + public function access() { + return user_access('access news feeds'); + } + + /** + * Implements BlockInterface::configure(). + */ + public function configure($form, &$form_state) { + $form = parent::configure($form, $form_state); + $form['block_count'] = array( + '#type' => 'select', + '#title' => t('Number of news items in block'), + '#default_value' => $this->config['block_count'], + '#options' => drupal_map_assoc(range(2, 20)), + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->config['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + $id = $this->derivative; + if ($feed = db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE block <> 0 AND fid = :fid', array(':fid' => $id))->fetchObject()) { + $result = db_query_range("SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC", 0, $this->config['block_count'], array(':fid' => $id)); + $read_more = theme('more_link', array('url' => 'aggregator/sources/' . $feed->fid, 'title' => t("View this feed's recent news."))); + + $items = array(); + foreach ($result as $item) { + $items[] = theme('aggregator_block_item', array('item' => $item)); + } + + // Only display the block if there are items to show. + if (count($items) > 0) { + return array( + '#block' => $this->config, + '#children' => theme('item_list', array('items' => $items)) . $read_more, + ); + } + } + } +} diff --git a/core/modules/block/block-library-form.tpl.php b/core/modules/block/block-library-form.tpl.php new file mode 100644 index 0000000..8179076 --- /dev/null +++ b/core/modules/block/block-library-form.tpl.php @@ -0,0 +1,32 @@ + +
+
+
+ +
+
+
+
+ +
+
+ +
+ +
diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc index aa018da..4c94134 100644 --- a/core/modules/block/block.admin.inc +++ b/core/modules/block/block.admin.inc @@ -114,18 +114,15 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r $form['blocks'] = array(); $form['#tree'] = TRUE; - foreach ($blocks as $i => $block) { - $key = $block['module'] . '_' . $block['delta']; - $form['blocks'][$key]['module'] = array( + foreach ($blocks as $key => $instance) { + $block = $instance->getConfig(); + $form['blocks'][$key]['config_id'] = array( '#type' => 'value', - '#value' => $block['module'], - ); - $form['blocks'][$key]['delta'] = array( - '#type' => 'value', - '#value' => $block['delta'], + '#value' => $block['config_id'], ); + $info = $instance->getDefinition(); $form['blocks'][$key]['info'] = array( - '#markup' => check_plain($block['info']), + '#markup' => check_plain($info['subject']), ); $form['blocks'][$key]['theme'] = array( '#type' => 'hidden', @@ -136,28 +133,27 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r '#default_value' => $block['weight'], '#delta' => $weight_delta, '#title_display' => 'invisible', - '#title' => t('Weight for @block block', array('@block' => $block['info'])), + '#title' => t('Weight for @block block', array('@block' => $info['subject'])), ); $form['blocks'][$key]['region'] = array( '#type' => 'select', '#default_value' => $block['region'] != BLOCK_REGION_NONE ? $block['region'] : NULL, '#empty_value' => BLOCK_REGION_NONE, '#title_display' => 'invisible', - '#title' => t('Region for @block block', array('@block' => $block['info'])), + '#title' => t('Region for @block block', array('@block' => $info['subject'])), '#options' => $block_regions, ); $form['blocks'][$key]['configure'] = array( '#type' => 'link', '#title' => t('configure'), - '#href' => 'admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', + '#href' => 'admin/structure/block/manage/' . $block['config_id'] . '/configure', ); - if ($block['module'] == 'block') { - $form['blocks'][$key]['delete'] = array( - '#type' => 'link', - '#title' => t('delete'), - '#href' => 'admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/delete', - ); - } + //drupal_set_message('
' . var_export($instance, TRUE) . '
'); + $form['blocks'][$key]['delete'] = array( + '#type' => 'link', + '#title' => t('delete'), + '#href' => 'admin/structure/block/manage/' . $block['config_id'] . '/delete', + ); } // Do not allow disabling the main system content block when it is present. if (isset($form['blocks']['system_main']['region'])) { @@ -182,27 +178,11 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r * @see block_admin_display_form() */ function block_admin_display_form_submit($form, &$form_state) { - $transaction = db_transaction(); - try { - foreach ($form_state['values']['blocks'] as $block) { - $block['status'] = (int) ($block['region'] != BLOCK_REGION_NONE); - $block['region'] = $block['status'] ? $block['region'] : ''; - db_update('block') - ->fields(array( - 'status' => $block['status'], - 'weight' => $block['weight'], - 'region' => $block['region'], - )) - ->condition('module', $block['module']) - ->condition('delta', $block['delta']) - ->condition('theme', $block['theme']) - ->execute(); - } - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception('block', $e); - throw $e; + foreach ($form_state['values']['blocks'] as $block) { + $config = config($block['config_id']); + $config->set('weight', $block['weight']); + $config->set('region', $block['region']); + $config->save(); } drupal_set_message(t('The block settings have been updated.')); cache_invalidate(array('content' => TRUE)); @@ -213,8 +193,10 @@ function block_admin_display_form_submit($form, &$form_state) { * * Callback for usort() in block_admin_display_prepare_blocks(). */ -function _block_compare($a, $b) { +function _block_compare($ainstance, $binstance) { global $theme_key; + $a = $ainstance->getConfig(); + $b = $binstance->getConfig(); // Theme should be set before calling this function, or the current theme // is being used. @@ -247,7 +229,9 @@ function _block_compare($a, $b) { } } // Sort by title. - return strcmp($a['info'], $b['info']); + $ainfo = $ainstance->getDefinition(); + $binfo = $binstance->getDefinition(); + return strcmp($ainfo['subject'], $binfo['subject']); } /** @@ -265,247 +249,13 @@ function _block_compare($a, $b) { * @see block_admin_configure_submit() * @ingroup forms */ -function block_admin_configure($form, &$form_state, $module, $delta) { - $block = block_load($module, $delta); - $form['module'] = array( +function block_admin_configure($form, &$form_state, $plugin_id) { + $instance = block_load($plugin_id); + $form['instance'] = array( '#type' => 'value', - '#value' => $block->module, - ); - $form['delta'] = array( - '#type' => 'value', - '#value' => $block->delta, - ); - - // Get the block subject for the page title. - $info = module_invoke($block->module, 'block_info'); - if (isset($info[$block->delta])) { - drupal_set_title(t("'%name' block", array('%name' => $info[$block->delta]['info'])), PASS_THROUGH); - } - - $form['settings']['title'] = array( - '#type' => 'textfield', - '#title' => t('Block title'), - '#maxlength' => 64, - '#description' => $block->module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use !placeholder to display no title, or leave blank to use the default block title.', array('!placeholder' => '<none>')), - '#default_value' => isset($block->title) ? $block->title : '', - '#weight' => -19, - ); - - // Module-specific block configuration. - if ($settings = module_invoke($block->module, 'block_configure', $block->delta)) { - foreach ($settings as $k => $v) { - $form['settings'][$k] = $v; - } - } - - // Region settings. - $form['regions'] = array( - '#type' => 'fieldset', - '#title' => t('Region settings'), - '#collapsible' => FALSE, - '#description' => t('Specify in which themes and regions this block is displayed.'), - '#tree' => TRUE, - ); - - $theme_default = variable_get('theme_default', 'stark'); - $admin_theme = variable_get('admin_theme'); - foreach (list_themes() as $key => $theme) { - // Only display enabled themes - if ($theme->status) { - $region = db_query("SELECT region FROM {block} WHERE module = :module AND delta = :delta AND theme = :theme", array( - ':module' => $block->module, - ':delta' => $block->delta, - ':theme' => $key, - ))->fetchField(); - - // Use a meaningful title for the main site theme and administrative - // theme. - $theme_title = $theme->info['name']; - if ($key == $theme_default) { - $theme_title = t('!theme (default theme)', array('!theme' => $theme_title)); - } - elseif ($admin_theme && $key == $admin_theme) { - $theme_title = t('!theme (administration theme)', array('!theme' => $theme_title)); - } - $form['regions'][$key] = array( - '#type' => 'select', - '#title' => $theme_title, - '#default_value' => !empty($region) && $region != -1 ? $region : NULL, - '#empty_value' => BLOCK_REGION_NONE, - '#options' => system_region_list($key, REGIONS_VISIBLE), - '#weight' => ($key == $theme_default ? 9 : 10), - ); - } - } - - // Visibility settings. - $form['visibility_title'] = array( - '#type' => 'item', - '#title' => t('Visibility settings'), - ); - $form['visibility'] = array( - '#type' => 'vertical_tabs', - '#attached' => array( - 'js' => array(drupal_get_path('module', 'block') . '/block.js'), - ), - ); - - // Per-path visibility. - $form['visibility']['path'] = array( - '#type' => 'fieldset', - '#title' => t('Pages'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#group' => 'visibility', - '#weight' => 0, - ); - - $access = user_access('use PHP for settings'); - if (isset($block->visibility) && $block->visibility == BLOCK_VISIBILITY_PHP && !$access) { - $form['visibility']['path']['visibility'] = array( - '#type' => 'value', - '#value' => BLOCK_VISIBILITY_PHP, - ); - $form['visibility']['path']['pages'] = array( - '#type' => 'value', - '#value' => isset($block->pages) ? $block->pages : '', - ); - } - else { - $options = array( - BLOCK_VISIBILITY_NOTLISTED => t('All pages except those listed'), - BLOCK_VISIBILITY_LISTED => t('Only the listed pages'), - ); - $description = t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %user for the current user's page and %user-wildcard for every user page. %front is the front page.", array('%user' => 'user', '%user-wildcard' => 'user/*', '%front' => '')); - - if (module_exists('php') && $access) { - $options += array(BLOCK_VISIBILITY_PHP => t('Pages on which this PHP code returns TRUE (experts only)')); - $title = t('Pages or PHP code'); - $description .= ' ' . t('If the PHP option is chosen, enter PHP code between %php. Note that executing incorrect PHP code can break your Drupal site.', array('%php' => '')); - } - else { - $title = t('Pages'); - } - $form['visibility']['path']['visibility'] = array( - '#type' => 'radios', - '#title' => t('Show block on specific pages'), - '#options' => $options, - '#default_value' => isset($block->visibility) ? $block->visibility : BLOCK_VISIBILITY_NOTLISTED, - ); - $form['visibility']['path']['pages'] = array( - '#type' => 'textarea', - '#title' => '' . $title . '', - '#default_value' => isset($block->pages) ? $block->pages : '', - '#description' => $description, - ); - } - - // Configure the block visibility per language. - if (module_exists('language') && language_multilingual()) { - $configurable_language_types = language_types_get_configurable(); - $existing_language_settings = db_query("SELECT type, langcode FROM {block_language} WHERE module = :module AND delta = :delta", array( - ':module' => $form['module']['#value'], - ':delta' => $form['delta']['#value'], - ))->fetchAll(); - $default_langcode_options = array(); - $default_language_type = $configurable_language_types[0]; - foreach ($existing_language_settings as $setting) { - $default_langcode_options[] = $setting->langcode; - // Overwrite default language type if we have it set. Although this - // theoretically would allow per language type association, our UI - // only allows language type association overall for a block, so we - // only need a single value. - $default_language_type = $setting->type; - } - - // Fetch languages. - $languages = language_list(LANGUAGE_ALL); - foreach ($languages as $language) { - // @TODO $language->name is not wrapped with t(), it should be replaced - // by CMI translation implementation. - $langcodes_options[$language->langcode] = $language->name; - } - $form['visibility']['language'] = array( - '#type' => 'fieldset', - '#title' => t('Languages'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#group' => 'visibility', - '#weight' => 5, - ); - // If there are multiple configurable language types, let the user pick - // which one should be applied to this visibility setting. This way users - // can limit blocks by interface language or content language for exmaple. - $language_types = language_types_info(); - $language_type_options = array(); - foreach ($configurable_language_types as $type_key) { - $language_type_options[$type_key] = $language_types[$type_key]['name']; - } - $form['visibility']['language']['language_type'] = array( - '#type' => 'radios', - '#title' => t('Language type'), - '#options' => $language_type_options, - '#default_value' => $default_language_type, - '#access' => count($language_type_options) > 1, - ); - $form['visibility']['language']['langcodes'] = array( - '#type' => 'checkboxes', - '#title' => t('Show this block only for specific languages'), - '#default_value' => $default_langcode_options, - '#options' => $langcodes_options, - '#description' => t('Show this block only for the selected language(s). If you select no languages, the block will be visibile in all languages.'), - ); - } - - // Per-role visibility. - $default_role_options = db_query("SELECT rid FROM {block_role} WHERE module = :module AND delta = :delta", array( - ':module' => $block->module, - ':delta' => $block->delta, - ))->fetchCol(); - $role_options = array_map('check_plain', user_roles()); - $form['visibility']['role'] = array( - '#type' => 'fieldset', - '#title' => t('Roles'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#group' => 'visibility', - '#weight' => 10, + '#value' => $instance, ); - $form['visibility']['role']['roles'] = array( - '#type' => 'checkboxes', - '#title' => t('Show block for specific roles'), - '#default_value' => $default_role_options, - '#options' => $role_options, - '#description' => t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'), - ); - - // Per-user visibility. - $form['visibility']['user'] = array( - '#type' => 'fieldset', - '#title' => t('Users'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - '#group' => 'visibility', - '#weight' => 20, - ); - $form['visibility']['user']['custom'] = array( - '#type' => 'radios', - '#title' => t('Customizable per user'), - '#options' => array( - BLOCK_CUSTOM_FIXED => t('Not customizable'), - BLOCK_CUSTOM_ENABLED => t('Customizable, visible by default'), - BLOCK_CUSTOM_DISABLED => t('Customizable, hidden by default'), - ), - '#description' => t('Allow individual users to customize the visibility of this block in their account settings.'), - '#default_value' => isset($block->custom) ? $block->custom : BLOCK_CUSTOM_FIXED, - ); - - $form['actions'] = array('#type' => 'actions'); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save block'), - ); - + $form += $instance->configure($form, $form_state); return $form; } @@ -516,15 +266,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) { * @see block_admin_configure_submit() */ function block_admin_configure_validate($form, &$form_state) { - if ($form_state['values']['module'] == 'block') { - $custom_block_exists = (bool) db_query_range('SELECT 1 FROM {block_custom} WHERE bid <> :bid AND info = :info', 0, 1, array( - ':bid' => $form_state['values']['delta'], - ':info' => $form_state['values']['info'], - ))->fetchField(); - if (empty($form_state['values']['info']) || $custom_block_exists) { - form_set_error('info', t('Ensure that each block description is unique.')); - } - } + $form_state['values']['instance']->configureValidate($form, $form_state); } /** @@ -534,78 +276,15 @@ function block_admin_configure_validate($form, &$form_state) { * @see block_admin_configure_validate() */ function block_admin_configure_submit($form, &$form_state) { - if (!form_get_errors()) { - $transaction = db_transaction(); - try { - db_update('block') - ->fields(array( - 'visibility' => (int) $form_state['values']['visibility'], - 'pages' => trim($form_state['values']['pages']), - 'custom' => (int) $form_state['values']['custom'], - 'title' => $form_state['values']['title'], - )) - ->condition('module', $form_state['values']['module']) - ->condition('delta', $form_state['values']['delta']) - ->execute(); - - db_delete('block_role') - ->condition('module', $form_state['values']['module']) - ->condition('delta', $form_state['values']['delta']) - ->execute(); - $query = db_insert('block_role')->fields(array('rid', 'module', 'delta')); - foreach (array_filter($form_state['values']['roles']) as $rid) { - $query->values(array( - 'rid' => $rid, - 'module' => $form_state['values']['module'], - 'delta' => $form_state['values']['delta'], - )); - } - $query->execute(); - - // Store regions per theme for this block. - foreach ($form_state['values']['regions'] as $theme => $region) { - db_merge('block') - ->key(array('theme' => $theme, 'delta' => $form_state['values']['delta'], 'module' => $form_state['values']['module'])) - ->fields(array( - 'region' => ($region == BLOCK_REGION_NONE ? '' : $region), - 'pages' => trim($form_state['values']['pages']), - 'status' => (int) ($region != BLOCK_REGION_NONE), - )) - ->execute(); - } - - // Update the block visibility settings if we have settings to store - // for the existing languages. - if (module_exists('language') && isset($form_state['values']['langcodes'])) { - db_delete('block_language') - ->condition('module', $form_state['values']['module']) - ->condition('delta', $form_state['values']['delta']) - ->execute(); - $query = db_insert('block_language')->fields(array( - 'type', 'langcode', 'module', 'delta' - )); - foreach (array_filter($form_state['values']['langcodes']) as $langcode) { - $query->values(array( - 'type' => $form_state['values']['language_type'], - 'langcode' => $langcode, - 'module' => $form_state['values']['module'], - 'delta' => $form_state['values']['delta'], - )); - } - $query->execute(); - } - - module_invoke($form_state['values']['module'], 'block_save', $form_state['values']['delta'], $form_state['values']); - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception('block', $e); - throw $e; - } - drupal_set_message(t('The block configuration has been saved.')); - cache_invalidate(array('content' => TRUE)); - $form_state['redirect'] = 'admin/structure/block'; + $form_state['values']['instance']->configureSubmit($form, $form_state); + $config_values = $form_state['values']['instance']->getConfig(); + $machine_name = 'plugin.core.block.' . $form_state['values']['machine_name']; + $config = config($machine_name); + $config->set('id', $form_state['values']['instance']->getPluginId()); + foreach ($config_values as $key => $value) { + $config->set($key, $value); } + $config->save(); } /** @@ -616,8 +295,38 @@ function block_admin_configure_submit($form, &$form_state) { * @see block_add_block_form_submit() * @ingroup forms */ -function block_add_block_form($form, &$form_state) { - return block_admin_configure($form, $form_state, 'block', NULL); +function block_library_block_form($form, &$form_state, $module = NULL) { + $blocks = block_manager()->getDefinitions(); + $form['#theme'] = 'block_library_form'; + $form['right']['block'] = array( + '#type' => 'textfield', + '#title' => t('Search'), + '#autocomplete_path' => 'block/autocomplete', + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Next'), + ); + $modules = array('all' => array('title' => t('All Blocks'), 'href' => 'admin/structure/block/library')); + $rows = array(); + foreach ($blocks as $plugin_id => $config) { + $row = array($config['subject'], l('Configure & Place Block', 'admin/structure/block/manage/' . $plugin_id)); + if (empty($module) || $module == $config['module']) { + $rows[] = $row; + } + $modules[$config['module']] = array('title' => $config['module'], 'href' => 'admin/structure/block/library/' . $config['module']); + } + // @todo This should be something other than modules, but as a good first + // pass, this works. + $form['right']['block_groups'] = array( + '#type' => 'markup', + '#markup' => theme('links', array('heading' => array('text' => t('Modules'), 'level' => 'h3'), 'links' => $modules)), + ); + $form['left']['block_library'] = array( + '#type' => 'markup', + '#markup' => theme('table', array('header' => array(t('Subject'), t('Operations')), 'rows' => $rows)), + ); + return $form; } /** @@ -626,13 +335,7 @@ function block_add_block_form($form, &$form_state) { * @see block_add_block_form() * @see block_add_block_form_submit() */ -function block_add_block_form_validate($form, &$form_state) { - $custom_block_exists = (bool) db_query_range('SELECT 1 FROM {block_custom} WHERE info = :info', 0, 1, array(':info' => $form_state['values']['info']))->fetchField(); - - if (empty($form_state['values']['info']) || $custom_block_exists) { - form_set_error('info', t('Ensure that each block description is unique.')); - } -} +function block_library_block_form_validate($form, &$form_state) {} /** * Form submission handler for block_add_block_form(). @@ -642,78 +345,8 @@ function block_add_block_form_validate($form, &$form_state) { * @see block_add_block_form() * @see block_add_block_form_validate() */ -function block_add_block_form_submit($form, &$form_state) { - $delta = db_insert('block_custom') - ->fields(array( - 'body' => $form_state['values']['body']['value'], - 'info' => $form_state['values']['info'], - 'format' => $form_state['values']['body']['format'], - )) - ->execute(); - // Store block delta to allow other modules to work with new block. - $form_state['values']['delta'] = $delta; - - $query = db_insert('block')->fields(array('visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache')); - foreach (list_themes() as $key => $theme) { - if ($theme->status) { - $query->values(array( - 'visibility' => (int) $form_state['values']['visibility'], - 'pages' => trim($form_state['values']['pages']), - 'custom' => (int) $form_state['values']['custom'], - 'title' => $form_state['values']['title'], - 'module' => $form_state['values']['module'], - 'theme' => $theme->name, - 'status' => 0, - 'weight' => 0, - 'delta' => $delta, - 'cache' => DRUPAL_NO_CACHE, - )); - } - } - $query->execute(); - - $query = db_insert('block_role')->fields(array('rid', 'module', 'delta')); - foreach (array_filter($form_state['values']['roles']) as $rid) { - $query->values(array( - 'rid' => $rid, - 'module' => $form_state['values']['module'], - 'delta' => $delta, - )); - } - $query->execute(); - - // Store regions per theme for this block. - foreach ($form_state['values']['regions'] as $theme => $region) { - db_merge('block') - ->key(array('theme' => $theme, 'delta' => $delta, 'module' => $form_state['values']['module'])) - ->fields(array( - 'region' => ($region == BLOCK_REGION_NONE ? '' : $region), - 'pages' => trim($form_state['values']['pages']), - 'status' => (int) ($region != BLOCK_REGION_NONE), - )) - ->execute(); - } - - // Update the block visibility settings if we have settings to store - // for the existing languages. - if (module_exists('language') && isset($form_state['values']['langcodes'])) { - $query = db_insert('block_language')->fields(array( - 'type', 'langcode', 'module', 'delta' - )); - foreach (array_filter($form_state['values']['langcodes']) as $langcode) { - $query->values(array( - 'type' => $form_state['values']['language_type'], - 'langcode' => $langcode, - 'module' => $form_state['values']['module'], - 'delta' => $form_state['values']['delta'], - )); - } - $query->execute(); - } - - drupal_set_message(t('The block has been created.')); - cache_invalidate(array('content' => TRUE)); - $form_state['redirect'] = 'admin/structure/block'; +function block_library_block_form_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/structure/block/manage/' . $form_state['values']['block']; } /** @@ -728,13 +361,15 @@ function block_add_block_form_submit($form, &$form_state) { * @see block_menu() * @see block_custom_block_delete_submit() */ -function block_custom_block_delete($form, &$form_state, $module, $delta) { - $block = block_load($module, $delta); - $custom_block = block_custom_block_get($block->delta); - $form['info'] = array('#type' => 'hidden', '#value' => $custom_block['info'] ? $custom_block['info'] : $custom_block['title']); - $form['bid'] = array('#type' => 'hidden', '#value' => $block->delta); - - return confirm_form($form, t('Are you sure you want to delete the block %name?', array('%name' => $custom_block['info'])), 'admin/structure/block', '', t('Delete'), t('Cancel')); +function block_custom_block_delete($form, &$form_state, $plugin_id) { + $block = block_load($plugin_id); + $form['id'] = array('#type' => 'value', '#value' => $plugin_id); + $definition = $block->getDefinition(); + $config = $block->getConfig(); + $subject = empty($config['subject']) ? $definition['subject'] : $config['subject']; + $form['subject'] = array('#type' => 'value', '#value' => $subject); + + return confirm_form($form, t('Are you sure you want to delete the block %name?', array('%name' => $subject)), 'admin/structure/block', '', t('Delete'), t('Cancel')); } /** @@ -743,26 +378,10 @@ function block_custom_block_delete($form, &$form_state, $module, $delta) { * @see block_custom_block_delete() */ function block_custom_block_delete_submit($form, &$form_state) { - db_delete('block_custom') - ->condition('bid', $form_state['values']['bid']) - ->execute(); - db_delete('block') - ->condition('module', 'block') - ->condition('delta', $form_state['values']['bid']) - ->execute(); - db_delete('block_role') - ->condition('module', 'block') - ->condition('delta', $form_state['values']['bid']) - ->execute(); - db_delete('block_language') - ->condition('module', 'block') - ->condition('delta', $form_state['values']['bid']) - ->execute(); - - drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['info']))); - cache_invalidate(array('content' => TRUE)); + $config = config($form_state['values']['id']); + $config->delete(); + drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['subject']))); $form_state['redirect'] = 'admin/structure/block'; - return; } /** @@ -812,3 +431,19 @@ function template_preprocess_block_admin_display_form(&$variables) { $variables['form_submit'] = drupal_render_children($variables['form']); } + +/** + * Processes variables for block-admin-display-form.tpl.php. + * + * The $variables array contains the following arguments: + * - $form + * + * @see block-admin-display.tpl.php + * @see theme_block_admin_display() + */ +function template_preprocess_block_library_form(&$variables) { + drupal_add_css(drupal_get_path('module', 'block') . '/block.library.css'); + $variables['left'] = drupal_render($variables['form']['left']); + $variables['right'] = drupal_render($variables['form']['right']); + $variables['form_submit'] = drupal_render_children($variables['form']); +} diff --git a/core/modules/block/block.library.css b/core/modules/block/block.library.css new file mode 100644 index 0000000..207a6ee --- /dev/null +++ b/core/modules/block/block.library.css @@ -0,0 +1,29 @@ +#block-library .left-col, +#block-library .right-col { + float:left; + width:66%; + height:100%; + background-color:#ffffff; +} + +#block-library .right-col { + width:34%; + background-color:#f7f7f7; +} + +#block-library .right-col h3 { + margin: 1em -20px; + background-color:#d7d7d7; + color:#333333; + padding:8px 15px; + font-size:1.1em; +} + +#block-library .inside { + margin:0 20px; +} + +#block-library .bottom-bar { + width:100%; + clear:both; +} \ No newline at end of file diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 4a3d6b9..f775de1 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -1,5 +1,8 @@ ' . t('Controlling visibility') . ''; $output .= '
' . t('Blocks can be configured to be visible only on certain pages, only to users of certain roles, or only on pages displaying certain content types. Administrators can also allow specific blocks to be enabled or disabled by users when they edit their My account page. Some dynamic blocks, such as those generated by modules, will be displayed only on certain pages.', array('@content-type' => url('admin/structure/types'), '@user' => url('user'))) . '
'; $output .= '
' . t('Creating custom blocks') . '
'; - $output .= '
' . t('Users with the Administer blocks permission can add custom blocks, which are then listed on the Blocks administration page. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/add'))) . '
'; + $output .= '
' . t('Users with the Administer blocks permission can add custom blocks, which are then listed on the Blocks administration page. Once created, custom blocks behave just like default and module-generated blocks.', array('@blocks' => url('admin/structure/block'), '@block-add' => url('admin/structure/block/library'))) . '
'; $output .= ''; return $output; - case 'admin/structure/block/add': + case 'admin/structure/block/library': return '

' . t('Use this page to create a new custom block.') . '

'; } if ($arg[0] == 'admin' && $arg[1] == 'structure' && $arg['2'] == 'block' && (empty($arg[3]) || $arg[3] == 'list')) { @@ -85,6 +88,11 @@ function block_theme() { 'file' => 'block.admin.inc', 'render element' => 'form', ), + 'block_library_form' => array( + 'template' => 'block-library-form', + 'file' => 'block.admin.inc', + 'render element' => 'form', + ), ); } @@ -112,35 +120,43 @@ function block_menu() { 'access arguments' => array('administer blocks'), 'file' => 'block.admin.inc', ); - $items['admin/structure/block/manage/%/%'] = array( + $items['admin/structure/block/manage/%'] = array( 'title' => 'Configure block', 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_admin_configure', 4, 5), + 'page arguments' => array('block_admin_configure', 4), 'access arguments' => array('administer blocks'), 'file' => 'block.admin.inc', ); - $items['admin/structure/block/manage/%/%/configure'] = array( + $items['admin/structure/block/manage/%/configure'] = array( 'title' => 'Configure block', 'type' => MENU_DEFAULT_LOCAL_TASK, 'context' => MENU_CONTEXT_INLINE, ); - $items['admin/structure/block/manage/%/%/delete'] = array( + $items['admin/structure/block/manage/%/delete'] = array( 'title' => 'Delete block', 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_custom_block_delete', 4, 5), + 'page arguments' => array('block_custom_block_delete', 4), 'access arguments' => array('administer blocks'), 'type' => MENU_LOCAL_TASK, 'context' => MENU_CONTEXT_NONE, 'file' => 'block.admin.inc', ); - $items['admin/structure/block/add'] = array( - 'title' => 'Add block', + $items['admin/structure/block/library'] = array( + 'title' => 'Block Library', 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_add_block_form'), + 'page arguments' => array('block_library_block_form'), 'access arguments' => array('administer blocks'), 'type' => MENU_LOCAL_ACTION, 'file' => 'block.admin.inc', ); + $items['admin/structure/block/library/%'] = array( + 'title' => 'Block Library', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('block_library_block_form', 4), + 'access arguments' => array('administer blocks'), + 'type' => MENU_CALLBACK, + 'file' => 'block.admin.inc', + ); foreach (list_themes() as $key => $theme) { $items['admin/structure/block/list/' . $key] = array( 'title' => check_plain($theme->info['name']), @@ -153,9 +169,9 @@ function block_menu() { ); if ($key != $default_theme) { $items['admin/structure/block/list/' . $key . '/add'] = array( - 'title' => 'Add block', + 'title' => 'Block Library', 'page callback' => 'drupal_get_form', - 'page arguments' => array('block_add_block_form'), + 'page arguments' => array('block_library_block_form'), 'access arguments' => array('administer blocks'), 'type' => MENU_LOCAL_ACTION, 'file' => 'block.admin.inc', @@ -173,9 +189,30 @@ function block_menu() { 'file' => 'block.admin.inc', ); } + $items['block/autocomplete'] = array( + 'title' => 'Block autocomplete', + 'page callback' => 'block_autocomplete', + 'access callback' => 'user_access', + 'access arguments' => array('administer blocks'), + 'type' => MENU_CALLBACK, + ); return $items; } +function block_autocomplete($string = '') { + $matches = array(); + if ($string) { + $blocks = block_manager()->getDefinitions(); + $block_titles = array(); + foreach($blocks as $plugin_id => $block) { + $block_titles[$plugin_id] = $block['subject']; + } + $matches = preg_grep("/\b". $string . "/i", $block_titles); + } + + return new JsonResponse($matches); +} + /** * Access callback: Only enabled themes can be accessed. * @@ -212,53 +249,6 @@ function _block_custom_theme($theme = NULL) { } /** - * Implements hook_block_info(). - */ -function block_block_info() { - $blocks = array(); - - $result = db_query('SELECT bid, info FROM {block_custom} ORDER BY info'); - foreach ($result as $block) { - $blocks[$block->bid]['info'] = $block->info; - // Not worth caching. - $blocks[$block->bid]['cache'] = DRUPAL_NO_CACHE; - } - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function block_block_configure($delta = 0) { - if ($delta) { - $custom_block = block_custom_block_get($delta); - } - else { - $custom_block = array(); - } - return block_custom_block_form($custom_block); -} - -/** - * Implements hook_block_save(). - */ -function block_block_save($delta = 0, $edit = array()) { - block_custom_block_save($edit, $delta); -} - -/** - * Implements hook_block_view(). - * - * Generates the administrator-defined blocks for display. - */ -function block_block_view($delta = '') { - $block = db_query('SELECT body, format FROM {block_custom} WHERE bid = :bid', array(':bid' => $delta))->fetchObject(); - $data['subject'] = NULL; - $data['content'] = check_markup($block->body, $block->format, '', TRUE); - return $data; -} - -/** * Implements hook_page_build(). * * Renders blocks into their regions. @@ -343,7 +333,6 @@ function block_get_blocks_by_region($region) { * A renderable array. */ function _block_get_renderable_region($list = array()) { - $weight = 0; $build = array(); // Block caching is not compatible with node_access modules. We also // preserve the submission of forms in blocks, by fetching from cache @@ -356,13 +345,15 @@ function _block_get_renderable_region($list = array()) { !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD')); foreach ($list as $key => $block) { + $config = $block->getConfig(); + $definition = $block->getDefinition(); $build[$key] = array( '#block' => $block, - '#weight' => ++$weight, + '#weight' => (int) $config['weight'], '#theme_wrappers' => array('block'), ); - if ($not_cacheable || in_array($block->cache, array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM))) { + if ($not_cacheable || in_array($config['cache'], array(DRUPAL_NO_CACHE, DRUPAL_CACHE_CUSTOM))) { // Non-cached blocks get built immediately. Provides more content // that can be easily manipulated during hook_page_alter(). $build[$key] = _block_get_renderable_block($build[$key]); @@ -371,8 +362,8 @@ function _block_get_renderable_region($list = array()) { $build[$key] += array( '#pre_render' => array('_block_get_renderable_block'), '#cache' => array( - 'keys' => array($block->module, $block->delta), - 'granularity' => $block->cache, + 'keys' => array($config['module'], $config['delta']), + 'granularity' => $config['cache'], 'bin' => 'block', 'tags' => array('content' => TRUE), ), @@ -384,11 +375,10 @@ function _block_get_renderable_region($list = array()) { // skip the help block, since we assume that most users do not need or want // to perform contextual actions on the help block, and the links needlessly // draw attention on it. - if ($key != 'system_main' && $key != 'system_help') { - $build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($block->module, $block->delta)); + if ($definition['class'] != 'Drupal\\system\\Plugin\\block\\block\\SystemHelpBlock' && $definition['class'] != 'Drupal\\system\\Plugin\\block\\block\\SystemMainBlock') { + $build[$key]['#contextual_links']['block'] = array('admin/structure/block/manage', array($key)); } } - $build['#sorted'] = TRUE; return $build; } @@ -403,107 +393,11 @@ function _block_get_renderable_region($list = array()) { * Blocks currently exported by modules. */ function _block_rehash($theme = NULL) { - global $theme_key; - - 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 the function will return. $blocks = array(); - // 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; - } - } - // Save the blocks defined in code for alter context. - $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; - } - if (!empty($block['region']) && $block['region'] != BLOCK_REGION_NONE && !isset($regions[$block['region']]) && $block['status'] == 1) { - drupal_set_message(t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => $block['info'], '%region' => $block['region'])), 'warning'); - // 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; - } - // There is no point saving disabled blocks. Still, we need to save them - // because the 'title' attribute is saved to the {blocks} table. - if (isset($block['bid'])) { - // If the block has a bid property, it comes from the database and - // the record needs to be updated, so set the primary key to 'bid' - // before passing to drupal_write_record(). - $primary_keys = array('bid'); - // Remove a block from the list of blocks to keep if it became disabled. - unset($bids[$block['bid']]); - } - else { - $primary_keys = array(); - } - drupal_write_record('block', $block, $primary_keys); - // Add to the list of blocks we return. - $blocks[] = $block; - } - } - if ($bids) { - // Remove disabled that are no longer defined by the code from the - // database. - db_delete('block') - ->condition('bid', $bids, 'NOT IN') - ->condition('theme', $theme) - ->execute(); + $instances = array(); + $block_configs = config_get_storage_names_with_prefix('plugin.core.block'); + foreach ($block_configs as $config) { + $blocks[$config] = block_load($config); } return $blocks; } @@ -721,31 +615,29 @@ function block_list($region) { return $blocks[$region]; } +function block_manager() { + return drupal_container()->get('plugin.manager.block'); +} + /** * Loads a block object from the database. * - * @param $module - * Name of the module that implements the block to load. - * @param $delta - * Unique ID of the block within the context of $module. Pass NULL to return - * an empty block object for $module. + * @param $plugin_id + * The plugin id to load. + * @param $conf + * An optional configuration array for creating a block instance from php + * instead of relying on configuration xml. * * @return * A block object. */ -function block_load($module, $delta) { - if (isset($delta)) { - $block = db_query('SELECT * FROM {block} WHERE module = :module AND delta = :delta', array(':module' => $module, ':delta' => $delta))->fetchObject(); +function block_load($plugin_id, $conf = array()) { + try { + $block = block_manager()->getInstance(array('config' => $plugin_id)); } - - // If the block does not exist in the database yet return a stub block - // object. - if (empty($block)) { - $block = new stdClass(); - $block->module = $module; - $block->delta = $delta; + catch (Drupal\Component\Plugin\Exception\PluginException $e) { + $block = block_manager()->createInstance($plugin_id, $conf); } - return $block; } @@ -756,28 +648,12 @@ function block_load($module, $delta) { * An array of blocks grouped by region. */ function _block_load_blocks() { - global $theme_key; - - $query = db_select('block', 'b'); - $query->addField('b', 'title', 'subject'); - $result = $query - ->fields('b') - ->condition('b.theme', $theme_key) - ->condition('b.status', 1) - ->orderBy('b.region') - ->orderBy('b.weight') - ->orderBy('b.module') - ->addTag('block_load') - ->addTag('translatable') - ->execute(); - - $block_info = $result->fetchAllAssoc('bid'); - // Allow modules to modify the block list. - drupal_alter('block_list', $block_info); - $blocks = array(); - foreach ($block_info as $block) { - $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block; + $instances = config_get_storage_names_with_prefix('plugin.core.block'); + foreach ($instances as $plugin_id) { + $block = block_manager()->getInstance(array('config' => $plugin_id)); + $config = $block->getConfig(); + $blocks[$config['region']]["$plugin_id"] = $block; } return $blocks; } @@ -904,45 +780,18 @@ function block_block_list_alter(&$blocks) { */ function _block_get_renderable_block($element) { $block = $element['#block']; - - // Render the block content if it has not been created already. - if (!isset($block->content)) { - $array = module_invoke($block->module, 'block_view', $block->delta); - - // Allow modules to modify the block before it is viewed, via either - // hook_block_view_alter() or hook_block_view_MODULE_DELTA_alter(). - drupal_alter(array('block_view', "block_view_{$block->module}_{$block->delta}"), $array, $block); - - if (empty($array['content'])) { - // Blocks without content should emit no markup at all. - $element += array( - '#access' => FALSE, - '#printed' => TRUE, - ); - } - elseif (isset($array) && is_array($array)) { - foreach ($array as $k => $v) { - $block->$k = $v; + // Don't bother to build blocks that aren't accessible. + if ($element['#access'] = $block->access()) { + $build = $block->build(); + if ($build) { + if (isset($build['#title'])) { + $element['#title'] = $build['#title']; } + $element += $build; } - } - - if (isset($block->content) && $block->content) { - // Normalize to the drupal_render() structure. - if (is_string($block->content)) { - $block->content = array('#markup' => $block->content); - } - // Override default block title if a custom display title is present. - if ($block->title) { - // Check plain here to allow module generated titles to keep any - // markup. - $block->subject = $block->title == '' ? '' : check_plain($block->title); + else { + $element = array(); } - - // Add the content renderable array to the main element. - $element['content'] = $block->content; - unset($block->content); - $element['#block'] = $block; } return $element; } @@ -986,7 +835,10 @@ function block_rebuild() { */ function template_preprocess_block(&$variables) { $block_counter = &drupal_static(__FUNCTION__, array()); - $variables['block'] = $variables['elements']['#block']; + $variables['block'] = (object) array_merge($variables['elements']['#block']->getDefinition(), $variables['elements']['#block']->getConfig()); + if (!empty($variables['elements']['#title']) && empty($variables['block']->subject)) { + $variables['block']->subject = $variables['elements']['#title']; + } // All blocks get an independent counter for each region. if (!isset($block_counter[$variables['block']->region])) { $block_counter[$variables['block']->region] = 1; @@ -1013,10 +865,19 @@ function template_preprocess_block(&$variables) { // contains a hyphen, it will end up as an underscore after this conversion, // and your function names won't be recognized. So, we need to convert // hyphens to underscores in block deltas for the theme suggestions. - $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . strtr($variables['block']->delta, '-', '_'); - - // Create a valid HTML ID and make sure it is unique. - $variables['block_html_id'] = drupal_html_id('block-' . $variables['block']->module . '-' . $variables['block']->delta); + if (!empty($variables['block']->derivative)) { + list($plugin, $derivative) = explode(':', $variables['block']->id); + $variables['theme_hook_suggestions'][] = 'block__' . strtr($plugin, '-', '_'); + $variables['theme_hook_suggestions'][] = 'block__' . strtr($plugin, '-', '_') . '__' . strtr($derivative, '-', '_'); + // Create a valid HTML ID and make sure it is unique. + $variables['block_html_id'] = drupal_html_id('block-' . $plugin . '-' . $derivative); + } + else { + $plugin = $variables['block']->id; + $variables['theme_hook_suggestions'][] = 'block__' . strtr($plugin, '-', '_'); + // Create a valid HTML ID and make sure it is unique. + $variables['block_html_id'] = drupal_html_id('block-' . $plugin); + } } /** diff --git a/core/modules/block/lib/Drupal/block/BlockBase.php b/core/modules/block/lib/Drupal/block/BlockBase.php new file mode 100644 index 0000000..eb7975c --- /dev/null +++ b/core/modules/block/lib/Drupal/block/BlockBase.php @@ -0,0 +1,291 @@ +configuration)) { + $definition = $this->getDefinition(); + $this->configuration = $definition['settings']; + } + return $this->configuration; + } + + /** + * Implements BlockInterface::access(). + */ + public function access() { + return TRUE; + } + + /** + * Implements BlockInterface::configure(). + */ + public function configure($form, &$form_state) { + $definition = $this->getDefinition(); + $config = $this->getConfig(); + $form['id'] = array( + '#type' => 'value', + '#value' => $definition['id'], + ); + $form['module'] = array( + '#type' => 'value', + '#value' => $definition['module'], + ); + + // Get the block subject for the page title. + $subject = isset($config['subject']) ? $config['subject'] : ''; + if ($subject) { + drupal_set_title(t("'%subject' block", array('%subject' => $subject)), PASS_THROUGH); + } + + $form['settings']['machine_name'] = array( + '#type' => 'textfield', + '#title' => t('Block machine name'), + '#maxlength' => 64, + '#description' => t('A unique name to save this block configuration. Must be alpha-numeric and be underscore separated.'), + '#default_value' => isset($config['config_id']) ? $config['config_id'] : '', + '#weight' => -20, + ); + if (isset($config['config_id'])) { + $form['settings']['machine_name']['#disabled'] = TRUE; + } + + $form['settings']['title'] = array( + '#type' => 'textfield', + '#title' => t('Block title'), + '#maxlength' => 64, + '#description' => $definition['module'] == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use !placeholder to display no title, or leave blank to use the default block title.', array('!placeholder' => '<none>')), + '#default_value' => isset($subject) ? $subject : '', + '#weight' => -19, + ); + + // Region settings. + $form['regions'] = array( + '#type' => 'fieldset', + '#title' => t('Region settings'), + '#collapsible' => FALSE, + '#description' => t('Specify in which themes and regions this block is displayed.'), + '#tree' => TRUE, + ); + + $theme_default = variable_get('theme_default', 'stark'); + $admin_theme = variable_get('admin_theme'); + foreach (list_themes() as $key => $theme) { + // Only display enabled themes + if ($theme->status) { + $region = $config['region']; + + // Use a meaningful title for the main site theme and administrative + // theme. + $theme_title = $theme->info['name']; + if ($key == $theme_default) { + $theme_title = t('!theme (default theme)', array('!theme' => $theme_title)); + } + elseif ($admin_theme && $key == $admin_theme) { + $theme_title = t('!theme (administration theme)', array('!theme' => $theme_title)); + } + $form['regions'][$key] = array( + '#type' => 'select', + '#title' => $theme_title, + '#default_value' => !empty($region) && $region != -1 ? $region : NULL, + '#empty_value' => BLOCK_REGION_NONE, + '#options' => system_region_list($key, REGIONS_VISIBLE), + '#weight' => ($key == $theme_default ? 9 : 10), + ); + } + } + + // Visibility settings. + $form['visibility_title'] = array( + '#type' => 'item', + '#title' => t('Visibility settings'), + ); + $form['visibility'] = array( + '#type' => 'vertical_tabs', + '#attached' => array( + 'js' => array(drupal_get_path('module', 'block') . '/block.js'), + ), + ); + + // Per-path visibility. + $form['visibility']['path'] = array( + '#type' => 'fieldset', + '#title' => t('Pages'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'visibility', + '#weight' => 0, + ); + + //@TODO remove this access check and inject it in some other way. + // In fact this entire visibility settings section probably needs a + // separate user interface in the near future. + $access = user_access('use PHP for settings'); + if (isset($block->visibility) && $block->visibility == BLOCK_VISIBILITY_PHP && !$access) { + $form['visibility']['path']['visibility'] = array( + '#type' => 'value', + '#value' => BLOCK_VISIBILITY_PHP, + ); + $form['visibility']['path']['pages'] = array( + '#type' => 'value', + '#value' => isset($block->pages) ? $block->pages : '', + ); + } + else { + $options = array( + BLOCK_VISIBILITY_NOTLISTED => t('All pages except those listed'), + BLOCK_VISIBILITY_LISTED => t('Only the listed pages'), + ); + $description = t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %user for the current user's page and %user-wildcard for every user page. %front is the front page.", array('%user' => 'user', '%user-wildcard' => 'user/*', '%front' => '')); + + if (module_exists('php') && $access) { + $options += array(BLOCK_VISIBILITY_PHP => t('Pages on which this PHP code returns TRUE (experts only)')); + $title = t('Pages or PHP code'); + $description .= ' ' . t('If the PHP option is chosen, enter PHP code between %php. Note that executing incorrect PHP code can break your Drupal site.', array('%php' => '')); + } + else { + $title = t('Pages'); + } + $form['visibility']['path']['visibility'] = array( + '#type' => 'radios', + '#title' => t('Show block on specific pages'), + '#options' => $options, + '#default_value' => isset($block->visibility) ? $block->visibility : BLOCK_VISIBILITY_NOTLISTED, + ); + $form['visibility']['path']['pages'] = array( + '#type' => 'textarea', + '#title' => '' . $title . '', + '#default_value' => isset($block->pages) ? $block->pages : '', + '#description' => $description, + ); + } + + // Per-role visibility. + $default_role_options = db_query("SELECT rid FROM {block_role} WHERE module = :module", array( + ':module' => $definition['module'], + ))->fetchCol(); + $role_options = array_map('check_plain', user_roles()); + $form['visibility']['role'] = array( + '#type' => 'fieldset', + '#title' => t('Roles'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'visibility', + '#weight' => 10, + ); + $form['visibility']['role']['roles'] = array( + '#type' => 'checkboxes', + '#title' => t('Show block for specific roles'), + '#default_value' => $default_role_options, + '#options' => $role_options, + '#description' => t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'), + ); + + // Per-user visibility. + $form['visibility']['user'] = array( + '#type' => 'fieldset', + '#title' => t('Users'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'visibility', + '#weight' => 20, + ); + $form['visibility']['user']['custom'] = array( + '#type' => 'radios', + '#title' => t('Customizable per user'), + '#options' => array( + BLOCK_CUSTOM_FIXED => t('Not customizable'), + BLOCK_CUSTOM_ENABLED => t('Customizable, visible by default'), + BLOCK_CUSTOM_DISABLED => t('Customizable, hidden by default'), + ), + '#description' => t('Allow individual users to customize the visibility of this block in their account settings.'), + '#default_value' => isset($block->custom) ? $block->custom : BLOCK_CUSTOM_FIXED, + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save block'), + ); + + return $form; + } + + /** + * Implements BlockInterface::configureValidate(). + */ + public function configureValidate($form, &$form_state) { + if (empty($form_state['values']['machine_name'])) { + form_set_error('machine_name', t('You must provide a block name.')); + } + if (preg_match('/[^a-zA-Z0-9_]/', $form_state['values']['machine_name'])) { + form_set_error('machine_name', t('Block name must be alphanumeric or underscores only.')); + } + if (in_array('plugin.core.block.' . $form_state['values']['machine_name'], config_get_storage_names_with_prefix('plugin.core.block'))) { + form_set_error('machine_name', t('Block name must be unique.')); + } + if ($form_state['values']['module'] == 'block') { + $custom_block_exists = (bool) db_query_range('SELECT 1 FROM {block_custom} WHERE bid <> :bid AND info = :info', 0, 1, array( + ':bid' => $form_state['values']['delta'], + ':info' => $form_state['values']['info'], + ))->fetchField(); + if (empty($form_state['values']['info']) || $custom_block_exists) { + form_set_error('info', t('Ensure that each block description is unique.')); + } + } + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + if (!form_get_errors()) { + $transaction = db_transaction(); + try { + $keys = array( + 'visibility' => 'visibility', + 'pages' => 'pages', + 'custom' => 'custom', + 'title' => 'subject', + 'module', + 'id', + ); + foreach ($keys as $key => $new_key) { + if (isset($form_state['values'][$key])) { + $this->configuration[$new_key] = $form_state['values'][$key]; + } + } + } + catch (Exception $e) { + $transaction->rollback(); + watchdog_exception('block', $e); + throw $e; + } + if (empty($this->configuration['weight'])) { + $this->configuration['weight'] = 0; + } + drupal_set_message(t('The block configuration has been saved.')); + drupal_flush_all_caches(); + $form_state['redirect'] = 'admin/structure/block'; + } + } + + /** + * Implements BlockInterface::build(). + */ + public function build() {} +} diff --git a/core/modules/block/lib/Drupal/block/BlockBundle.php b/core/modules/block/lib/Drupal/block/BlockBundle.php new file mode 100644 index 0000000..a66ac60 --- /dev/null +++ b/core/modules/block/lib/Drupal/block/BlockBundle.php @@ -0,0 +1,24 @@ +register('plugin.manager.block', 'Drupal\block\Plugins\Type\BlockManager'); + } +} \ No newline at end of file diff --git a/core/modules/block/lib/Drupal/block/BlockInterface.php b/core/modules/block/lib/Drupal/block/BlockInterface.php new file mode 100644 index 0000000..4ac723d --- /dev/null +++ b/core/modules/block/lib/Drupal/block/BlockInterface.php @@ -0,0 +1,44 @@ +manager = $manager; + } + + /** + * Implements MapperInterface::getInstance(). + */ + public function getInstance(array $options) { + $config = config($options['config']); + if ($config) { + $plugin_id = $config->get('id'); + $settings = $config->get(); + $settings['config_id'] = $options['config']; + return $this->manager->createInstance($plugin_id, $settings); + } + // @Todo throw an exception. + } +} \ No newline at end of file diff --git a/core/modules/block/lib/Drupal/block/Plugins/Type/BlockManager.php b/core/modules/block/lib/Drupal/block/Plugins/Type/BlockManager.php new file mode 100644 index 0000000..c852fda --- /dev/null +++ b/core/modules/block/lib/Drupal/block/Plugins/Type/BlockManager.php @@ -0,0 +1,17 @@ +discovery = new DerivativeDiscoveryDecorator(new AnnotatedClassDiscovery('block', 'block')); + $this->factory = new DefaultFactory($this); + $this->mapper = new ConfigMapper($this); + } +} \ No newline at end of file diff --git a/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php new file mode 100644 index 0000000..db0a366 --- /dev/null +++ b/core/modules/block/tests/lib/Drupal/block_test/Plugin/block/block/TestCacheBlock.php @@ -0,0 +1,26 @@ +book['bid']) ? 0 : $node->book['bid']; - } - - if (config('book.settings')->get('block.navigation.mode') == 'all pages') { - $block['subject'] = t('Book navigation'); - $book_menus = array(); - $pseudo_tree = array(0 => array('below' => FALSE)); - foreach (book_get_books() as $book_id => $book) { - if ($book['bid'] == $current_bid) { - // If the current page is a node associated with a book, the menu - // needs to be retrieved. - $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book)); - } - else { - // Since we know we will only display a link to the top node, there - // is no reason to run an additional menu tree query for each book. - $book['in_active_trail'] = FALSE; - // Check whether user can access the book link. - $book_node = node_load($book['nid']); - $book['access'] = node_access('view', $book_node); - $pseudo_tree[0]['link'] = $book; - $book_menus[$book_id] = menu_tree_output($pseudo_tree); - } - } - if ($block['content'] = $book_menus) { - $book_menus['#theme'] = 'book_all_books_block'; - } - } - elseif ($current_bid) { - // Only display this block when the user is browsing a book. - $select = db_select('node', 'n') - ->fields('n', array('title')) - ->condition('n.nid', $node->book['bid']) - ->addTag('node_access'); - $title = $select->execute()->fetchField(); - // Only show the block if the user has view access for the top-level node. - if ($title) { - $tree = menu_tree_all_data($node->book['menu_name'], $node->book); - // There should only be one element at the top level. - $data = array_shift($tree); - $block['subject'] = theme('book_title_link', array('link' => $data['link'])); - $block['content'] = ($data['below']) ? menu_tree_output($data['below']) : ''; - } - } - - return $block; -} - -/** - * Implements hook_block_configure(). - */ -function book_block_configure($delta = '') { - $block = array(); - $options = array( - 'all pages' => t('Show block on all pages'), - 'book pages' => t('Show block only on book pages'), - ); - $form['book_block_mode'] = array( - '#type' => 'radios', - '#title' => t('Book navigation block display'), - '#options' => $options, - '#default_value' => config('book.settings')->get('block.navigation.mode'), - '#description' => t("If Show block on all pages is selected, the block will contain the automatically generated menus for all of the site's books. If Show block only on book pages is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The Page specific visibility settings or other visibility settings can be used in addition to selectively display this block."), - ); - - return $form; -} - -/** - * Implements hook_block_save(). - */ -function book_block_save($delta = '', $edit = array()) { - $block = array(); - config('book.settings')->set('block.navigation.mode', $edit['book_block_mode'])->save(); -} - -/** * Returns HTML for a link to a book title when used as a block title. * * @param $variables diff --git a/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php b/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php new file mode 100644 index 0000000..112b157 --- /dev/null +++ b/core/modules/book/lib/Drupal/book/Plugin/block/block/BookNavigationBlock.php @@ -0,0 +1,101 @@ + t('Show block on all pages'), + 'book pages' => t('Show block only on book pages'), + ); + $form['book_block_mode'] = array( + '#type' => 'radios', + '#title' => t('Book navigation block display'), + '#options' => $options, + '#default_value' => $this->configuration['block_mode'], + '#description' => t("If Show block on all pages is selected, the block will contain the automatically generated menus for all of the site's books. If Show block only on book pages is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The Page specific visibility settings or other visibility settings can be used in addition to selectively display this block."), + ); + + return $form; + } + + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['block_mode'] = $form_state['values']['book_block_mode']; + } + + public function build() { + $block = array(); + $current_bid = 0; + if ($node = menu_get_object()) { + $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid']; + } + + if ($this->configuration['block_mode'] == 'all pages') { + $book_menus = array(); + $pseudo_tree = array(0 => array('below' => FALSE)); + foreach (book_get_books() as $book_id => $book) { + if ($book['bid'] == $current_bid) { + // If the current page is a node associated with a book, the menu + // needs to be retrieved. + $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book)); + } + else { + // Since we know we will only display a link to the top node, there + // is no reason to run an additional menu tree query for each book. + $book['in_active_trail'] = FALSE; + // Check whether user can access the book link. + $book_node = node_load($book['nid']); + $book['access'] = node_access('view', $book_node); + $pseudo_tree[0]['link'] = $book; + $book_menus[$book_id] = menu_tree_output($pseudo_tree); + } + } + if ($book_menus) { + return array( + '#theme' => 'book_all_books_block', + $book_menus + ); + } + } + elseif ($current_bid) { + // Only display this block when the user is browsing a book. + $select = db_select('node', 'n') + ->fields('n', array('title')) + ->condition('n.nid', $node->book['bid']) + ->addTag('node_access'); + $title = $select->execute()->fetchField(); + // Only show the block if the user has view access for the top-level node. + if ($title) { + $tree = menu_tree_all_data($node->book['menu_name'], $node->book); + // There should only be one element at the top level. + $data = array_shift($tree); + return array( + '#title' => theme('book_title_link', array('link' => $data['link'])), + ($data['below']) ? menu_tree_output($data['below']) : '', + ); + } + } + return array(); + } +} diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 39faf90..03b5522 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -211,7 +211,7 @@ function comment_field_extra_fields() { function comment_theme() { return array( 'comment_block' => array( - 'variables' => array(), + 'variables' => array('number' => NULL), ), 'comment_preview' => array( 'variables' => array('comment' => NULL), @@ -437,51 +437,6 @@ function comment_permission() { } /** - * Implements hook_block_info(). - */ -function comment_block_info() { - $blocks['recent']['info'] = t('Recent comments'); - $blocks['recent']['properties']['administrative'] = TRUE; - - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function comment_block_configure($delta = '') { - $form['comment_block_count'] = array( - '#type' => 'select', - '#title' => t('Number of recent comments'), - '#default_value' => variable_get('comment_block_count', 10), - '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), - ); - - return $form; -} - -/** - * Implements hook_block_save(). - */ -function comment_block_save($delta = '', $edit = array()) { - variable_set('comment_block_count', (int) $edit['comment_block_count']); -} - -/** - * Implements hook_block_view(). - * - * Generates a block with the most recent comments. - */ -function comment_block_view($delta = '') { - if (user_access('access comments')) { - $block['subject'] = t('Recent comments'); - $block['content'] = theme('comment_block'); - - return $block; - } -} - -/** * Redirects comment links to the correct page depending on comment settings. * * Since comments are paged there is no way to guarantee which page a comment @@ -618,9 +573,9 @@ function comment_new_page_count($num_comments, $new_replies, Node $node) { * * @ingroup themeable */ -function theme_comment_block() { +function theme_comment_block($variables) { $items = array(); - $number = variable_get('comment_block_count', 10); + $number = $variables['number']; foreach (comment_get_recent($number) as $comment) { $items[] = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)) . ' ' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->changed))) . ''; } diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentBlock.php b/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentBlock.php new file mode 100644 index 0000000..8d35a22 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Plugin/block/block/RecentBlock.php @@ -0,0 +1,61 @@ + 'select', + '#title' => t('Number of recent comments'), + '#default_value' => $this->configuration['block_count'], + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(); + */ + public function build() { + return array( + '#theme' => 'comment_block', + '#number' => $this->configuration['block_count'], + ); + } +} diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index c3ec1af..e279867 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -640,81 +640,7 @@ function forum_form_node_form_alter(&$form, &$form_state, $form_id) { } /** - * Implements hook_block_info(). - */ -function forum_block_info() { - $blocks['active'] = array( - 'info' => t('Active forum topics'), - 'cache' => DRUPAL_CACHE_CUSTOM, - 'properties' => array('administrative' => TRUE), - ); - $blocks['new'] = array( - 'info' => t('New forum topics'), - 'cache' => DRUPAL_CACHE_CUSTOM, - 'properties' => array('administrative' => TRUE), - ); - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function forum_block_configure($delta = '') { - $form['block_num_' . $delta] = array( - '#type' => 'select', - '#title' => t('Number of topics'), - '#default_value' => config('forum.settings')->get('block.num_' . $delta), - '#options' => drupal_map_assoc(range(2, 20)), - ); - return $form; -} - -/** - * Implements hook_block_save(). - */ -function forum_block_save($delta = '', $edit = array()) { - config('forum.settings')->set('block.num_' . $delta, $edit['block_num_' . $delta])->save(); -} - -/** - * Implements hook_block_view(). - * - * Generates a block containing the currently active forum topics and the most - * recently added forum topics. - */ -function forum_block_view($delta = '') { - $config = config('forum.settings'); - $query = db_select('forum_index', 'f') - ->fields('f') - ->addTag('node_access') - ->addMetaData('base_table', 'forum_index'); - switch ($delta) { - case 'active': - $title = t('Active forum topics'); - $query - ->orderBy('f.last_comment_timestamp', 'DESC') - ->range(0, $config->get('block.active.limit')); - break; - - case 'new': - $title = t('New forum topics'); - $query - ->orderBy('f.created', 'DESC') - ->range(0, $config->get('block.new.limit')); - break; - } - - $block['subject'] = $title; - // Cache based on the altered query. Enables us to cache with node access enabled. - $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view'); - $block['content']['#access'] = user_access('access content'); - return $block; -} - -/** - * Render API callback: Lists nodes based on the element's #query property. - * - * This function can be used as a #pre_render callback. + * A #pre_render callback. Lists nodes based on the element's #query property. * * @see forum_block_view() */ diff --git a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveBlock.php b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveBlock.php new file mode 100644 index 0000000..fc2d9b8 --- /dev/null +++ b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/ActiveBlock.php @@ -0,0 +1,69 @@ + 'select', + '#title' => t('Number of topics'), + '#default_value' => $this->configuration['block_count'], + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + $query = db_select('forum_index', 'f') + ->fields('f') + ->addTag('node_access') + ->orderBy('f.last_comment_timestamp', 'DESC') + ->range(0, $this->configuration['block_count']); + + return array( + drupal_render_cache_by_query($query, 'forum_block_view'), + ); + } +} diff --git a/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewBlock.php b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewBlock.php new file mode 100644 index 0000000..7a93bbb --- /dev/null +++ b/core/modules/forum/lib/Drupal/forum/Plugin/block/block/NewBlock.php @@ -0,0 +1,69 @@ + 'select', + '#title' => t('Number of topics'), + '#default_value' => $this->configuration['block_count'], + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + $query = db_select('forum_index', 'f') + ->fields('f') + ->addTag('node_access') + ->orderBy('f.created', 'DESC') + ->range(0, $this->configuration['block_count']); + + return array( + drupal_render_cache_by_query($query, 'forum_block_view'), + ); + } +} diff --git a/core/modules/help/help.module b/core/modules/help/help.module index a74bf52..aac8636 100644 --- a/core/modules/help/help.module +++ b/core/modules/help/help.module @@ -71,7 +71,7 @@ function help_help($path, $arg) { * Implements hook_preprocess_HOOK() for block.tpl.php. */ function help_preprocess_block(&$variables) { - if ($variables['block']->module == 'system' && $variables['block']->delta == 'help') { + if ($variables['block']->id == 'system_help_block') { $variables['attributes']['role'] = 'complementary'; } } diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 3fb39e0..c43d0ba 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -455,45 +455,6 @@ function language_language_delete($language) { } /** - * Implements hook_block_info(). - */ -function language_block_info() { - include_once DRUPAL_ROOT . '/core/includes/language.inc'; - $block = array(); - $info = language_types_info(); - foreach (language_types_get_configurable(FALSE) as $type) { - $block[$type] = array( - // We do not need to escape the language type name since the block 'info' - // value is supposed not to be sanitized. It is escaped later, if needed. - 'info' => t('Language switcher (!type)', array('!type' => $info[$type]['name'])), - // Not worth caching. - 'cache' => DRUPAL_NO_CACHE, - ); - } - return $block; -} - -/** - * Implements hook_block_view(). - * - * Displays a language switcher. Only show if we have at least two languages. - */ -function language_block_view($type) { - if (language_multilingual()) { - $path = drupal_is_front_page() ? '' : current_path(); - $links = language_negotiation_get_switch_links($type, $path); - - if (isset($links->links)) { - $class = "language-switcher-{$links->method_id}"; - $variables = array('links' => $links->links, 'attributes' => array('class' => array($class))); - $block['content'] = theme('links__language_block', $variables); - $block['subject'] = t('Languages'); - return $block; - } - } -} - -/** * Implements hook_preprocess_HOOK() for block.tpl.php. */ function language_preprocess_block(&$variables) { diff --git a/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php b/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php new file mode 100644 index 0000000..e2e64cd --- /dev/null +++ b/core/modules/language/lib/Drupal/language/Plugin/Derivative/LanguageBlock.php @@ -0,0 +1,34 @@ +derivatives) && !empty($this->derivatives[$derivative_id])) { + return $this->derivatives[$derivative_id]; + } + $this->getDerivativeDefinitions($base_plugin_definition); + return $this->derivatives[$derivative_id]; + } + + /** + * Implements DerivativeInterface::getDerivativeDefinitions(). + */ + public function getDerivativeDefinitions(array $base_plugin_definition) { + include_once DRUPAL_ROOT . '/core/includes/language.inc'; + $info = language_types_info(); + foreach (language_types_get_configurable(FALSE) as $type) { + $this->derivatives[$type] = $base_plugin_definition; + $this->derivatives[$type]['subject'] = t('Language switcher (!type)', array('!type' => $info[$type]['name'])); + $this->derivatives[$type]['cache'] = DRUPAL_NO_CACHE; + } + return $this->derivatives; + } +} diff --git a/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php b/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php new file mode 100644 index 0000000..0e18314 --- /dev/null +++ b/core/modules/language/lib/Drupal/language/Plugin/block/block/LanguageBlock.php @@ -0,0 +1,40 @@ +' : current_path(); + list($plugin_id, $type) = explode(':', $this->getPluginId()); + $links = language_negotiation_get_switch_links($type, $path); + + if (isset($links->links)) { + $class = "language-switcher-{$links->method_id}"; + $variables = array('links' => $links->links, 'attributes' => array('class' => array($class))); + return array( + '#children' => theme('links__language_block', $variables) + ); + } + } +} diff --git a/core/modules/menu/lib/Drupal/menu/Plugin/Derivative/MenuBlock.php b/core/modules/menu/lib/Drupal/menu/Plugin/Derivative/MenuBlock.php new file mode 100644 index 0000000..6d0bf79 --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/Plugin/Derivative/MenuBlock.php @@ -0,0 +1,20 @@ + $name) { + $this->derivatives[$menu] = $base_plugin_definition; + $this->derivatives[$menu]['delta'] = $menu; + $this->derivatives[$menu]['subject'] = t('Menu: @menu', array('@menu' => $name)); + $this->derivatives[$menu]['cache'] = DRUPAL_NO_CACHE; + } + return $this->derivatives; + } +} diff --git a/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php b/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php new file mode 100644 index 0000000..ca06127 --- /dev/null +++ b/core/modules/menu/lib/Drupal/menu/Plugin/block/block/MenuBlock.php @@ -0,0 +1,22 @@ + $title) { - $blocks[$name]['info'] = check_plain($title); - // Menu blocks can't be cached because each menu item can have - // a custom access callback. menu.inc manages its own caching. - $blocks[$name]['cache'] = DRUPAL_NO_CACHE; - } - return $blocks; -} - -/** - * Implements hook_block_view(). - */ -function menu_block_view($delta = '') { - $menus = menu_get_menus(FALSE); - $data['subject'] = check_plain($menus[$delta]); - $data['content'] = menu_tree($delta); - // Add contextual links for this block. - if (!empty($data['content'])) { - $data['content']['#contextual_links']['menu'] = array('admin/structure/menu/manage', array($delta)); - } - return $data; -} - -/** * Implements hook_block_view_alter(). */ function menu_block_view_alter(&$data, $block) { diff --git a/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentBlock.php b/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentBlock.php new file mode 100644 index 0000000..b2a6d11 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Plugin/block/block/RecentBlock.php @@ -0,0 +1,68 @@ + 'select', + '#title' => t('Number of recent content items to display'), + '#default_value' => $this->configuration['block_count'], + '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['block_count'] = $form_state['values']['block_count']; + } + + /** + * Implements BlockInterface::build(); + */ + public function build() { + if ($nodes = node_get_recent($this->configuration['block_count'])) { + return array( + '#theme' => 'node_recent_block', + '#nodes' => $nodes, + ); + } + else { + return array( + '#children' => t('No content available.'), + ); + } + } +} diff --git a/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php b/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php new file mode 100644 index 0000000..0fa20c2 --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Plugin/block/block/SyndicateBlock.php @@ -0,0 +1,39 @@ + 'feed_icon', + '#url' => 'rss.xml', + ); + } +} diff --git a/core/modules/node/node.module b/core/modules/node/node.module index be15dee..9661976 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1362,11 +1362,11 @@ function node_is_page(Node $node) { */ function node_preprocess_block(&$variables) { if ($variables['block']->module == 'node') { - switch ($variables['block']->delta) { - case 'syndicate': + switch ($variables['block']->id) { + case 'node_syndicate_block': $variables['attributes']['role'] = 'complementary'; break; - case 'recent': + case 'node_recent_block': $variables['attributes']['role'] = 'navigation'; break; } @@ -2124,78 +2124,6 @@ function node_revision_list(Node $node) { } /** - * Implements hook_block_info(). - */ -function node_block_info() { - $blocks['syndicate']['info'] = t('Syndicate'); - // Not worth caching. - $blocks['syndicate']['cache'] = DRUPAL_NO_CACHE; - - $blocks['recent']['info'] = t('Recent content'); - $blocks['recent']['properties']['administrative'] = TRUE; - - return $blocks; -} - -/** - * Implements hook_block_view(). - */ -function node_block_view($delta = '') { - $block = array(); - - switch ($delta) { - case 'syndicate': - $block['subject'] = t('Syndicate'); - $block['content'] = array( - '#theme' => 'feed_icon', - '#url' => 'rss.xml', - '#title' => t('Syndicate'), - ); - break; - - case 'recent': - if (user_access('access content')) { - $block['subject'] = t('Recent content'); - if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) { - $block['content'] = array( - '#theme' => 'node_recent_block', - '#nodes' => $nodes, - ); - } else { - $block['content'] = t('No content available.'); - } - } - break; - } - return $block; -} - -/** - * Implements hook_block_configure(). - */ -function node_block_configure($delta = '') { - $form = array(); - if ($delta == 'recent') { - $form['node_recent_block_count'] = array( - '#type' => 'select', - '#title' => t('Number of recent content items to display'), - '#default_value' => variable_get('node_recent_block_count', 10), - '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)), - ); - } - return $form; -} - -/** - * Implements hook_block_save(). - */ -function node_block_save($delta = '', $edit = array()) { - if ($delta == 'recent') { - variable_set('node_recent_block_count', $edit['node_recent_block_count']); - } -} - -/** * Finds the most recently changed nodes that are available to the current user. * * @param $number @@ -2309,7 +2237,7 @@ function theme_node_recent_content($variables) { * Adds node-type specific visibility options to add block form. */ function node_form_block_add_block_form_alter(&$form, &$form_state) { - node_form_block_admin_configure_alter($form, $form_state); + //node_form_block_admin_configure_alter($form, $form_state); } /** @@ -2320,9 +2248,8 @@ function node_form_block_add_block_form_alter(&$form, &$form_state) { * @see node_form_block_admin_configure_submit() */ function node_form_block_admin_configure_alter(&$form, &$form_state) { - $default_type_options = db_query("SELECT type FROM {block_node_type} WHERE module = :module AND delta = :delta", array( + $default_type_options = db_query("SELECT type FROM {block_node_type} WHERE module = :module", array( ':module' => $form['module']['#value'], - ':delta' => $form['delta']['#value'], ))->fetchCol(); $form['visibility']['node_type'] = array( '#type' => 'fieldset', @@ -2348,41 +2275,18 @@ function node_form_block_admin_configure_alter(&$form, &$form_state) { function node_form_block_admin_configure_submit($form, &$form_state) { db_delete('block_node_type') ->condition('module', $form_state['values']['module']) - ->condition('delta', $form_state['values']['delta']) ->execute(); - $query = db_insert('block_node_type')->fields(array('type', 'module', 'delta')); + $query = db_insert('block_node_type')->fields(array('type', 'module')); foreach (array_filter($form_state['values']['types']) as $type) { $query->values(array( 'type' => $type, 'module' => $form_state['values']['module'], - 'delta' => $form_state['values']['delta'], )); } $query->execute(); } /** - * Implements hook_form_FORM_ID_alter() for block_custom_block_delete(). - * - * Adds node specific submit handler to delete custom block form. - * - * @see node_form_block_custom_block_delete_submit() - */ -function node_form_block_custom_block_delete_alter(&$form, &$form_state) { - $form['#submit'][] = 'node_form_block_custom_block_delete_submit'; -} - -/** - * Form submission handler for node_form_block_custom_block_delete_alter(). - */ -function node_form_block_custom_block_delete_submit($form, &$form_state) { - db_delete('block_node_type') - ->condition('module', 'block') - ->condition('delta', $form_state['values']['bid']) - ->execute(); -} - -/** * Implements hook_modules_uninstalled(). * * Cleans up the {block_node_type} table from modules' blocks. diff --git a/core/modules/poll/lib/Drupal/poll/Plugin/block/block/PollRecentBlock.php b/core/modules/poll/lib/Drupal/poll/Plugin/block/block/PollRecentBlock.php new file mode 100644 index 0000000..4dc3d03 --- /dev/null +++ b/core/modules/poll/lib/Drupal/poll/Plugin/block/block/PollRecentBlock.php @@ -0,0 +1,63 @@ +join('poll', 'p', 'p.nid = n.nid'); + $select->fields('n', array('nid')) + ->condition('n.status', 1) + ->condition('p.active', 1) + ->orderBy('n.created', 'DESC') + ->range(0, 1) + ->addTag('node_access'); + + $record = $select->execute()->fetchObject(); + if ($record) { + $this->record = $record; + return TRUE; + } + } + return FALSE; + } + + /** + * Implements BlockInterface::build(). + */ + function build() { + $poll = node_load($this->record->nid); + if ($poll->nid) { + $poll = poll_block_latest_poll_view($poll); + return array( + $poll->content + ); + } + return array(); + } +} \ No newline at end of file diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module index 259ff14..db08309 100644 --- a/core/modules/poll/poll.module +++ b/core/modules/poll/poll.module @@ -113,45 +113,6 @@ function _poll_menu_access($node, $perm, $inspect_allowvotes) { } /** - * Implements hook_block_info(). - */ -function poll_block_info() { - $blocks['recent']['info'] = t('Most recent poll'); - $blocks['recent']['properties']['administrative'] = TRUE; - return $blocks; -} - -/** - * Implements hook_block_view(). - * - * Generates a block containing the latest poll. - */ -function poll_block_view($delta = '') { - if (user_access('access content')) { - // Retrieve the latest poll. - $select = db_select('node', 'n'); - $select->join('poll', 'p', 'p.nid = n.nid'); - $select->fields('n', array('nid')) - ->condition('n.status', 1) - ->condition('p.active', 1) - ->orderBy('n.created', 'DESC') - ->range(0, 1) - ->addTag('node_access'); - - $record = $select->execute()->fetchObject(); - if ($record) { - $poll = node_load($record->nid); - if ($poll->nid) { - $poll = poll_block_latest_poll_view($poll); - $block['subject'] = t('Poll'); - $block['content'] = $poll->content; - return $block; - } - } - } -} - -/** * Implements hook_cron(). * * Closes polls that have exceeded their allowed runtime. diff --git a/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php b/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php new file mode 100644 index 0000000..0de439d --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Plugin/block/block/SearchBlock.php @@ -0,0 +1,36 @@ +module == 'search' && $variables['block']->delta == 'form') { + if ($variables['block']->id == 'search_form_block') { $variables['attributes']['role'] = 'search'; $variables['content_attributes']['class'][] = 'container-inline'; } diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php new file mode 100644 index 0000000..2440013 --- /dev/null +++ b/core/modules/shortcut/lib/Drupal/shortcut/Plugin/block/block/ShortcutsBlock.php @@ -0,0 +1,31 @@ + $shortcut_set->title)); - $data['content'] = shortcut_renderable_links($shortcut_set); - return $data; - } -} - -/** * Access callback for editing a shortcut set. * * @param object $shortcut_set diff --git a/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php b/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php new file mode 100644 index 0000000..c64b125 --- /dev/null +++ b/core/modules/statistics/lib/Drupal/statistics/Plugin/block/block/StatisticsPopularBlock.php @@ -0,0 +1,121 @@ + t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40)); + $form['statistics_block_top_day_num'] = array( + '#type' => 'select', + '#title' => t("Number of day's top views to display"), + '#default_value' => $this->configuration['top_day_num'], + '#options' => $numbers, + '#description' => t('How many content items to display in "day" list.') + ); + $form['statistics_block_top_all_num'] = array( + '#type' => 'select', + '#title' => t('Number of all time views to display'), + '#default_value' => $this->configuration['top_all_num'], + '#options' => $numbers, + '#description' => t('How many content items to display in "all time" list.') + ); + $form['statistics_block_top_last_num'] = array( + '#type' => 'select', + '#title' => t('Number of most recent views to display'), + '#default_value' => $this->configuration['top_last_num'], + '#options' => $numbers, + '#description' => t('How many content items to display in "recently viewed" list.') + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['top_day_num'] = $form_state['values']['statistics_block_top_day_num']; + $this->configuration['top_all_num'] = $form_state['values']['statistics_block_top_all_num']; + $this->configuration['top_last_num'] = $form_state['values']['statistics_block_top_last_num']; + } + + /** + * Implements BlockInterface::access(). + */ + public function access() { + if (user_access('access content')) { + $daytop = $this->configuration['top_day_num']; + if (!$daytop || !($result = statistics_title_list('daycount', $daytop)) || !($this->day_list = node_title_list($result, t("Today's:")))) { + return FALSE; + } + $alltimetop = $this->configuration['top_all_num']; + if (!$alltimetop || !($result = statistics_title_list('totalcount', $alltimetop)) || !($this->all_time_list = node_title_list($result, t('All time:')))) { + return FALSE; + } + $lasttop = $this->configuration['top_last_num']; + if (!$lasttop || !($result = statistics_title_list('timestamp', $lasttop)) || !($this->last_list = node_title_list($result, t('Last viewed:')))) { + return FALSE; + } + return TRUE; + } + return FALSE; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + $content = array(); + + if ($this->day_list) { + $content['top_day'] = $this->day_list; + $content['top_day']['#suffix'] = '
'; + } + + if ($this->all_time_list) { + $content['top_all'] = $this->all_time_list; + $content['top_all']['#suffix'] = '
'; + } + + if ($this->last_list) { + $content['top_last'] = $this->last_list; + $content['top_last']['#suffix'] = '
'; + } + + return $content; + } + +} diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module index 35f625a..75db73a 100644 --- a/core/modules/statistics/statistics.module +++ b/core/modules/statistics/statistics.module @@ -308,79 +308,6 @@ function statistics_get($nid) { } /** - * Implements hook_block_info(). - */ -function statistics_block_info() { - $blocks = array(); - - $statistics_count_content_views = config('statistics.settings')->get('count_content_views'); - if (!empty($statistics_count_content_views)) { - $blocks['popular']['info'] = t('Popular content'); - // Too dynamic to cache. - $blocks['popular']['cache'] = DRUPAL_NO_CACHE; - } - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function statistics_block_configure($delta = '') { - $config = config('statistics.settings'); - // Popular content block settings - $numbers = array('0' => t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40)); - $form['statistics_block_popular_top_day_limit'] = array('#type' => 'select', '#title' => t("Number of day's top views to display"), '#default_value' => $config->get('block.popular.top_day_limit'), '#options' => $numbers, '#description' => t('How many content items to display in "day" list.')); - $form['statistics_block_popular_top_all_limit'] = array('#type' => 'select', '#title' => t('Number of all time views to display'), '#default_value' => $config->get('block.popular.top_all_limit'), '#options' => $numbers, '#description' => t('How many content items to display in "all time" list.')); - $form['statistics_block_popular_top_recent_limit'] = array('#type' => 'select', '#title' => t('Number of most recent views to display'), '#default_value' => $config->get('block.popular.top_recent_limit'), '#options' => $numbers, '#description' => t('How many content items to display in "recently viewed" list.')); - return $form; -} - -/** - * Implements hook_block_save(). - */ -function statistics_block_save($delta = '', $edit = array()) { - config('statistics.settings') - ->set('block.popular.top_day_limit', $edit['statistics_block_popular_top_day_limit']) - ->set('block.popular.top_all_limit', $edit['statistics_block_popular_top_all_limit']) - ->set('block.popular.top_recent_limit', $edit['statistics_block_popular_top_recent_limit']) - ->save(); -} - -/** - * Implements hook_block_view(). - */ -function statistics_block_view($delta = '') { - if (user_access('access content')) { - $content = array(); - - $config = config('statistics.settings'); - $daytop = $config->get('block.popular.top_day_limit'); - if ($daytop && ($result = statistics_title_list('daycount', $daytop)) && ($node_title_list = node_title_list($result, t("Today's:")))) { - $content['top_day'] = $node_title_list; - $content['top_day']['#suffix'] = '
'; - } - - $alltimetop = $config->get('block.popular.top_all_limit'); - if ($alltimetop && ($result = statistics_title_list('totalcount', $alltimetop)) && ($node_title_list = node_title_list($result, t('All time:')))) { - $content['top_all'] = $node_title_list; - $content['top_all']['#suffix'] = '
'; - } - - $lasttop = $config->get('block.popular.top_recent_limit'); - if ($lasttop && ($result = statistics_title_list('timestamp', $lasttop)) && ($node_title_list = node_title_list($result, t('Last viewed:')))) { - $content['top_last'] = $node_title_list; - $content['top_last']['#suffix'] = '
'; - } - - if (count($content)) { - $block['content'] = $content; - $block['subject'] = t('Popular content'); - return $block; - } - } -} - -/** * Generates a link to a path, truncating the displayed text to a given width. * * @param string $path diff --git a/core/modules/system/lib/Drupal/system/Plugin/Derivative/SystemMenuBlock.php b/core/modules/system/lib/Drupal/system/Plugin/Derivative/SystemMenuBlock.php new file mode 100644 index 0000000..35df4bb --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/Derivative/SystemMenuBlock.php @@ -0,0 +1,33 @@ +derivatives) && !empty($this->derivatives[$derivative_id])) { + return $this->derivatives[$derivative_id]; + } + $this->getDerivativeDefinitions($base_plugin_definition); + return $this->derivatives[$derivative_id]; + } + + /** + * Implements DerivativeInterface::getDerivativeDefinitions(). + */ + public function getDerivativeDefinitions(array $base_plugin_definition) { + foreach (menu_list_system_menus() as $menu => $name) { + $this->derivatives[$menu] = $base_plugin_definition; + $this->derivatives[$menu]['delta'] = $menu; + $this->derivatives[$menu]['subject'] = t('System Menu: @menu', array('@menu' => $name)); + $this->derivatives[$menu]['cache'] = DRUPAL_NO_CACHE; + } + return $this->derivatives; + } +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php new file mode 100644 index 0000000..837ca0a --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemHelpBlock.php @@ -0,0 +1,43 @@ +help = menu_get_active_help(); + return $this->help ? TRUE : FALSE; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + if (empty($this->help)) { + $this->help = menu_get_active_help(); + } + return array( + '#children' => $this->help, + ); + } +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php new file mode 100644 index 0000000..2905317 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemMainBlock.php @@ -0,0 +1,31 @@ +uid) { + return FALSE; + } + return parent::access(); + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + list($plugin, $derivative) = explode(':', $this->getPluginId()); + return menu_tree($derivative); + } +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php new file mode 100644 index 0000000..42e8c6c --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/block/block/SystemPoweredByBlock.php @@ -0,0 +1,31 @@ + theme('system_powered_by'), + ); + } +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 4cf5780..4b871bf 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2276,95 +2276,23 @@ function system_user_timezone(&$form, &$form_state) { } /** - * Implements hook_block_info(). + * Implements hook_preprocess_HOOK() for block.tpl.php. */ -function system_block_info() { - $blocks['main'] = array( - 'info' => t('Main page content'), - // Cached elsewhere. - 'cache' => DRUPAL_NO_CACHE, - // Auto-enable in 'content' region by default, which always exists. - // @see system_themes_page(), drupal_render_page() - 'region' => 'content', - 'status' => 1, - ); - $blocks['powered-by'] = array( - 'info' => t('Powered by Drupal'), - 'weight' => '10', - 'cache' => DRUPAL_NO_CACHE, - ); - $blocks['help'] = array( - 'info' => t('System help'), - 'weight' => '5', - 'cache' => DRUPAL_NO_CACHE, - // Auto-enable in 'help' region by default, if the theme defines one. - 'region' => 'help', - 'status' => 1, - ); - // System-defined menu blocks. - foreach (menu_list_system_menus() as $menu_name => $title) { - $blocks[$menu_name]['info'] = t($title); - // Menu blocks can't be cached because each menu item can have - // a custom access callback. menu.inc manages its own caching. - $blocks[$menu_name]['cache'] = DRUPAL_NO_CACHE; - } - return $blocks; -} +function system_preprocess_block(&$variables) { + switch ($variables['block']->id) { + case 'system_powered_by_block': + $variables['attributes_array']['role'] = 'complementary'; + break; + case 'system_help_block': + $variables['attributes_array']['role'] = 'complementary'; + break; -/** - * Implements hook_block_view(). - * - * Generate a block with a promotional link to Drupal.org and - * all system menu blocks. - */ -function system_block_view($delta = '') { - $block = array(); - switch ($delta) { - case 'main': - $block['subject'] = NULL; - $block['content'] = drupal_set_page_content(); - return $block; - case 'powered-by': - $block['subject'] = NULL; - $block['content'] = theme('system_powered_by'); - return $block; - case 'help': - $block['subject'] = NULL; - $block['content'] = menu_get_active_help(); - return $block; + // System menu blocks should get the same class as menu module blocks. default: - // All system menu blocks. - $system_menus = menu_list_system_menus(); - if (isset($system_menus[$delta])) { - $block['subject'] = t($system_menus[$delta]); - $block['content'] = menu_tree($delta); - return $block; + if ($variables['block']->class == 'Drupal\\system\\Plugin\\block\\block\\SystemMenuBlock') { + $variables['attributes_array']['role'] = 'navigation'; + $variables['classes_array'][] = 'block-menu'; } - break; - } -} - -/** - * Implements hook_preprocess_HOOK() for block.tpl.php. - */ -function system_preprocess_block(&$variables) { - if ($variables['block']->module == 'system') { - - switch ($variables['block']->delta) { - case 'powered-by': - $variables['attributes']['role'] = 'complementary'; - break; - case 'help': - $variables['attributes']['role'] = 'complementary'; - break; - - // System menu blocks should get the same class as menu module blocks. - default: - if (in_array($variables['block']->delta, array_keys(menu_list_system_menus()))) { - $variables['attributes']['role'] = 'navigation'; - $variables['attributes']['class'][] = 'block-menu'; - } - } } } diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php new file mode 100644 index 0000000..0409cad --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserLoginBlock.php @@ -0,0 +1,37 @@ +uid && !(arg(0) == 'user' && !is_numeric(arg(1)))); + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + return drupal_get_form('user_login_block'); + } +} diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php new file mode 100644 index 0000000..ac8a727 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserNewBlock.php @@ -0,0 +1,64 @@ + 'select', + '#title' => t('Number of users to display'), + '#default_value' => $this->configuration['whois_new_count'], + '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, $form_state); + $this->configuration['whois_new_count'] = $form_state['values']['user_block_whois_new_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + // Retrieve a list of new users who have subsequently accessed the site successfully. + $items = db_query_range('SELECT uid, name FROM {users} WHERE status <> 0 AND access <> 0 ORDER BY created DESC', 0, $this->configuration['whois_new_count'])->fetchAll(); + return array( + '#children' => theme('user_list', array('users' => $items)), + ); + } +} diff --git a/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php new file mode 100644 index 0000000..a186c21 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Plugin/block/block/UserOnlineBlock.php @@ -0,0 +1,90 @@ + 'select', + '#title' => t('User activity'), + '#default_value' => $this->configuration['seconds_online'], + '#options' => $period, + '#description' => t('A user is considered online for this long after they have last viewed a page.') + ); + $form['user_block_max_list_count'] = array( + '#type' => 'select', + '#title' => t('User list length'), + '#default_value' => $this->configuration['max_list_count'], + '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), + '#description' => t('Maximum number of currently online users to display.') + ); + return $form; + } + + /** + * Implements BlockInterface::configureSubmit(). + */ + public function configureSubmit($form, &$form_state) { + parent::configureSubmit($form, &$form_state); + $this->configuration['seconds_online'] = $form_state['values']['user_block_seconds_online']; + $this->configuration['max_list_count'] = $form_state['values']['user_block_max_list_count']; + } + + /** + * Implements BlockInterface::build(). + */ + public function build() { + // Count users active within the defined period. + $interval = REQUEST_TIME - $this->configuration['max_list_count']; + + // Perform database queries to gather online user lists. We use s.timestamp + // rather than u.access because it is much faster. + $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField(); + + $output = '

' . format_plural($authenticated_count, 'There is currently 1 user online.', 'There are currently @count users online.') . '

'; + + // Display a list of currently online users. + $max_users = $this->configuration['max_list_count']; + if ($authenticated_count && $max_users) { + $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', 0, $max_users, array(':interval' => $interval))->fetchAll(); + $output .= theme('user_list', array('users' => $items)); + } + + return array( + '#children' => $output, + ); + } +} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 1f72aa6..be8f49c 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -1068,135 +1068,18 @@ function user_login_block($form) { } /** - * Implements hook_block_info(). - */ -function user_block_info() { - global $user; - - $blocks['login']['info'] = t('User login'); - // Not worth caching. - $blocks['login']['cache'] = DRUPAL_NO_CACHE; - - $blocks['new']['info'] = t('Who\'s new'); - $blocks['new']['properties']['administrative'] = TRUE; - - // Too dynamic to cache. - $blocks['online']['info'] = t('Who\'s online'); - $blocks['online']['cache'] = DRUPAL_NO_CACHE; - $blocks['online']['properties']['administrative'] = TRUE; - - return $blocks; -} - -/** - * Implements hook_block_configure(). - */ -function user_block_configure($delta = '') { - global $user; - - switch ($delta) { - case 'new': - $form['user_block_whois_new_count'] = array( - '#type' => 'select', - '#title' => t('Number of users to display'), - '#default_value' => variable_get('user_block_whois_new_count', 5), - '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), - ); - return $form; - - case 'online': - $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval'); - $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.')); - $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.')); - return $form; - } -} - -/** - * Implements hook_block_save(). - */ -function user_block_save($delta = '', $edit = array()) { - global $user; - - switch ($delta) { - case 'new': - variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']); - break; - - case 'online': - variable_set('user_block_seconds_online', $edit['user_block_seconds_online']); - variable_set('user_block_max_list_count', $edit['user_block_max_list_count']); - break; - } -} - -/** - * Implements hook_block_view(). - */ -function user_block_view($delta = '') { - global $user; - - $block = array(); - - switch ($delta) { - case 'login': - // For usability's sake, avoid showing two login forms on one page. - if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) { - - $block['subject'] = t('User login'); - $block['content'] = drupal_get_form('user_login_block'); - } - return $block; - - case 'new': - if (user_access('access content')) { - // Retrieve a list of new users who have subsequently accessed the site successfully. - $items = db_query_range('SELECT uid, name FROM {users} WHERE status <> 0 AND access <> 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5))->fetchAll(); - $output = theme('user_list', array('users' => $items)); - - $block['subject'] = t('Who\'s new'); - $block['content'] = $output; - } - return $block; - - case 'online': - if (user_access('access content')) { - // Count users active within the defined period. - $interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900); - - // Perform database queries to gather online user lists. We use s.timestamp - // rather than u.access because it is much faster. - $authenticated_count = db_query("SELECT COUNT(DISTINCT s.uid) FROM {sessions} s WHERE s.timestamp >= :timestamp AND s.uid > 0", array(':timestamp' => $interval))->fetchField(); - - $output = '

' . format_plural($authenticated_count, 'There is currently 1 user online.', 'There are currently @count users online.') . '

'; - - // Display a list of currently online users. - $max_users = variable_get('user_block_max_list_count', 10); - if ($authenticated_count && $max_users) { - $items = db_query_range('SELECT u.uid, u.name, MAX(s.timestamp) AS max_timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= :interval AND s.uid > 0 GROUP BY u.uid, u.name ORDER BY max_timestamp DESC', 0, $max_users, array(':interval' => $interval))->fetchAll(); - $output .= theme('user_list', array('users' => $items)); - } - - $block['subject'] = t('Who\'s online'); - $block['content'] = $output; - } - return $block; - } -} - -/** - * Implements hook_preprocess_HOOK() for block.tpl.php. + * Implements hook_preprocess_block(). */ function user_preprocess_block(&$variables) { if ($variables['block']->module == 'user') { - switch ($variables['block']->delta) { - case 'login': + switch ($variables['block']->id) { + case 'user_login_block': $variables['attributes']['role'] = 'form'; break; - case 'new': + case 'user_new_block': $variables['attributes']['role'] = 'complementary'; break; - case 'online': + case 'user_online_block': $variables['attributes']['role'] = 'complementary'; break; }