Issues (3)

src/Wrapper.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Compolomus\Mysqli;
6
7
use mysqli;
8
use mysqli_driver;
9
use mysqli_stmt;
10
11
class Wrapper
12
{
13
    public const FETCHTOARRAY = 0;
14
15
    public const FETCHTOOBJECT = 1;
16
17
    private mysqli $mysqli;
18
19
    private ?mysqli_stmt $stmt = null;
20
21 10
    public function __construct(mysqli $mysqli)
22
    {
23 10
        $this->mysqli = $mysqli;
24 10
        $driver = new mysqli_driver();
25 10
        $driver->report_mode = MYSQLI_REPORT_STRICT;
26 10
    }
27
28 8
    public function query(string $query, ?array $placeholders = null)
29
    {
30 8
        $this->stmt = $this->mysqli->prepare($query);
31
32 8
        if ($placeholders && $this->countParams() === count($placeholders)) {
33 4
            $this->bindParam($placeholders);
34
        }
35
36 8
        $this->stmt->execute();
37
38 8
        if (!$this->isFetch($query)) {
39 4
            return $this->stmt->affected_rows;
40
        }
41
42 4
        if ($placeholders) {
43 2
            $this->bindResult();
44
        }
45
46 4
        return $this;
47
    }
48
49 4
    public function result($mode = self::FETCHTOARRAY)
50
    {
51 4
        $data = [];
52 4
        $method = $mode ? 'fetch_object' : 'fetch_assoc';
53
54 4
        $x = 0;
55 4
        $res = $this->stmt->get_result();
56 4
        while ($row = $res->$method()) {
57 4
            $data[] = $row;
58 4
            $x++;
59
        }
60
61 4
        return $this->count_fields() === 1 && $x === 1 ? array_values($data[0])[0] : $data;
62
    }
63
64 2
    private function bindResult(): void
65
    {
66 2
        call_user_func_array([$this->stmt, 'bind_result'], $this->getMeta());
67 2
    }
68
69 2
    private function getMeta(): array
70
    {
71 2
        $binds = [];
72 2
        $meta = $this->stmt->result_metadata();
73 2
        while ($field = $meta->fetch_field()) {
74 2
            $binds[] = &$row[$field->name];
75
        }
76
77 2
        return $binds;
78
    }
79
80 4
    private function bindParam(array $placeholders): void
81
    {
82 4
        @call_user_func([$this->stmt, 'bind_param'], $this->placeholdersTypes($placeholders), ...$placeholders);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for call_user_func(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

82
        /** @scrutinizer ignore-unhandled */ @call_user_func([$this->stmt, 'bind_param'], $this->placeholdersTypes($placeholders), ...$placeholders);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
83 4
    }
84
85 4
    private function placeholdersTypes(array $placeholders): string
86
    {
87 4
        return implode('', array_map([$this, 'types'], $placeholders));
88
    }
89
90 4
    private function types($value): string
91
    {
92 4
        return is_numeric($value)
93 4
            ? (is_float($value) ? 'd' : 'i') // int or float
94 4
            : (strlen((string)$value) <= 65536 ? 's' : 'b'); // string or blob
95
    }
96
97 4
    private function countParams(): int
98
    {
99 4
        return $this->stmt->param_count;
100
    }
101
102 8
    private function isFetch(string $query): bool
103
    {
104 8
        return false !== stripos($query, 'select');
105
    }
106
107 4
    private function count_fields(): int
108
    {
109 4
        return $this->stmt->field_count;
110
    }
111
}
112