Completed
Push — master ( d6e759...68bd75 )
by Lars
03:32
created

Helper::phoneticSearch()   B

Complexity

Conditions 8
Paths 50

Size

Total Lines 53
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 8.216

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 17
cts 20
cp 0.85
rs 7.1199
c 0
b 0
f 0
cc 8
eloc 27
nc 50
nop 8
crap 8.216

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace voku\db;
4
5
use voku\helper\Phonetic;
6
7
/**
8
 * Helper: this handles extra functions that use the "DB"-Class
9
 *
10
 * @package   voku\db
11
 */
12
class Helper
13
{
14
  /**
15
   * Check if "mysqlnd"-driver is used.
16
   *
17 34
   * @return bool
18
   */
19 34
  public static function isMysqlndIsUsed()
20
  {
21 34
    static $_mysqlnd_is_used = null;
22 1
23 1
    if ($_mysqlnd_is_used === null) {
24
      $_mysqlnd_is_used = (extension_loaded('mysqlnd') && function_exists('mysqli_fetch_all'));
25 34
    }
26
27
    return $_mysqlnd_is_used;
28
  }
29
30
  /**
31
   * Check if the current environment supports "utf8mb4".
32
   *
33
   * @param DB $dbConnection
34
   *
35 7
   * @return bool
36
   */
37
  public static function isUtf8mb4Supported(DB $dbConnection = null)
38
  {
39
    /**
40
     *  https://make.wordpress.org/core/2015/04/02/the-utf8mb4-upgrade/
41
     *
42
     * - You’re currently using the utf8 character set.
43
     * - Your MySQL server is version 5.5.3 or higher (including all 10.x versions of MariaDB).
44
     * - Your MySQL client libraries are version 5.5.3 or higher. If you’re using mysqlnd, 5.0.9 or higher.
45
     *
46
     * INFO: utf8mb4 is 100% backwards compatible with utf8.
47 7
     */
48 7
49
    if ($dbConnection === null) {
50
      $dbConnection = DB::getInstance();
51
    }
52 7
53
    $server_version = self::get_mysql_server_version($dbConnection);
54
    $client_version = self::get_mysql_client_version($dbConnection);
55 7
56 7
    if (
57
        $server_version >= 50503
58 7
        &&
59
        (
60
            (
61 7
                self::isMysqlndIsUsed() === true
62 7
                &&
63
                $client_version >= 50009
64
            )
65 7
            ||
66
            (
67 7
                self::isMysqlndIsUsed() === false
68
                &&
69
                $client_version >= 50503
70
            )
71 7
        )
72
73
    ) {
74
      return true;
75
    }
76
77
    return false;
78
  }
79
80
  /**
81 7
   * A phonetic search algorithms for different languages.
82
   *
83 7
   * @param string      $searchString
84
   * @param string      $searchFieldName
85 7
   * @param string      $idFieldName
86 1
   * @param string      $language <p>en, de, fr</p>
87 1
   * @param string      $table
88
   * @param array       $whereArray
89 7
   * @param DB|null     $dbConnection <p>use <strong>null</strong> if you will use the current database-connection</p>
90
   * @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p>
91
   *
92
   * @return array
93
   */
94
  public static function phoneticSearch($searchString, $searchFieldName, $idFieldName = null, $language = 'de', $table, array $whereArray = null, DB $dbConnection = null, $databaseName = null)
95
  {
96
    // init
97
    $searchString = (string)$searchString;
98
    $searchFieldName = (string)$searchFieldName;
99
100 7
    if ($dbConnection === null) {
101
      $dbConnection = DB::getInstance();
102 7
    }
103
104 7
    if ($table === '') {
105 1
      $debug = new Debug($dbConnection);
106 1
      $debug->displayError('invalid table name');
107
108 7
      return array();
109
    }
110
111
    if ($idFieldName === null) {
112
      $idFieldName = 'id';
113
    }
114
115
    $whereSQL = $dbConnection->_parseArrayPair($whereArray, 'AND');
0 ignored issues
show
Bug introduced by
It seems like $whereArray defined by parameter $whereArray on line 94 can also be of type null; however, voku\db\DB::_parseArrayPair() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
116
    if ($whereSQL) {
117
      $whereSQL = 'AND ' . $whereSQL;
118
    }
119
120
    if ($databaseName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $databaseName of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
121 1
      $databaseName = $dbConnection->quote_string(trim($databaseName)) . '.';
122
    }
123 1
124
    // get the row
125
    $query = 'SELECT ' . $dbConnection->quote_string($searchFieldName) . ', ' . $dbConnection->quote_string($idFieldName) . ' 
126
      FROM ' . $databaseName . $dbConnection->quote_string($table) . '
127
      WHERE 1 = 1
128 1
      ' . $whereSQL . '
129 1
    ';
130 1
    $result = $dbConnection->query($query);
131 1
132
    // make sure the row exists
133
    if ($result->num_rows <= 0) {
134
      return array();
135 1
    }
136
137 1
    $dataToSearchIn = array();
138 1
    /** @noinspection LoopWhichDoesNotLoopInspection */
139 1
    /** @noinspection PhpAssignmentInConditionInspection */
140
    while ($tmpArray = $result->fetchArray()) {
141 1
      $dataToSearchIn[$tmpArray[$idFieldName]] = $tmpArray[$searchFieldName];
142
    }
143
144
    $phonetic = new Phonetic($language);
145
    return $phonetic->phonetic_matches($searchString, $dataToSearchIn);
146
  }
147
148 1
  /**
149
   * A string that represents the MySQL client library version.
150
   *
151
   * @param DB $dbConnection
152 1
   *
153 1
   * @return string
154
   */
155 1 View Code Duplication
  public static function get_mysql_client_version(DB $dbConnection = null)
0 ignored issues
show
Duplication introduced by
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...
156 1
  {
157 1
    static $_mysqli_client_version = null;
158 1
159 1
    if ($dbConnection === null) {
160
      $dbConnection = DB::getInstance();
161
    }
162 1
163
    if ($_mysqli_client_version === null) {
164 1
      $_mysqli_client_version = \mysqli_get_client_version($dbConnection->getLink());
165
    }
166
167
    return $_mysqli_client_version;
168
  }
169
170
171
  /**
172
   * Returns a string representing the version of the MySQL server that the MySQLi extension is connected to.
173
   *
174
   * @param DB $dbConnection
175
   *
176
   * @return string
177
   */
178 View Code Duplication
  public static function get_mysql_server_version(DB $dbConnection = null)
0 ignored issues
show
Duplication introduced by
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...
179
  {
180 1
    static $_mysqli_server_version = null;
181
182
    if ($dbConnection === null) {
183 1
      $dbConnection = DB::getInstance();
184
    }
185 1
186 1
    if ($_mysqli_server_version === null) {
187 1
      $_mysqli_server_version = \mysqli_get_server_version($dbConnection->getLink());
188
    }
189 1
190
    return $_mysqli_server_version;
191
  }
192
193
  /**
194
   * Return all db-fields from a table.
195
   *
196 1
   * @param string      $table
197 1
   * @param bool        $useStaticCache
198 1
   * @param DB|null     $dbConnection <p>use <strong>null</strong> if you will use the current database-connection</p>
199 1
   * @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p>
200
   *
201 1
   * @return array
202
   */
203
  public static function getDbFields($table, $useStaticCache = true, DB $dbConnection = null, $databaseName = null)
204
  {
205
    static $DB_FIELDS_CACHE = array();
206 1
207
    // use the static cache
208 1
    if (
209 1
        $useStaticCache === true
210 1
        &&
211
        isset($DB_FIELDS_CACHE[$table])
212
    ) {
213 1
      return $DB_FIELDS_CACHE[$table];
214
    }
215
216
    // init
217 1
    $dbFields = array();
218
219
    if ($dbConnection === null) {
220 1
      $dbConnection = DB::getInstance();
221 1
    }
222 1
223
    if ($table === '') {
224 1
      $debug = new Debug($dbConnection);
225
      $debug->displayError('invalid table name');
226 1
227 1
      return array();
228 1
    }
229 1
230 1
    if ($databaseName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $databaseName of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
231 1
      $databaseName = $dbConnection->quote_string(trim($databaseName)) . '.';
232 1
    }
233 1
234 1
    $sql = 'SHOW COLUMNS FROM ' . $databaseName . $dbConnection->escape($table);
235
    $result = $dbConnection->query($sql);
236 1
237 1
    if ($result && $result->num_rows > 0) {
238
      foreach ($result->fetchAllArray() as $tmpResult) {
239 1
        $dbFields[] = $tmpResult['Field'];
240 1
      }
241
    }
242
243 1
    // add to static cache
244 1
    $DB_FIELDS_CACHE[$table] = $dbFields;
245
246 1
    return $dbFields;
247 1
  }
248 1
249
  /**
250
   * Copy row within a DB table and making updates to the columns.
251
   *
252
   * @param string  $table
253
   * @param array   $whereArray
254
   * @param array   $updateArray
255
   * @param array   $ignoreArray
256
   * @param DB|null $dbConnection <p>Use <strong>null</strong> to get your first singleton instance.</p>
257
   * @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p>
258
   *
259
   * @return bool|int "int" (insert_id) by "<b>INSERT / REPLACE</b>"-queries<br />
260
   *                   "false" on error
261
   */
262
  public static function copyTableRow($table, array $whereArray, array $updateArray = array(), array $ignoreArray = array(), DB $dbConnection = null, $databaseName = null)
263
  {
264
    // init
265
    $table = trim($table);
266
267
    if ($dbConnection === null) {
268
      $dbConnection = DB::getInstance();
269
    }
270
271
    if ($table === '') {
272
      $debug = new Debug($dbConnection);
273
      $debug->displayError('invalid table name');
274
275
      return false;
276
    }
277
278
    $whereSQL = $dbConnection->_parseArrayPair($whereArray, 'AND');
279
    if ($whereSQL) {
280
      $whereSQL = 'AND ' . $whereSQL;
281
    }
282
283
    if ($databaseName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $databaseName of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
284
      $databaseName = $dbConnection->quote_string(trim($databaseName)) . '.';
285
    }
286
287
    // get the row
288
    $query = 'SELECT * FROM ' . $databaseName . $dbConnection->quote_string($table) . '
289
      WHERE 1 = 1
290
      ' . $whereSQL . '
291
    ';
292
    $result = $dbConnection->query($query);
293
294
    // make sure the row exists
295
    if ($result->num_rows > 0) {
296
297
      /** @noinspection LoopWhichDoesNotLoopInspection */
298
      /** @noinspection PhpAssignmentInConditionInspection */
299
      while ($tmpArray = $result->fetchArray()) {
300
301
        // re-build a new DB query and ignore some field-names
302
        $bindings = array();
303
        $insert_keys = '';
304
        $insert_values = '';
305
306
        foreach ($tmpArray as $fieldName => $value) {
307
308
          if (!in_array($fieldName, $ignoreArray, true)) {
309
            if (array_key_exists($fieldName, $updateArray)) {
310
              $insert_keys .= ',' . $fieldName;
311
              $insert_values .= ',?';
312
              $bindings[] = $updateArray[$fieldName]; // INFO: do not escape non selected data
313
            } else {
314
              $insert_keys .= ',' . $fieldName;
315
              $insert_values .= ',?';
316
              $bindings[] = $value; // INFO: do not escape non selected data
317
            }
318
          }
319
        }
320
321
        $insert_keys = ltrim($insert_keys, ',');
322
        $insert_values = ltrim($insert_values, ',');
323
324
        // insert the "copied" row
325
        $new_query = 'INSERT INTO ' . $databaseName . $dbConnection->quote_string($table) . ' 
326
          (' . $insert_keys . ')
327
          VALUES 
328
          (' . $insert_values . ')
329
        ';
330
        return $dbConnection->query($new_query, $bindings);
331
      }
332
    }
333
334
    return false;
335
  }
336
}
337