1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 13:12:41 +00:00

Support PHP 8.1

This commit is contained in:
J. King 2022-01-11 17:54:02 -05:00
parent b660508009
commit b5579d6e43
18 changed files with 236 additions and 211 deletions

View file

@ -13,7 +13,7 @@ require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
ignore_user_abort(true);
ini_set("memory_limit", "-1");
ini_set("max_execution_time", "0");
// FIXME: This is required by a dependency of Picofeed
// FIXME: This is required because various dependencies have yet to adjust to PHP 8.1
error_reporting(\E_ALL & ~\E_DEPRECATED);
if (\PHP_SAPI === "cli") {

View file

@ -40,6 +40,9 @@
"config": {
"platform": {
"php": "7.1.33"
},
"allow-plugins": {
"bamarni/composer-bin-plugin": true
}
},
"scripts": {

View file

@ -163,6 +163,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
}
protected function makeConnection(string $db, string $user, string $password, string $host, int $port, string $socket): void {
$drv = new \mysqli_driver;
$drv->report_mode = \MYSQLI_REPORT_OFF;
$this->db = mysqli_init();
$this->db->options(\MYSQLI_SET_CHARSET_NAME, "utf8mb4");
$this->db->options(\MYSQLI_OPT_INT_AND_FLOAT_NATIVE, false);

View file

@ -29,6 +29,7 @@ class PDODriver extends Driver {
try {
$this->db = new \PDO($dsn, $user, $password, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
} catch (\PDOException $e) {
$msg = $e->getMessage();

View file

@ -211,7 +211,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
public function query(string $query): \JKingWeb\Arsse\Db\Result {
$r = $this->dispatchQuery($query);
if (is_resource($r)) {
if (is_resource($r) || $r instanceof \PgSql\Result) { //class since PHP 8.1
return new Result($this->db, $r);
} else {
[$excClass, $excMsg, $excData] = $r;

View file

@ -35,7 +35,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
$this->bindValues($values);
$r = $this->dispatchQuery($this->qMunged, $this->in);
$this->in = [];
if (is_resource($r)) {
if (is_resource($r) || $r instanceof \PgSql\Result) { //class since PHP 8.1
return new Result($this->db, $r);
} else {
[$excClass, $excMsg, $excData] = $r;

View file

@ -7,10 +7,15 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\Db;
interface Result extends \Iterator {
#[\ReturnTypeWillChange]
public function current();
#[\ReturnTypeWillChange]
public function key();
#[\ReturnTypeWillChange]
public function next();
#[\ReturnTypeWillChange]
public function rewind();
#[\ReturnTypeWillChange]
public function valid();
public function getRow();

View file

@ -19,6 +19,7 @@ class PDODriver extends AbstractPDODriver {
protected function makeConnection(string $file, string $key): void {
$this->db = new \PDO("sqlite:".$file, "", "", [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
}

View file

@ -12,9 +12,7 @@ const DOCROOT = BASE."tests".DIRECTORY_SEPARATOR."docroot".DIRECTORY_SEPARATOR;
ini_set("memory_limit", "-1");
ini_set("zend.assertions", "1");
ini_set("assert.exception", "true");
// FIXME: Workaround for a bug in PCRE2 10.37
ini_set("pcre.jit", "0");
// FIXME: This is required by a dependency of Picofeed
// FIXME: This is required because various dependencies have yet to adjust to PHP 8.1
error_reporting(\E_ALL & ~\E_DEPRECATED);
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";

View file

@ -7,9 +7,10 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait MySQL {
use MySQLCommon;
protected static $implementation = "MySQL";
protected static $backend = "MySQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\MySQL\Result::class;
@ -21,6 +22,8 @@ trait MySQL {
if (!class_exists("mysqli")) {
return null;
}
$drv = new \mysqli_driver;
$drv->report_mode = \MYSQLI_REPORT_OFF;
$d = mysqli_init();
$d->options(\MYSQLI_OPT_INT_AND_FLOAT_NATIVE, false);
$d->options(\MYSQLI_SET_CHARSET_NAME, "utf8mb4");
@ -34,53 +37,4 @@ trait MySQL {
}
return $d;
}
public static function dbTableList($db): array {
$listTables = "SELECT table_name as name from information_schema.tables where table_schema = database() and table_name like 'arsse_%'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
} elseif ($db instanceof \PDO) {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$tables = $db->query($listTables)->fetch_all(\MYSQLI_ASSOC);
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'");
} else {
$db->query("TRUNCATE TABLE $table");
}
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
$db->query("DROP TABLE IF EXISTS $table");
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
}

View file

@ -0,0 +1,60 @@
<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Db\Driver;
trait MySQLCommon {
public static function dbTableList($db): array {
$listTables = "SELECT table_name as name from information_schema.tables where table_schema = database() and table_name like 'arsse_%'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
} elseif ($db instanceof \PDO) {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$tables = $db->query($listTables)->fetch_all(\MYSQLI_ASSOC);
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'");
} else {
$db->query("TRUNCATE TABLE $table");
}
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
$db->query("DROP TABLE IF EXISTS $table");
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
}

View file

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait MySQLPDO {
use MySQLCommon;
protected static $implementation = "PDO MySQL";
protected static $backend = "MySQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PDOResult::class;
@ -31,6 +33,7 @@ trait MySQLPDO {
$dsn = "mysql:".implode(";", $dsn);
$d = new \PDO($dsn, Arsse::$conf->dbMySQLUser, Arsse::$conf->dbMySQLPass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
\PDO::MYSQL_ATTR_MULTI_STATEMENTS => false,
]);
foreach (\JKingWeb\Arsse\Db\MySQL\PDODriver::makeSetupQueries() as $q) {
@ -41,16 +44,4 @@ trait MySQLPDO {
return;
}
}
public static function dbTableList($db): array {
return MySQL::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
MySQL::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
MySQL::dbRaze($db, $afterStatements);
}
}

View file

@ -10,6 +10,8 @@ use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait PostgreSQL {
use PostgreSQLCommon;
protected static $implementation = "PostgreSQL";
protected static $backend = "PostgreSQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PostgreSQL\Result::class;
@ -28,61 +30,4 @@ trait PostgreSQL {
return;
}
}
public static function dbExec($db, $q): void {
if ($db instanceof Driver) {
$db->exec($q);
} elseif ($db instanceof \PDO) {
$db->exec($q);
} else {
pg_query($db, $q);
}
}
public static function dbTableList($db): array {
$listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()";
if ($db instanceof Driver) {
return $db->query($listObjects)->getAll();
} elseif ($db instanceof \PDO) {
return $db->query($listObjects)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$r = @pg_query($db, $listObjects);
$out = $r ? pg_fetch_all($r) : false;
return $out ? $out : [];
}
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
if ($obj['type'] !== "TABLE") {
continue;
} elseif ($obj['name'] === "arsse_meta") {
self::dbExec($db, "DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
self::dbExec($db, "TRUNCATE TABLE {$obj['name']} restart identity cascade");
}
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
self::dbExec($db, "DROP {$obj['type']} IF EXISTS {$obj['name']} cascade");
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
}

View file

@ -0,0 +1,69 @@
<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait PostgreSQLCommon {
public static function dbExec($db, $q): void {
if ($db instanceof Driver) {
$db->exec($q);
} elseif ($db instanceof \PDO) {
$db->exec($q);
} else {
pg_query($db, $q);
}
}
public static function dbTableList($db): array {
$listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()";
if ($db instanceof Driver) {
return $db->query($listObjects)->getAll();
} elseif ($db instanceof \PDO) {
return $db->query($listObjects)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$r = @pg_query($db, $listObjects);
$out = $r ? pg_fetch_all($r) : false;
return $out ? $out : [];
}
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
if ($obj['type'] !== "TABLE") {
continue;
} elseif ($obj['name'] === "arsse_meta") {
self::dbExec($db, "DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
self::dbExec($db, "TRUNCATE TABLE {$obj['name']} restart identity cascade");
}
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
self::dbExec($db, "DROP {$obj['type']} IF EXISTS {$obj['name']} cascade");
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
}

View file

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait PostgreSQLPDO {
use PostgreSQLCommon;
protected static $implementation = "PDO PostgreSQL";
protected static $backend = "PostgreSQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PostgreSQL\PDOResult::class;
@ -28,16 +30,4 @@ trait PostgreSQLPDO {
}
return $d;
}
public static function dbTableList($db): array {
return PostgreSQL::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
PostgreSQL::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
PostgreSQL::dbRaze($db, $afterStatements);
}
}

View file

@ -10,6 +10,8 @@ use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait SQLite3 {
use SQLite3Common;
protected static $implementation = "SQLite 3";
protected static $backend = "SQLite 3";
protected static $dbResultClass = \JKingWeb\Arsse\Db\SQLite3\Result::class;
@ -26,63 +28,4 @@ trait SQLite3 {
$d->enableExceptions(true);
return $d;
}
public static function dbTableList($db): array {
$listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse^_%' escape '^'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} elseif ($db instanceof \PDO) {
retry:
try {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
goto retry;
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} else {
$tables = [];
$result = $db->query($listTables);
while ($r = $result->fetchArray(\SQLITE3_ASSOC)) {
$tables[] = $r['name'];
}
$result->finalize();
}
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
$db->exec("PRAGMA foreign_keys=0");
foreach (self::dbTableList($db) as $table) {
$db->exec("DROP TABLE IF EXISTS $table");
}
$db->exec("PRAGMA user_version=0");
$db->exec("PRAGMA foreign_keys=1");
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
}

View file

@ -0,0 +1,70 @@
<?php
/** @license MIT
* Copyright 2017 J. King, Dustin Wilson et al.
* See LICENSE and AUTHORS files for details */
declare(strict_types=1);
namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Db\Driver;
trait SQLite3Common {
public static function dbTableList($db): array {
$listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse^_%' escape '^'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} elseif ($db instanceof \PDO) {
retry:
try {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
goto retry;
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} else {
$tables = [];
$result = $db->query($listTables);
while ($r = $result->fetchArray(\SQLITE3_ASSOC)) {
$tables[] = $r['name'];
}
$result->finalize();
}
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
$db->exec("PRAGMA foreign_keys=0");
foreach (self::dbTableList($db) as $table) {
$db->exec("DROP TABLE IF EXISTS $table");
}
$db->exec("PRAGMA user_version=0");
$db->exec("PRAGMA foreign_keys=1");
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
}

View file

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait SQLite3PDO {
use SQLite3Common;
protected static $implementation = "PDO SQLite 3";
protected static $backend = "SQLite 3";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PDOResult::class;
@ -18,23 +20,14 @@ trait SQLite3PDO {
public static function dbInterface() {
try {
$d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
$d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
$d->exec("PRAGMA busy_timeout=0");
return $d;
} catch (\Throwable $e) {
return;
}
}
public static function dbTableList($db): array {
return SQLite3::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
SQLite3::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
SQLite3::dbRaze($db, $afterStatements);
}
}