Completed
Push — 8.x-2.x ( 8af97d...4c7eae )
by Frédéric G.
03:11
created

modules/mongodb_watchdog/mongodb_watchdog.admin.inc::mongodb_watchdog_event()   F

Complexity

Conditions 10
Paths 288

Size

Total Lines 100
Code Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 80
c 0
b 0
f 0
nc 288
nop 1
dl 0
loc 100
rs 3.1304

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @file
4
 * Settings for mongodb. Moved back to module file.
5
 */
6
7
/**
8
 * Display watchdogs entries in mongodb.
9
 * @TODO
10
 *   Use theme function.
11
 *   Use exposed filter like dblog.
12
 *
13
 * @return array
14
 *   a form array
15
 */
16
function mongodb_watchdog_overview() {
17
  $rows = array();
0 ignored issues
show
Unused Code introduced by
$rows is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
18
  $icons = array(
19
    WATCHDOG_DEBUG    => '',
20
    WATCHDOG_INFO     => '',
21
    WATCHDOG_NOTICE   => '',
22
    WATCHDOG_WARNING  => theme('image', array('path' => 'misc/watchdog-warning.png', 'alt' => t('warning'), 'title' => t('warning'))),
23
    WATCHDOG_ERROR    => theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => t('error'), 'title' => t('error'))),
24
    WATCHDOG_CRITICAL => theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => t('critical'), 'title' => t('critical'))),
25
    WATCHDOG_ALERT    => theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => t('alert'), 'title' => t('alert'))),
26
    WATCHDOG_EMERGENCY    => theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => t('emergency'), 'title' => t('emergency'))),
27
  );
28
  $classes = array(
0 ignored issues
show
Unused Code introduced by
$classes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
29
    WATCHDOG_DEBUG    => 'mongodb_watchdog-debug',
30
    WATCHDOG_INFO     => 'mongodb_watchdog-info',
31
    WATCHDOG_NOTICE   => 'mongodb_watchdog-notice',
32
    WATCHDOG_WARNING  => 'mongodb_watchdog-warning',
33
    WATCHDOG_ERROR    => 'mongodb_watchdog-error',
34
    WATCHDOG_CRITICAL => 'mongodb_watchdog-critical',
35
    WATCHDOG_ALERT    => 'mongodb_watchdog-alert',
36
    WATCHDOG_EMERGENCY => 'mongodb_watchdog-emergency',
37
  );
38
39
  global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
40
  $per_page = 50;
41
  $page = isset($_GET['page']) ? $_GET['page'] : '';
42
  $pager_page_array = explode(',', $page);
43
  $on_page = $pager_page_array[0];
44
45
  $cursor = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'))
0 ignored issues
show
Bug introduced by
The method find does only exist in MongoCollection and MongoDebugCollection, but not in MongoDummy.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
46
    ->find(mongodb_watchdog_build_filter_query())
47
    ->limit($per_page)
48
    ->skip($on_page * $per_page)
49
    ->sort(array('timestamp' => -1));
50
51
  $build['mongodb_watchdog_filter_form'] = drupal_get_form('mongodb_watchdog_filter_form');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$build was never initialized. Although not strictly required by PHP, it is generally a good practice to add $build = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
52
  $build['mongodb_watchdog_clear_log_form'] = drupal_get_form('mongodb_watchdog_clear_log_form');
53
54
  $header = array(
55
    '', // Icon column.
56
    t('#'),
57
    array('data' => t('Type')),
58
    array('data' => t('Date')),
59
    t('Source'),
60
    t('Message'),
61
  );
62
63
  $rows = array();
64
  foreach ($cursor as $id => $value) {
65
    if ($value['type'] == 'php' && $value['message'] == '%type: %message in %function (line %line of %file).') {
66
      $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
67
      $collection = $collection->db->selectCollection('watchdog_event_' . $value['_id']);
68
      if ($result = $collection->find()->sort(array('$natural' => -1))->limit(1)->getNext()) {
69
        $value['file'] = basename($result['variables']['%file']);
70
        $value['line'] = $result['variables']['%line'];
71
        $value['message'] = '%type in %function';
72
        $value['variables'] = $result['variables'];
73
      }
74
    }
75
    $message = truncate_utf8(strip_tags(_mongodb_watchdog_format_message($value)), 56, TRUE, TRUE);
76
    $rows[$id] = array(
77
      $icons[$value['severity']],
78
      isset($value['count']) && $value['count'] > 1 ? $value['count'] : '',
79
      t($value['type']),
80
      empty($value['timestamp']) ? '' : format_date($value['timestamp'], 'short'),
81
      empty($value['file']) ? '' : truncate_utf8(basename($value['file']), 30) . (empty($value['line']) ? '' : ('+' . $value['line'])),
82
      l($message, "admin/reports/mongodb/$id"),
83
    );
84
  }
85
86
  $build['mongodb_watchdog_table'] = array(
87
    '#theme' => 'table',
88
    '#header' => $header,
89
    '#rows' => $rows,
90
    '#attributes' => array('id' => 'admin-mongodb_watchdog'),
91
  );
92
93
  // Add the pager.
94
  if ($on_page > 0 || count($rows) >= $per_page) {
95
    $pager_total_items[0] = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'))
96
      ->find(mongodb_watchdog_build_filter_query())
97
      ->count();
98
    $pager_total[0] = ceil($pager_total_items[0] / $per_page);
99
    $pager_page_array[0] = max(0, min((int) $pager_page_array[0], ((int)$pager_total[0]) - 1));
100
    $pager_limits[0] = $per_page;
101
    $build['pager'] = array(
102
      '#theme' => 'pager',
103
    );
104
  }
105
106
  return $build;
107
}
108
109
/**
110
 * Display watchdogs entry details in MongoDB.
111
 *
112
 * @param array $dblog
113
 */
114
function mongodb_watchdog_event($dblog) {
115
  $severity = watchdog_severity_levels();
116
  $rows = array(
117
    array(
118
      array('data' => t('Type'), 'header' => TRUE),
119
      t($dblog['type']),
120
    ),
121
    array(
122
      array('data' => t('Severity'), 'header' => TRUE),
123
      $severity[$dblog['severity']],
124
    ),
125
    array(
126
      array('data' => t('Function'), 'header' => TRUE),
127
      isset($dblog['function']) ? $dblog['function'] : '',
128
    ),
129
    array(
130
      array('data' => t('File'), 'header' => TRUE),
131
      isset($dblog['file']) ? $dblog['file'] : '',
132
    ),
133
    array(
134
      array('data' => t('Line'), 'header' => TRUE),
135
      isset($dblog['line']) ? $dblog['line'] : '',
136
    ),
137
    array(
138
      array('data' => t('Count'), 'header' => TRUE),
139
      isset($dblog['count']) ? $dblog['count'] : '',
140
    ),
141
  );
142
  $build['reports'] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$build was never initialized. Although not strictly required by PHP, it is generally a good practice to add $build = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
143
    '#type' => 'markup',
144
    '#markup' => l(t('Return to log report'), 'admin/reports/mongodb'),
145
  );
146
  $build['mongodb_watchdog_event_table']['header'] = array(
147
    '#theme' => 'table',
148
    '#rows' => $rows,
149
    '#attributes' => array('class' => array('dblog-event')),
150
  );
151
  // @todo: the count is unreliable, so just get the actual number of entries.
152
//$total = min($dblog['count'], variable_get('mongodb_watchdog_items', 10000));
153
  $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
154
  $collection = $collection->db->selectCollection('watchdog_event_' . $dblog['_id']);
155
  $total = $collection->count();
156
  $limit = 20;
157
  $pagenumber = mongodb_watchdog_pager_init(0, $limit, $total);
158
  $result = $collection
159
    ->find()
160
    ->skip($pagenumber * $limit)
161
    ->limit($limit)
162
    ->sort(array('$natural' => -1));
163
  $severity = watchdog_severity_levels();
0 ignored issues
show
Unused Code introduced by
$severity is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
164
  $rows = array();
165
  $header = array(
166
    array('data' => t('Date'), 'header' => TRUE),
167
    array('data' => t('User'), 'header' => TRUE),
168
    array('data' => t('Location'), 'header' => TRUE),
169
    array('data' => t('Referrer'), 'header' => TRUE),
170
    array('data' => t('Hostname'), 'header' => TRUE),
171
    array('data' => t('Message'), 'header' => TRUE),
172
    array('data' => t('Operations'), 'header' => TRUE),
173
  );
174
  foreach ($result as $event) {
175
    if (isset($event['wd-user'])) {
176
      $account = $event['wd-user'];
177
      unset($event['wd-user']);
178
      $ip = $dblog['ip'];
179
      $request_uri = $dblog['request_uri'];
180
      $referer = $dblog['referer'];
181
      $link = $dblog['link'];
182
      $dblog['variables'] = $event;
183
    }
184
    else {
185
      $account = $event['user'];
186
      $ip = $event['ip'];
187
      $request_uri = $event['request_uri'];
188
      $referer = $event['referer'];
189
      $link = $event['link'];
190
      $dblog['variables'] = $event['variables'];
191
    }
192
    $rows[] = array(
193
      format_date($event['timestamp'], 'short'),
194
      l($account['name'], 'user/' . $account['uid']),
195
      $request_uri ? l(truncate_utf8(basename(($request_uri)), 20), $request_uri) : '',
196
      $referer ? l(truncate_utf8(basename(($referer)), 20), $referer) : '',
197
      check_plain($ip),
198
      _mongodb_watchdog_format_message($dblog),
199
      $link,
200
    );
201
  }
202
  $build['mongodb_watchdog_event_table']['messages'] = array(
203
    '#theme' => 'table',
204
    '#header' => $header,
205
    '#rows' => $rows,
206
  );
207
  if ($total > $limit) {
208
    $build['mongodb_watchdog_event_table']['pager'] = array(
209
      '#theme' => 'pager',
210
    );
211
  }
212
  return $build;
213
}
214
215
/**
216
 * Initialize the global pager variables for use in a mongodb_watchdog event list.
217
 */
218
function mongodb_watchdog_pager_init($element, $limit, $total) {
219
  global $pager_page_array, $pager_total, $pager_total_items;
220
221
  // Initialize pager, see pager.inc.
222
  $page = isset($_GET['page']) ? $_GET['page'] : '';
223
  $pager_page_array = explode(',', $page);
224
  if (!isset($pager_page_array[$element])) {
225
    $pager_page_array[$element] = 0;
226
  }
227
  $pager_total_items[$element] = $total;
228
  $pager_total[$element] = ceil($pager_total_items[$element] / $limit);
229
  $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1));
230
  return isset($pager_page_array[$element]) ? $pager_page_array[$element] : 0;
231
}
232
233
/**
234
 * Formats a log message for display.
235
 *
236
 * @param $dblog
237
 *   An object with at least the message and variables properties
238
 *
239
 * @return string
240
 */
241
function _mongodb_watchdog_format_message($dblog) {
242
  // Legacy messages and user specified text
243
  if (!isset($dblog['variables'])) {
244
    return $dblog['message'];
245
  }
246
  // Message to translate with injected variables
247
  return t($dblog['message'], $dblog['variables']);
248
}
249
250
/*
251
 * List mongodb_watchdog administration filters that can be applied.
252
 *
253
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<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...
254
 *   A form array
255
 */
256
function mongodb_watchdog_filters() {
257
  $filters = array();
258
259
  foreach (_mongodb_watchdog_get_message_types() as $type) {
260
    $types[$type] = $type;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$types was never initialized. Although not strictly required by PHP, it is generally a good practice to add $types = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
261
  }
262
263
  if (!empty($types)) {
264
    $filters['type'] = array(
265
      'title' => t('Type'),
266
      'options' => $types,
267
    );
268
  }
269
270
  $filters['severity'] = array(
271
    'title' => t('Severity'),
272
    'options' => watchdog_severity_levels(),
273
  );
274
275
  return $filters;
276
}
277
278
/**
279
 * Build the filter form.
280
 *
281
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<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...
282
 *   A form array
283
 */
284
function mongodb_watchdog_filter_form($form) {
285
  $filters = mongodb_watchdog_filters();
286
287
  $form['filters'] = array(
288
    '#type' => 'fieldset',
289
    '#title' => t('Filter log messages'),
290
    '#collapsible' => TRUE,
291
    '#collapsed' => empty($_SESSION),
292
    '#attached' => array(
293
      'css' => array(
294
        drupal_get_path('module', 'mongodb_watchdog') . '/mongodb_watchdog.css',
295
    )),
296
  );
297
298
  foreach ($filters as $key => $filter) {
299
    $form['filters']['status'][$key] = array(
300
      '#title' => check_plain($filter['title']),
301
      '#type' => 'select',
302
      '#multiple' => TRUE,
303
      '#size' => 8,
304
      '#options' => $filter['options'],
305
    );
306
    if (!empty($_SESSION['mongodb_watchdog_overview_filter'][$key])) {
307
      $form['filters']['status'][$key]['#default_value'] = $_SESSION['mongodb_watchdog_overview_filter'][$key];
308
    }
309
  }
310
311
  $form['filters']['buttons']['submit'] = array(
312
    '#type' => 'submit',
313
    '#value' => t('Filter'),
314
  );
315
  if (!empty($_SESSION['mongodb_watchdog_overview_filter'])) {
316
    $form['filters']['buttons']['reset'] = array(
317
      '#type' => 'submit',
318
      '#value' => t('Reset')
319
    );
320
  }
321
322
  return $form;
323
}
324
325
/**
326
 * Validate result from mongodb_watchdog administration filter form.
327
 */
328
function mongodb_watchdog_filter_form_validate($form, &$form_state) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
329
  if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['type']) && empty($form_state['values']['severity'])) {
330
    form_set_error('type', t('You must select something to filter by.'));
331
  }
332
}
333
334
/**
335
 * Process result from mongodb_watchdog administration filter form.
336
 */
337
function mongodb_watchdog_filter_form_submit($form, &$form_state) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
338
  $op = $form_state['values']['op'];
339
  $filters = mongodb_watchdog_filters();
340
  switch ($op) {
341
    case t('Filter'):
342
      foreach ($filters as $name => $filter) {
343
        if (isset($form_state['values'][$name])) {
344
          $_SESSION['mongodb_watchdog_overview_filter'][$name] = $form_state['values'][$name];
345
        }
346
      }
347
      break;
348
349
    case t('Reset'):
350
      $_SESSION['mongodb_watchdog_overview_filter'] = array();
351
      break;
352
  }
353
  return 'admin/reports/mongodb';
354
}
355
356
/**
357
 * Gets all available filter types.
358
 *
359
 * @return array
360
 *   An array of message type names.
361
 */
362
function _mongodb_watchdog_get_message_types() {
363
  // As of version 1.0.1, the PHP driver doesn't expose the 'distinct' command.
364
  $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
365
  $result = $collection->db->command(array('distinct' => $collection->getName(), 'key' => 'type'));
0 ignored issues
show
Bug introduced by
The method getName does only exist in MongoCollection, but not in MongoDebugCollection and MongoDummy.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
366
  return $result['values'];
367
}
368
369
/**
370
 * Return form for mongodb_watchdog clear button.
371
 *
372
 * @ingroup forms
373
 * @see dblog_clear_log_submit()
374
 *
375
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<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...
376
 *   A form array.
377
 */
378
function mongodb_watchdog_clear_log_form($form) {
379
  $form['mongodb_watchdog_clear'] = array(
380
    '#type' => 'fieldset',
381
    '#title' => t('Clear log messages'),
382
    '#description' => t('This will permanently remove the log messages from the database.'),
383
    '#collapsible' => TRUE,
384
    '#collapsed' => TRUE,
385
  );
386
387
  $form['mongodb_watchdog_clear']['clear'] = array(
388
    '#type' => 'submit',
389
    '#value' => t('Clear log messages'),
390
    '#submit' => array('mongodb_watchdog_clear_log_submit'),
391
  );
392
393
  return $form;
394
}
395
396
/**
397
 * Submit callback: clear database with log messages.
398
 */
399
function mongodb_watchdog_clear_log_submit() {
400
  try {
401
    // Drop the watchdog collection.
402
    $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
403
    $collection->db->dropCollection($collection->getName());
0 ignored issues
show
Bug introduced by
The method getName does only exist in MongoCollection, but not in MongoDebugCollection and MongoDummy.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
404
405
    // Recreate the indexes.
406
    module_load_include('install', 'mongodb_watchdog');
407
    mongodb_watchdog_ensure_indexes();
408
409
    // Drop the event collections.
410
    foreach ($collection->db->listCollections() as $table) {
411
      $parts = explode('.', $table);
412
      if (substr($parts[1], 0, 15) == 'watchdog_event_') {
413
        $collection->db->dropCollection($table);
414
      }
415
    }
416
417
    drupal_set_message(t('MongoDB log cleared.'));
418
  }
419
  catch (Exception $e) {
420
    drupal_set_message(t('An error occured while clearing the MongoDB log.'), 'error');
421
  }
422
}
423
424
/**
425
 * Build a MongoDB query based on the selected filters.
426
 *
427
 * Refer to the @link https://jira.mongodb.org/browse/PHP-1051 Mongo Issue regarding the $in value @endlink
428
 * Refer to the @link https://jira.mongodb.org/browse/PHP-104 Mongo Issue regarding numeric keys on objects @endlink
429
 * @return array
430
 *   An array to build a MongoDB query.
431
 */
432
function mongodb_watchdog_build_filter_query() {
433
  if (empty($_SESSION['mongodb_watchdog_overview_filter'])) {
434
    return array();
435
  }
436
437
  // Build query.
438
  $where = $args = array();
0 ignored issues
show
Unused Code introduced by
$args is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Unused Code introduced by
$where is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
439
  $types = $_SESSION['mongodb_watchdog_overview_filter']['type'] ? $_SESSION['mongodb_watchdog_overview_filter']['type'] : NULL;
440
  $severities = $_SESSION['mongodb_watchdog_overview_filter']['severity'] ? $_SESSION['mongodb_watchdog_overview_filter']['severity'] : NULL;
441
442
  $find = array();
443
  if ($types) {
444
    $find['type'] = array('$in' => array_values($types));
445
  }
446
  if ($severities) {
447
    // MongoDB is picky about types, ensure the severities are all integers.
448
    $find['severity'] = array('$in' => array_values(array_map('intval', $severities)));
449
  }
450
  return $find;
451
}
452
453
/**
454
 * Page callback for "admin/reports/[access-denied|page-not-found]".
455
 *
456
 * @return array
457
 */
458
function mongodb_watchdog_page_top($type) {
459
  $ret = array();
460
  $type_param = array('%type' => $type);
461
  $limit = 50;
462
463
  // Safety net
464
  $types = array(
465
    'page not found',
466
    'access denied',
467
  );
468
  if (!in_array($type, $types)) {
469
    drupal_set_message(t('Unknown top report type: %type', $type_param), 'error');
470
    watchdog('mongodb_watchdog', 'Unknown top report type: %type', $type_param, WATCHDOG_WARNING);
471
    $ret = '';
472
    return $ret;
473
  }
474
475
  // Find _id for the error type.
476
  $watchdog = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
477
  $template = $watchdog->findOne(array('type' => $type), array('_id'));
0 ignored issues
show
Bug introduced by
The method findOne does only exist in MongoCollection, but not in MongoDebugCollection and MongoDummy.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
478
479
  // findOne() will return NULL if no row is found
480
  if (empty($template)) {
481
    $ret['empty'] = array(
482
      '#markup' => t('No "%type" message found', $type_param),
483
      '#prefix' => '<div class="mongodb-watchdog-message">',
484
      '#suffix' => '</div>',
485
    );
486
    $ret = drupal_render($ret);
487
    return $ret;
488
  }
489
490
  // Find occurrences of error type.
491
  $key = $template['_id'];
492
  $event_collection = mongodb_collection('watchdog_event_' . $key);
493
  $reduce = <<<EOT
494
function (doc, accumulator) {
495
  accumulator.count++;
496
}
497
EOT;
498
499
  $counts = $event_collection->group(
0 ignored issues
show
Bug introduced by
The method group does only exist in MongoCollection, but not in MongoDebugCollection and MongoDummy.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
500
    array('variables.@param' => 1),
501
    array('count' => array()),
502
    $reduce
503
  );
504
  if (!$counts['ok']) {
505
    drupal_set_message(t('No "%type" occurrence found', $type_param), 'error');
506
    $ret = '';
507
    return $ret;
508
  }
509
  $counts = $counts['retval'];
510
  usort($counts, '_mongodb_watchdog_sort_top');
511
  $counts = array_slice($counts, 0, $limit);
512
513
  $header = array(
514
    t('#'),
515
    t('Paths'),
516
  );
517
  $rows = array();
518
  foreach ($counts as $count) {
519
    $rows[] = array(
520
      $count['variables.@param'],
521
      $count['count'],
522
    );
523
  }
524
525
  $ret = array(
526
    '#theme' => 'table',
527
    '#header' => $header,
528
    '#rows' => $rows,
529
  );
530
  return $ret;
531
}
532
533
/**
534
 * usort() helper function to sort top entries returned from a group query.
535
 *
536
 * @param array $x
537
 * @param array $y
538
 *
539
 * @return boolean
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

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...
540
 */
541
function _mongodb_watchdog_sort_top($x, $y) {
542
  $cx = $x['count'];
543
  $cy = $y['count'];
544
  return $cy - $cx;
545
}
546