annotate core/modules/breakpoint/src/BreakpointManager.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\breakpoint;
Chris@0 4
Chris@0 5 use Drupal\Core\Cache\Cache;
Chris@0 6 use Drupal\Core\Cache\CacheBackendInterface;
Chris@0 7 use Drupal\Core\Extension\ModuleHandlerInterface;
Chris@0 8 use Drupal\Core\Extension\ThemeHandlerInterface;
Chris@0 9 use Drupal\Core\Plugin\DefaultPluginManager;
Chris@0 10 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
Chris@0 11 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
Chris@0 12 use Drupal\Core\Plugin\Factory\ContainerFactory;
Chris@0 13 use Drupal\Core\StringTranslation\StringTranslationTrait;
Chris@0 14 use Drupal\Core\StringTranslation\TranslationInterface;
Chris@0 15
Chris@0 16 /**
Chris@0 17 * Defines a breakpoint plugin manager to deal with breakpoints.
Chris@0 18 *
Chris@0 19 * Extension can define breakpoints in a EXTENSION_NAME.breakpoints.yml file
Chris@0 20 * contained in the extension's base directory. Each breakpoint has the
Chris@0 21 * following structure:
Chris@0 22 * @code
Chris@0 23 * MACHINE_NAME:
Chris@0 24 * label: STRING
Chris@0 25 * mediaQuery: STRING
Chris@0 26 * weight: INTEGER
Chris@0 27 * multipliers:
Chris@0 28 * - STRING
Chris@0 29 * @endcode
Chris@0 30 * For example:
Chris@0 31 * @code
Chris@0 32 * bartik.mobile:
Chris@0 33 * label: mobile
Chris@0 34 * mediaQuery: '(min-width: 0px)'
Chris@0 35 * weight: 0
Chris@0 36 * multipliers:
Chris@0 37 * - 1x
Chris@0 38 * - 2x
Chris@0 39 * @endcode
Chris@0 40 * Optionally a breakpoint can provide a group key. By default an extensions
Chris@0 41 * breakpoints will be placed in a group labelled with the extension name.
Chris@0 42 *
Chris@0 43 * @see \Drupal\breakpoint\Breakpoint
Chris@0 44 * @see \Drupal\breakpoint\BreakpointInterface
Chris@0 45 * @see plugin_api
Chris@0 46 */
Chris@0 47 class BreakpointManager extends DefaultPluginManager implements BreakpointManagerInterface {
Chris@0 48 use StringTranslationTrait;
Chris@0 49
Chris@0 50 /**
Chris@0 51 * {@inheritdoc}
Chris@0 52 */
Chris@0 53 protected $defaults = [
Chris@0 54 // Human readable label for breakpoint.
Chris@0 55 'label' => '',
Chris@0 56 // The media query for the breakpoint.
Chris@0 57 'mediaQuery' => '',
Chris@0 58 // Weight used for ordering breakpoints.
Chris@0 59 'weight' => 0,
Chris@0 60 // Breakpoint multipliers.
Chris@0 61 'multipliers' => [],
Chris@0 62 // The breakpoint group.
Chris@0 63 'group' => '',
Chris@0 64 // Default class for breakpoint implementations.
Chris@0 65 'class' => 'Drupal\breakpoint\Breakpoint',
Chris@0 66 // The plugin id. Set by the plugin system based on the top-level YAML key.
Chris@0 67 'id' => '',
Chris@0 68 ];
Chris@0 69
Chris@0 70 /**
Chris@0 71 * The theme handler.
Chris@0 72 *
Chris@0 73 * @var \Drupal\Core\Extension\ThemeHandlerInterface
Chris@0 74 */
Chris@0 75 protected $themeHandler;
Chris@0 76
Chris@0 77 /**
Chris@0 78 * Static cache of breakpoints keyed by group.
Chris@0 79 *
Chris@0 80 * @var array
Chris@0 81 */
Chris@0 82 protected $breakpointsByGroup;
Chris@0 83
Chris@0 84 /**
Chris@0 85 * The plugin instances.
Chris@0 86 *
Chris@0 87 * @var array
Chris@0 88 */
Chris@0 89 protected $instances = [];
Chris@0 90
Chris@0 91 /**
Chris@0 92 * Constructs a new BreakpointManager instance.
Chris@0 93 *
Chris@0 94 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
Chris@0 95 * The module handler.
Chris@0 96 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
Chris@0 97 * The theme handler.
Chris@0 98 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
Chris@0 99 * The cache backend.
Chris@0 100 * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
Chris@0 101 * The string translation service.
Chris@0 102 */
Chris@0 103 public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend, TranslationInterface $string_translation) {
Chris@0 104 $this->factory = new ContainerFactory($this);
Chris@0 105 $this->moduleHandler = $module_handler;
Chris@0 106 $this->themeHandler = $theme_handler;
Chris@0 107 $this->setStringTranslation($string_translation);
Chris@0 108 $this->alterInfo('breakpoints');
Chris@0 109 $this->setCacheBackend($cache_backend, 'breakpoints', ['breakpoints']);
Chris@0 110 }
Chris@0 111
Chris@0 112 /**
Chris@0 113 * {@inheritdoc}
Chris@0 114 */
Chris@0 115 protected function getDiscovery() {
Chris@0 116 if (!isset($this->discovery)) {
Chris@0 117 $this->discovery = new YamlDiscovery('breakpoints', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories());
Chris@0 118 $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
Chris@0 119 }
Chris@0 120 return $this->discovery;
Chris@0 121 }
Chris@0 122
Chris@0 123 /**
Chris@0 124 * {@inheritdoc}
Chris@0 125 */
Chris@0 126 public function processDefinition(&$definition, $plugin_id) {
Chris@0 127 parent::processDefinition($definition, $plugin_id);
Chris@0 128 // Allow custom groups and therefore more than one group per extension.
Chris@0 129 if (empty($definition['group'])) {
Chris@0 130 $definition['group'] = $definition['provider'];
Chris@0 131 }
Chris@0 132 // Ensure a 1x multiplier exists.
Chris@0 133 if (!in_array('1x', $definition['multipliers'])) {
Chris@0 134 $definition['multipliers'][] = '1x';
Chris@0 135 }
Chris@0 136 // Ensure that multipliers are sorted correctly.
Chris@0 137 sort($definition['multipliers']);
Chris@0 138 }
Chris@0 139
Chris@0 140 /**
Chris@0 141 * {@inheritdoc}
Chris@0 142 */
Chris@0 143 protected function providerExists($provider) {
Chris@0 144 return $this->moduleHandler->moduleExists($provider) || $this->themeHandler->themeExists($provider);
Chris@0 145 }
Chris@0 146
Chris@0 147 /**
Chris@0 148 * {@inheritdoc}
Chris@0 149 */
Chris@0 150 public function getBreakpointsByGroup($group) {
Chris@0 151 if (!isset($this->breakpointsByGroup[$group])) {
Chris@0 152 if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $group)) {
Chris@0 153 $this->breakpointsByGroup[$group] = $cache->data;
Chris@0 154 }
Chris@0 155 else {
Chris@0 156 $breakpoints = [];
Chris@0 157 foreach ($this->getDefinitions() as $plugin_id => $plugin_definition) {
Chris@0 158 if ($plugin_definition['group'] == $group) {
Chris@0 159 $breakpoints[$plugin_id] = $plugin_definition;
Chris@0 160 }
Chris@0 161 }
Chris@0 162 uasort($breakpoints, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
Chris@0 163 $this->cacheBackend->set($this->cacheKey . ':' . $group, $breakpoints, Cache::PERMANENT, ['breakpoints']);
Chris@0 164 $this->breakpointsByGroup[$group] = $breakpoints;
Chris@0 165 }
Chris@0 166 }
Chris@0 167
Chris@0 168 $instances = [];
Chris@0 169 foreach ($this->breakpointsByGroup[$group] as $plugin_id => $definition) {
Chris@0 170 if (!isset($this->instances[$plugin_id])) {
Chris@0 171 $this->instances[$plugin_id] = $this->createInstance($plugin_id);
Chris@0 172 }
Chris@0 173 $instances[$plugin_id] = $this->instances[$plugin_id];
Chris@0 174 }
Chris@0 175 return $instances;
Chris@0 176 }
Chris@0 177
Chris@0 178 /**
Chris@0 179 * {@inheritdoc}
Chris@0 180 */
Chris@0 181 public function getGroups() {
Chris@0 182 // Use a double colon so as to not clash with the cache for each group.
Chris@0 183 if ($cache = $this->cacheBackend->get($this->cacheKey . '::groups')) {
Chris@0 184 $groups = $cache->data;
Chris@0 185 }
Chris@0 186 else {
Chris@0 187 $groups = [];
Chris@0 188 foreach ($this->getDefinitions() as $plugin_definition) {
Chris@0 189 if (!isset($groups[$plugin_definition['group']])) {
Chris@0 190 $groups[$plugin_definition['group']] = $plugin_definition['group'];
Chris@0 191 }
Chris@0 192 }
Chris@0 193 $this->cacheBackend->set($this->cacheKey . '::groups', $groups, Cache::PERMANENT, ['breakpoints']);
Chris@0 194 }
Chris@0 195 // Get the labels. This is not cacheable due to translation.
Chris@0 196 $group_labels = [];
Chris@0 197 foreach ($groups as $group) {
Chris@0 198 $group_labels[$group] = $this->getGroupLabel($group);
Chris@0 199 }
Chris@0 200 asort($group_labels);
Chris@0 201 return $group_labels;
Chris@0 202 }
Chris@0 203
Chris@0 204 /**
Chris@0 205 * {@inheritdoc}
Chris@0 206 */
Chris@0 207 public function getGroupProviders($group) {
Chris@0 208 $providers = [];
Chris@0 209 $breakpoints = $this->getBreakpointsByGroup($group);
Chris@0 210 foreach ($breakpoints as $breakpoint) {
Chris@0 211 $provider = $breakpoint->getProvider();
Chris@0 212 $extension = FALSE;
Chris@0 213 if ($this->moduleHandler->moduleExists($provider)) {
Chris@0 214 $extension = $this->moduleHandler->getModule($provider);
Chris@0 215 }
Chris@0 216 elseif ($this->themeHandler->themeExists($provider)) {
Chris@0 217 $extension = $this->themeHandler->getTheme($provider);
Chris@0 218 }
Chris@0 219 if ($extension) {
Chris@0 220 $providers[$extension->getName()] = $extension->getType();
Chris@0 221 }
Chris@0 222 }
Chris@0 223 return $providers;
Chris@0 224 }
Chris@0 225
Chris@0 226 /**
Chris@0 227 * {@inheritdoc}
Chris@0 228 */
Chris@0 229 public function clearCachedDefinitions() {
Chris@0 230 parent::clearCachedDefinitions();
Chris@0 231 $this->breakpointsByGroup = NULL;
Chris@0 232 $this->instances = [];
Chris@0 233 }
Chris@0 234
Chris@0 235 /**
Chris@0 236 * Gets the label for a breakpoint group.
Chris@0 237 *
Chris@0 238 * @param string $group
Chris@0 239 * The breakpoint group.
Chris@0 240 *
Chris@0 241 * @return string
Chris@0 242 * The label.
Chris@0 243 */
Chris@0 244 protected function getGroupLabel($group) {
Chris@0 245 // Extension names are not translatable.
Chris@0 246 if ($this->moduleHandler->moduleExists($group)) {
Chris@0 247 $label = $this->moduleHandler->getName($group);
Chris@0 248 }
Chris@0 249 elseif ($this->themeHandler->themeExists($group)) {
Chris@0 250 $label = $this->themeHandler->getName($group);
Chris@0 251 }
Chris@0 252 else {
Chris@0 253 // Custom group label that should be translatable.
Chris@0 254 $label = $this->t($group, [], ['context' => 'breakpoint']);
Chris@0 255 }
Chris@0 256 return $label;
Chris@0 257 }
Chris@0 258
Chris@0 259 }