Completed
Push — 8.x-2.x ( 8fc000...ebbf75 )
by Frédéric G.
04:51 queued 01:34
created

OverviewController::overview()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 14
rs 9.4285
1
<?php
2
3
namespace Drupal\mongodb_watchdog\Controller;
4
5
use Drupal\Component\Utility\SafeMarkup;
6
use Drupal\Component\Utility\Unicode;
7
use Drupal\Core\Controller\ControllerBase;
8
use Drupal\Core\Datetime\DateFormatterInterface;
9
use Drupal\Core\Link;
10
use Drupal\Core\Logger\RfcLogLevel;
11
use Drupal\mongodb_watchdog\Event;
12
use Drupal\mongodb_watchdog\EventTemplate;
13
use Drupal\mongodb_watchdog\Form\OverviewFilterForm;
14
use Drupal\mongodb_watchdog\Logger;
15
use MongoDB\Database;
16
use Psr\Log\LoggerInterface;
17
use Psr\Log\LogLevel;
18
use Symfony\Component\DependencyInjection\ContainerInterface;
19
use Drupal\Core\Extension\ModuleHandlerInterface;
20
use Drupal\Core\Form\FormBuilderInterface;
21
22
/**
23
 * Class OverviewController provides the main MongoDB Watchdog report page.
24
 */
25
class OverviewController extends ControllerBase {
26
  const EVENT_TYPE_MAP = [
27
    'typeMap' => [
28
      'array' => 'array',
29
      'document' => 'array',
30
      'root' => 'Drupal\mongodb_watchdog\Event',
31
    ],
32
  ];
33
  const SEVERITY_PREFIX = 'mongodb_watchdog__severity_';
34
  const SEVERITY_CLASSES = [
35
    RfcLogLevel::DEBUG => self::SEVERITY_PREFIX . LogLevel::DEBUG,
36
    RfcLogLevel::INFO => self::SEVERITY_PREFIX . LogLevel::INFO,
37
    RfcLogLevel::NOTICE => self::SEVERITY_PREFIX . LogLevel::NOTICE,
38
    RfcLogLevel::WARNING => self::SEVERITY_PREFIX . LogLevel::WARNING,
39
    RfcLogLevel::ERROR => self::SEVERITY_PREFIX . LogLevel::ERROR,
40
    RfcLogLevel::CRITICAL => self::SEVERITY_PREFIX . LogLevel::CRITICAL,
41
    RfcLogLevel::ALERT => self::SEVERITY_PREFIX . LogLevel::ALERT,
42
    RfcLogLevel::EMERGENCY => self::SEVERITY_PREFIX . LogLevel::EMERGENCY,
43
  ];
44
45
  /**
46
   * The MongoDB database for the logger alias.
47
   *
48
   * @var \MongoDB\Database
49
   */
50
  protected $database;
51
52
  /**
53
   * The core date.formatter service.
54
   *
55
   * @var \Drupal\Core\Datetime\DateFormatterInterface
56
   */
57
  protected $dateFormatter;
58
59
  /**
60
   * The form builder service.
61
   *
62
   * @var \Drupal\Core\Form\FormBuilderInterface
63
   */
64
  protected $formBuilder;
65
66
  /**
67
   * The core logger channel, to log intervening events.
68
   *
69
   * @var \Psr\Log\LoggerInterface
70
   */
71
  protected $logger;
72
73
  /**
74
   * The module handler service.
75
   *
76
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
77
   */
78
  protected $moduleHandler;
79
80
  /**
81
   * The length of the disk path to DRUPAL_ROOT, plus 1.
82
   *
83
   * @var int
84
   *
85
   * @see \Drupal\mongodb_watchdog\Controller\OverviewController::getEventSource()
86
   */
87
  protected $rootLength;
88
89
  /**
90
   * The MongoDB logger, to load events.
91
   *
92
   * @var \Drupal\mongodb_watchdog\Logger
93
   */
94
  protected $watchdog;
95
96
  /**
97
   * Constructor.
98
   *
99
   * @param \MongoDB\Database $database
100
   *   The watchdog database.
101
   * @param \Psr\Log\LoggerInterface $logger
102
   *   The logger service, to log intervening events.
103
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
104
   *   The MongoDB logger, to load stored events.
105
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
106
   *   A module handler.
107
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
108
   *   The form builder service.
109
   */
110
  public function __construct(
111
    Database $database,
112
    LoggerInterface $logger,
113
    Logger $watchdog,
114
    ModuleHandlerInterface $module_handler,
115
    FormBuilderInterface $form_builder,
116
    DateFormatterInterface $date_formatter) {
117
    $this->database = $database;
118
    $this->dateFormatter = $date_formatter;
119
    $this->formBuilder = $form_builder;
120
    $this->logger = $logger;
121
    $this->moduleHandler = $module_handler;
122
    $this->watchdog = $watchdog;
123
124
    // Add terminal "/".
125
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT) + 1;
126
127
  }
128
129
  /**
130
   * {@inheritdoc}
131
   */
132
  public static function create(ContainerInterface $container) {
133
    /** @var \MongoDB\Database $database */
134
    $database = $container->get('mongodb.watchdog_storage');
135
136
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
137
    $date_formatter = $container->get('date.formatter');
138
139
    /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
140
    $form_builder = $container->get('form_builder');
141
142
    /** @var \Psr\Log\LoggerInterface $logger */
143
    $logger = $container->get('logger.channel.mongodb_watchdog');
144
145
    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
146
    $module_handler = $container->get('module_handler');
147
148
    /** @var \Drupal\mongodb_watchdog\Logger $logger */
149
    $watchdog = $container->get('mongodb.logger');
150
151
    return new static($database, $logger, $watchdog, $module_handler, $form_builder, $date_formatter);
152
  }
153
154
  /**
155
   * Build the link to the event or top report for the event template.
156
   *
157
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
158
   *   The event template for which to buildl the link.
159
   *
160
   * @return string
161
   *   An internal link in string form.
162
   */
163
  protected function getEventLink(EventTemplate $template) {
164
    switch ($template->type) {
165
      case 'page not found':
166
        $cell = Link::createFromRoute(t('( Top 404 )'), 'mongodb_watchdog.reports.top404');
167
        break;
168
169
      case 'access denied':
170
        $cell = Link::createFromRoute(t('( Top 403 )'), 'mongodb_watchdog.reports.top403');
171
        break;
172
173
      default:
174
        // Limited-length message.
175
        $message = Unicode::truncate(strip_tags(SafeMarkup::format($template->message, [])), 56, TRUE, TRUE);
176
        $cell = Link::createFromRoute($message, 'mongodb_watchdog.reports.detail', [
177
          'event_template' => $template->_id,
178
        ]);
179
        break;
180
    }
181
182
    return $cell;
183
  }
184
185
  /**
186
   * Get the location in source code where the event was logged.
187
   *
188
   * @param \Drupal\mongodb_watchdog\EventTemplate $template
189
   *   The template for which to find a source location.
190
   *
191
   * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array<string,string|array>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
192
   *   A render array for the source location, possibly empty or wrong.
193
   */
194
  protected function getEventSource(EventTemplate $template) {
195
    if (in_array($template->type, TopController::TYPES)) {
196
      return '';
197
    }
198
199
    $event_collection = $this->watchdog->eventCollection($template->_id);
200
    $event = $event_collection->findOne([], static::EVENT_TYPE_MAP);
201
    if (!($event instanceof Event)) {
202
      return '';
203
    }
204
205
    $file = $event->variables['%file'] ?? '';
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
206
    $hover = $file
207
      ? Unicode::substr($file, $this->rootLength)
208
      : '';
209
    $file = Unicode::truncate(basename($file), 30);
210
    $line = $event->variables['%line'] ?? NULL;
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
211
    $cell = [
212
      '#type' => 'html_tag',
213
      '#tag' => 'span',
214
      '#value' => "${file}#${line}",
215
      '#attributes' => [
216
        'class' => 'mongodb_watchdog__code_path',
217
        'title' => $hover,
218
      ],
219
    ];
220
221
    return $cell;
222
  }
223
224
  /**
225
   * Controller for mongodb_watchdog.overview.
226
   *
227
   * @return array
228
   *   A render array.
229
   */
230
  public function overview() {
231
    $ret = [
232
      'filter_form' => $this->formBuilder->getForm('Drupal\mongodb_watchdog\Form\OverviewFilterForm'),
233
      'rows' => $this->overviewRows(),
234
      'pager' => [
235
        '#type' => 'pager',
236
      ],
237
      '#attached' => [
238
        'library' => ['mongodb_watchdog/styling'],
239
      ],
240
    ];
241
242
    return $ret;
243
  }
244
245
  /**
246
   * Build a table from the event rows.
247
   *
248
   * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
249
   *   A render array.
250
   */
251
  public function overviewRows() {
252
    $header = [
253
      t('#'),
254
      t('Severity'),
255
      t('Type'),
256
      t('Latest'),
257
      t('Source'),
258
      t('Message'),
259
    ];
260
    $rows = [];
261
    $levels = RfcLogLevel::getLevels();
262
    $filters = $_SESSION[OverviewFilterForm::SESSION_KEY] ?? NULL;
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
263
    $cursor = $this->watchdog->templates($filters['type'] ?? [], $filters['severity'] ?? []);
1 ignored issue
show
introduced by
Expected 1 space after "?"; 0 found
Loading history...
264
265
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
266
    foreach ($cursor as $template) {
267
      $row = [];
268
      $row[] = $template->count;
269
      $row[] = [
270
        'class' => static::SEVERITY_CLASSES[$template->severity],
271
        'data' => $levels[$template->severity],
272
      ];
273
      $row[] = $template->type;
274
      $row[] = $this->dateFormatter->format($template->changed, 'short');
275
      $row[] = [
276
        'data' => $this->getEventSource($template, $row),
277
      ];
278
      $row[] = $this->getEventLink($template);
279
280
      $rows[] = $row;
281
    }
282
283
    return [
284
      '#type' => 'table',
285
      '#header' => $header,
286
      '#rows' => $rows,
287
    ];
288
  }
289
290
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
291