GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

PanelizerThumbnailFormatter::getFileFromEntity()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Drupal\df_tools_panelizer\Plugin\Field\FieldFormatter;
4
5
use Drupal\block_content\Plugin\Block\BlockContentBlock;
6
use Drupal\Core\Entity\EntityRepositoryInterface;
7
use Drupal\Core\Entity\EntityStorageInterface;
8
use Drupal\Core\Entity\FieldableEntityInterface;
9
use Drupal\Core\Field\EntityReferenceFieldItemList;
10
use Drupal\Core\Field\FieldDefinitionInterface;
11
use Drupal\Core\Field\FieldItemListInterface;
12
use Drupal\Core\Field\FormatterBase;
13
use Drupal\Core\Form\FormStateInterface;
14
use Drupal\Core\Image\ImageFactory;
15
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
16
use Drupal\ctools_block\Plugin\Block\EntityField;
17
use Drupal\file\FileInterface;
18
use Drupal\media\MediaInterface;
19
use Drupal\panelizer\PanelizerInterface;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
22
/**
23
 * Renders a thumbnail based on a given Panelizer field.
24
 *
25
 * @FieldFormatter(
26
 *   id = "panelizer_thumbnail",
27
 *   label = @Translation("Panelizer Thumbnail"),
28
 *   field_types = {
29
 *     "panelizer"
30
 *   }
31
 * )
32
 */
33
class PanelizerThumbnailFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
34
35
  /**
36
   * How deep this formatter should look for a file.
37
   *
38
   * @var int
39
   */
40
  const DEPTH_LIMIT = 5;
41
42
  /**
43
   * @var \Drupal\Core\Entity\EntityStorageInterface
44
   */
45
  protected $responsiveImageStyleStorage;
46
47
  /**
48
   * @var \Drupal\panelizer\PanelizerInterface
49
   */
50
  protected $panelizer;
51
52
  /**
53
   * @var \Drupal\Core\Image\ImageFactory
54
   */
55
  protected $imageFactory;
56
57
  /**
58
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
59
   */
60
  protected $entityRepository;
61
62
  /**
63
   * Constructs a PanelizerThumbnailFormatter object.
64
   *
65
   * @param string $plugin_id
66
   *   The plugin_id for the formatter.
67
   * @param mixed $plugin_definition
68
   *   The plugin implementation definition.
69
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
70
   *   The definition of the field to which the formatter is associated.
71
   * @param array $settings
72
   *   The formatter settings.
73
   * @param string $label
74
   *   The formatter label display setting.
75
   * @param string $view_mode
76
   *   The view mode.
77
   * @param array $third_party_settings
78
   *   Any third party settings.
79
   * @param \Drupal\Core\Entity\EntityStorageInterface $responsive_image_style_storage
80
   *   The responsive image style storage.
81
   * @param \Drupal\panelizer\PanelizerInterface $panelizer
82
   *   The panelizer service.
83
   */
84
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, EntityStorageInterface $responsive_image_style_storage, PanelizerInterface $panelizer, ImageFactory $image_factory, EntityRepositoryInterface $entity_repository) {
85
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
86
87
    $this->responsiveImageStyleStorage = $responsive_image_style_storage;
88
    $this->panelizer = $panelizer;
89
    $this->imageFactory = $image_factory;
90
    $this->entityRepository = $entity_repository;
91
  }
92
93
  /**
94
   * {@inheritdoc}
95
   */
96
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
97
    return new static(
98
      $plugin_id,
99
      $plugin_definition,
100
      $configuration['field_definition'],
101
      $configuration['settings'],
102
      $configuration['label'],
103
      $configuration['view_mode'],
104
      $configuration['third_party_settings'],
105
      $container->get('entity.manager')->getStorage('responsive_image_style'),
106
      $container->get('panelizer'),
0 ignored issues
show
Bug introduced by
It seems like $container->get('panelizer') can also be of type null; however, parameter $panelizer of Drupal\df_tools_panelize...ormatter::__construct() does only seem to accept Drupal\panelizer\PanelizerInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
      /** @scrutinizer ignore-type */ $container->get('panelizer'),
Loading history...
107
      $container->get('image.factory'),
0 ignored issues
show
Bug introduced by
It seems like $container->get('image.factory') can also be of type null; however, parameter $image_factory of Drupal\df_tools_panelize...ormatter::__construct() does only seem to accept Drupal\Core\Image\ImageFactory, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

107
      /** @scrutinizer ignore-type */ $container->get('image.factory'),
Loading history...
108
      $container->get('entity.repository')
0 ignored issues
show
Bug introduced by
It seems like $container->get('entity.repository') can also be of type null; however, parameter $entity_repository of Drupal\df_tools_panelize...ormatter::__construct() does only seem to accept Drupal\Core\Entity\EntityRepositoryInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

108
      /** @scrutinizer ignore-type */ $container->get('entity.repository')
Loading history...
109
    );
110
  }
111
112
  /**
113
   * {@inheritdoc}
114
   */
115
  public static function defaultSettings() {
116
    return [
117
        'responsive_image_style' => '',
118
        'image_link' => FALSE,
119
      ] + parent::defaultSettings();
120
  }
121
122
  /**
123
   * {@inheritdoc}
124
   */
125
  public function settingsSummary() {
126
    $summary = [];
127
128
    $responsive_image_style = $this->responsiveImageStyleStorage->load($this->getSetting('responsive_image_style'));
129
    if ($responsive_image_style) {
130
      $summary[] = $this->t('Responsive image style: @responsive_image_style', ['@responsive_image_style' => $responsive_image_style->label()]);
131
132
      if ($this->getSetting('image_link')) {
133
        $summary[] = $this->t('Thumbnail is linked to entity');
134
      }
135
    }
136
    else {
137
      $summary[] = $this->t('Please select a responsive image style.');
138
    }
139
140
    return $summary;
141
  }
142
143
  /**
144
   * {@inheritdoc}
145
   */
146
  public function settingsForm(array $form, FormStateInterface $form_state) {
147
    $responsive_image_options = [];
148
    $responsive_image_styles = $this->responsiveImageStyleStorage->loadMultiple();
149
    if ($responsive_image_styles && !empty($responsive_image_styles)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $responsive_image_styles of type Drupal\Core\Entity\EntityInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
150
      foreach ($responsive_image_styles as $machine_name => $responsive_image_style) {
151
        if ($responsive_image_style->hasImageStyleMappings()) {
0 ignored issues
show
Bug introduced by
The method hasImageStyleMappings() does not exist on Drupal\Core\Entity\EntityInterface. It seems like you code against a sub-type of Drupal\Core\Entity\EntityInterface such as Drupal\responsive_image\...ty\ResponsiveImageStyle or Drupal\responsive_image\...siveImageStyleInterface or Drupal\views_ui\ViewUI or Drupal\responsive_image\...ty\ResponsiveImageStyle or Drupal\responsive_image\...siveImageStyleInterface or Drupal\views_ui\ViewUI or Drupal\responsive_image\...ty\ResponsiveImageStyle. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
        if ($responsive_image_style->/** @scrutinizer ignore-call */ hasImageStyleMappings()) {
Loading history...
152
          $responsive_image_options[$machine_name] = $responsive_image_style->label();
153
        }
154
      }
155
    }
156
157
    $elements['responsive_image_style'] = [
0 ignored issues
show
Comprehensibility Best Practice introduced by
$elements was never initialized. Although not strictly required by PHP, it is generally a good practice to add $elements = array(); before regardless.
Loading history...
158
      '#title' => $this->t('Responsive image style'),
159
      '#type' => 'select',
160
      '#default_value' => $this->getSetting('responsive_image_style'),
161
      '#required' => TRUE,
162
      '#options' => $responsive_image_options,
163
    ];
164
165
    $elements['image_link'] = [
166
      '#title' => $this->t('Link image to content'),
167
      '#type' => 'checkbox',
168
      '#default_value' => $this->getSetting('image_link'),
169
    ];
170
171
    return $elements;
172
  }
173
174
  /**
175
   * {@inheritdoc}
176
   */
177
  public function viewElements(FieldItemListInterface $items, $langcode) {
178
    $elements = [];
179
180
    $entity = $items->getEntity();
181
    if ($file = $this->getFileFromPanelizedEntity($entity)) {
182
      if (($image = $this->imageFactory->get($file->getFileUri())) && $image->isValid()) {
183
        $item = new \stdClass();
184
        $item->width = $image->getWidth();
185
        $item->height = $image->getHeight();
186
        $item->alt = '';
187
        $item->title = $file->getFilename();
188
        $item->entity = $file;
189
190
        $url = NULL;
191
        if ($this->getSetting('image_link')) {
192
          $entity = $items->getEntity();
193
          if (!$entity->isNew()) {
194
            $url = $entity->toUrl();
195
          }
196
        }
197
198
        $elements = [
199
          '#theme' => 'responsive_image_formatter',
200
          '#item' => $item,
201
          '#responsive_image_style_id' => $this->getSetting('responsive_image_style'),
202
          '#url' => $url,
203
        ];
204
      }
205
    }
206
207
    return $elements;
208
  }
209
210
  /**
211
   * Finds the first file from a given Panelized entity.
212
   *
213
   * @param \Drupal\Core\Entity\EntityInterface|FieldableEntityInterface $entity
214
   *   A Panelized entity.
215
   * @return \Drupal\file\FileInterface|bool
216
   *   The first file displayed in a given display, or FALSE if none was found.
217
   */
218
  protected function getFileFromPanelizedEntity($entity) {
219
    if ($display = $this->panelizer->getPanelsDisplay($entity, 'full')) {
220
      $regions = $display->getRegionAssignments();
221
      foreach ($regions as $region => $blocks) {
222
        foreach ($blocks as $block) {
223
          if ($block instanceof BlockContentBlock) {
224
            $uuid = $block->getDerivativeId();
225
            /** @var \Drupal\block_content\BlockContentInterface $block_content */
226
            $block_content = $this->entityRepository->loadEntityByUuid('block_content', $uuid);
227
            if ($file = $this->getFileFromEntity($block_content)) {
228
              return $file;
229
            }
230
          }
231
          else if ($block instanceof EntityField) {
232
            list (, $field_name) = explode(':', $block->getDerivativeId());
233
            if ($entity->hasField($field_name) && $field = $entity->get($field_name)) {
0 ignored issues
show
Bug introduced by
The method get() does not exist on Drupal\Core\Entity\EntityInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Drupal\Core\Entity\EntityChangedInterface or Drupal\Core\Entity\RevisionableInterface or Drupal\Core\Entity\EntityBase or Drupal\Core\Entity\EntityPublishedInterface or Drupal\Core\Entity\TranslatableInterface or Drupal\Core\Entity\SynchronizableInterface or Drupal\Tests\Core\Entity...rageTestEntityInterface or Drupal\Core\Entity\EntityDescriptionInterface or Drupal\Core\Entity\Entit...uginCollectionInterface or Drupal\Core\Entity\RevisionLogInterface or Drupal\Core\Entity\Trans...leRevisionableInterface or Drupal\Tests\Core\Entity\RevisionableEntity or Drupal\Core\Entity\Entity or Drupal\Tests\Core\Entity\SimpleTestEntity or Drupal\Tests\content_mod...n\Unit\SimpleTestEntity or Drupal\Tests\Core\Entity\RevisionableEntity or Drupal\Core\Entity\Trans...leRevisionableInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

233
            if ($entity->hasField($field_name) && $field = $entity->/** @scrutinizer ignore-call */ get($field_name)) {
Loading history...
Bug introduced by
The method hasField() does not exist on Drupal\Core\Entity\EntityInterface. It seems like you code against a sub-type of Drupal\Core\Entity\EntityInterface such as Drupal\Core\Entity\FieldableEntityInterface or Drupal\Core\Entity\EditorialContentEntityBase or Drupal\fontyourface\FontInterface or Drupal\media\MediaInterface or Drupal\simple_oauth\Entity\Oauth2TokenInterface or Drupal\block_content\BlockContentInterface or Drupal\user\UserInterface or Drupal\menu_link_content\MenuLinkContentInterface or Drupal\taxonomy\TermInterface or Drupal\entity_test\Entity\EntityTestConstraints or Drupal\basic_data\Entity\BasicDataInterface or Drupal\file\FileInterface or Drupal\entity_gallery\EntityGalleryInterface or Drupal\moderation_note\ModerationNoteInterface or Drupal\workspaces\WorkspaceInterface or Drupal\entity_test\Entity\EntityTestMulChanged or Drupal\node\NodeInterface or Drupal\comment\CommentInterface or Drupal\Core\Entity\EditorialContentEntityBase or Drupal\media\MediaInterface or Drupal\block_content\BlockContentInterface or Drupal\menu_link_content\MenuLinkContentInterface or Drupal\Core\Entity\RevisionableContentEntityBase or Drupal\taxonomy\TermInterface or Drupal\entity_gallery\EntityGalleryInterface or Drupal\entity_test\Entit...vChangedWithRevisionLog or Drupal\node\NodeInterface or Drupal\Core\Entity\ContentEntityInterface or Drupal\Core\Entity\ContentEntityBase or Drupal\Core\Entity\EditorialContentEntityBase or Drupal\entity_test\Entity\EntityTestMulRevPub or Drupal\media\MediaInterface or Drupal\block_content\BlockContentInterface or Drupal\menu_link_content\MenuLinkContentInterface or Drupal\taxonomy\TermInterface or Drupal\moderation_note\ModerationNoteInterface or Drupal\node\NodeInterface or Drupal\comment\CommentInterface or Drupal\Core\Entity\ContentEntityInterface or Drupal\Core\Entity\ContentEntityInterface or Drupal\views_ui\ViewUI or Drupal\views_ui\ViewUI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

233
            if ($entity->/** @scrutinizer ignore-call */ hasField($field_name) && $field = $entity->get($field_name)) {
Loading history...
234
              if ($file = $this->getFileFromField($field)) {
235
                return $file;
236
              }
237
            }
238
          }
239
        }
240
      }
241
    }
242
243
    return FALSE;
244
  }
245
246
  /**
247
   * Gets the first file present in a given entity.
248
   *
249
   * @param \Drupal\Core\Entity\EntityInterface|FieldableEntityInterface $entity
250
   *   The entity you want to find a file for.
251
   * @return \Drupal\file\FileInterface|bool
252
   *   The first file found for a given entity, or FALSE
253
   */
254
  protected function getFileFromEntity(FieldableEntityInterface $entity) {
255
    foreach ($entity->getFields() as $field) {
256
      if ($file = $this->getFileFromField($field)) {
257
        return $file;
258
      }
259
    }
260
261
    return FALSE;
262
  }
263
264
  /**
265
   * Gets the first file from a given field.
266
   *
267
   * If the field is a Media reference, recursion is used to find nested
268
   * file fields.
269
   *
270
   * @param \Drupal\Core\Field\FieldItemListInterface $field
271
   * @return \Drupal\file\FileInterface|bool
272
   */
273
  protected function getFileFromField(FieldItemListInterface $field) {
274
    static $depth = 0;
275
    $depth++;
276
277
    $return = FALSE;
278
279
    if ($field instanceof EntityReferenceFieldItemList) {
280
      $referenced_entities = $field->referencedEntities();
281
      $referenced_entity = reset($referenced_entities);
282
      if ($referenced_entity instanceof FileInterface) {
283
        $return = $referenced_entity;
284
      }
285
      else if ($referenced_entity instanceof MediaInterface) {
286
        if ($depth < self::DEPTH_LIMIT && $file = $this->getFileFromEntity($referenced_entity)) {
287
          $return =  $file;
288
        }
289
      }
290
    }
291
292
    $depth--;
293
    return $return;
294
  }
295
296
}
297