Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
539061c7
Commit
539061c7
authored
Jun 25, 2014
by
webchick
Browse files
Issue
#2286357
by tim.plunkett: Introduce Display Variants, use for the block rendering flow.
parent
234ed4f8
Changes
11
Hide whitespace changes
Inline
Side-by-side
core/config/schema/core.data_types.schema.yml
View file @
539061c7
...
...
@@ -312,3 +312,20 @@ condition.plugin:
label
:
'
Context
assignments'
sequence
:
-
type
:
string
display_variant.plugin
:
type
:
mapping
label
:
'
Display
variant'
mapping
:
id
:
type
:
string
label
:
'
ID'
label
:
type
:
label
label
:
'
Label'
weight
:
type
:
integer
label
:
'
Weight'
uuid
:
type
:
string
label
:
'
UUID'
core/core.services.yml
View file @
539061c7
...
...
@@ -263,6 +263,9 @@ services:
plugin.manager.menu.contextual_link
:
class
:
Drupal\Core\Menu\ContextualLinkManager
arguments
:
[
'
@controller_resolver'
,
'
@module_handler'
,
'
@cache.discovery'
,
'
@language_manager'
,
'
@access_manager'
,
'
@current_user'
,
'
@request_stack'
]
plugin.manager.display_variant
:
class
:
Drupal\Core\Display\VariantManager
parent
:
default_plugin_manager
plugin.cache_clearer
:
class
:
Drupal\Core\Plugin\CachedDiscoveryClearer
request
:
...
...
core/lib/Drupal/Core/Display/Annotation/DisplayVariant.php
0 → 100644
View file @
539061c7
<?php
/**
* @file
* Contains \Drupal\Core\Display\Annotation\DisplayVariant.
*/
namespace
Drupal\Core\Display\Annotation
;
use
Drupal\Component\Annotation\Plugin
;
/**
* Defines a display variant annotation object.
*
* Display variants are used to dictate the output of a given Display, which
* can be used to control the output of many parts of Drupal. For example, the
* FullPageVariant is used by the Block module to control regions and output
* block content placed in those regions.
*
* Variants are usually chosen by some selection criteria, and are instantiated
* directly. Each variant must define its own approach to rendering, and can
* either load its own data or be injected with data from another Display
* object.
*
* @todo: Revise description when/if Displays are added to core:
* https://www.drupal.org/node/2292733
*
* @see \Drupal\Core\Display\VariantInterface
* @see \Drupal\Core\Display\VariantManager
*
* @Annotation
*/
class
DisplayVariant
extends
Plugin
{
/**
* The plugin ID.
*
* @var string
*/
public
$id
;
/**
* The administrative label.
*
* @var \Drupal\Core\Annotation\Translation
*
* @ingroup plugin_translatable
*/
public
$admin_label
=
''
;
}
core/lib/Drupal/Core/Display/VariantBase.php
0 → 100644
View file @
539061c7
<?php
/**
* @file
* Contains \Drupal\Core\Display\VariantBase.
*/
namespace
Drupal\Core\Display
;
use
Drupal\Core\Plugin\PluginBase
;
use
Drupal\Core\Plugin\PluginDependencyTrait
;
use
Drupal\Core\Session\AccountInterface
;
/**
* Provides a base class for DisplayVariant plugins.
*/
abstract
class
VariantBase
extends
PluginBase
implements
VariantInterface
{
use
PluginDependencyTrait
;
/**
* {@inheritdoc}
*/
public
function
__construct
(
array
$configuration
,
$plugin_id
,
$plugin_definition
)
{
parent
::
__construct
(
$configuration
,
$plugin_id
,
$plugin_definition
);
$this
->
setConfiguration
(
$configuration
);
}
/**
* {@inheritdoc}
*/
public
function
label
()
{
return
$this
->
configuration
[
'label'
];
}
/**
* {@inheritdoc}
*/
public
function
adminLabel
()
{
return
$this
->
pluginDefinition
[
'admin_label'
];
}
/**
* {@inheritdoc}
*/
public
function
id
()
{
return
$this
->
configuration
[
'uuid'
];
}
/**
* {@inheritdoc}
*/
public
function
getWeight
()
{
return
(
int
)
$this
->
configuration
[
'weight'
];
}
/**
* {@inheritdoc}
*/
public
function
setWeight
(
$weight
)
{
$this
->
configuration
[
'weight'
]
=
(
int
)
$weight
;
}
/**
* {@inheritdoc}
*/
public
function
getConfiguration
()
{
return
array
(
'id'
=>
$this
->
getPluginId
(),
)
+
$this
->
configuration
;
}
/**
* {@inheritdoc}
*/
public
function
setConfiguration
(
array
$configuration
)
{
$this
->
configuration
=
$configuration
+
$this
->
defaultConfiguration
();
return
$this
;
}
/**
* {@inheritdoc}
*/
public
function
defaultConfiguration
()
{
return
array
(
'label'
=>
''
,
'uuid'
=>
''
,
'weight'
=>
0
,
);
}
/**
* {@inheritdoc}
*/
public
function
calculateDependencies
()
{
return
$this
->
dependencies
;
}
/**
* {@inheritdoc}
*/
public
function
buildConfigurationForm
(
array
$form
,
array
&
$form_state
)
{
$form
[
'label'
]
=
array
(
'#type'
=>
'textfield'
,
'#title'
=>
$this
->
t
(
'Label'
),
'#description'
=>
$this
->
t
(
'The label for this display variant.'
),
'#default_value'
=>
$this
->
label
(),
'#maxlength'
=>
'255'
,
);
return
$form
;
}
/**
* {@inheritdoc}
*/
public
function
validateConfigurationForm
(
array
&
$form
,
array
&
$form_state
)
{
}
/**
* {@inheritdoc}
*/
public
function
submitConfigurationForm
(
array
&
$form
,
array
&
$form_state
)
{
$this
->
configuration
[
'label'
]
=
$form_state
[
'values'
][
'label'
];
}
/**
* {@inheritdoc}
*/
public
function
access
(
AccountInterface
$account
=
NULL
)
{
return
TRUE
;
}
}
core/lib/Drupal/Core/Display/VariantInterface.php
0 → 100644
View file @
539061c7
<?php
/**
* @file
* Contains \Drupal\Core\Display\VariantInterface.
*/
namespace
Drupal\Core\Display
;
use
Drupal\Component\Plugin\ConfigurablePluginInterface
;
use
Drupal\Component\Plugin\PluginInspectionInterface
;
use
Drupal\Core\Plugin\PluginFormInterface
;
use
Drupal\Core\Session\AccountInterface
;
/**
* Provides an interface for DisplayVariant plugins.
*
* @see \Drupal\Core\Display\Annotation\DisplayVariant
* @see \Drupal\Core\Display\VariantManager
*/
interface
VariantInterface
extends
PluginInspectionInterface
,
ConfigurablePluginInterface
,
PluginFormInterface
{
/**
* Returns the user-facing display variant label.
*
* @return string
* The display variant label.
*/
public
function
label
();
/**
* Returns the admin-facing display variant label.
*
* This is for the type of display variant, not the configured variant itself.
*
* @return string
* The display variant administrative label.
*/
public
function
adminLabel
();
/**
* Returns the unique ID for the display variant.
*
* @return string
* The display variant ID.
*/
public
function
id
();
/**
* Returns the weight of the display variant.
*
* @return int
* The display variant weight.
*/
public
function
getWeight
();
/**
* Sets the weight of the display variant.
*
* @param int $weight
* The weight to set.
*/
public
function
setWeight
(
$weight
);
/**
* Determines if this display variant is accessible.
*
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) The user for which to check access, or NULL to check access
* for the current user. Defaults to NULL.
*
* @return bool
* TRUE if this display variant is accessible, FALSE otherwise.
*/
public
function
access
(
AccountInterface
$account
=
NULL
);
/**
* Builds and returns the renderable array for the display variant.
*
* @return array
* A render array for the display variant.
*/
public
function
build
();
}
core/lib/Drupal/Core/Display/VariantManager.php
0 → 100755
View file @
539061c7
<?php
/**
* @file
* Contains \Drupal\Core\Display\VariantManager.
*/
namespace
Drupal\Core\Display
;
use
Drupal\Core\Cache\CacheBackendInterface
;
use
Drupal\Core\Extension\ModuleHandlerInterface
;
use
Drupal\Core\Plugin\DefaultPluginManager
;
/**
* Manages discovery of display variant plugins.
*
* @see \Drupal\Core\Display\Annotation\DisplayVariant
* @see \Drupal\Core\Display\VariantInterface
*/
class
VariantManager
extends
DefaultPluginManager
{
/**
* Constructs a new VariantManager.
*
* @param \Traversable $namespaces
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* Cache backend instance to use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler to invoke the alter hook with.
*/
public
function
__construct
(
\
Traversable
$namespaces
,
CacheBackendInterface
$cache_backend
,
ModuleHandlerInterface
$module_handler
)
{
parent
::
__construct
(
'Plugin/DisplayVariant'
,
$namespaces
,
$module_handler
,
'Drupal\Core\Display\Annotation\DisplayVariant'
);
$this
->
setCacheBackend
(
$cache_backend
,
'variant_plugins'
);
$this
->
alterInfo
(
'display_variant_plugin'
);
}
}
core/modules/block/block.module
View file @
539061c7
...
...
@@ -86,22 +86,11 @@ function block_page_build(&$page) {
// Fetch a list of regions for the current theme.
$all_regions
=
system_region_list
(
$theme
);
if
(
\
Drupal
::
routeMatch
()
->
getRouteName
()
!=
'block.admin_demo'
)
{
// Load all region content assigned via blocks.
foreach
(
array_keys
(
$all_regions
)
as
$region
)
{
// Assign blocks to region.
if
(
$blocks
=
block_get_blocks_by_region
(
$region
))
{
$page
[
$region
]
=
$blocks
;
}
}
// Once we've finished attaching all blocks to the page, clear the static
// cache to allow modules to alter the block list differently in different
// contexts. For example, any code that triggers hook_page_build() more
// than once in the same page request may need to alter the block list
// differently each time, so that only certain parts of the page are
// actually built. We do not clear the cache any earlier than this, though,
// because it is used each time block_get_blocks_by_region() gets called
// above.
drupal_static_reset
(
'block_list'
);
// Create a full page display variant, which will load blocks into their
// regions.
$page
+=
\
Drupal
::
service
(
'plugin.manager.display_variant'
)
->
createInstance
(
'full_page'
)
->
build
();
}
else
{
// Append region description if we are rendering the regions demo page.
...
...
@@ -123,33 +112,6 @@ function block_page_build(&$page) {
}
}
/**
* Gets a renderable array of a region containing all enabled blocks.
*
* @param $region
* The requested region.
*
* @return
* A renderable array of a region containing all enabled blocks.
*/
function
block_get_blocks_by_region
(
$region
)
{
$build
=
array
();
if
(
$list
=
block_list
(
$region
))
{
foreach
(
$list
as
$key
=>
$block
)
{
if
(
$block
->
access
(
'view'
))
{
$build
[
$key
]
=
entity_view
(
$block
,
'block'
);
}
}
// If none of the blocks in this region are visible, then don't set anything
// else in the render array, because that would cause the region to show up.
if
(
!
empty
(
$build
))
{
// block_list() already returned the blocks in sorted order.
$build
[
'#sorted'
]
=
TRUE
;
}
}
return
$build
;
}
/**
* Returns an array of block class instances by theme.
*
...
...
@@ -240,43 +202,6 @@ function block_theme_initialize($theme) {
}
}
/**
* Returns all blocks in the specified region for the current user.
*
* @param $region
* The name of a region.
*
* @return
* An array of block objects, indexed with the configuration object name
* that represents the configuration. If you are displaying your blocks in
* one or two sidebars, you may check whether this array is empty to see
* how many columns are going to be displayed.
*/
function
block_list
(
$region
)
{
$blocks
=
&
drupal_static
(
__FUNCTION__
);
if
(
!
isset
(
$blocks
))
{
global
$theme
;
$blocks
=
array
();
foreach
(
entity_load_multiple_by_properties
(
'block'
,
array
(
'theme'
=>
$theme
))
as
$block_id
=>
$block
)
{
// Onlye include valid blocks in the list.
// @todo Remove this check as part of https://drupal.org/node/1776830.
if
(
$block
->
getPlugin
())
{
$blocks
[
$block
->
get
(
'region'
)][
$block_id
]
=
$block
;
}
}
}
// Create an empty array if there are no entries.
if
(
!
isset
(
$blocks
[
$region
]))
{
$blocks
[
$region
]
=
array
();
}
uasort
(
$blocks
[
$region
],
'Drupal\block\Entity\Block::sort'
);
return
$blocks
[
$region
];
}
/**
* Implements hook_rebuild().
*/
...
...
core/modules/block/src/Plugin/DisplayVariant/FullPageVariant.php
0 → 100644
View file @
539061c7
<?php
/**
* @file
* Contains \Drupal\block\Plugin\DisplayVariant\FullPageVariant.
*/
namespace
Drupal\block\Plugin\DisplayVariant
;
use
Drupal\Core\Entity\EntityStorageInterface
;
use
Drupal\Core\Entity\EntityViewBuilderInterface
;
use
Drupal\Core\Plugin\ContainerFactoryPluginInterface
;
use
Drupal\Core\Display\VariantBase
;
use
Drupal\Core\Routing\RouteMatchInterface
;
use
Drupal\Core\Theme\ThemeNegotiatorInterface
;
use
Symfony\Component\DependencyInjection\ContainerInterface
;
/**
* Provides a display variant that represents the full page.
*
* @DisplayVariant(
* id = "full_page",
* admin_label = @Translation("Full page")
* )
*/
class
FullPageVariant
extends
VariantBase
implements
ContainerFactoryPluginInterface
{
/**
* The block storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected
$blockStorage
;
/**
* The block view builder.
*
* @var \Drupal\Core\Entity\EntityViewBuilderInterface
*/
protected
$blockViewBuilder
;
/**
* The current theme.
*
* @var string
*/
protected
$theme
;
/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected
$routeMatch
;
/**
* The theme negotiator.
*
* @var \Drupal\Core\Theme\ThemeNegotiatorInterface
*/
protected
$themeNegotiator
;
/**
* Constructs a new FullPageVariant.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityStorageInterface $block_storage
* The block entity storage.
* @param \Drupal\Core\Entity\EntityViewBuilderInterface $block_view_builder
* The block view builder.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @param \Drupal\Core\Theme\ThemeNegotiatorInterface $theme_negotiator
* The theme negotiator.
*/
public
function
__construct
(
array
$configuration
,
$plugin_id
,
$plugin_definition
,
EntityStorageInterface
$block_storage
,
EntityViewBuilderInterface
$block_view_builder
,
RouteMatchInterface
$route_match
,
ThemeNegotiatorInterface
$theme_negotiator
)
{
parent
::
__construct
(
$configuration
,
$plugin_id
,
$plugin_definition
);
$this
->
blockStorage
=
$block_storage
;
$this
->
blockViewBuilder
=
$block_view_builder
;
$this
->
routeMatch
=
$route_match
;
$this
->
themeNegotiator
=
$theme_negotiator
;
}
/**
* {@inheritdoc}
*/
public
static
function
create
(
ContainerInterface
$container
,
array
$configuration
,
$plugin_id
,
$plugin_definition
)
{
return
new
static
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$container
->
get
(
'entity.manager'
)
->
getStorage
(
'block'
),
$container
->
get
(
'entity.manager'
)
->
getViewBuilder
(
'block'
),
$container
->
get
(
'current_route_match'
),
$container
->
get
(
'theme.negotiator'
)
);
}
/**
* Gets the current theme for this page.
*
* @return string
* The current theme.
*/
protected
function
getTheme
()
{
return
$this
->
themeNegotiator
->
determineActiveTheme
(
$this
->
routeMatch
);
}
/**
* {@inheritdoc}
*/
public
function
build
()
{
$build
=
array
();
// Load all region content assigned via blocks.
foreach
(
$this
->
getRegionAssignments
()
as
$region
=>
$blocks
)
{
/** @var $blocks \Drupal\block\BlockInterface[] */
foreach
(
$blocks
as
$key
=>
$block
)
{
if
(
$block
->
access
(
'view'
))
{
$build
[
$region
][
$key
]
=
$this
->
blockViewBuilder
->
view
(
$block
);
}
}
if
(
!
empty
(
$build
[
$region
]))
{
// self::getRegionAssignments() returns the blocks in sorted order.
$build
[
$region
][
'#sorted'
]
=
TRUE
;
}
}
return
$build
;
}
/**
* Returns the human-readable list of regions keyed by machine name.
*
* @return array
* An array of human-readable region names keyed by machine name.
*/
protected
function
getRegionNames
()
{
return
system_region_list
(
$this
->
getTheme
());
}
/**
* Returns an array of regions and their block entities.
*
* @return array
* The array is first keyed by region machine name, with the values
* containing an array keyed by block ID, with block entities as the values.
*/
protected
function
getRegionAssignments
()
{
// Build an array of the region names in the right order.
$empty
=
array_fill_keys
(
array_keys
(
$this
->
getRegionNames
()),
array
());
$full
=
array
();
foreach
(
$this
->
blockStorage
->
loadByProperties
(
array
(
'theme'
=>
$this
->
getTheme
()))
as
$block_id
=>
$block
)
{
$full
[
$block
->
get
(
'region'
)][
$block_id
]
=
$block
;
}
// Merge it with the actual values to maintain the region ordering.
$assignments
=
array_intersect_key
(
array_merge
(
$empty
,
$full
),
$empty
);
foreach
(
$assignments
as
&
$assignment
)
{