3 namespace Drupal\bootstrap_layouts;
5 use Drupal\bootstrap_layouts\Plugin\Layout\BootstrapLayoutsBase;
6 use Drupal\Component\Serialization\Yaml;
7 use Drupal\Component\Utility\NestedArray;
8 use Drupal\Component\Utility\Unicode;
9 use Drupal\Core\Cache\CacheBackendInterface;
10 use Drupal\Core\Extension\ModuleHandlerInterface;
11 use Drupal\Core\Extension\ThemeHandlerInterface;
12 use Drupal\Core\Theme\ThemeManagerInterface;
13 use Drupal\layout_plugin\Plugin\Layout\LayoutPluginManager;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
17 * Class BootstrapLayoutsManager
19 class BootstrapLayoutsManager extends BootstrapLayoutsPluginManager {
22 * @var \Drupal\layout_plugin\Plugin\Layout\LayoutPluginManager
24 protected $layoutManager;
27 * @var \Drupal\bootstrap_layouts\BootstrapLayoutsUpdateManager
29 protected $updateManager;
32 * Constructs a new \Drupal\bootstrap_layouts\BootstrapLayoutsManager object.
34 * @param \Traversable $namespaces
35 * An object that implements \Traversable which contains the root paths
36 * keyed by the corresponding namespace to look for plugin implementations.
37 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
38 * Cache backend instance to use.
39 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
40 * The module handler to invoke the alter hook with.
41 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
42 * The theme manager used to invoke the alter hook with.
43 * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
44 * The theme manager used to invoke the alter hook with.
45 * @param \Drupal\layout_plugin\Plugin\Layout\LayoutPluginManager $layout_manager
47 * @param \Drupal\bootstrap_layouts\BootstrapLayoutsUpdateManager $update_manager
48 * The Bootstrap Layouts update manager.
50 public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, ThemeManagerInterface $theme_manager, LayoutPluginManager $layout_manager, BootstrapLayoutsUpdateManager $update_manager) {
51 parent::__construct($namespaces, $cache_backend, $module_handler, $theme_handler, $theme_manager, 'Drupal\bootstrap_layouts\Plugin\BootstrapLayouts\BootstrapLayoutsHandlerInterface', 'Drupal\bootstrap_layouts\Annotation\BootstrapLayoutsHandler');
52 $this->layoutManager = $layout_manager;
53 $this->updateManager = $update_manager;
54 $this->alterInfo('bootstrap_layouts_handler_info');
55 $this->setCacheBackend($cache_backend, 'bootstrap_layouts_handler_info');
61 public static function create(ContainerInterface $container) {
63 $container->get('container.namespaces'),
64 $container->get('cache.discovery'),
65 $container->get('module_handler'),
66 $container->get('theme_handler'),
67 $container->get('theme.manager'),
68 $container->get('plugin.manager.layout_plugin'),
69 $container->get('plugin.manager.bootstrap_layouts.update')
76 protected function findDefinitions() {
77 $definitions = parent::findDefinitions();
78 // The handler plugin identifiers represent the module or theme that
79 // implements said layouts. Remove any handler plugins that not installed.
80 foreach (array_keys($definitions) as $provider) {
81 if (!$this->providerExists($provider)) {
82 unset($definitions[$provider]);
85 // Attempt to retrieve the theme human readable label first.
87 $label = $this->themeHandler->getName($provider);
89 // Otherwise attempt to retrieve the module human readable label.
90 catch (\Exception $e) {
91 $label = $this->moduleHandler->getName($provider);
93 $definitions[$provider]['label'] = $label;
100 * Retrieves classes that can be used in Bootstrap layouts as select options.
103 * An associative array of grouped classes to be used in select options.
105 public function getClassOptions() {
108 if (!isset($classes)) {
116 'text-left' => $this->t('Left'),
117 'text-right' => $this->t('Right'),
118 'text-center' => $this->t('Center'),
119 'text-justify' => $this->t('Justify'),
120 'text-nowrap' => $this->t('No Wrap'),
122 $text_transformation = [
123 'text-lowercase' => $this->t('Lowercase'),
124 'text-uppercase' => $this->t('Uppercase'),
125 'text-capitalize' => $this->t('Capitalize'),
129 $utility['clearfix'] = $this->t('Clear Fix');
130 $utility['row'] = $this->t('Row');
133 'xs' => $this->t('Extra Small'),
134 'sm' => $this->t('Small'),
135 'md' => $this->t('Medium'),
136 'lg' => $this->t('Large'),
139 foreach ($sizes as $size => $size_label) {
140 $hidden["hidden-$size"] = $size_label;
141 $visible["visible-$size"] = $size_label;
142 foreach (range(1, 12) as $column) {
143 $col["col-$size-$column"] = $this->t('@size: @column', [
144 '@size' => $size_label,
145 '@column' => $column,
150 // Background/text color classes.
151 foreach (['primary', 'danger', 'info', 'warning', 'success'] as $type) {
152 $bg["bg-$type"] = $this->t('@type', ['@type' => Unicode::ucfirst($type)]);
153 $text_color["text-$type"] = $this->t('@type', ['@type' => Unicode::ucfirst($type)]);
155 $text_color['text-muted'] = $this->t('Muted');
159 'utility' => $this->t('Utility'),
160 'columns' => $this->t('Columns'),
161 'hidden' => $this->t('Hidden'),
162 'visible' => $this->t('Visible'),
163 'background' => $this->t('Background'),
164 'text_alignment' => $this->t('Text alignment'),
165 'text_color' => $this->t('Text color'),
166 'text_transformation' => $this->t('Text transformation'),
169 // Classes, keyed by group.
171 'utility' => $utility,
174 'visible' => $visible,
176 'text_alignment' => $text_alignment,
177 'text_color' => $text_color,
178 'text_transformation' => $text_transformation,
181 // Invokes hook_bootstrap_layouts_class_options_alter().
182 $this->moduleHandler->alter('bootstrap_layouts_class_options', $classes, $groups);
183 $this->themeManager->alter('bootstrap_layouts_class_options', $classes, $groups);
185 // Render the group labels and use them for optgroup values.
187 foreach ($classes as $group => $data) {
188 $group = (string) (isset($groups[$group]) ? $groups[$group] : $group);
189 $grouped[$group] = $data;
198 * Indicates if provided layout identifier is a Bootstrap Layouts layout.
201 * The layout identifier to test.
206 public function isBootstrapLayout($id) {
208 if (!isset($layouts)) {
210 foreach (array_keys($this->layoutManager->getDefinitions()) as $layout_id) {
211 $plugin = $this->layoutManager->createInstance($layout_id);
212 if ($plugin instanceof BootstrapLayoutsBase) {
213 $layouts[] = $layout_id;
217 return in_array($id, $layouts);
221 * Retrieves all available handler instances.
223 * @return \Drupal\bootstrap_layouts\Plugin\BootstrapLayouts\BootstrapLayoutsHandlerInterface[]
225 public function getHandlers() {
227 foreach (array_keys($this->getDefinitions()) as $plugin_id) {
228 $instances[$plugin_id] = $this->createInstance($plugin_id);
234 * Runs update(s) for a specific schema version.
237 * The schema version to update.
238 * @param bool $display_messages
239 * Flag determining whether a message will be displayed indicating whether
240 * the layout was processed successfully or not.
242 public function update($schema, $display_messages = TRUE) {
243 $handlers = $this->getHandlers();
245 foreach ($this->updateManager->getUpdates($schema) as $update) {
246 // See if there's an adjoining YML file with the update plugin.
247 $r = new \ReflectionClass($update);
248 $data_paths = [dirname($r->getFileName()), $update->getPath()];
250 // Merge in any update data.
251 foreach ($data_paths as $path) {
252 $file = "$path/bootstrap_layouts.update.$schema.yml";
253 if (file_exists($file) && ($yaml = Yaml::decode(file_get_contents($file)))) {
254 $data = NestedArray::mergeDeep($data, $yaml);
258 // Perform the update.
259 $update->update($this, $data, $display_messages);
261 // Process any existing layouts after the update.
262 foreach ($handlers as $handler_id => $handler) {
263 foreach ($handler->loadInstances() as $storage_id => $layout) {
264 $update->processExistingLayout($layout, $data, $display_messages);
266 // Determine if the layout has changed and then save it.
267 if ($layout->hasChanged()) {
269 $handler->saveInstance($storage_id, $layout);
270 if ($display_messages) {
271 \drupal_set_message($this->t('Successfully updated the existing Bootstrap layout found in "@id".', ['@id' => $storage_id]));
273 } catch (\Exception $e) {
274 \drupal_set_message($this->t('Unable to update the existing Bootstrap layout found in "@id":', ['@id' => $storage_id]), 'error');
275 \drupal_set_message($e->getMessage(), 'error');