Completed
Pull Request — master (#2282)
by ྅༻ Ǭɀħ
01:46
created

Logger::addProfile()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 3
nop 4
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * YOURLS simple logger
5
 *
6
 * @since 1.7.3
7
 */
8
9
namespace YOURLS\Admin;
10
11
use YOURLS\Database\YDB;
12
13
class Logger extends \Aura\Sql\Profiler {
14
15
    /**
16
     * the YDB instance
17
     * @var YOURLS\Database\YDB
18
     */
19
    protected $ydb;
20
21
    /**
22
     * Debug log where messages are stored
23
     * @var array
24
     */
25
    protected $debug_log = array();
26
27
    /**
28
     * Are we emulating prepare statements ?
29
     * @var bool
30
     */
31
    protected $is_emulate_prepare;
32
33
    public function __construct(YDB $ydb) {
34
        $this->ydb = $ydb;
0 ignored issues
show
Documentation Bug introduced by
It seems like $ydb of type object<YOURLS\Database\YDB> is incompatible with the declared type object<YOURLS\Admin\YOURLS\Database\YDB> of property $ydb.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
35
        /**
36
         * @todo Extend this to allow calling an external logger
37
         */
38
39
        /* Check if current driver can PDO::getAttribute(PDO::ATTR_EMULATE_PREPARES)
40
         * Some combinations of PHP/MySQL don't support this function. See
41
         * https://travis-ci.org/YOURLS/YOURLS/jobs/271423782#L481
42
         */
43
        try {
44
            $this->is_emulate_prepare = $this->ydb->getAttribute(\PDO::ATTR_EMULATE_PREPARES);
45
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class YOURLS\Admin\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
46
            $this->is_emulate_prepare = false;
47
        }
48
    }
49
50
    /**
51
     * @param string $message
52
     */
53
    public function log($message) {
54
        yourls_do_action('debug_log', $message);
55
        $this->debug_log[] = $message;
56
    }
57
58
    public function get_log() {
59
        return $this->debug_log;
60
    }
61
62
    /**
63
     * Extends \Aura\Sql\Profiler::addProfile() to log queries in our YOURLS logger
64
     *
65
     * @since  1.7.3
66
     * @param  float  $duration     The query duration.
67
     * @param  string $function     The PDO method that made the entry.
68
     * @param  string $statement    The SQL query statement.
69
     * @param  array  $bind_values  The values bound to the statement.
70
     * @return void
71
     */
72
    public function addProfile($duration, $function, $statement, array $bind_values = array() ) {
73
        parent::addProfile($duration, $function, $statement, $bind_values);
74
75
        if($function == 'connect') {
76
            $this->log( sprintf('SQL: CONNECT (%s s)', number_format($duration, 5)) );
77
            return;
78
        }
79
80
        // If we are emulating prepare, don't log 'prepare' statement, as they are not actual queries sent to the server
81
        if ($this->is_emulate_prepare && $function !== 'prepare') {
82
            $this->log( sprintf('SQL: %s (%s s)', $this->pretty_format($statement, $bind_values), number_format($duration, 5) ) );
83
        }
84
    }
85
86
    /**
87
     * Format PDO statement with bind/values replacement
88
     *
89
     * This replaces PDO binds such as 'key_name = :name' with corresponding array values, eg array('name'=>'some value')
90
     * This is merely a cosmetic replacement to allow for readability: the result WILL NOT be valid SQL! (eg no proper quotes)
91
     *
92
     * @since  1.7.3
93
     * @param  string $statement  SQL query with PDO style named placeholders
94
     * @param  array  $values     Optional array of values corresponding to placeholders
95
     * @return string             Readable SQL query with placeholders replaced
96
     */
97
    public function pretty_format($statement, array $values = array() ) {
98
        if (!$values) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $values of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
99
            return $statement;
100
        }
101
102
        return preg_replace_callback(
103
            '/:([^\s;)]*)/',
104
105
            /**
106
             * @param string $matches
107
             */
108
            function ($matches) use ($values) {
109
                $replacement = isset( $values[$matches[1]] ) ? $values[$matches[1]] : '';
110
                if(is_array($replacement)) {
111
                    $replacement = implode(",", $replacement);
112
                }
113
                return "'$replacement'";
114
            },
115
            $statement
116
        );
117
    }
118
119
}
120