123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- <?php
- namespace Drupal\breakpoint;
- use Drupal\Core\Cache\Cache;
- use Drupal\Core\Cache\CacheBackendInterface;
- use Drupal\Core\Extension\ModuleHandlerInterface;
- use Drupal\Core\Extension\ThemeHandlerInterface;
- use Drupal\Core\Plugin\DefaultPluginManager;
- use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
- use Drupal\Core\Plugin\Discovery\YamlDiscovery;
- use Drupal\Core\Plugin\Factory\ContainerFactory;
- use Drupal\Core\StringTranslation\StringTranslationTrait;
- use Drupal\Core\StringTranslation\TranslationInterface;
- /**
- * Defines a breakpoint plugin manager to deal with breakpoints.
- *
- * Extension can define breakpoints in a EXTENSION_NAME.breakpoints.yml file
- * contained in the extension's base directory. Each breakpoint has the
- * following structure:
- * @code
- * MACHINE_NAME:
- * label: STRING
- * mediaQuery: STRING
- * weight: INTEGER
- * multipliers:
- * - STRING
- * @endcode
- * For example:
- * @code
- * bartik.mobile:
- * label: mobile
- * mediaQuery: '(min-width: 0px)'
- * weight: 0
- * multipliers:
- * - 1x
- * - 2x
- * @endcode
- * Optionally a breakpoint can provide a group key. By default an extensions
- * breakpoints will be placed in a group labelled with the extension name.
- *
- * @see \Drupal\breakpoint\Breakpoint
- * @see \Drupal\breakpoint\BreakpointInterface
- * @see plugin_api
- */
- class BreakpointManager extends DefaultPluginManager implements BreakpointManagerInterface {
- use StringTranslationTrait;
- /**
- * {@inheritdoc}
- */
- protected $defaults = [
- // Human readable label for breakpoint.
- 'label' => '',
- // The media query for the breakpoint.
- 'mediaQuery' => '',
- // Weight used for ordering breakpoints.
- 'weight' => 0,
- // Breakpoint multipliers.
- 'multipliers' => [],
- // The breakpoint group.
- 'group' => '',
- // Default class for breakpoint implementations.
- 'class' => 'Drupal\breakpoint\Breakpoint',
- // The plugin id. Set by the plugin system based on the top-level YAML key.
- 'id' => '',
- ];
- /**
- * The theme handler.
- *
- * @var \Drupal\Core\Extension\ThemeHandlerInterface
- */
- protected $themeHandler;
- /**
- * Static cache of breakpoints keyed by group.
- *
- * @var array
- */
- protected $breakpointsByGroup;
- /**
- * The plugin instances.
- *
- * @var array
- */
- protected $instances = [];
- /**
- * Constructs a new BreakpointManager instance.
- *
- * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
- * The module handler.
- * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
- * The theme handler.
- * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
- * The cache backend.
- * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
- * The string translation service.
- */
- public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend, TranslationInterface $string_translation) {
- $this->factory = new ContainerFactory($this);
- $this->moduleHandler = $module_handler;
- $this->themeHandler = $theme_handler;
- $this->setStringTranslation($string_translation);
- $this->alterInfo('breakpoints');
- $this->setCacheBackend($cache_backend, 'breakpoints', ['breakpoints']);
- }
- /**
- * {@inheritdoc}
- */
- protected function getDiscovery() {
- if (!isset($this->discovery)) {
- $this->discovery = new YamlDiscovery('breakpoints', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories());
- $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
- }
- return $this->discovery;
- }
- /**
- * {@inheritdoc}
- */
- public function processDefinition(&$definition, $plugin_id) {
- parent::processDefinition($definition, $plugin_id);
- // Allow custom groups and therefore more than one group per extension.
- if (empty($definition['group'])) {
- $definition['group'] = $definition['provider'];
- }
- // Ensure a 1x multiplier exists.
- if (!in_array('1x', $definition['multipliers'])) {
- $definition['multipliers'][] = '1x';
- }
- // Ensure that multipliers are sorted correctly.
- sort($definition['multipliers']);
- }
- /**
- * {@inheritdoc}
- */
- protected function providerExists($provider) {
- return $this->moduleHandler->moduleExists($provider) || $this->themeHandler->themeExists($provider);
- }
- /**
- * {@inheritdoc}
- */
- public function getBreakpointsByGroup($group) {
- if (!isset($this->breakpointsByGroup[$group])) {
- if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $group)) {
- $this->breakpointsByGroup[$group] = $cache->data;
- }
- else {
- $breakpoints = [];
- foreach ($this->getDefinitions() as $plugin_id => $plugin_definition) {
- if ($plugin_definition['group'] == $group) {
- $breakpoints[$plugin_id] = $plugin_definition;
- }
- }
- uasort($breakpoints, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
- $this->cacheBackend->set($this->cacheKey . ':' . $group, $breakpoints, Cache::PERMANENT, ['breakpoints']);
- $this->breakpointsByGroup[$group] = $breakpoints;
- }
- }
- $instances = [];
- foreach ($this->breakpointsByGroup[$group] as $plugin_id => $definition) {
- if (!isset($this->instances[$plugin_id])) {
- $this->instances[$plugin_id] = $this->createInstance($plugin_id);
- }
- $instances[$plugin_id] = $this->instances[$plugin_id];
- }
- return $instances;
- }
- /**
- * {@inheritdoc}
- */
- public function getGroups() {
- // Use a double colon so as to not clash with the cache for each group.
- if ($cache = $this->cacheBackend->get($this->cacheKey . '::groups')) {
- $groups = $cache->data;
- }
- else {
- $groups = [];
- foreach ($this->getDefinitions() as $plugin_definition) {
- if (!isset($groups[$plugin_definition['group']])) {
- $groups[$plugin_definition['group']] = $plugin_definition['group'];
- }
- }
- $this->cacheBackend->set($this->cacheKey . '::groups', $groups, Cache::PERMANENT, ['breakpoints']);
- }
- // Get the labels. This is not cacheable due to translation.
- $group_labels = [];
- foreach ($groups as $group) {
- $group_labels[$group] = $this->getGroupLabel($group);
- }
- asort($group_labels);
- return $group_labels;
- }
- /**
- * {@inheritdoc}
- */
- public function getGroupProviders($group) {
- $providers = [];
- $breakpoints = $this->getBreakpointsByGroup($group);
- foreach ($breakpoints as $breakpoint) {
- $provider = $breakpoint->getProvider();
- $extension = FALSE;
- if ($this->moduleHandler->moduleExists($provider)) {
- $extension = $this->moduleHandler->getModule($provider);
- }
- elseif ($this->themeHandler->themeExists($provider)) {
- $extension = $this->themeHandler->getTheme($provider);
- }
- if ($extension) {
- $providers[$extension->getName()] = $extension->getType();
- }
- }
- return $providers;
- }
- /**
- * {@inheritdoc}
- */
- public function clearCachedDefinitions() {
- parent::clearCachedDefinitions();
- $this->breakpointsByGroup = NULL;
- $this->instances = [];
- }
- /**
- * Gets the label for a breakpoint group.
- *
- * @param string $group
- * The breakpoint group.
- *
- * @return string
- * The label.
- */
- protected function getGroupLabel($group) {
- // Extension names are not translatable.
- if ($this->moduleHandler->moduleExists($group)) {
- $label = $this->moduleHandler->getName($group);
- }
- elseif ($this->themeHandler->themeExists($group)) {
- $label = $this->themeHandler->getName($group);
- }
- else {
- // Custom group label that should be translatable.
- $label = $this->t($group, [], ['context' => 'breakpoint']);
- }
- return $label;
- }
- }
|