Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 36 | * ) |
||
| 37 | */ |
||
| 38 | class IFrame extends DisplayBase implements DisplayRouterInterface { |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Current route match service. |
||
| 42 | * |
||
| 43 | * @var \Drupal\Core\Routing\RouteMatchInterface |
||
| 44 | */ |
||
| 45 | protected $currentRouteMatch; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * UUID generator interface. |
||
| 49 | * |
||
| 50 | * @var \Drupal\Component\Uuid\UuidInterface |
||
| 51 | */ |
||
| 52 | protected $uuidGenerator; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * UIID string. |
||
| 56 | * |
||
| 57 | * @var string |
||
| 58 | */ |
||
| 59 | protected $uuid = NULL; |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Current path. |
||
| 63 | * |
||
| 64 | * @var \Drupal\Core\Path\CurrentPathStack |
||
| 65 | */ |
||
| 66 | protected $currentPath; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * Current request. |
||
| 70 | * |
||
| 71 | * @var \Symfony\Component\HttpFoundation\Request |
||
| 72 | */ |
||
| 73 | protected $request; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * Constructs display plugin. |
||
| 77 | * |
||
| 78 | * @param array $configuration |
||
| 79 | * A configuration array containing information about the plugin instance. |
||
| 80 | * @param string $plugin_id |
||
| 81 | * The plugin_id for the plugin instance. |
||
| 82 | * @param mixed $plugin_definition |
||
| 83 | * The plugin implementation definition. |
||
| 84 | * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher |
||
| 85 | * Event dispatcher service. |
||
| 86 | * @param \Drupal\Core\Routing\RouteMatchInterface |
||
| 87 | * The currently active route match object. |
||
| 88 | * @param \Drupal\Component\Uuid\UuidInterface |
||
| 89 | * UUID generator interface. |
||
| 90 | * @param \Drupal\Core\Path\CurrentPathStack $current_path |
||
| 91 | * The current path. |
||
| 92 | */ |
||
| 93 | public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $event_dispatcher, RouteMatchInterface $current_route_match, UuidInterface $uuid, Request $request, CurrentPathStack $current_path) { |
||
| 94 | parent::__construct($configuration, $plugin_id, $plugin_definition, $event_dispatcher); |
||
| 95 | $this->currentRouteMatch = $current_route_match; |
||
| 96 | $this->uuidGenerator = $uuid; |
||
| 97 | $this->request = $request; |
||
| 98 | $this->currentPath = $current_path; |
||
| 99 | } |
||
| 100 | |||
| 101 | /** |
||
| 102 | * {@inheritdoc} |
||
| 103 | */ |
||
| 104 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
||
| 105 | return new static( |
||
| 106 | $configuration, |
||
| 107 | $plugin_id, |
||
| 108 | $plugin_definition, |
||
| 109 | $container->get('event_dispatcher'), |
||
| 110 | $container->get('current_route_match'), |
||
| 111 | $container->get('uuid'), |
||
| 112 | $container->get('request_stack')->getCurrentRequest(), |
||
| 113 | $container->get('path.current') |
||
| 114 | ); |
||
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * {@inheritdoc} |
||
| 119 | */ |
||
| 120 | public function defaultConfiguration() { |
||
| 121 | return array( |
||
| 122 | 'width' => '650', |
||
| 123 | 'height' => '500', |
||
| 124 | 'link_text' => t('Select entities'), |
||
| 125 | 'auto_open' => FALSE, |
||
| 126 | ) + parent::defaultConfiguration(); |
||
| 127 | } |
||
| 128 | |||
| 129 | /** |
||
| 130 | * {@inheritdoc} |
||
| 131 | */ |
||
| 132 | public function displayEntityBrowser(FormStateInterface $form_state) { |
||
| 133 | $uuid = $this->getUuid(); |
||
| 134 | /** @var \Drupal\entity_browser\Events\RegisterJSCallbacks $event */ |
||
| 135 | // TODO - $uuid is unused in this event but we need to pass it as |
||
| 136 | // constructor expects it. See https://www.drupal.org/node/2600706 for more |
||
| 137 | // info. |
||
| 138 | $js_event_object = new RegisterJSCallbacks($this->configuration['entity_browser_id'], $uuid); |
||
| 139 | $js_event_object->registerCallback('Drupal.entityBrowser.selectionCompleted'); |
||
| 140 | $callback_event = $this->eventDispatcher->dispatch(Events::REGISTER_JS_CALLBACKS, $js_event_object); |
||
| 141 | $original_path = $this->currentPath->getPath(); |
||
| 142 | $data = [ |
||
| 143 | 'query_parameters' => [ |
||
| 144 | 'query' => [ |
||
| 145 | 'uuid' => $uuid, |
||
| 146 | 'original_path' => $original_path, |
||
| 147 | ], |
||
| 148 | ], |
||
| 149 | 'attributes' => [ |
||
| 150 | 'href' => '#browser', |
||
| 151 | 'class' => ['entity-browser-handle', 'entity-browser-iframe'], |
||
| 152 | 'data-uuid' => $uuid, |
||
| 153 | 'data-original-path' => $original_path, |
||
| 154 | ], |
||
| 155 | ]; |
||
| 156 | $event_object = new AlterEntityBrowserDisplayData($this->configuration['entity_browser_id'], $uuid, $this->getPluginDefinition(), $form_state, $data); |
||
| 157 | $event = $this->eventDispatcher->dispatch(Events::ALTER_BROWSER_DISPLAY_DATA, $event_object); |
||
| 158 | $data = $event->getData(); |
||
| 159 | return [ |
||
| 160 | '#theme_wrappers' => ['container'], |
||
| 161 | 'link' => [ |
||
| 162 | '#type' => 'html_tag', |
||
| 163 | '#tag' => 'a', |
||
| 164 | '#value' => $this->configuration['link_text'], |
||
| 165 | '#attributes' => $data['attributes'], |
||
| 166 | '#attached' => [ |
||
| 167 | 'library' => ['entity_browser/iframe'], |
||
| 168 | 'drupalSettings' => [ |
||
| 169 | 'entity_browser' => [ |
||
| 170 | 'iframe' => [ |
||
| 171 | $uuid => [ |
||
| 172 | 'src' => Url::fromRoute('entity_browser.' . $this->configuration['entity_browser_id'], [], $data['query_parameters']) |
||
| 173 | ->toString(), |
||
| 174 | 'width' => $this->configuration['width'], |
||
| 175 | 'height' => $this->configuration['height'], |
||
| 176 | 'js_callbacks' => $callback_event->getCallbacks(), |
||
| 177 | 'entity_browser_id' => $this->configuration['entity_browser_id'], |
||
| 178 | 'auto_open' => $this->configuration['auto_open'], |
||
| 179 | ], |
||
| 180 | ], |
||
| 181 | ], |
||
| 182 | ] |
||
| 183 | ], |
||
| 184 | ], |
||
| 185 | ]; |
||
| 186 | } |
||
| 187 | |||
| 188 | /** |
||
| 189 | * {@inheritdoc} |
||
| 190 | */ |
||
| 191 | public function selectionCompleted(array $entities) { |
||
| 192 | $this->entities = $entities; |
||
| 193 | $this->eventDispatcher->addListener(KernelEvents::RESPONSE, [$this, 'propagateSelection']); |
||
| 194 | } |
||
| 195 | |||
| 196 | /** |
||
| 197 | * KernelEvents::RESPONSE listener. Intercepts default response and injects |
||
| 198 | * response that will trigger JS to propagate selected entities upstream. |
||
| 199 | * |
||
| 200 | * @param FilterResponseEvent $event |
||
| 201 | * Response event. |
||
| 202 | */ |
||
| 203 | public function propagateSelection(FilterResponseEvent $event) { |
||
| 204 | $render = [ |
||
| 205 | 'labels' => [ |
||
| 206 | '#markup' => 'Labels: ' . implode(', ', array_map(function (EntityInterface $item) {return $item->label();}, $this->entities)), |
||
| 207 | '#attached' => [ |
||
| 208 | 'library' => ['entity_browser/iframe_selection'], |
||
| 209 | 'drupalSettings' => [ |
||
| 210 | 'entity_browser' => [ |
||
| 211 | 'iframe' => [ |
||
| 212 | 'entities' => array_map(function (EntityInterface $item) {return [$item->id(), $item->uuid(), $item->getEntityTypeId()];}, $this->entities), |
||
| 213 | 'uuid' => $this->request->query->get('uuid'), |
||
| 214 | ], |
||
| 215 | ], |
||
| 216 | ], |
||
| 217 | ], |
||
| 218 | ], |
||
| 219 | ]; |
||
| 220 | |||
| 221 | $event->setResponse(new Response(\Drupal::service('bare_html_page_renderer')->renderBarePage($render, 'Entity browser', 'page'))); |
||
| 222 | } |
||
| 223 | |||
| 224 | /** |
||
| 225 | * {@inheritdoc} |
||
| 226 | */ |
||
| 227 | public function getUuid() { |
||
| 228 | if (empty($this->uuid)) { |
||
| 229 | $this->uuid = $this->uuidGenerator->generate(); |
||
| 230 | } |
||
| 231 | return $this->uuid; |
||
| 232 | } |
||
| 233 | |||
| 234 | /** |
||
| 235 | * {@inheritdoc} |
||
| 236 | */ |
||
| 237 | public function setUuid($uuid) { |
||
| 238 | $this->uuid = $uuid; |
||
| 239 | } |
||
| 240 | |||
| 241 | /** |
||
| 242 | * {@inheritdoc} |
||
| 243 | */ |
||
| 244 | public function path() { |
||
| 245 | return '/entity-browser/iframe/' . $this->configuration['entity_browser_id']; |
||
| 246 | } |
||
| 247 | |||
| 248 | /** |
||
| 249 | * {@inheritdoc} |
||
| 250 | */ |
||
| 251 | public function buildConfigurationForm(array $form, FormStateInterface $form_state) { |
||
| 252 | $configuration = $this->getConfiguration(); |
||
| 253 | $form['width'] = [ |
||
| 254 | '#type' => 'number', |
||
| 255 | '#title' => $this->t('Width of the iFrame'), |
||
| 256 | '#min' => 1, |
||
| 257 | '#default_value' => $configuration['width'], |
||
| 258 | ]; |
||
| 259 | |||
| 260 | $form['height'] = [ |
||
| 261 | '#type' => 'number', |
||
| 262 | '#title' => $this->t('Height of the iFrame'), |
||
| 263 | '#min' => 1, |
||
| 264 | '#default_value' => $configuration['height'], |
||
| 265 | ]; |
||
| 266 | |||
| 267 | $form['link_text'] = [ |
||
| 268 | '#type' => 'textfield', |
||
| 269 | '#title' => $this->t('Link text'), |
||
| 270 | '#default_value' => $configuration['link_text'], |
||
| 271 | ]; |
||
| 272 | |||
| 273 | $form['auto_open'] = [ |
||
| 274 | '#type' => 'checkbox', |
||
| 275 | '#title' => $this->t('Auto open entity browser'), |
||
| 276 | '#default_value' => $configuration['auto_open'], |
||
| 277 | ]; |
||
| 278 | |||
| 279 | return $form; |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * {@inheritdoc} |
||
| 284 | */ |
||
| 285 | public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { |
||
| 295 |