Completed
Pull Request — 8.x-2.x (#5)
by Frédéric G.
05:46 queued 02:41
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

3 Methods

Rating   Name   Duplication   Size   Complexity  
A modules/mongodb_watchdog/mongodb_watchdog.admin.inc::mongodb_watchdog_filters() 0 23 3
B modules/mongodb_watchdog/mongodb_watchdog.admin.inc::mongodb_watchdog_filter_form() 12 40 4
A modules/mongodb_watchdog/mongodb_watchdog.admin.inc::mongodb_watchdog_filter_form_validate() 0 5 4

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
/**
4
 * @file
5
 * Administrative page callbacks for the Database Logging module.
6
 */
7
8
use Drupal\Core\Logger\RfcLogLevel;
9
10
/**
11
 * Creates a list of database log administration filters that can be applied.
12
 *
13
 * @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...
14
 *   Associative array of filters. The top-level keys are used as the form
15
 *   element names for the filters, and the values are arrays with the following
16
 *   elements:
17
 *   - title: Title of the filter.
18
 *   - where: The filter condition.
19
 *   - options: Array of options for the select list for the filter.
20
 */
21
function mongodb_watchdog_filters() {
22
  $filters = array();
23
24
  foreach (_dblog_get_message_types() as $type) {
25
    $types[$type] = t($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...
26
  }
27
28
  if (!empty($types)) {
29
    $filters['type'] = array(
30
      'title' => t('Type'),
31
      'where' => "w.type = ?",
32
      'options' => $types,
33
    );
34
  }
35
36
  $filters['severity'] = array(
37
    'title' => t('Severity'),
38
    'where' => 'w.severity = ?',
39
    'options' => RfcLogLevel::getLevels(),
40
  );
41
42
  return $filters;
43
}
44
45
/**
46
 * Build the filter form.
47
 *
48
 * @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...
49
 *   A form array
50
 */
51
function mongodb_watchdog_filter_form($form) {
52
  $filters = mongodb_watchdog_filters();
53
54
  $form['filters'] = array(
55
    '#type' => 'fieldset',
56
    '#title' => t('Filter log messages'),
57
    '#collapsible' => TRUE,
58
    '#collapsed' => empty($_SESSION),
59
    '#attached' => array(
60
      'css' => array(
61
        drupal_get_path('module', 'mongodb_watchdog') . '/mongodb_watchdog.css',
62
    )),
63
  );
64
65 View Code Duplication
  foreach ($filters as $key => $filter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
66
    $form['filters']['status'][$key] = array(
67
      '#title' => check_plain($filter['title']),
68
      '#type' => 'select',
69
      '#multiple' => TRUE,
70
      '#size' => 8,
71
      '#options' => $filter['options'],
72
    );
73
    if (!empty($_SESSION['mongodb_watchdog_overview_filter'][$key])) {
74
      $form['filters']['status'][$key]['#default_value'] = $_SESSION['mongodb_watchdog_overview_filter'][$key];
75
    }
76
  }
77
78
  $form['filters']['buttons']['submit'] = array(
79
    '#type' => 'submit',
80
    '#value' => t('Filter'),
81
  );
82
  if (!empty($_SESSION['mongodb_watchdog_overview_filter'])) {
83
    $form['filters']['buttons']['reset'] = array(
84
      '#type' => 'submit',
85
      '#value' => t('Reset')
86
    );
87
  }
88
89
  return $form;
90
}
91
92
/**
93
 * Validate result from mongodb_watchdog administration filter form.
94
 */
95
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...
96
  if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['type']) && empty($form_state['values']['severity'])) {
97
    form_set_error('type', t('You must select something to filter by.'));
98
  }
99
}
100
101
/**
102
 * Process result from mongodb_watchdog administration filter form.
103
 */
104
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...
105
  $op = $form_state['values']['op'];
106
  $filters = mongodb_watchdog_filters();
107
  switch ($op) {
108
    case t('Filter'):
109
      foreach ($filters as $name => $filter) {
110
        if (isset($form_state['values'][$name])) {
111
          $_SESSION['mongodb_watchdog_overview_filter'][$name] = $form_state['values'][$name];
112
        }
113
      }
114
      break;
115
116
    case t('Reset'):
117
      $_SESSION['mongodb_watchdog_overview_filter'] = array();
118
      break;
119
  }
120
  return 'admin/reports/mongodb';
121
}
122
123
/**
124
 * Gets all available filter types.
125
 *
126
 * @return array
127
 *   An array of message type names.
128
 */
129
function _mongodb_watchdog_get_message_types() {
130
  // As of version 1.0.1, the PHP driver doesn't expose the 'distinct' command.
131
  $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
132
  $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...
133
  return $result['values'];
134
}
135
136
/**
137
 * Return form for mongodb_watchdog clear button.
138
 *
139
 * @ingroup forms
140
 * @see dblog_clear_log_submit()
141
 *
142
 * @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...
143
 *   A form array.
144
 */
145
function mongodb_watchdog_clear_log_form($form) {
146
  $form['mongodb_watchdog_clear'] = array(
147
    '#type' => 'fieldset',
148
    '#title' => t('Clear log messages'),
149
    '#description' => t('This will permanently remove the log messages from the database.'),
150
    '#collapsible' => TRUE,
151
    '#collapsed' => TRUE,
152
  );
153
154
  $form['mongodb_watchdog_clear']['clear'] = array(
155
    '#type' => 'submit',
156
    '#value' => t('Clear log messages'),
157
    '#submit' => array('mongodb_watchdog_clear_log_submit'),
158
  );
159
160
  return $form;
161
}
162
163
/**
164
 * Submit callback: clear database with log messages.
165
 */
166
function mongodb_watchdog_clear_log_submit() {
167
  try {
168
    // Drop the watchdog collection.
169
    $collection = mongodb_collection(variable_get('mongodb_watchdog', 'watchdog'));
170
    $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...
171
172
    // Recreate the indexes.
173
    module_load_include('install', 'mongodb_watchdog');
174
    mongodb_watchdog_ensure_indexes();
175
176
    // Drop the event collections.
177
    foreach ($collection->db->listCollections() as $table) {
178
      $parts = explode('.', $table);
179
      if (substr($parts[1], 0, 15) == 'watchdog_event_') {
180
        $collection->db->dropCollection($table);
181
      }
182
    }
183
184
    drupal_set_message(t('MongoDB log cleared.'));
185
  }
186
  catch (Exception $e) {
187
    drupal_set_message(t('An error occured while clearing the MongoDB log.'), 'error');
188
  }
189
}
190
191
/**
192
 * Build a MongoDB query based on the selected filters.
193
 *
194
 * Refer to the @link https://jira.mongodb.org/browse/PHP-1051 Mongo Issue regarding the $in value @endlink
195
 * Refer to the @link https://jira.mongodb.org/browse/PHP-104 Mongo Issue regarding numeric keys on objects @endlink
196
 * @return array
197
 *   An array to build a MongoDB query.
198
 */
199
function mongodb_watchdog_build_filter_query() {
200
  if (empty($_SESSION['mongodb_watchdog_overview_filter'])) {
201
    return array();
202
  }
203
204
  // Build query.
205
  $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...
206
  $types = $_SESSION['mongodb_watchdog_overview_filter']['type'] ? $_SESSION['mongodb_watchdog_overview_filter']['type'] : NULL;
207
  $severities = $_SESSION['mongodb_watchdog_overview_filter']['severity'] ? $_SESSION['mongodb_watchdog_overview_filter']['severity'] : NULL;
208
209
  $find = array();
210
  if ($types) {
211
    $find['type'] = array('$in' => array_values($types));
212
  }
213
  if ($severities) {
214
    // MongoDB is picky about types, ensure the severities are all integers.
215
    $find['severity'] = array('$in' => array_values(array_map('intval', $severities)));
216
  }
217
  return $find;
218
}
219