Completed
Push — master ( d4201d...06cb54 )
by Tomáš
03:43
created

Helper   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 42.55%

Importance

Changes 0
Metric Value
wmc 14
lcom 0
cbo 0
dl 0
loc 77
ccs 20
cts 47
cp 0.4255
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
C dumpSql() 0 71 14
1
<?php declare(strict_types=1);
2
3
namespace Portiny\Doctrine\Adapter\Nette\Tracy;
4
5
use Doctrine\DBAL\Connection;
6
use Nette\Utils\Strings;
7
8
final class Helper
9
{
10
	/**
11
	 * Returns syntax highlighted SQL command.
12
	 */
13 1
	public static function dumpSql(string $sql, ?array $params = NULL, ?Connection $connection = NULL): string
14
	{
15 1
		static $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|'
16
			. 'DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|'
17
			. 'INNER\s+JOIN|TRUNCATE';
18 1
		static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|[RI]?LIKE|'
19
			. 'REGEXP|TRUE|FALSE';
20
21
		// insert new lines
22 1
		$sql = " ${sql} ";
23
		$sql = preg_replace("#(?<=[\\s,(])(${keywords1})(?=[\\s,)])#i", "\n\$1", $sql);
24
		// reduce spaces
25 1
		$sql = preg_replace('#[ \t]{2,}#', ' ', $sql);
26 1
		$sql = wordwrap($sql, 100);
27 1
		$sql = preg_replace('#([ \t]*\r?\n){2,}#', "\n", $sql);
28
		// syntax highlight
29 1
		$sql = htmlspecialchars($sql, ENT_IGNORE, 'UTF-8');
30
		$closure = function ($matches) {
31 1
			if (! empty($matches[1])) { // comment
32
				return '<em style="color:gray">' . $matches[1] . '</em>';
33 1
			} elseif (! empty($matches[2])) { // error
34
				return '<strong style="color:red">' . $matches[2] . '</strong>';
35 1
			} elseif (! empty($matches[3])) { // most important keywords
36 1
				return '<strong style="color:blue">' . $matches[3] . '</strong>';
37
			} elseif (! empty($matches[4])) { // other keywords
38
				return '<strong style="color:green">' . $matches[4] . '</strong>';
39
			}
40 1
		};
41 1
		$sql = preg_replace_callback(
42 1
			"#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])(${keywords1})(?=[\\s,)])|'
43 1
			. '(?<=[\\s,(=])(${keywords2})(?=[\\s,)=])#is",
44 1
			$closure,
45 1
			$sql
46
		);
47
48
		// parameters
49
		$sql = preg_replace_callback('#\?#', function () use ($params, $connection) {
50
			static $i = 0;
51
			if (! isset($params[$i])) {
52
				return '?';
53
			}
54
55
			$param = $params[$i++];
56
			if (is_string($param)
57
				&& (preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $param) || preg_last_error())
58
			) {
59
				return '<i title="Length ' . strlen($param) . ' bytes">&lt;binary&gt;</i>';
60
			} elseif (is_string($param)) {
61
				$length = Strings::length($param);
62
				$truncated = Strings::truncate($param, 120);
63
				$text = htmlspecialchars(
64
					$connection ? $connection->quote($truncated) : '\'' . $truncated . '\'',
65
					ENT_NOQUOTES,
66
					'UTF-8'
67
				);
68
				return '<span title="Length ' . $length . ' characters">' . $text . '</span>';
69
			} elseif (is_resource($param)) {
70
				$type = get_resource_type($param);
71
				if ($type === 'stream') {
72
					$info = stream_get_meta_data($param);
73
					return '<i' . (isset($info['uri']) ? ' title="' .
74
							htmlspecialchars($info['uri'], ENT_NOQUOTES, 'UTF-8') . '"' : NULL)
75
						. '>&lt;' . htmlspecialchars($type, ENT_NOQUOTES, 'UTF-8') . ' resource&gt;</i> ';
76
				}
77
			}
78
79
			return htmlspecialchars((string) $param, ENT_NOQUOTES, 'UTF-8');
80 1
		}, $sql);
81
82 1
		return '<pre class="dump">' . trim($sql) . "</pre>\n";
83
	}
84
}
85