Hash   B
last analyzed

Complexity

Total Complexity 48

Size/Duplication

Total Lines 185
Duplicated Lines 11.89 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 22
loc 185
rs 8.5599
c 0
b 0
f 0
wmc 48
lcom 0
cbo 1

9 Methods

Rating   Name   Duplication   Size   Complexity  
A make() 0 3 2
A verify() 0 3 1
A methods() 0 4 1
A can() 0 4 1
A __callStatic() 0 3 1
B uuid() 22 40 8
F murmur() 0 37 20
A random() 0 3 1
C random_bytes() 0 40 13

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Hash often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Hash, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Hash
5
 *
6
 * Hashing shorthands.
7
 *
8
 * @package core
9
 * @author [email protected]
10
 * @copyright Caffeina srl - 2015 - http://caffeina.it
11
 */
12
13
class Hash {
14
	use Module;
15
16
	/**
17
   * Create ah hash for payload
18
   * @param  mixed $payload    The payload string/object/array
19
   * @param  integer $method   The hashing method, default is "md5"
20
   * @param  bool $raw_output  When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.
21
   * @return string            The hash string
22
   */
23
	public static function make($payload, $method = 'md5', $raw_output = false) {
24
		return $method == 'murmur' ? static::murmur(serialize($payload)) : hash($method, serialize($payload), $raw_output);
25
	}
26
27
	/**
28
	 * Verify if given payload matches hash
29
	 * @param  mixed $payload  The payload string/object/array
30
	 * @param  string $hash    The hash string
31
	 * @param  integer $method The hashing method
32
	 * @return bool            Returns `true` if payload matches hash
33
	 */
34
	public static function verify($payload, $hash, $method = 'md5') {
35
		return static::make($payload, $method) == $hash;
36
	}
37
38
	/**
39
	 * List registered hashing algorithms
40
	 *
41
	 * @method methods
42
	 *
43
	 * @return array   Array containing the list of supported hashing algorithms.
44
	 */
45
	public static function methods() {
46
    // Merge PHP provided algos with ours (murmur)
47
		return array_merge(hash_algos(), ['murmur','murmurhash3']);
48
	}
49
50
	/**
51
	 * Check if an alghoritm is registered in current PHP
52
	 *
53
	 * @method can
54
	 *
55
	 * @param  string $algo The hashing algorithm name
56
	 *
57
	 * @return bool
58
	 */
59
	public static function can($algo) {
60
    // Faster than : in_array(explode(',',implode(',',static::methods())))
61
		return strpos(implode(',',static::methods()).',', "$algo,") !== false;
62
	}
63
64
	/**
65
	 * Static magic for creating hashes with a specified algorithm.
66
	 *
67
	 * See [hash-algos](http://php.net/manual/it/function.hash-algos.php) for a list of algorithms
68
	 */
69
	public static function __callStatic($method, $params) {
70
		return self::make(current($params), $method);
71
	}
72
73
	public static function uuid($type = 4, $namespace = '', $name = '') {
74
		switch ($type) {
75 View Code Duplication
		case 3:if (preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?' .
76
				'[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/Si', $namespace) !== 1) {
77
				return false;
78
			}
79
80
			$nhex = str_replace(array('-', '{', '}'), '', $namespace);
81
			$nstr = '';for ($i = 0; $i < strlen($nhex); $i += 2) {
82
				$nstr .= chr(hexdec($nhex[$i] . $nhex[$i + 1]));
83
			}
84
85
			$hash = md5($nstr . $name);
86
			return sprintf('%08s-%04s-%04x-%04x-%12s',
87
				substr($hash, 0, 8), substr($hash, 8, 4),
88
				(hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x3000,
89
				(hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
90
				substr($hash, 20, 12));
91 View Code Duplication
		case 5:if (preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?' .
92
				'[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/Si', $namespace) !== 1) {
93
				return false;
94
			}
95
96
			$nhex = str_replace(array('-', '{', '}'), '', $namespace);
97
			$nstr = '';for ($i = 0; $i < strlen($nhex); $i += 2) {
98
				$nstr .= chr(hexdec($nhex[$i] . $nhex[$i + 1]));
99
			}
100
101
			$hash = sha1($nstr . $name);
102
			return sprintf('%08s-%04s-%04x-%04x-%12s',
103
				substr($hash, 0, 8), substr($hash, 8, 4),
104
				(hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x5000,
105
				(hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
106
				substr($hash, 20, 12));
107
		default:case 4:return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
108
				mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
109
				mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
110
				mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
111
		}
112
	}
113
114
  public static function murmur($key, $seed = 0, $as_integer=false) {
115
    $key  = array_values(unpack('C*',(string) $key));
116
    $klen = count($key);
117
    $h1   = (int)$seed;
118
    for ($i=0,$bytes=$klen-($remainder=$klen&3) ; $i<$bytes ; ) {
119
      $k1 = $key[$i]
120
        | ($key[++$i] << 8)
121
        | ($key[++$i] << 16)
122
        | ($key[++$i] << 24);
123
      ++$i;
124
      $k1  = (((($k1 & 0xffff) * 0xcc9e2d51) + ((((($k1 >= 0 ? $k1 >> 16 : (($k1 & 0x7fffffff) >> 16) | 0x8000)) * 0xcc9e2d51) & 0xffff) << 16))) & 0xffffffff;
125
      $k1  = $k1 << 15 | ($k1 >= 0 ? $k1 >> 17 : (($k1 & 0x7fffffff) >> 17) | 0x4000);
126
      $k1  = (((($k1 & 0xffff) * 0x1b873593) + ((((($k1 >= 0 ? $k1 >> 16 : (($k1 & 0x7fffffff) >> 16) | 0x8000)) * 0x1b873593) & 0xffff) << 16))) & 0xffffffff;
127
      $h1 ^= $k1;
128
      $h1  = $h1 << 13 | ($h1 >= 0 ? $h1 >> 19 : (($h1 & 0x7fffffff) >> 19) | 0x1000);
129
      $h1b = (((($h1 & 0xffff) * 5) + ((((($h1 >= 0 ? $h1 >> 16 : (($h1 & 0x7fffffff) >> 16) | 0x8000)) * 5) & 0xffff) << 16))) & 0xffffffff;
130
      $h1  = ((($h1b & 0xffff) + 0x6b64) + ((((($h1b >= 0 ? $h1b >> 16 : (($h1b & 0x7fffffff) >> 16) | 0x8000)) + 0xe654) & 0xffff) << 16));
131
    }
132
    $k1 = 0;
133
    switch ($remainder) {
134
      case 3: $k1 ^= $key[$i + 2] << 16;
135
      case 2: $k1 ^= $key[$i + 1] << 8;
136
      case 1: $k1 ^= $key[$i];
137
      $k1  = ((($k1 & 0xffff) * 0xcc9e2d51) + ((((($k1 >= 0 ? $k1 >> 16 : (($k1 & 0x7fffffff) >> 16) | 0x8000)) * 0xcc9e2d51) & 0xffff) << 16)) & 0xffffffff;
138
      $k1  = $k1 << 15 | ($k1 >= 0 ? $k1 >> 17 : (($k1 & 0x7fffffff) >> 17) | 0x4000);
139
      $k1  = ((($k1 & 0xffff) * 0x1b873593) + ((((($k1 >= 0 ? $k1 >> 16 : (($k1 & 0x7fffffff) >> 16) | 0x8000)) * 0x1b873593) & 0xffff) << 16)) & 0xffffffff;
140
      $h1 ^= $k1;
141
    }
142
    $h1 ^= $klen;
143
    $h1 ^= ($h1 >= 0 ? $h1 >> 16 : (($h1 & 0x7fffffff) >> 16) | 0x8000);
144
    $h1  = ((($h1 & 0xffff) * 0x85ebca6b) + ((((($h1 >= 0 ? $h1 >> 16 : (($h1 & 0x7fffffff) >> 16) | 0x8000)) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
145
    $h1 ^= ($h1 >= 0 ? $h1 >> 13 : (($h1 & 0x7fffffff) >> 13) | 0x40000);
146
    $h1  = (((($h1 & 0xffff) * 0xc2b2ae35) + ((((($h1 >= 0 ? $h1 >> 16 : (($h1 & 0x7fffffff) >> 16) | 0x8000)) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
147
    $h1 ^= ($h1 >= 0 ? $h1 >> 16 : (($h1 & 0x7fffffff) >> 16) | 0x8000);
148
149
		return $as_integer ? $h1 : base_convert($h1 ,10, 32);
150
	}
151
152
  public static function random($bytes=9){
153
    return strtr(base64_encode(static::random_bytes($bytes)),'+/=','-_');
154
  }
155
156
  public static function random_bytes($bytes){
157
    static $randf = null;
158
    if (function_exists('random_bytes')) {
159
      return \random_bytes($bytes);
160
    } else if (function_exists('mcrypt_create_iv')) {
161
      return @\mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
162
    } else {
163
      if (null === $randf) {
164
        if ($randf = fopen('/dev/urandom', 'rb')) {
165
          $st = fstat($randf);
166
          function_exists('stream_set_read_buffer')
167
            && stream_set_read_buffer($randf, 8);
168
          function_exists('stream_set_chunk_size')
169
            && stream_set_chunk_size($randf, 8);
170
          if (($st['mode'] & 0170000) !== 020000) {
171
            fclose($randf);
172
            $randf = false;
173
          }
174
        }
175
      }
176
      if ($randf) {
177
        $remaining = $bytes;
178
        $buf = '';
179
        do {
180
          $read = fread($randf, $remaining);
181
          if ($read === false) {
182
            $buf = false;
183
            break;
184
          }
185
          $remaining -= strlen($read);
186
          $buf .= $read;
187
        } while ($remaining > 0);
188
        if ($buf !== false) {
189
          if (strlen($buf) === $bytes) {
190
            return $buf;
191
          }
192
        }
193
      }
194
    }
195
  }
196
197
}
198