Completed
Push — 8.x-2.x ( 0cda8a...8af97d )
by Frédéric G.
02:15
created

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

Complexity

Conditions 13
Paths 388

Size

Total Lines 92
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 72
c 0
b 0
f 0
nc 388
nop 0
dl 0
loc 92
rs 3.7737

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