annotate modules/contrib/views_slideshow/src/Plugin/views/style/Slideshow.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents c69a71b4f40f
children
rev   line source
Chris@5 1 <?php
Chris@5 2
Chris@5 3 namespace Drupal\views_slideshow\Plugin\views\style;
Chris@5 4
Chris@5 5 use Drupal\Core\Form\FormStateInterface;
Chris@5 6 use Drupal\views\Plugin\views\style\StylePluginBase;
Chris@5 7 use Drupal\Core\Url;
Chris@5 8 use Drupal\Core\Link;
Chris@5 9
Chris@5 10 /**
Chris@5 11 * Style plugin to render each item in a slideshow.
Chris@5 12 *
Chris@5 13 * @ingroup views_style_plugins
Chris@5 14 *
Chris@5 15 * @ViewsStyle(
Chris@5 16 * id = "slideshow",
Chris@5 17 * title = @Translation("Slideshow"),
Chris@5 18 * help = @Translation("Display the results as a slideshow."),
Chris@5 19 * theme = "views_view_slideshow",
Chris@5 20 * display_types = {"normal"}
Chris@5 21 * )
Chris@5 22 */
Chris@5 23 class Slideshow extends StylePluginBase {
Chris@5 24
Chris@5 25 /**
Chris@5 26 * Does the style plugin allows to use style plugins.
Chris@5 27 *
Chris@5 28 * @var bool
Chris@5 29 */
Chris@5 30 protected $usesRowPlugin = TRUE;
Chris@5 31
Chris@5 32 /**
Chris@5 33 * Does the style plugin support custom css class for the rows.
Chris@5 34 *
Chris@5 35 * @var bool
Chris@5 36 */
Chris@5 37 protected $usesRowClass = TRUE;
Chris@5 38
Chris@5 39 /**
Chris@5 40 * Does the style plugin support grouping of rows.
Chris@5 41 *
Chris@5 42 * @var bool
Chris@5 43 */
Chris@5 44 protected $usesGrouping = FALSE;
Chris@5 45
Chris@5 46 /**
Chris@5 47 * Does the style plugin for itself support to add fields to it's output.
Chris@5 48 *
Chris@5 49 * This option only makes sense on style plugins without row plugins, like
Chris@5 50 * for example table.
Chris@5 51 *
Chris@5 52 * @var bool
Chris@5 53 */
Chris@5 54 protected $usesFields = TRUE;
Chris@5 55
Chris@5 56 /**
Chris@5 57 * {@inheritdoc}
Chris@5 58 */
Chris@5 59 protected function defineOptions() {
Chris@5 60 $options = parent::defineOptions();
Chris@5 61 $options['row_class_custom'] = ['default' => ''];
Chris@5 62 $options['row_class_default'] = ['default' => TRUE];
Chris@5 63 $options['slideshow_type'] = ['default' => 'views_slideshow_cycle'];
Chris@5 64 $options['slideshow_skin'] = ['default' => 'default'];
Chris@5 65
Chris@5 66 $typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
Chris@5 67 foreach ($typeManager->getDefinitions() as $id => $definition) {
Chris@5 68 $instance = $typeManager->createInstance($id, []);
Chris@5 69 $options[$id] = $instance->defaultConfiguration();
Chris@5 70 }
Chris@5 71
Chris@5 72 $widgetTypeManager = \Drupal::service('plugin.manager.views_slideshow.widget_type');
Chris@5 73 $widgetTypes = $widgetTypeManager->getDefinitions();
Chris@5 74 foreach (['top', 'bottom'] as $location) {
Chris@5 75 foreach ($widgetTypes as $widgetTypeId => $widgetTypeDefinition) {
Chris@5 76 $options['widgets']['contains'][$location]['contains'][$widgetTypeId]['contains'] = $widgetTypeManager->createInstance($widgetTypeId, [])->defaultConfiguration();
Chris@5 77 }
Chris@5 78 }
Chris@5 79
Chris@5 80 return $options;
Chris@5 81 }
Chris@5 82
Chris@5 83 /**
Chris@5 84 * {@inheritdoc}
Chris@5 85 */
Chris@5 86 public function buildOptionsForm(&$form, FormStateInterface $form_state) {
Chris@5 87 parent::buildOptionsForm($form, $form_state);
Chris@5 88
Chris@5 89 // Wrap all the form elements to help style the form.
Chris@5 90 $form['views_slideshow_wrapper'] = [
Chris@5 91 '#markup' => '<div id="views-slideshow-form-wrapper">',
Chris@5 92 ];
Chris@5 93
Chris@5 94 // Skins.
Chris@5 95 $form['slideshow_skin_header'] = [
Chris@5 96 '#markup' => '<h2>' . $this->t('Style') . '</h2>',
Chris@5 97 ];
Chris@5 98
Chris@5 99 /* @var \Drupal\Component\Plugin\PluginManagerInterface */
Chris@5 100 $skinManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_skin');
Chris@5 101
Chris@5 102 // Get all skins to create the option list.
Chris@5 103 $skins = [];
Chris@5 104 foreach ($skinManager->getDefinitions() as $id => $definition) {
Chris@5 105 $skins[$id] = $definition['label'];
Chris@5 106 }
Chris@5 107 asort($skins);
Chris@5 108
Chris@5 109 // Create the drop down box so users can choose an available skin.
Chris@5 110 $form['slideshow_skin'] = [
Chris@5 111 '#type' => 'select',
Chris@5 112 '#title' => $this->t('Skin'),
Chris@5 113 '#options' => $skins,
Chris@5 114 '#default_value' => $this->options['slideshow_skin'],
Chris@5 115 '#description' => $this->t('Select the skin to use for this display. Skins allow for easily swappable layouts of things like next/prev links and thumbnails. Note that not all skins support all widgets, so a combination of skins and widgets may lead to unpredictable results in layout.'),
Chris@5 116 ];
Chris@5 117
Chris@5 118 // Slides.
Chris@5 119 $form['slides_header'] = [
Chris@5 120 '#markup' => '<h2>' . $this->t('Slides') . '</h2>',
Chris@5 121 ];
Chris@5 122
Chris@5 123 // Get all slideshow types.
Chris@5 124 $typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
Chris@5 125 $types = $typeManager->getDefinitions();
Chris@5 126
Chris@5 127 if ($types) {
Chris@5 128
Chris@5 129 // Build our slideshow options for the form.
Chris@5 130 $slideshow_options = [];
Chris@5 131 foreach ($types as $id => $definition) {
Chris@5 132 $slideshow_options[$id] = $definition['label'];
Chris@5 133 }
Chris@5 134
Chris@5 135 $form['slideshow_type'] = [
Chris@5 136 '#type' => 'select',
Chris@5 137 '#title' => $this->t('Slideshow Type'),
Chris@5 138 '#options' => $slideshow_options,
Chris@5 139 '#default_value' => $this->options['slideshow_type'],
Chris@5 140 ];
Chris@5 141
Chris@5 142 // @todo: check if default values are properly passed to the buildConfigurationForm().
Chris@5 143 foreach ($types as $id => $definition) {
Chris@5 144 $configuration = [];
Chris@5 145 if (!empty($this->options[$id])) {
Chris@5 146 $configuration = $this->options[$id];
Chris@5 147 }
Chris@5 148 $instance = $typeManager->createInstance($id, $configuration);
Chris@5 149
Chris@5 150 $form[$id] = [
Chris@5 151 '#type' => 'fieldset',
Chris@5 152 '#title' => $this->t('@module options', ['@module' => $definition['label']]),
Chris@5 153 '#collapsible' => TRUE,
Chris@5 154 '#attributes' => ['class' => [$id]],
Chris@5 155 '#states' => [
Chris@5 156 'visible' => [
Chris@5 157 ':input[name="style_options[slideshow_type]"]' => ['value' => $id],
Chris@5 158 ],
Chris@5 159 ],
Chris@5 160 ];
Chris@5 161
Chris@5 162 $form = $instance->buildConfigurationForm($form, $form_state);
Chris@5 163 }
Chris@5 164 }
Chris@5 165 else {
Chris@5 166 $form['enable_module'] = [
Chris@5 167 '#markup' => $this->t('There is no Views Slideshow plugin enabled. Go to the @modules and enable a Views Slideshow plugin module. For example Views Slideshow Cycle.', ['@modules' => Link::fromTextAndUrl($this->t('Modules Page'), Url::fromRoute('system.modules_list'))->toString()]),
Chris@5 168 ];
Chris@5 169 }
Chris@5 170
Chris@5 171 // Widgets.
Chris@5 172 // @todo: Improve the UX by using Ajax.
Chris@5 173 $form['widgets_header'] = [
Chris@5 174 '#markup' => '<h2>' . $this->t('Widgets') . '</h2>',
Chris@5 175 ];
Chris@5 176
Chris@5 177 // Define the available locations.
Chris@5 178 $location = ['top' => $this->t('Top'), 'bottom' => $this->t('Bottom')];
Chris@5 179
Chris@5 180 // Loop through all locations so we can add header for each location.
Chris@5 181 foreach ($location as $location_id => $location_name) {
Chris@5 182 $form['widgets'][$location_id]['header'] = [
Chris@5 183 '#markup' => '<h3>' . $this->t('@location Widgets', ['@location' => $location_name]) . '</h3>',
Chris@5 184 ];
Chris@5 185 }
Chris@5 186
Chris@5 187 /* @var \Drupal\Component\Plugin\PluginManagerInterface */
Chris@5 188 $widgetTypeManager = \Drupal::service('plugin.manager.views_slideshow.widget_type');
Chris@5 189
Chris@5 190 // Get all widgets types that are registered.
Chris@5 191 $widgets = $widgetTypeManager->getDefinitions();
Chris@5 192 if (!empty($widgets)) {
Chris@5 193
Chris@5 194 // Build our weight values by number of widgets.
Chris@5 195 $weights = [];
Chris@5 196 for ($i = 1; $i <= count($widgets); $i++) {
Chris@5 197 $weights[$i] = $i;
Chris@5 198 }
Chris@5 199
Chris@5 200 // Loop through our widgets and locations to build our form values for
Chris@5 201 // each widget.
Chris@5 202 foreach ($widgets as $widget_id => $widget_info) {
Chris@5 203
Chris@5 204 // Determine if this widget type is compatible with any slideshow type.
Chris@5 205 $compatible_slideshows = [];
Chris@5 206 foreach ($types as $slideshow_id => $slideshow_info) {
Chris@5 207 if ($widgetTypeManager->createInstance($widget_id, [])->checkCompatiblity($slideshow_info)) {
Chris@5 208 $compatible_slideshows[] = $slideshow_id;
Chris@5 209 }
Chris@5 210 }
Chris@5 211
Chris@5 212 // Display the widget config form only if the widget type is compatible
Chris@5 213 // with at least one slideshow type.
Chris@5 214 if (!empty($compatible_slideshows)) {
Chris@5 215 foreach ($location as $location_id => $location_name) {
Chris@5 216 // Use Widget Checkbox.
Chris@5 217 $form['widgets'][$location_id][$widget_id]['enable'] = [
Chris@5 218 '#type' => 'checkbox',
Chris@5 219 '#title' => $widget_info['label'],
Chris@5 220 '#default_value' => $this->options['widgets'][$location_id][$widget_id]['enable'],
Chris@5 221 '#description' => $this->t('Should @name be rendered at the @location of the slides.', ['@name' => $widget_info['label'], '@location' => $location_name]),
Chris@5 222 '#dependency' => [
Chris@5 223 'edit-style-options-slideshow-type' => $compatible_slideshows,
Chris@5 224 ],
Chris@5 225 ];
Chris@5 226
Chris@5 227 // Need to wrap this so it indents correctly.
Chris@5 228 $form['widgets'][$location_id][$widget_id]['wrapper'] = [
Chris@5 229 '#markup' => '<div class="vs-dependent">',
Chris@5 230 ];
Chris@5 231
Chris@5 232 // Widget weight.
Chris@5 233 // We check to see if the default value is greater than the number
Chris@5 234 // of widgets just in case a widget has been removed and the form
Chris@5 235 // hasn't been saved again.
Chris@5 236 $weight = (isset($this->options['widgets'][$location_id][$widget_id]['weight'])) ? $this->options['widgets'][$location_id][$widget_id]['weight'] : 0;
Chris@5 237 if ($weight > count($widgets)) {
Chris@5 238 $weight = count($widgets);
Chris@5 239 }
Chris@5 240 $form['widgets'][$location_id][$widget_id]['weight'] = [
Chris@5 241 '#type' => 'select',
Chris@5 242 '#title' => $this->t('Weight of the @name', ['@name' => $widget_info['label']]),
Chris@5 243 '#default_value' => $weight,
Chris@5 244 '#options' => $weights,
Chris@5 245 '#description' => $this->t('Determines in what order the @name appears. A lower weight will cause the @name to be above higher weight items.', ['@name' => $widget_info['label']]),
Chris@5 246 '#prefix' => '<div class="vs-dependent">',
Chris@5 247 '#suffix' => '</div>',
Chris@5 248 '#states' => [
Chris@5 249 'visible' => [
Chris@5 250 ':input[name="style_options[widgets][' . $location_id . '][' . $widget_id . '][enable]"]' => ['checked' => TRUE],
Chris@5 251 ],
Chris@5 252 ],
Chris@5 253 ];
Chris@5 254
Chris@5 255 // Build the appropriate array for the states API.
Chris@5 256 $widget_dependency = 'style_options[widgets][' . $location_id . '][' . $widget_id . ']';
Chris@5 257
Chris@5 258 // Get the current configuration of this widget type.
Chris@5 259 $configuration = [];
Chris@5 260 if (!empty($this->options['widgets'][$location_id][$widget_id])) {
Chris@5 261 $configuration = $this->options['widgets'][$location_id][$widget_id];
Chris@5 262 }
Chris@5 263 $configuration['dependency'] = $widget_dependency;
Chris@5 264 $instance = $widgetTypeManager->createInstance($widget_id, $configuration);
Chris@5 265
Chris@5 266 // Get the configuration form of this widget type.
Chris@5 267 $form['widgets'][$location_id][$widget_id] = $instance->buildConfigurationForm($form['widgets'][$location_id][$widget_id], $form_state);
Chris@5 268
Chris@5 269 // Close the vs-dependent wrapper.
Chris@5 270 $form['widgets'][$location_id][$widget_id]['wrapper_close'] = [
Chris@5 271 '#markup' => '</div>',
Chris@5 272 ];
Chris@5 273 }
Chris@5 274 }
Chris@5 275 }
Chris@5 276 }
Chris@5 277
Chris@5 278 // Browse locations and remove the header if no widget is available.
Chris@5 279 foreach ($location as $location_id => $location_name) {
Chris@5 280 // If no widget is available, the only key is "header".
Chris@5 281 if (count(array_keys($form['widgets'][$location_id])) == 1) {
Chris@5 282 unset($form['widgets'][$location_id]);
Chris@5 283 }
Chris@5 284 }
Chris@5 285
Chris@5 286 // Remove the widget section header if there is no widget available.
Chris@5 287 if (empty($form['widgets'])) {
Chris@5 288 unset($form['widgets']);
Chris@5 289 unset($form['widgets_header']);
Chris@5 290 }
Chris@5 291
Chris@5 292 $form['views_slideshow_wrapper_close'] = [
Chris@5 293 '#markup' => '</div>',
Chris@5 294 ];
Chris@5 295
Chris@5 296 // Add a library to style the form.
Chris@5 297 $form['#attached']['library'] = ['views_slideshow/form'];
Chris@5 298 }
Chris@5 299
Chris@5 300 /**
Chris@5 301 * {@inheritdoc}
Chris@5 302 */
Chris@5 303 public function validateOptionsForm(&$form, FormStateInterface $form_state) {
Chris@5 304 // Validate all slideshow type plugins values.
Chris@5 305 $typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
Chris@5 306 foreach ($typeManager->getDefinitions() as $id => $definition) {
Chris@5 307 $type = $typeManager->createInstance($id);
Chris@5 308 $type->validateConfigurationForm($form, $form_state);
Chris@5 309 }
Chris@5 310 }
Chris@5 311
Chris@5 312 /**
Chris@5 313 * {@inheritdoc}
Chris@5 314 */
Chris@5 315 public function submitOptionsForm(&$form, FormStateInterface $form_state) {
Chris@5 316 // Submit all slideshow type plugins values.
Chris@5 317 $typeManager = \Drupal::service('plugin.manager.views_slideshow.slideshow_type');
Chris@5 318 foreach ($typeManager->getDefinitions() as $id => $definition) {
Chris@5 319 $type = $typeManager->createInstance($id);
Chris@5 320 $type->submitConfigurationForm($form, $form_state);
Chris@5 321 }
Chris@5 322 }
Chris@5 323
Chris@5 324 }