Completed
Push — 8.x-2.x ( f7089a...f2468c )
by Frédéric G.
03:14
created

src/Controller/RequestController.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Drupal\mongodb_watchdog\Controller;
4
5
use Drupal\Component\Utility\Unicode;
6
use Drupal\Core\Datetime\DateFormatterInterface;
7
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
8
use Drupal\Core\Link;
9
use Drupal\Core\Logger\RfcLogLevel;
10
use Drupal\mongodb_watchdog\Logger;
11
use Symfony\Component\DependencyInjection\ContainerInterface;
12
use Symfony\Component\HttpFoundation\Request;
13
14
/**
15
 * Implements the controller for the request events page.
16
 */
17
class RequestController implements ContainerInjectionInterface {
18
19
  /**
20
   * The core date.formatter service.
21
   *
22
   * @var \Drupal\Core\Datetime\DateFormatterInterface
23
   */
24
  protected $dateFormatter;
25
26
  /**
27
   * The items_per_page configuration value.
28
   *
29
   * @var int
30
   */
31
  protected $itemsPerPage;
32
33
  /**
34
   * The length of the absolute path to the site root, in runes.
35
   *
36
   * @var int
37
   */
38
  protected $rootLength;
39
40
  /**
41
   * The mongodb_watchdog logger, to access events.
42
   *
43
   * @var \Drupal\mongodb_watchdog\Logger
44
   */
45
  protected $watchdog;
46
47
  /**
48
   * RequestController constructor.
49
   *
50
   * @param \Drupal\mongodb_watchdog\Logger $watchdog
51
   *   The MongoDB logger service, to load event data.
52
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
53
   *   The core date.formatter service.
54
   * @param int $items_per_page
55
   *   The items_per_page configuration value.
56
   */
57
  public function __construct(Logger $watchdog, DateFormatterInterface $date_formatter, $items_per_page) {
58
    $this->dateFormatter = $date_formatter;
59
    $this->itemsPerPage = $items_per_page;
60
    $this->watchdog = $watchdog;
61
62
    // Add terminal "/".
63
    $this->rootLength = Unicode::strlen(DRUPAL_ROOT) + 1;
64
  }
65
66
  /**
67
   * Build the top part of the page, about the request.
68
   *
69
   * @param string $unique_id
70
   *   The unique request id.
71
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
72
   *   A fully loaded array of events and their templates.
73
   *
74
   * @return array
75
   *   A render array for a table.
76
   */
77
  public function buildTrackRequest($unique_id, array $events) {
78
    if ($events) {
79
      $row = array_slice($events, 0, 1);
80
      /** @var \Drupal\mongodb_watchdog\Event $first */
81
      list($template, $first) = reset($row);
0 ignored issues
show
The assignment to $template is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused variable $template.
Loading history...
82
83
      $location = $first->location;
84
      $timestamp = isset($first->timestamp)
85
        ? $this->dateFormatter->format($first->timestamp, 'long')
86
        : t('No information');
87
    }
88
    else {
89
      $location = $timestamp = t('No information');
90
    }
91
92
    $rows = [
93
      [t('Request ID'), $unique_id],
94
      [t('Location'), $location],
95
      [t('Date/time'), $timestamp],
96
    ];
97
98
    foreach ($rows as &$row) {
99
      $row[0] = [
100
        'data' => $row[0],
101
        'header' => TRUE,
102
      ];
103
    }
104
105
    $ret = [
106
      '#type' => 'table',
107
      '#rows' => $rows,
108
    ];
109
    return $ret;
110
  }
111
112
  /**
113
   * Build the bottom part of the page, about the events during the request.
114
   *
115
   * @param array<\Drupal\mongodb_watchdog\EventTemplate\Drupal\mongodb_watchdog\Event[]> $events
116
   *   A fully loaded array of events and their templates.
117
   *
118
   * @return array
119
   *   A render array for a table.
120
   */
121
  public function buildTrackRows(array $events) {
122
    $header = [
123
      t('Sequence'),
124
      t('Type'),
125
      t('Severity'),
126
      t('Event'),
127
      t('File'),
128
      t('Line'),
129
    ];
130
    $rows = [];
131
    $levels = RfcLogLevel::getLevels();
132
133
    /** @var \Drupal\mongodb_watchdog\EventTemplate $template */
134
    /** @var \Drupal\mongodb_watchdog\Event $event */
135
    foreach ($events as list($template, $event)) {
136
      $row = [
137
        ['data' => $event->requestTracking_sequence],
138
        $template->type,
139
        [
140
          'data' => $levels[$template->severity],
141
          'class' => OverviewController::SEVERITY_CLASSES[$template->severity],
142
        ],
143
        [
144
          'data' => Link::createFromRoute($template->asString($event->variables), 'mongodb_watchdog.reports.detail', [
145
            'event_template' => $template->_id,
146
          ]),
147
        ],
148
        $this->simplifyPath($event->variables['%file']),
149
        $event->variables['%line'],
150
      ];
151
      $rows[] = $row;
152
    }
153
154
    $ret = [
155
      '#type' => 'table',
156
      '#rows' => $rows,
157
      '#header' => $header,
158
    ];
159
    return $ret;
160
  }
161
162
  /**
163
   * {@inheritdoc}
164
   */
165 View Code Duplication
  public static function create(ContainerInterface $container) {
0 ignored issues
show
This method seems to be duplicated in your project.

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.

Loading history...
166
    /** @var \Drupal\mongodb_watchdog\Logger $watchdog */
167
    $watchdog = $container->get('mongodb.logger');
168
169
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
170
    $date_formatter = $container->get('date.formatter');
171
172
    /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */
173
    $config_factory = $container->get('config.factory');
174
    $items_per_page = $config_factory->get('mongodb_watchdog.settings')->get('items_per_page');
175
    return new static($watchdog, $date_formatter, $items_per_page);
176
  }
177
178
  /**
179
   * Set up the templates pager.
180
   *
181
   * @param \Symfony\Component\HttpFoundation\Request $request
182
   *   The current request.
183
   * @param int $uniqueId
184
   *   The uniqueId of the current request.
185
   *
186
   * @return int
187
   *   The number of the page to display, starting at 0.
188
   */
189 View Code Duplication
  public function setupPager(Request $request, $uniqueId) {
0 ignored issues
show
This method seems to be duplicated in your project.

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.

Loading history...
190
    $count = $this->watchdog->requestEventsCount($uniqueId);
191
    $height = $this->itemsPerPage;
192
    pager_default_initialize($count, $height);
193
194
    $page = intval($request->query->get('page'));
195
    if ($page < 0) {
196
      $page = 0;
197
    }
198
    else {
199
      $page_max = intval(min(ceil($count / $height), PHP_INT_MAX) - 1);
200
      if ($page > $page_max) {
201
        $page = $page_max;
202
      }
203
    }
204
205
    return $page;
206
  }
207
208
  /**
209
   * Convert an absolute path to a relative one if below the site root.
210
   *
211
   * @param string $path
212
   *   An absolute path on the filesystem.
213
   *
214
   * @return string
215
   *   A relative path if possible, otherwise the input path.
216
   */
217
  public function simplifyPath($path) {
218
    $ret = (Unicode::strpos($path, DRUPAL_ROOT) === 0)
219
      ? Unicode::substr($path, $this->rootLength)
220
      : $path;
221
    return $ret;
222
  }
223
224
  /**
225
   * Controller.
226
   *
227
   * @param string $uniqueId
228
   *   The unique request id from mod_unique_id. Unsafe.
229
   *
230
   * @return array
0 ignored issues
show
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...
231
   *   A render array.
232
   */
233
  public function track(Request $request, $uniqueId) {
234
    if (!preg_match('/[\w-]+/', $uniqueId)) {
235
      return ['#markup' => ''];
236
    }
237
238
    $page = $this->setupPager($request, $uniqueId);
239
    $skip = $page * $this->itemsPerPage;
240
    $height = $this->itemsPerPage;
241
242
    $events = $this->watchdog->requestEvents($uniqueId, $skip, $height);
243
    $ret = [
244
      '#attached' => [
245
        'library' => ['mongodb_watchdog/styling'],
246
      ],
247
      'request' => $this->buildTrackRequest($uniqueId, $events),
248
      'events' => $this->buildTrackRows($events),
249
      'pager' => [
250
        '#type' => 'pager',
251
      ],
252
    ];
253
    return $ret;
254
  }
255
256
}
257