PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.1
Booking for Appointments and Events Calendar – Amelia v2.4.1
2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Infrastructure / DB / WPDB / Statement.php
ameliabooking / src / Infrastructure / DB / WPDB Last commit date
Connection.php 5 months ago Statement.php 3 months ago
Statement.php
157 lines
1 <?php
2
3 namespace AmeliaBooking\Infrastructure\DB\WPDB;
4
5 use wpdb;
6
7 class Statement
8 {
9 public const FETCH_ASSOC = 'assoc';
10 public const FETCH_COLUMN = 'column';
11
12 /** @var wpdb */
13 private $wpdb;
14
15 /** @var string */
16 private $statement;
17
18 /** @var array */
19 private $bindings = [];
20
21 /** @var int */
22 private $fetchIndex = 0;
23
24 /** @var array|null Cached result set for fetch operations */
25 private $results = null;
26
27 /** @var int */
28 private $affectedRows = 0;
29
30 /**
31 * @param wpdb $wpdb
32 * @param string $statement
33 */
34 public function __construct($wpdb, $statement)
35 {
36 $this->wpdb = $wpdb;
37 $this->statement = $statement;
38 }
39
40 /**
41 * @param int|string $parameter
42 * @param mixed $variable
43 */
44 public function bindValue($parameter, $variable)
45 {
46 $this->bindings[$parameter] = $variable;
47 }
48
49 /**
50 * @param int|string $parameter
51 * @param mixed $variable
52 */
53 public function bindParam($parameter, $variable)
54 {
55 $this->bindValue($parameter, $variable);
56 }
57
58 /**
59 * Execute the statement.
60 * Accepts optional params array (e.g. [':id' => 5]).
61 * Repositories previously called execute($params); this now works.
62 *
63 * @param array $params
64 * @return void
65 */
66 public function execute(array $params = [])
67 {
68 // Merge passed params into bindings (allows both bindParam + execute($params))
69 if ($params) {
70 foreach ($params as $key => $value) {
71 $this->bindings[$key] = $value;
72 }
73 }
74
75 $query = $this->statement;
76
77 if ($this->bindings) {
78 // Sort bindings by key length, descending, to avoid replacing ":p1" with value of ":p10"
79 uksort($this->bindings, function ($a, $b) {
80 return strlen($b) - strlen($a);
81 });
82
83 foreach ($this->bindings as $placeholder => $value) {
84 $replacement = 'NULL';
85
86 if ($value !== null) {
87 $format = is_int($value) || is_bool($value) ? '%d' : (is_float($value) ? '%f' : '%s');
88 $replacement = $this->wpdb->prepare($format, $value);
89 }
90
91 $query = str_replace($placeholder, $replacement, $query);
92 }
93 }
94
95 $this->fetchIndex = 0; // reset pointer for subsequent fetch() calls
96
97 // Execute using query() - this handles all query types (SELECT, INSERT, UPDATE, etc.)
98 // It populates $wpdb->last_result (for rows) and returns the count
99 $result = $this->wpdb->query($query);
100
101 if ($result === false) {
102 $this->results = [];
103 $this->affectedRows = 0;
104 throw new \RuntimeException($this->wpdb->last_error ?: 'Database query failed.');
105 }
106
107 // Capture affected rows immediately so it's stable even if other WP queries run later
108 $this->affectedRows = (int) $result;
109
110 // If the query produced results (SELECT, SHOW, etc.), wpdb stores them in last_result as objects
111 // Convert objects to arrays to match PDO::FETCH_ASSOC behavior
112 $this->results = array_map(function ($row) {
113 return (array) $row;
114 }, $this->wpdb->last_result ?? []);
115 }
116
117 /**
118 * @param string $fetchMode Fetch mode (FETCH_ASSOC or FETCH_COLUMN)
119 * @return array
120 */
121 public function fetchAll(string $fetchMode = self::FETCH_ASSOC)
122 {
123 if (!$this->results) {
124 return [];
125 }
126
127 // If FETCH_COLUMN, return only the first column from each row
128 if ($fetchMode === self::FETCH_COLUMN) {
129 return array_map(function ($row) {
130 return reset($row); // Get first value from associative array
131 }, $this->results);
132 }
133
134 return $this->results;
135 }
136
137 /**
138 * @return array|false
139 */
140 public function fetch()
141 {
142 if ($this->results && isset($this->results[$this->fetchIndex])) {
143 return $this->results[$this->fetchIndex++];
144 }
145
146 return false;
147 }
148
149 /**
150 * @return int
151 */
152 public function rowCount()
153 {
154 return $this->affectedRows;
155 }
156 }
157