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 |
||
29 | class ImageFieldFormatter extends FileFieldFormatter { |
||
30 | |||
31 | /** |
||
32 | * The image factory. |
||
33 | * |
||
34 | * @var \Drupal\Core\Image\ImageFactory |
||
35 | */ |
||
36 | protected $imageFactory; |
||
37 | |||
38 | /** |
||
39 | * {@inheritdoc} |
||
40 | * |
||
41 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager |
||
42 | * The entity manager service. |
||
43 | * @param \Drupal\Core\Field\FormatterPluginManager $formatter_plugin_manager |
||
44 | * The field formatter plugin manager. |
||
45 | * @param \Drupal\Core\TypedData\TypedDataManager $typed_data_manager |
||
46 | * The typed data manager. |
||
47 | * @param \Drupal\Core\Image\ImageFactory $image_factory |
||
48 | * The image factory. |
||
49 | * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager |
||
50 | * The language manager. |
||
51 | */ |
||
52 | public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, FormatterPluginManager $formatter_plugin_manager, TypedDataManager $typed_data_manager, ImageFactory $image_factory, LanguageManagerInterface $language_manager) { |
||
53 | parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $formatter_plugin_manager, $typed_data_manager, $language_manager); |
||
54 | $this->imageFactory = $image_factory; |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * {@inheritdoc} |
||
59 | */ |
||
60 | View Code Duplication | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { |
|
|
|||
61 | return new static( |
||
62 | $configuration, |
||
63 | $plugin_id, |
||
64 | $plugin_definition, |
||
65 | $container->get('entity_type.manager'), |
||
66 | $container->get('plugin.manager.field.formatter'), |
||
67 | $container->get('typed_data_manager'), |
||
68 | $container->get('image.factory'), |
||
69 | $container->get('language_manager') |
||
70 | ); |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * {@inheritdoc} |
||
75 | */ |
||
76 | public function getFieldValue() { |
||
77 | $value = parent::getFieldValue(); |
||
78 | // File field support descriptions, but images do not. |
||
79 | unset($value['description']); |
||
80 | $value += array_intersect_key($this->getAttributeValues(), array('alt' => '', 'title' => '')); |
||
81 | return $value; |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * {@inheritdoc} |
||
86 | */ |
||
87 | public function access(AccountInterface $account = NULL) { |
||
88 | return parent::access($account)->andIf($this->isValidImage()); |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Checks if the image is valid. |
||
93 | * |
||
94 | * @return \Drupal\Core\Access\AccessResult |
||
95 | * Returns the access result. |
||
96 | */ |
||
97 | protected function isValidImage() { |
||
98 | // If entity type is not file we have to return early to prevent fatal in |
||
99 | // the condition above. Access should already be forbidden at this point, |
||
100 | // which means this won't have any effect. |
||
101 | // @see EntityEmbedDisplayBase::access() |
||
102 | if ($this->getEntityTypeFromContext() != 'file') { |
||
103 | return AccessResult::forbidden(); |
||
104 | } |
||
105 | $access = AccessResult::allowed(); |
||
106 | |||
107 | // @todo needs cacheability metadata for getEntityFromContext. |
||
108 | // @see \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayBase::getEntityFromContext() |
||
109 | /** @var \Drupal\file\FileInterface $entity */ |
||
110 | if ($entity = $this->getEntityFromContext()) { |
||
111 | // Loading large files is slow, make sure it is an image mime type before |
||
112 | // doing that. |
||
113 | list($type,) = explode('/', $entity->getMimeType(), 2); |
||
114 | $access = AccessResult::allowedIf($type == 'image' && $this->imageFactory->get($entity->getFileUri())->isValid()) |
||
115 | // See the above @todo, this is the best we can do for now. |
||
116 | ->addCacheableDependency($entity); |
||
117 | } |
||
118 | |||
119 | return $access; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * {@inheritdoc} |
||
124 | */ |
||
125 | public function buildConfigurationForm(array $form, FormStateInterface $form_state) { |
||
126 | $form = parent::buildConfigurationForm($form, $form_state); |
||
127 | |||
128 | // File field support descriptions, but images do not. |
||
129 | unset($form['description']); |
||
130 | |||
131 | // Ensure that the 'Link image to: Content' setting is not available. |
||
132 | if ($this->getDerivativeId() == 'image') { |
||
133 | unset($form['image_link']['#options']['content']); |
||
134 | } |
||
135 | |||
136 | $entity_element = $form_state->get('entity_element'); |
||
137 | // The alt attribute is *required*, but we allow users to opt-in to empty |
||
138 | // alt attributes for the very rare edge cases where that is valid by |
||
139 | // specifying two double quotes as the alternative text in the dialog. |
||
140 | // However, that *is* stored as an empty alt attribute, so if we're editing |
||
141 | // an existing image (which means the src attribute is set) and its alt |
||
142 | // attribute is empty, then we show that as two double quotes in the dialog. |
||
143 | // @see https://www.drupal.org/node/2307647 |
||
144 | // Alt attribute behavior is taken from the Core image dialog to ensure a |
||
145 | // consistent UX across various forms. |
||
146 | // @see Drupal\editor\Form\EditorImageDialog::buildForm() |
||
147 | $alt = $this->getAttributeValue('alt', ''); |
||
148 | if ($alt === '') { |
||
149 | // Do not change empty alt text to two double quotes if the previously |
||
150 | // used Entity Embed Display plugin was not 'image:image'. That means that |
||
151 | // some other plugin was used so if this image formatter is selected at a |
||
152 | // later stage, then this should be treated as a new edit. We show two |
||
153 | // double quotes in place of empty alt text only if that was filled |
||
154 | // intentionally by the user. |
||
155 | if (!empty($entity_element) && $entity_element['data-entity-embed-display'] == 'image:image') { |
||
156 | $alt = '""'; |
||
157 | } |
||
158 | } |
||
159 | |||
160 | // Add support for editing the alternate and title text attributes. |
||
161 | $form['alt'] = array( |
||
162 | '#type' => 'textfield', |
||
163 | '#title' => $this->t('Alternate text'), |
||
164 | '#default_value' => $alt, |
||
165 | '#description' => $this->t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'), |
||
166 | '#parents' => array('attributes', 'alt'), |
||
167 | '#required' => TRUE, |
||
168 | '#required_error' => $this->t('Alternative text is required.<br />(Only in rare cases should this be left empty. To create empty alternative text, enter <code>""</code> — two double quotes without any content).'), |
||
169 | '#maxlength' => 512, |
||
170 | ); |
||
171 | $form['title'] = array( |
||
172 | '#type' => 'textfield', |
||
173 | '#title' => $this->t('Title'), |
||
174 | '#default_value' => $this->getAttributeValue('title', ''), |
||
175 | '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'), |
||
176 | '#parents' => array('attributes', 'title'), |
||
177 | '#maxlength' => 1024, |
||
178 | ); |
||
179 | |||
180 | return $form; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * {@inheritdoc} |
||
185 | */ |
||
186 | public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { |
||
193 | |||
194 | } |
||
195 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.