diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 0f481ad10db..9820348e66b 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -441,6 +441,10 @@ function block_list($region) { $blocks[$region] = array(); } + uasort($blocks[$region], function($first, $second) { + return $first->weight === $second->weight ? 0 : ($first->weight < $second->weight ? -1 : 1); + }); + return $blocks[$region]; } diff --git a/core/modules/block/lib/Drupal/block/BlockListController.php b/core/modules/block/lib/Drupal/block/BlockListController.php index 66774a780b1..9ba757b504f 100644 --- a/core/modules/block/lib/Drupal/block/BlockListController.php +++ b/core/modules/block/lib/Drupal/block/BlockListController.php @@ -46,7 +46,8 @@ class BlockListController extends ConfigEntityListController implements FormInte // Load only blocks for this theme, and sort them. // @todo Move the functionality of _block_rehash() out of the listing page. $entities = _block_rehash($this->theme); - uasort($entities, 'static::sort'); + + uasort($entities, array($this->entityInfo['class'], 'sort')); return $entities; } @@ -60,39 +61,6 @@ class BlockListController extends ConfigEntityListController implements FormInte return drupal_get_form($this); } - /** - * Sorts active blocks by region then weight; sorts inactive blocks by name. - */ - protected function sort(Block $a, Block $b) { - static $regions; - // We need the region list to correctly order by region. - if (!isset($regions)) { - $regions = array_flip(array_keys($this->regions)); - $regions[BLOCK_REGION_NONE] = count($regions); - } - - // Separate enabled from disabled. - $status = $b->get('status') - $a->get('status'); - if ($status) { - return $status; - } - // Sort by region (in the order defined by theme .info.yml file). - $aregion = $a->get('region'); - $bregion = $b->get('region'); - if ((!empty($aregion) && !empty($bregion)) && ($place = ($regions[$aregion] - $regions[$bregion]))) { - return $place; - } - // Sort by weight, unless disabled. - if ($a->get('region') != BLOCK_REGION_NONE) { - $weight = $a->get('weight') - $b->get('weight'); - if ($weight) { - return $weight; - } - } - // Sort by label. - return strcmp($a->label(), $b->label()); - } - /** * Implements \Drupal\Core\Form\FormInterface::getFormID(). */ diff --git a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php index bb3a1d45336..b2b7cccfa5f 100644 --- a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php @@ -172,4 +172,24 @@ class Block extends ConfigEntityBase implements BlockInterface { $this->set('settings', $this->getPlugin()->getConfiguration()); } + /** + * Sorts active blocks by weight; sorts inactive blocks by name. + */ + public static function sort($a, $b) { + // Separate enabled from disabled. + $status = $b->get('status') - $a->get('status'); + if ($status) { + return $status; + } + // Sort by weight, unless disabled. + if ($a->get('region') != BLOCK_REGION_NONE) { + $weight = $a->get('weight') - $b->get('weight'); + if ($weight) { + return $weight; + } + } + // Sort by label. + return strcmp($a->label(), $b->label()); + } + } diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockRenderOrderTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockRenderOrderTest.php new file mode 100644 index 00000000000..680a94fd3e2 --- /dev/null +++ b/core/modules/block/lib/Drupal/block/Tests/BlockRenderOrderTest.php @@ -0,0 +1,87 @@ + 'Block Render Order', + 'description' => 'Test blocks are being rendered in order by weight.', + 'group' => 'Block', + ); + } + + function setUp() { + parent::setUp(); + // Create a test user. + $end_user = $this->drupalCreateUser(array( + 'access content', + )); + $this->drupalLogin($end_user); + } + + /** + * Tests the render order of the blocks. + */ + function testBlockRenderOrder() { + // Enable test blocks and place them in the same region. + $region = 'header'; + $test_blocks = array( + 'stark.powered' => array( + 'weight' => '-3', + 'machine_name' => 'powered', + ), + 'stark.by' => array( + 'weight' => '3', + 'machine_name' => 'by', + ), + 'stark.drupal' => array( + 'weight' => '3', + 'machine_name' => 'drupal', + ), + ); + + // Place the test blocks. + foreach ($test_blocks as $test_block) { + $this->drupalPlaceBlock('system_powered_by_block', array( + 'label' => 'Test Block', + 'region' => $region, + 'weight' => $test_block['weight'], + 'machine_name' => $test_block['machine_name'], + )); + } + + $this->drupalGet(''); + $test_content = $this->drupalGetContent(''); + + $controller = $this->container->get('plugin.manager.entity')->getStorageController('block'); + foreach ($controller->loadMultiple() as $return_block) { + $settings = $return_block->get('settings'); + $id = $return_block->get('id'); + if ($return_block_weight = $return_block->get('weight')) { + $this->assertTrue($test_blocks[$id]['weight'] == $return_block_weight, 'Block weight is set as "' . $return_block_weight . '" for ' . $id . ' block.'); + $position[$id] = strpos($test_content, 'block-' . $test_blocks[$id]['machine_name']); + } + } + $this->assertTrue($position['stark.powered'] < $position['stark.by'], 'Blocks with different weight are rendered in the correct order.'); + $this->assertTrue($position['stark.drupal'] < $position['stark.by'], 'Blocks with identical weight are rendered in reverse alphabetical order.'); + } +} diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 91a8397d8ac..ab24fc8a633 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -369,9 +369,11 @@ abstract class WebTestBase extends TestBase { 'theme' => config('system.theme')->get('default'), 'label' => $this->randomName(8), 'visibility' => array(), + 'weight' => 0, ); - foreach (array('region', 'machine_name', 'theme', 'plugin', 'visibility') as $key) { + foreach (array('region', 'machine_name', 'theme', 'plugin', 'visibility', 'weight') as $key) { $values[$key] = $settings[$key]; + // Remove extra values that do not belong in the settings array. unset($settings[$key]); } $values['settings'] = $settings;