Exception:Array
(
[message] => Call to undefined function mysqli_report()
[file] => /home/www/vvveb/www/system/db/mysqli.php
[line_no] => 120
[line] => \mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // <==
[lines] => Array
(
[0] => public function connect(string $host = DB_HOST, string $dbname = DB_NAME, string $user = DB_USER, string $pass = DB_PASS, ?int $port = DB_PORT, string $prefix = DB_PREFIX): ?\mysqli {
[1] => //connect to database
[2] => if (self :: $link) {
[3] => return self :: $link;
[4] => }
[5] => $this->prefix = $prefix;
[6] =>
[7] => \mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // <==
[8] =>
[9] => try {
[10] => self :: $link = new \mysqli($host, $user, $pass, $dbname, $port);
[11] => } catch (\mysqli_sql_exception $e) {
[12] => $errorMessage = str_replace($pass, '*****', $e->getMessage());
[13] =>
)
[trace] => #0 /home/www/vvveb/www/system/db/mysqli.php(441): Vvveb\System\Db\Mysqli->connect()
#1 /home/www/vvveb/www/storage/model/app/settingsql.mysqli.php(308): Vvveb\System\Db\Mysqli->execute()
#2 /home/www/vvveb/www/system/setting.php(143): Vvveb\Sql\SettingSQL->getMulti()
#3 /home/www/vvveb/www/system/functions/settings.php(36): Vvveb\System\Setting->get()
#4 /home/www/vvveb/www/plugins/insert-scripts/plugin.php(66): Vvveb\getSetting()
#5 /home/www/vvveb/www/plugins/insert-scripts/plugin.php(80): InsertScriptsPlugin->app()
#6 /home/www/vvveb/www/plugins/insert-scripts/plugin.php(85): InsertScriptsPlugin->__construct()
#7 /home/www/vvveb/www/system/extensions/plugins.php(354): include('...')
#8 /home/www/vvveb/www/system/core/startup.php(512): Vvveb\System\Extensions\Plugins::loadPlugins()
#9 /home/www/vvveb/www/index.php(170): Vvveb\System\Core\start()
#10 /home/www/vvveb/www/public/index.php(28): include('...')
#11 {main}
[code] => Array
(
[0] =>
[2] => /**
[3] => * Vvveb
[4] => *
[5] => * Copyright (C) 2022 Ziadin Givan
[6] => *
[7] => * This program is free software: you can redistribute it and/or modify
[8] => * it under the terms of the GNU Affero General Public License as
[9] => * published by the Free Software Foundation, either version 3 of the
[10] => * License, or (at your option) any later version.
[11] => *
[12] => * This program is distributed in the hope that it will be useful,
[13] => * but WITHOUT ANY WARRANTY; without even the implied warranty of
[14] => * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
[15] => * GNU Affero General Public License for more details.
[16] => *
[17] => * You should have received a copy of the GNU Affero General Public License
[18] => * along with this program. If not, see .
[19] => *
[20] => */
[21] =>
[22] => namespace Vvveb\System\Db;
[23] =>
[24] => use Vvveb\System\Event;
[25] =>
[26] => class Mysqli extends DBDriver {
[27] => /** @var ?\MySQLi The shared database connection (singleton per process). */
[28] => private static ?\mysqli $link = null;
[29] =>
[30] => /** @var int Number of rows affected by the last query. */
[31] => public int $affected_rows = 0;
[32] =>
[33] => /** @var ?int The auto-increment ID generated by the last INSERT. */
[34] => public ?int $insert_id = null;
[35] =>
[36] => /** @var string Identifier quote character for MySQL. */
[37] => public string $quote = '`';
[38] =>
[39] => /** @var string Table name prefix. */
[40] => public string $prefix = ''; //'vv_';
[41] =>
[42] => /**
[43] => * Get the MySQL server version as an integer.
[44] => *
[45] => * @return int|null The server version (e.g. 80031) or null if not connected.
[46] => */
[47] => public static function version(): ?int {
[48] => if (self :: $link) {
[49] => return mysqli_get_server_version(self :: $link);
[50] => }
[51] =>
[52] => return null;
[53] => }
[54] =>
[55] => /**
[56] => * Get the MySQL server version string.
[57] => *
[58] => * @return string|null The version string (e.g. '8.0.31') or null if not connected.
[59] => */
[60] => public static function info(): ?string {
[61] => if (self :: $link) {
[62] => return mysqli_get_server_info(self :: $link);
[63] => }
[64] =>
[65] => return null;
[66] => }
[67] =>
[68] => /**
[69] => * Get the error message from the last MySQL operation.
[70] => *
[71] => * @return string|null The error message, or null if not connected.
[72] => */
[73] => public function error(): ?string {
[74] => if (self :: $link) {
[75] => return self :: $link->error;
[76] => }
[77] =>
[78] => return null;
[79] => }
[80] =>
[81] => /**
[82] => * Get the error code from the last MySQL operation.
[83] => *
[84] => * @return int|null The error code, or null if not connected.
[85] => */
[86] => public function errorCode(): ?int {
[87] => if (self :: $link) {
[88] => return self :: $link->errno;
[89] => }
[90] =>
[91] => return null;
[92] => }
[93] =>
[94] => public function __construct() {}
[95] =>
[96] => /**
[97] => * Connect to the MySQL database.
[98] => *
[99] => * Uses a singleton pattern — returns the existing connection if already open.
[100] => * Throws an exception with a sanitised error message on failure.
[101] => *
[102] => * @param string $host Database host.
[103] => * @param string $dbname Database name.
[104] => * @param string $user Database user.
[105] => * @param string $pass Database password.
[106] => * @param int|null $port Database port.
[107] => * @param string $prefix Table name prefix.
[108] => *
[109] => * @throws \Exception On connection failure.
[110] => *
[111] => * @return ?\MySQLi The database connection, or null on failure.
[112] => */
[113] => public function connect(string $host = DB_HOST, string $dbname = DB_NAME, string $user = DB_USER, string $pass = DB_PASS, ?int $port = DB_PORT, string $prefix = DB_PREFIX): ?\mysqli {
[114] => //connect to database
[115] => if (self :: $link) {
[116] => return self :: $link;
[117] => }
[118] => $this->prefix = $prefix;
[119] =>
[120] => \mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // <==
[121] =>
[122] => try {
[123] => self :: $link = new \mysqli($host, $user, $pass, $dbname, $port);
[124] => } catch (\mysqli_sql_exception $e) {
[125] => $errorMessage = str_replace($pass, '*****', $e->getMessage());
[126] =>
[127] => throw new \Exception($errorMessage, $e->getCode());
[128] => }
[129] =>
[130] => // check if a connection established
[131] => if (\mysqli_connect_errno()) {
[132] => $error = mysqli_connect_error();
[133] => $errorMessage = str_replace($pass, '*****', $error);
[134] =>
[135] => throw new \Exception($errorMessage, mysqli_connect_errno());
[136] => }
[137] =>
[138] => //sync database time
[139] => //$this->execute('SET `time_zone` = :zone', ['zone' => $this->escape(date('P'))]);
[140] =>
[141] => return self :: $link;
[142] => }
[143] =>
[144] => /**
[145] => * Get all columns for a table used for sanitizing input.
[146] => *
[147] => * @param string $tableName The table name to introspect.
[148] => * @param bool $comment Whether to include the column comment field.
[149] => *
[150] => * @return array|false
[151] => * Associative array keyed by column name, or false on failure.
[152] => */
[153] => public function getColumnsMeta(string $tableName, bool $comment = false): array|false {
[154] => $sql =
[155] => 'SELECT COLUMN_NAME as name, COLUMN_DEFAULT as d, IS_NULLABLE as n, DATA_TYPE as t, EXTRA as e, CHARACTER_MAXIMUM_LENGTH as l'
[156] => . ($comment ? ', COLUMN_COMMENT as c' : '') .
[157] => ' FROM `INFORMATION_SCHEMA`.`COLUMNS`
[158] => WHERE `TABLE_SCHEMA`= "' . DB_NAME . '"
[159] => AND `TABLE_NAME`="' . $tableName . '"';
[160] =>
[161] => if ($result = $this->query($sql)) {
[162] => //$columns = $result->fetch_all(MYSQLI_ASSOC);
[163] => $columns = [];
[164] =>
[165] => while ($row = $result->fetch_assoc()) {
[166] => $columns[$row['name']] = $row;
[167] => }
[168] =>
[169] => // free result set
[170] => $result->close();
[171] =>
[172] => return $columns;
[173] => }
[174] =>
[175] => return false;
[176] => }
[177] =>
[178] => /**
[179] => * Get all table names in the database.
[180] => *
[181] => * @param string $db The database name.
[182] => *
[183] => * @return array|false List of table names, or false on failure.
[184] => */
[185] => public function getTableNames(string $db = DB_NAME): array|false {
[186] => $sql = "SELECT table_name as name
[187] => FROM information_schema.tables
[188] => WHERE table_schema = '$db' ORDER BY table_name";
[189] =>
[190] => if ($result = $this->query($sql)) {
[191] => //$names = $result->fetch_all(MYSQLI_ASSOC);
[192] => $names = [];
[193] =>
[194] => while ($row = $result->fetch_assoc()) {
[195] => $names[] = $row['name'];
[196] => }
[197] =>
[198] => // free result set
[199] => $result->close();
[200] =>
[201] => return $names;
[202] => }
[203] =>
[204] => return false;
[205] => }
[206] =>
[207] => /**
[208] => * Select a different database on the current connection.
[209] => *
[210] => * @param string $db The database name.
[211] => *
[212] => * @return bool True on success, false on failure.
[213] => */
[214] => public function select_db(string $db): bool {
[215] => return self :: $link->select_db($db);
[216] => }
[217] =>
[218] => /**
[219] => * Execute a raw SQL query.
[220] => *
[221] => * Automatically connects if not connected. Updates affected_rows and insert_id.
[222] => *
[223] => * @param string $sql The SQL query to execute.
[224] => *
[225] => * @throws \Exception On query failure.
[226] => *
[227] => * @return bool|\mysqli_result Query result or true for success, false on failure.
[228] => */
[229] => public function query(string $sql): bool|\mysqli_result {
[230] => if (!self :: $link) {
[231] => $this->connect();
[232] => }
[233] =>
[234] => if (LOG_SQL_QUERIES) {
[235] => error_log($sql);
[236] => }
[237] =>
[238] => try {
[239] => $result = self :: $link->query($sql);
[240] => } catch (\mysqli_sql_exception $e) {
[241] => $message = $e->getMessage() . "\n" . $sql . "\n - " . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1), true);
[242] =>
[243] => throw new \Exception($message, $e->getCode());
[244] => }
[245] =>
[246] => if ($result) {
[247] => $this->affected_rows = self :: $link->affected_rows;
[248] => $this->insert_id = self :: $link->insert_id;
[249] => }
[250] =>
[251] => return $result;
[252] => }
[253] =>
[254] => /**
[255] => * Execute multiple SQL statements in a single call.
[256] => *
[257] => * @param string $sql The SQL statements to execute (semicolon-separated).
[258] => *
[259] => * @return bool True on success, false on failure.
[260] => */
[261] => public function multi_query(string $sql): bool {
[262] => if (!self :: $link) {
[263] => $this->connect();
[264] => }
[265] =>
[266] => $result = self :: $link->multi_query($sql);
[267] =>
[268] => if ($result) {
[269] => $this->affected_rows = self :: $link->affected_rows;
[270] => $this->insert_id = self :: $link->insert_id;
[271] => }
[272] =>
[273] => return $result;
[274] => }
[275] =>
[276] => /**
[277] => * Escape a value for safe inclusion in a SQL query.
[278] => *
[279] => * Strings are escaped with real_escape_string. Null values become 'null'.
[280] => * All other types are returned as-is.
[281] => *
[282] => * @param mixed $string The value to escape.
[283] => *
[284] => * @return mixed The escaped value.
[285] => */
[286] => public function escape(mixed $string): mixed {
[287] => if (is_string($string)) {
[288] => return self :: $link->real_escape_string($string);
[289] => }
[290] =>
[291] => if (is_null($string)) {
[292] => return 'null';
[293] => }
[294] =>
[295] => return $string;
[296] => }
[297] =>
[298] => /**
[299] => * Escape a string value for use in a SQL literal.
[300] => *
[301] => * @param string $string The string to escape.
[302] => *
[303] => * @return string The escaped string.
[304] => */
[305] => public function escapeLiteral(string $string): string {
[306] => return $this->escape($string);
[307] => }
[308] =>
[309] => /**
[310] => * Generate a MySQL-compatible LIMIT clause.
[311] => *
[312] => * @param int|string $start Offset (0-based).
[313] => * @param int|string $limit Maximum number of rows.
[314] => *
[315] => * @return string The LIMIT clause (e.g. 'LIMIT 0, 10').
[316] => */
[317] => public function sqlLimit(int|string $start, int|string $limit): string {
[318] => return "LIMIT $start, $limit";
[319] => }
[320] =>
[321] => /**
[322] => * Fetch a single row from a statement or result set.
[323] => *
[324] => * @param \mysqli_stmt|\mysqli_result $stmt The statement or result to fetch from.
[325] => *
[326] => * @return array The fetched row, or empty array if no rows.
[327] => */
[328] => public function fetchArray(\mysqli_stmt|\mysqli_result $stmt): array {
[329] => $data = [];
[330] => $statement = ($stmt instanceof \mysqli_stmt);
[331] =>
[332] => if ($statement) {
[333] => $this->store_result();
[334] => $result = $stmt->get_result();
[335] => } else {
[336] => $result = $stmt;
[337] => }
[338] =>
[339] => if ($result) {
[340] => $result = $result->fetch_array(MYSQLI_ASSOC);
[341] =>
[342] => if ($result) {
[343] => $data = $result;
[344] =>
[345] => if ($statement && $stmt->more_results()) {
[346] => $stmt->next_result();
[347] => }
[348] => }
[349] => }
[350] =>
[351] => return $data;
[352] => }
[353] =>
[354] => /**
[355] => * Fetch all rows from a statement or result set.
[356] => *
[357] => * @param \mysqli_stmt|\mysqli_result $stmt The statement or result to fetch from.
[358] => *
[359] => * @return array> All result rows.
[360] => */
[361] => public function fetchAll(\mysqli_stmt|\mysqli_result $stmt): array {
[362] => $data = [];
[363] => $statement = ($stmt instanceof \mysqli_stmt);
[364] =>
[365] => if ($statement) {
[366] => $this->store_result();
[367] => $result = $stmt->get_result();
[368] => } else {
[369] => $result = $stmt;
[370] => }
[371] =>
[372] => if ($result) {
[373] => $data = $result->fetch_all(MYSQLI_ASSOC);
[374] => }
[375] =>
[376] => return $data;
[377] => }
[378] =>
[379] => /**
[380] => * Store the result of the last query in the client-side buffer.
[381] => *
[382] => * @return \mysqli_result|false The stored result, or false on failure.
[383] => */
[384] => public function store_result(): \mysqli_result|false {
[385] => return self :: $link->store_result();
[386] => }
[387] =>
[388] => /**
[389] => * Check if the current statement has more result sets.
[390] => *
[391] => * @return bool True if more results are available.
[392] => */
[393] => public function more_results(): bool {
[394] => return self :: $link->more_results();
[395] => }
[396] =>
[397] => /**
[398] => * Move to the next result set in a multi-query.
[399] => *
[400] => * @return bool True on success, false on failure.
[401] => */
[402] => public function next_result(): bool {
[403] => return self :: $link->next_result();
[404] => }
[405] =>
[406] => /**
[407] => * Close the database connection.
[408] => *
[409] => * @return ?bool True on success, null if not connected.
[410] => */
[411] => public function close(): ?bool {
[412] => if ((self :: $link instanceof \mysqli)/* && self :: $link->ping()*/) {
[413] => return self :: $link->close();
[414] => }
[415] =>
[416] => return null;
[417] => }
[418] =>
[419] => /**
[420] => * Prepare and execute a parameterized query.
[421] => *
[422] => * Fires an Event::trigger hook before execution. Converts named parameters
[423] => * to positional placeholders, binds parameters, and executes the statement.
[424] => * Updates affected_rows and insert_id on success.
[425] => *
[426] => * @param string $sql The SQL query with :named parameters.
[427] => * @param array $params Named parameter values.
[428] => * @param array $paramTypes Optional explicit type overrides.
[429] => *
[430] => * @throws \Exception On prepare or execute failure.
[431] => *
[432] => * @return ?\mysqli_stmt The executed statement, or null on failure.
[433] => */
[434] => public function execute(string $sql, array $params = [], array $paramTypes = []): ?\mysqli_stmt {
[435] => [$sql, $params] = Event::trigger(__CLASS__, __FUNCTION__, $sql, $params);
[436] => //save orig sql for debugging info
[437] => $origSql = $sql;
[438] =>
[439] => if (!self :: $link) {
[440] => $this->connect();
[441] => }
[442] =>
[443] => [$parameters, $types] = $this->paramsToQmark($sql, $params, $paramTypes);
[444] =>
[445] => try {
[446] => $stmt = self::$link->prepare($sql);
[447] => } catch (\mysqli_sql_exception $e) {
[448] => $message = $e->getMessage() . "\n" . $this->debugSql($origSql, $params, $paramTypes) . "\n - " . $origSql . "\n - " . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1), true);
[449] =>
[450] => throw new \Exception($message, $e->getCode());
[451] => }
[452] =>
[453] => if ($stmt && !empty($types)) {
[454] => array_unshift($parameters, $types);
[455] =>
[456] => //hack for php 7.x bind_param "expected to be a reference, value given" stupid warning
[457] => $referenceArray = [];
[458] =>
[459] => foreach ($parameters as $key => $value) {
[460] => $referenceArray[$key] = &$parameters[$key];
[461] => }
[462] =>
[463] => @call_user_func_array([$stmt, 'bind_param'], $referenceArray);
[464] => }
[465] =>
[466] => if (LOG_SQL_QUERIES) {
[467] => error_log($this->debugSql($origSql, $params, $paramTypes));
[468] => }
[469] =>
[470] => if ($stmt) {
[471] => try {
[472] => if ($stmt->execute()) {
[473] => $this->affected_rows = self :: $link->affected_rows;
[474] => $this->insert_id = self :: $link->insert_id;
[475] =>
[476] => return $stmt;
[477] => } else {
[478] => error_log(print_r($stmt, true));
[479] => error_log($this->debugSql($sql, $params, $paramTypes));
[480] => }
[481] => } catch (\mysqli_sql_exception $e) {
[482] => $message = $e->getMessage() . "\n" . $origSql . "\n" . $this->debugSql($origSql, $params, $paramTypes) . "\n" . print_r($parameters, true) . $types . "\n" . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1), true);
[483] =>
[484] => throw new \Exception($message, $e->getCode());
[485] => }
[486] => } else {
[487] => error_log(print_r($stmt, true));
[488] => error_log($this->debugSql($origSql, $params, $paramTypes));
[489] => }
[490] =>
[491] => return $stmt;
[492] => }
[493] => }
)
)