From 77c37ff2dbdf50086565ccf903cc370ea4cf4f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Thu, 16 Jun 2022 19:31:50 +0200 Subject: [PATCH 01/18] Fixed: - Uncaught Exception TypeError: "Argument 3 passed to Friendica\Protocol\DFRN::createActivity() must be of the type string, null given, called ..." --- src/Protocol/DFRN.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 878b1570b..f42d5ed93 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -904,12 +904,12 @@ class DFRN XML::addElement($doc, $entry, "activity:object-type", Activity\ObjectType::COMMENT); } - $actobj = self::createActivity($doc, "activity:object", $item['object'], $item['uri-id']); + $actobj = self::createActivity($doc, "activity:object", $item['object'] ?? '', $item['uri-id']); if ($actobj) { $entry->appendChild($actobj); } - $actarg = self::createActivity($doc, "activity:target", $item['target'], $item['uri-id']); + $actarg = self::createActivity($doc, "activity:target", $item['target'] ?? '', $item['uri-id']); if ($actarg) { $entry->appendChild($actarg); } From f1867463a054b5a8bed33d5835afc099f60761a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Mon, 20 Jun 2022 02:30:09 +0200 Subject: [PATCH 02/18] Changes: - added more type-hints --- src/Util/ParseUrl.php | 61 ++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index f4c78df8a..9f0fd8a9b 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -101,7 +101,7 @@ class ParseUrl * @see ParseUrl::getSiteinfo() for more information about scraping * embeddable content */ - public static function getSiteinfoCached($url, $do_oembed = true): array + public static function getSiteinfoCached(string $url, bool $do_oembed = true): array { if (empty($url)) { return [ @@ -180,7 +180,7 @@ class ParseUrl * * @endverbatim */ - public static function getSiteinfo($url, $do_oembed = true, $count = 1) + public static function getSiteinfo(string $url, bool $do_oembed = true, int $count = 1) { if (empty($url)) { return [ @@ -633,15 +633,16 @@ class ParseUrl * @param string $string Tags * @return array with formatted Hashtags */ - public static function convertTagsToArray($string) + public static function convertTagsToArray(string $string): array { $arr_tags = str_getcsv($string); if (count($arr_tags)) { // add the # sign to every tag - array_walk($arr_tags, ["self", "arrAddHashes"]); + array_walk($arr_tags, ['self', 'arrAddHashes']); return $arr_tags; } + return []; } /** @@ -653,9 +654,9 @@ class ParseUrl * @param int $k Counter for internal use * @return void */ - private static function arrAddHashes(&$tag, $k) + private static function arrAddHashes(string &$tag, int $k) { - $tag = "#" . $tag; + $tag = '#' . $tag; } /** @@ -672,41 +673,41 @@ class ParseUrl * * @return string The url with a scheme */ - private static function completeUrl($url, $scheme) + private static function completeUrl(string $url, string $scheme): string { $urlarr = parse_url($url); // If the url does allready have an scheme // we can stop the process here - if (isset($urlarr["scheme"])) { - return($url); + if (isset($urlarr['scheme'])) { + return $url; } $schemearr = parse_url($scheme); - $complete = $schemearr["scheme"]."://".$schemearr["host"]; + $complete = $schemearr['scheme'] . '://' . $schemearr['host']; - if (!empty($schemearr["port"])) { - $complete .= ":".$schemearr["port"]; + if (!empty($schemearr['port'])) { + $complete .= ':' . $schemearr['port']; } - if (!empty($urlarr["path"])) { - if (strpos($urlarr["path"], "/") !== 0) { - $complete .= "/"; + if (!empty($urlarr['path'])) { + if (strpos($urlarr['path'], '/') !== 0) { + $complete .= '/'; } - $complete .= $urlarr["path"]; + $complete .= $urlarr['path']; } - if (!empty($urlarr["query"])) { - $complete .= "?".$urlarr["query"]; + if (!empty($urlarr['query'])) { + $complete .= '?' . $urlarr['query']; } - if (!empty($urlarr["fragment"])) { - $complete .= "#".$urlarr["fragment"]; + if (!empty($urlarr['fragment'])) { + $complete .= '#' . $urlarr['fragment']; } - return($complete); + return $complete; } /** @@ -716,7 +717,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseParts(array $siteinfo, array $jsonld) + private static function parseParts(array $siteinfo, array $jsonld): array { if (!empty($jsonld['@graph']) && is_array($jsonld['@graph'])) { foreach ($jsonld['@graph'] as $part) { @@ -761,7 +762,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLd(array $siteinfo, array $jsonld) + private static function parseJsonLd(array $siteinfo, array $jsonld): array { $type = JsonLD::fetchElement($jsonld, '@type'); if (empty($type)) { @@ -854,7 +855,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdAuthor(array $siteinfo, array $jsonld) + private static function parseJsonLdAuthor(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -938,7 +939,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdArticle(array $siteinfo, array $jsonld) + private static function parseJsonLdArticle(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -1008,7 +1009,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdWebPage(array $siteinfo, array $jsonld) + private static function parseJsonLdWebPage(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -1047,7 +1048,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdWebSite(array $siteinfo, array $jsonld) + private static function parseJsonLdWebSite(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -1085,7 +1086,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdWebOrganization(array $siteinfo, array $jsonld) + private static function parseJsonLdWebOrganization(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -1131,7 +1132,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdWebPerson(array $siteinfo, array $jsonld) + private static function parseJsonLdWebPerson(array $siteinfo, array $jsonld): array { $jsonldinfo = []; @@ -1176,7 +1177,7 @@ class ParseUrl * @param array $jsonld * @return array siteinfo */ - private static function parseJsonLdMediaObject(array $siteinfo, array $jsonld, string $name) + private static function parseJsonLdMediaObject(array $siteinfo, array $jsonld, string $name): array { $media = []; From cefffde69169b049b0256a74ec487d7800c2eb47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Mon, 20 Jun 2022 03:10:02 +0200 Subject: [PATCH 03/18] Changes: - added type-hints - added some missing documentation --- src/Database/DBA.php | 6 +++--- src/Database/Database.php | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Database/DBA.php b/src/Database/DBA.php index e519a63cd..a797d3235 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -218,12 +218,12 @@ class DBA /** * Check if data exists * - * @param string|array $table Table name or array [schema => table] - * @param array $condition array of fields for condition + * @param string $table Table name or array [schema => table] + * @param array $condition Array of fields for condition * @return boolean Are there rows for that condition? * @throws \Exception */ - public static function exists($table, array $condition): bool + public static function exists(string $table, array $condition): bool { return DI::dba()->exists($table, $condition); } diff --git a/src/Database/Database.php b/src/Database/Database.php index 8c2cd0241..384e1d1a6 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1527,6 +1527,7 @@ class Database */ public function count($table, array $condition = [], array $params = []): int { + // @TODO Can we dump this to have ": int" as returned type-hint? if (empty($table)) { throw new InvalidArgumentException('Parameter "table" cannot be empty.'); } From f62c28008ae94da1730ab792b7f736f8eea41a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 11:10:11 +0200 Subject: [PATCH 04/18] Removed comment --- src/Database/Database.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 384e1d1a6..8c2cd0241 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1527,7 +1527,6 @@ class Database */ public function count($table, array $condition = [], array $params = []): int { - // @TODO Can we dump this to have ": int" as returned type-hint? if (empty($table)) { throw new InvalidArgumentException('Parameter "table" cannot be empty.'); } From 44a9ec9b17ba449a861940e81f3f10875f1ef39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 11:44:23 +0200 Subject: [PATCH 05/18] Rewrite: - avoid having array|string for $table to have a "string" type-hint for $table - you now have to do it for yourself by giving 'schema.table' as parameter --- src/Content/BoundariesPager.php | 2 +- src/Content/Pager.php | 4 +- src/Core/UserImport.php | 5 ++- src/Database/DBA.php | 57 +++++++++++------------- src/Database/DBStructure.php | 26 ++++++----- src/Database/Database.php | 78 ++++++++++++++++----------------- src/Module/Admin/Summary.php | 4 +- src/Util/PidFile.php | 6 ++- 8 files changed, 89 insertions(+), 93 deletions(-) diff --git a/src/Content/BoundariesPager.php b/src/Content/BoundariesPager.php index a8b873f22..dbfa4ca73 100644 --- a/src/Content/BoundariesPager.php +++ b/src/Content/BoundariesPager.php @@ -130,7 +130,7 @@ class BoundariesPager extends Pager return Renderer::replaceMacros($tpl, ['pager' => $data]); } - public function renderFull($itemCount) + public function renderFull(int $itemCount) { throw new \BadMethodCallException(); } diff --git a/src/Content/Pager.php b/src/Content/Pager.php index bf5a5f691..4e8a760a1 100644 --- a/src/Content/Pager.php +++ b/src/Content/Pager.php @@ -160,7 +160,7 @@ class Pager * @return string HTML string of the pager * @throws \Exception */ - public function renderMinimal(int $itemCount) + public function renderMinimal(int $itemCount): string { $displayedItemCount = max(0, intval($itemCount)); @@ -203,7 +203,7 @@ class Pager * @return string HTML string of the pager * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public function renderFull($itemCount) + public function renderFull(int $itemCount): string { $totalItemCount = max(0, intval($itemCount)); diff --git a/src/Core/UserImport.php b/src/Core/UserImport.php index b6ecd74a2..339ce0b65 100644 --- a/src/Core/UserImport.php +++ b/src/Core/UserImport.php @@ -86,7 +86,7 @@ class UserImport * @return array|bool * @throws \Exception */ - private static function dbImportAssoc($table, $arr) + private static function dbImportAssoc(string $table, array $arr) { if (isset($arr['id'])) { unset($arr['id']); @@ -105,10 +105,11 @@ class UserImport * Import account file exported from mod/uexport * * @param array $file array from $_FILES + * @return void * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function importAccount($file) + public static function importAccount(array $file) { Logger::notice("Start user import from " . $file['tmp_name']); /* diff --git a/src/Database/DBA.php b/src/Database/DBA.php index a797d3235..cb5015968 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -289,14 +289,13 @@ class DBA /** * Insert a row into a table * - * @param string|array $table Table name or array [schema => table] - * @param array $param parameter array - * @param int $duplicate_mode What to do on a duplicated entry - * + * @param string $table Table name or array [schema => table] + * @param array $param parameter array + * @param int $duplicate_mode What to do on a duplicated entry * @return boolean was the insert successful? * @throws \Exception */ - public static function insert($table, array $param, int $duplicate_mode = Database::INSERT_DEFAULT): bool + public static function insert(string $table, array $param, int $duplicate_mode = Database::INSERT_DEFAULT): bool { return DI::dba()->insert($table, $param, $duplicate_mode); } @@ -305,13 +304,12 @@ class DBA * Inserts a row with the provided data in the provided table. * If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead. * - * @param string|array $table Table name or array [schema => table] - * @param array $param parameter array - * + * @param string $table Table name or array [schema => table] + * @param array $param parameter array * @return boolean was the insert successful? * @throws \Exception */ - public static function replace($table, array $param): bool + public static function replace(string $table, array $param): bool { return DI::dba()->replace($table, $param); } @@ -331,12 +329,11 @@ class DBA * * This function can be extended in the future to accept a table array as well. * - * @param string|array $table Table name or array [schema => table] - * + * @param string $table Table name or array [schema => table] * @return boolean was the lock successful? * @throws \Exception */ - public static function lock($table): bool + public static function lock(string $table): bool { return DI::dba()->lock($table); } @@ -385,13 +382,13 @@ class DBA /** * Delete a row from a table * - * @param string|array $table Table name - * @param array $conditions Field condition(s) + * @param string $table Table name + * @param array $conditions Field condition(s) * * @return boolean was the delete successful? * @throws \Exception */ - public static function delete($table, array $conditions, array $options = []): bool + public static function delete(string $table, array $conditions, array $options = []): bool { return DI::dba()->delete($table, $conditions, $options); } @@ -417,7 +414,7 @@ class DBA * Only set $old_fields to a boolean value when you are sure that you will update a single row. * When you set $old_fields to "true" then $fields must contain all relevant fields! * - * @param string|array $table Table name or array [schema => table] + * @param string $table Table name or array [schema => table] * @param array $fields contains the fields that are updated * @param array $condition condition array with the key values * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields) @@ -426,7 +423,7 @@ class DBA * @return boolean was the update successfull? * @throws \Exception */ - public static function update($table, array $fields, array $condition, $old_fields = [], array $params = []): bool + public static function update(string $table, array $fields, array $condition, $old_fields = [], array $params = []): bool { return DI::dba()->update($table, $fields, $condition, $old_fields, $params); } @@ -467,10 +464,10 @@ class DBA /** * Select rows from a table * - * @param string|array $table Table name or array [schema => table] - * @param array $fields Array of selected fields, empty for all - * @param array $condition Array of fields for condition - * @param array $params Array of several parameters + * @param string $table Table name or array [schema => table] + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * * @return boolean|object * @@ -487,7 +484,7 @@ class DBA * $data = DBA::select($table, $fields, $condition, $params); * @throws \Exception */ - public static function select($table, array $fields = [], array $condition = [], array $params = []) + public static function select(string $table, array $fields = [], array $condition = [], array $params = []) { return DI::dba()->select($table, $fields, $condition, $params); } @@ -495,9 +492,9 @@ class DBA /** * Counts the rows from a table satisfying the provided condition * - * @param string|array $table Table name or array [schema => table] - * @param array $condition array of fields for condition - * @param array $params Array of several parameters + * @param string $table Table name or array [schema => table] + * @param array $condition array of fields for condition + * @param array $params Array of several parameters * * @return int * @@ -511,7 +508,7 @@ class DBA * $count = DBA::count($table, $condition); * @throws \Exception */ - public static function count($table, array $condition = [], array $params = []): int + public static function count(string $table, array $condition = [], array $params = []): int { return DI::dba()->count($table, $condition, $params); } @@ -524,15 +521,11 @@ class DBA * - [table1, table2, ...] * - [schema1 => table1, schema2 => table2, table3, ...] * - * @param string|array $tables + * @param array $tables Table names * @return string */ - public static function buildTableString($tables): string + public static function buildTableString(array $tables): string { - if (is_string($tables)) { - $tables = [$tables]; - } - $quotedTables = []; foreach ($tables as $schema => $table) { diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 3c82986fa..8f68cc2b0 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -465,19 +465,19 @@ class DBStructure private static function createIndex(string $indexName, array $fieldNames, string $method = 'ADD') { $method = strtoupper(trim($method)); - if ($method != "" && $method != "ADD") { + if ($method != '' && $method != 'ADD') { throw new Exception("Invalid parameter 'method' in self::createIndex(): '$method'"); } - if (in_array($fieldNames[0], ["UNIQUE", "FULLTEXT"])) { + if (in_array($fieldNames[0], ['UNIQUE', 'FULLTEXT'])) { $index_type = array_shift($fieldNames); $method .= " " . $index_type; } $names = ""; foreach ($fieldNames as $fieldName) { - if ($names != "") { - $names .= ","; + if ($names != '') { + $names .= ','; } if (preg_match('|(.+)\((\d+)\)|', $fieldName, $matches)) { @@ -487,7 +487,7 @@ class DBStructure } } - if ($indexName == "PRIMARY") { + if ($indexName == 'PRIMARY') { return sprintf("%s PRIMARY KEY(%s)", $method, $names); } @@ -1106,7 +1106,7 @@ class DBStructure */ public static function existsForeignKeyForField(string $table, string $field): bool { - return DBA::exists(['INFORMATION_SCHEMA' => 'KEY_COLUMN_USAGE'], + return DBA::exists('INFORMATION_SCHEMA.KEY_COLUMN_USAGE', ["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ? AND `REFERENCED_TABLE_SCHEMA` IS NOT NULL", DBA::databaseName(), $table, $field]); } @@ -1126,7 +1126,7 @@ class DBStructure $condition = ['table_schema' => DBA::databaseName(), 'table_name' => $table]; - return DBA::exists(['information_schema' => 'tables'], $condition); + return DBA::exists('information_schema.tables', $condition); } /** @@ -1181,9 +1181,9 @@ class DBStructure if (self::existsTable('user') && !DBA::exists('user', ['uid' => 0])) { $user = [ - "verified" => true, - "page-flags" => User::PAGE_FLAGS_SOAPBOX, - "account-type" => User::ACCOUNT_TYPE_RELAY, + 'verified' => true, + 'page-flags' => User::PAGE_FLAGS_SOAPBOX, + 'account-type' => User::ACCOUNT_TYPE_RELAY, ]; DBA::insert('user', $user); $lastid = DBA::lastInsertId(); @@ -1287,8 +1287,10 @@ class DBStructure { $isUpdate = false; - $processes = DBA::select(['information_schema' => 'processlist'], ['info'], - ['db' => DBA::databaseName(), 'command' => ['Query', 'Execute']]); + $processes = DBA::select('information_schema.processlist', ['info'], [ + 'db' => DBA::databaseName(), + 'command' => ['Query', 'Execute'] + ]); while ($process = DBA::fetch($processes)) { $parts = explode(' ', $process['info']); diff --git a/src/Database/Database.php b/src/Database/Database.php index 8c2cd0241..fcc6f6337 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -820,13 +820,13 @@ class Database /** * Check if data exists * - * @param string|array $table Table name or array [schema => table] - * @param array $condition array of fields for condition + * @param string $table Table name or array [schema => table] + * @param array $condition Array of fields for condition * * @return boolean Are there rows for that condition? * @throws \Exception */ - public function exists($table, array $condition): bool + public function exists(string $table, array $condition): bool { if (empty($table)) { return false; @@ -1003,14 +1003,14 @@ class Database /** * Insert a row into a table. Field value objects will be cast as string. * - * @param string|array $table Table name or array [schema => table] - * @param array $param parameter array - * @param int $duplicate_mode What to do on a duplicated entry + * @param string $table Table name or array [schema => table] + * @param array $param parameter array + * @param int $duplicate_mode What to do on a duplicated entry * * @return boolean was the insert successful? * @throws \Exception */ - public function insert($table, array $param, int $duplicate_mode = self::INSERT_DEFAULT): bool + public function insert(string $table, array $param, int $duplicate_mode = self::INSERT_DEFAULT): bool { if (empty($table) || empty($param)) { $this->logger->info('Table and fields have to be set'); @@ -1019,7 +1019,7 @@ class Database $param = $this->castFields($table, $param); - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $fields_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], array_keys($param))); @@ -1054,13 +1054,12 @@ class Database * Inserts a row with the provided data in the provided table. * If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead. * - * @param string|array $table Table name or array [schema => table] - * @param array $param parameter array - * + * @param string $table Table name or array [schema => table] + * @param array $param parameter array * @return boolean was the insert successful? * @throws \Exception */ - public function replace($table, array $param): bool + public function replace(string $table, array $param): bool { if (empty($table) || empty($param)) { $this->logger->info('Table and fields have to be set'); @@ -1069,7 +1068,7 @@ class Database $param = $this->castFields($table, $param); - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $fields_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], array_keys($param))); @@ -1103,12 +1102,11 @@ class Database * * This function can be extended in the future to accept a table array as well. * - * @param string|array $table Table name or array [schema => table] - * + * @param string $table Table name or array [schema => table] * @return boolean was the lock successful? * @throws \Exception */ - public function lock($table): bool + public function lock(string $table): bool { // See here: https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html if ($this->driver == self::PDO) { @@ -1118,7 +1116,7 @@ class Database $this->connection->autocommit(false); } - $success = $this->e("LOCK TABLES " . DBA::buildTableString($table) . " WRITE"); + $success = $this->e("LOCK TABLES " . DBA::buildTableString([$table]) . " WRITE"); if ($this->driver == self::PDO) { $this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, $this->pdo_emulate_prepares); @@ -1265,14 +1263,14 @@ class Database * @return boolean was the delete successful? * @throws \Exception */ - public function delete($table, array $conditions): bool + public function delete(string $table, array $conditions): bool { if (empty($table) || empty($conditions)) { $this->logger->info('Table and conditions have to be set'); return false; } - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $condition_string = DBA::buildCondition($conditions); @@ -1302,7 +1300,7 @@ class Database * Only set $old_fields to a boolean value when you are sure that you will update a single row. * When you set $old_fields to "true" then $fields must contain all relevant fields! * - * @param string|array $table Table name or array [schema => table] + * @param string $table Table name or array [schema => table] * @param array $fields contains the fields that are updated * @param array $condition condition array with the key values * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields) @@ -1312,7 +1310,7 @@ class Database * @throws \Exception * @todo Implement "bool $update_on_duplicate" to avoid mixed type for $old_fields */ - public function update($table, array $fields, array $condition, $old_fields = [], array $params = []) + public function update(string $table, array $fields, array $condition, $old_fields = [], array $params = []) { if (empty($table) || empty($fields) || empty($condition)) { $this->logger->info('Table, fields and condition have to be set'); @@ -1345,7 +1343,7 @@ class Database $fields = $this->castFields($table, $fields); - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $condition_string = DBA::buildCondition($condition); @@ -1469,14 +1467,14 @@ class Database * * $data = DBA::select($table, $fields, $condition, $params); * - * @param string|array $table Table name or array [schema => table] - * @param array $fields Array of selected fields, empty for all - * @param array $condition Array of fields for condition - * @param array $params Array of several parameters + * @param string $table Table name or array [schema => table] + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * @return boolean|object * @throws \Exception */ - public function select($table, array $fields = [], array $condition = [], array $params = []) + public function select(string $table, array $fields = [], array $condition = [], array $params = []) { if (empty($table)) { return false; @@ -1489,7 +1487,7 @@ class Database $select_string = '*'; } - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $condition_string = DBA::buildCondition($condition); @@ -1509,9 +1507,9 @@ class Database /** * Counts the rows from a table satisfying the provided condition * - * @param string|array $table Table name or array [schema => table] - * @param array $condition Array of fields for condition - * @param array $params Array of several parameters + * @param string $table Table name or array [schema => table] + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * * @return int Count of rows * @@ -1525,13 +1523,13 @@ class Database * $count = DBA::count($table, $condition); * @throws \Exception */ - public function count($table, array $condition = [], array $params = []): int + public function count(string $table, array $condition = [], array $params = []): int { if (empty($table)) { throw new InvalidArgumentException('Parameter "table" cannot be empty.'); } - $table_string = DBA::buildTableString($table); + $table_string = DBA::buildTableString([$table]); $condition_string = DBA::buildCondition($condition); @@ -1619,7 +1617,7 @@ class Database return $fields; } - foreach(array_keys($fields) as $field) { + foreach (array_keys($fields) as $field) { if (!empty($views[$table]['fields'][$field])) { $viewdef = $views[$table]['fields'][$field]; if (!empty($tables[$viewdef[0]]['fields'][$viewdef[1]]['type'])) { @@ -1823,14 +1821,14 @@ class Database /** * Replaces a string in the provided fields of the provided table * - * @param string $table_name Table name + * @param string $table Table name * @param array $fields List of field names in the provided table - * @param string $search - * @param string $replace + * @param string $search String to search for + * @param string $replace String to replace with * @return void * @throws \Exception */ - public function replaceInTableFields(string $table_name, array $fields, string $search, string $replace) + public function replaceInTableFields(string $table, array $fields, string $search, string $replace) { $search = $this->escape($search); $replace = $this->escape($replace); @@ -1843,9 +1841,9 @@ class Database $upds = implode(', ', $upd); - $r = $this->e(sprintf("UPDATE %s SET %s;", DBA::quoteIdentifier($table_name), $upds)); + $r = $this->e(sprintf("UPDATE %s SET %s;", DBA::quoteIdentifier($table), $upds)); if (!$this->isResult($r)) { - throw new \RuntimeException("Failed updating `$table_name`: " . $this->errorMessage()); + throw new \RuntimeException("Failed updating `$table`: " . $this->errorMessage()); } } } diff --git a/src/Module/Admin/Summary.php b/src/Module/Admin/Summary.php index 557ecd7f5..667b32242 100644 --- a/src/Module/Admin/Summary.php +++ b/src/Module/Admin/Summary.php @@ -54,12 +54,12 @@ class Summary extends BaseAdmin $warningtext[] = DI::l10n()->t('Template engine (%s) error: %s', $templateEngine::$name, $error); } - if (DBA::count(['information_schema' => 'tables'], ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) { + if (DBA::count('information_schema.tables', ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) { $warningtext[] = DI::l10n()->t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html'); } // are there InnoDB tables in Antelope in the DB? If so, trigger a warning message - if (DBA::count(['information_schema' => 'tables'], ['ENGINE' => 'InnoDB', 'ROW_FORMAT' => ['COMPACT', 'REDUNDANT'], 'table_schema' => DBA::databaseName()])) { + if (DBA::count('information_schema.tables', ['ENGINE' => 'InnoDB', 'ROW_FORMAT' => ['COMPACT', 'REDUNDANT'], 'table_schema' => DBA::databaseName()])) { $warningtext[] = DI::l10n()->t('Your DB still runs with InnoDB tables in the Antelope file format. You should change the file format to Barracuda. Friendica is using features that are not provided by the Antelope format. See here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
', 'https://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html'); } diff --git a/src/Util/PidFile.php b/src/Util/PidFile.php index 6f8233a6a..38408bcf4 100644 --- a/src/Util/PidFile.php +++ b/src/Util/PidFile.php @@ -97,7 +97,8 @@ class PidFile * * @return boolean|string PID or "false" if not created */ - static public function create($file) { + static public function create(string $file) + { $pid = self::pidFromFile($file); // We have a process id? then we quit @@ -119,7 +120,8 @@ class PidFile * * @return boolean Is it running? */ - static public function delete($file) { + static public function delete(string $file): bool + { return @unlink($file); } } From 0d81a08e3cf52e820752f3011d5182b0eb7b5580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 12:09:51 +0200 Subject: [PATCH 06/18] WIP: Properly some fixes? Also why is DROP VIEW IF EXISTS is being killed? --- database.sql | 17 ----------------- src/Database/DBA.php | 10 +++++----- src/Database/DBStructure.php | 14 +++++++------- src/Database/Database.php | 21 ++++++++++----------- src/Database/View.php | 4 ++-- 5 files changed, 24 insertions(+), 42 deletions(-) diff --git a/database.sql b/database.sql index 10b18d4ca..62546556c 100644 --- a/database.sql +++ b/database.sql @@ -1673,7 +1673,6 @@ CREATE TABLE IF NOT EXISTS `worker-ipc` ( -- -- VIEW application-view -- -DROP VIEW IF EXISTS `application-view`; CREATE VIEW `application-view` AS SELECT `application`.`id` AS `id`, `application-token`.`uid` AS `uid`, @@ -1696,7 +1695,6 @@ CREATE VIEW `application-view` AS SELECT -- -- VIEW post-user-view -- -DROP VIEW IF EXISTS `post-user-view`; CREATE VIEW `post-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, @@ -1870,7 +1868,6 @@ CREATE VIEW `post-user-view` AS SELECT -- -- VIEW post-thread-user-view -- -DROP VIEW IF EXISTS `post-thread-user-view`; CREATE VIEW `post-thread-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, @@ -2043,7 +2040,6 @@ CREATE VIEW `post-thread-user-view` AS SELECT -- -- VIEW post-view -- -DROP VIEW IF EXISTS `post-view`; CREATE VIEW `post-view` AS SELECT `item-uri`.`uri` AS `uri`, `post`.`uri-id` AS `uri-id`, @@ -2179,7 +2175,6 @@ CREATE VIEW `post-view` AS SELECT -- -- VIEW post-thread-view -- -DROP VIEW IF EXISTS `post-thread-view`; CREATE VIEW `post-thread-view` AS SELECT `item-uri`.`uri` AS `uri`, `post-thread`.`uri-id` AS `uri-id`, @@ -2315,7 +2310,6 @@ CREATE VIEW `post-thread-view` AS SELECT -- -- VIEW category-view -- -DROP VIEW IF EXISTS `category-view`; CREATE VIEW `category-view` AS SELECT `post-category`.`uri-id` AS `uri-id`, `post-category`.`uid` AS `uid`, @@ -2329,7 +2323,6 @@ CREATE VIEW `category-view` AS SELECT -- -- VIEW collection-view -- -DROP VIEW IF EXISTS `collection-view`; CREATE VIEW `collection-view` AS SELECT `post-collection`.`uri-id` AS `uri-id`, `post-collection`.`type` AS `type`, @@ -2350,7 +2343,6 @@ CREATE VIEW `collection-view` AS SELECT -- -- VIEW tag-view -- -DROP VIEW IF EXISTS `tag-view`; CREATE VIEW `tag-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-tag`.`type` AS `type`, @@ -2366,7 +2358,6 @@ CREATE VIEW `tag-view` AS SELECT -- -- VIEW network-item-view -- -DROP VIEW IF EXISTS `network-item-view`; CREATE VIEW `network-item-view` AS SELECT `post-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, @@ -2397,7 +2388,6 @@ CREATE VIEW `network-item-view` AS SELECT -- -- VIEW network-thread-view -- -DROP VIEW IF EXISTS `network-thread-view`; CREATE VIEW `network-thread-view` AS SELECT `post-thread-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, @@ -2426,7 +2416,6 @@ CREATE VIEW `network-thread-view` AS SELECT -- -- VIEW owner-view -- -DROP VIEW IF EXISTS `owner-view`; CREATE VIEW `owner-view` AS SELECT `contact`.`id` AS `id`, `contact`.`uid` AS `uid`, @@ -2554,7 +2543,6 @@ CREATE VIEW `owner-view` AS SELECT -- -- VIEW account-view -- -DROP VIEW IF EXISTS `account-view`; CREATE VIEW `account-view` AS SELECT `contact`.`id` AS `id`, `contact`.`url` AS `url`, @@ -2640,7 +2628,6 @@ CREATE VIEW `account-view` AS SELECT -- -- VIEW account-user-view -- -DROP VIEW IF EXISTS `account-user-view`; CREATE VIEW `account-user-view` AS SELECT `ucontact`.`id` AS `id`, `contact`.`id` AS `pid`, @@ -2744,7 +2731,6 @@ CREATE VIEW `account-user-view` AS SELECT -- -- VIEW pending-view -- -DROP VIEW IF EXISTS `pending-view`; CREATE VIEW `pending-view` AS SELECT `register`.`id` AS `id`, `register`.`hash` AS `hash`, @@ -2766,7 +2752,6 @@ CREATE VIEW `pending-view` AS SELECT -- -- VIEW tag-search-view -- -DROP VIEW IF EXISTS `tag-search-view`; CREATE VIEW `tag-search-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-user`.`uid` AS `uid`, @@ -2788,7 +2773,6 @@ CREATE VIEW `tag-search-view` AS SELECT -- -- VIEW workerqueue-view -- -DROP VIEW IF EXISTS `workerqueue-view`; CREATE VIEW `workerqueue-view` AS SELECT `process`.`pid` AS `pid`, `workerqueue`.`priority` AS `priority` @@ -2799,7 +2783,6 @@ CREATE VIEW `workerqueue-view` AS SELECT -- -- VIEW profile_field-view -- -DROP VIEW IF EXISTS `profile_field-view`; CREATE VIEW `profile_field-view` AS SELECT `profile_field`.`id` AS `id`, `profile_field`.`uid` AS `uid`, diff --git a/src/Database/DBA.php b/src/Database/DBA.php index cb5015968..38590eb56 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -447,16 +447,16 @@ class DBA /** * Select rows from a table and fills an array with the data * - * @param string|array $table Table name or array [schema => table] - * @param array $fields Array of selected fields, empty for all - * @param array $condition Array of fields for condition - * @param array $params Array of several parameters + * @param string $table Table name or array [schema => table] + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * * @return array Data array * @throws \Exception * @see self::select */ - public static function selectToArray($table, array $fields = [], array $condition = [], array $params = []) + public static function selectToArray(string $table, array $fields = [], array $condition = [], array $params = []) { return DI::dba()->selectToArray($table, $fields, $condition, $params); } diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 8f68cc2b0..0756ad099 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -84,7 +84,7 @@ class DBStructure 'deliverq', 'dsprphotoq', 'ffinder', 'sign', 'spam', 'term', 'user-item', 'thread', 'item', 'challenge', 'auth_codes', 'tokens', 'clients', 'profile_check', 'host']; - $tables = DBA::selectToArray(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_NAME'], + $tables = DBA::selectToArray('INFORMATION_SCHEMA.TABLES', ['TABLE_NAME'], ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_TYPE' => 'BASE TABLE']); if (empty($tables)) { @@ -119,13 +119,13 @@ class DBStructure public static function convertToInnoDB() { $tables = DBA::selectToArray( - ['information_schema' => 'tables'], + 'information_schema.tables', ['table_name'], ['engine' => 'MyISAM', 'table_schema' => DBA::databaseName()] ); $tables = array_merge($tables, DBA::selectToArray( - ['information_schema' => 'tables'], + 'information_schema.tables', ['table_name'], ['engine' => 'InnoDB', 'ROW_FORMAT' => ['COMPACT', 'REDUNDANT'], 'table_schema' => DBA::databaseName()] )); @@ -851,18 +851,18 @@ class DBStructure // This query doesn't seem to be executable as a prepared statement $indexes = DBA::toArray(DBA::p("SHOW INDEX FROM " . DBA::quoteIdentifier($table))); - $fields = DBA::selectToArray(['INFORMATION_SCHEMA' => 'COLUMNS'], + $fields = DBA::selectToArray('INFORMATION_SCHEMA.COLUMNS', ['COLUMN_NAME', 'COLUMN_TYPE', 'IS_NULLABLE', 'COLUMN_DEFAULT', 'EXTRA', 'COLUMN_KEY', 'COLLATION_NAME', 'COLUMN_COMMENT'], ["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?", DBA::databaseName(), $table]); - $foreign_keys = DBA::selectToArray(['INFORMATION_SCHEMA' => 'KEY_COLUMN_USAGE'], + $foreign_keys = DBA::selectToArray('INFORMATION_SCHEMA.KEY_COLUMN_USAGE', ['COLUMN_NAME', 'CONSTRAINT_NAME', 'REFERENCED_TABLE_NAME', 'REFERENCED_COLUMN_NAME'], ["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `REFERENCED_TABLE_SCHEMA` IS NOT NULL", DBA::databaseName(), $table]); - $table_status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], + $table_status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES', ['ENGINE', 'TABLE_COLLATION', 'TABLE_COMMENT'], ["`TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?", DBA::databaseName(), $table]); @@ -1064,7 +1064,7 @@ class DBStructure * @return boolean Does the table exist? * @throws Exception */ - public static function existsColumn($table, $columns = []) + public static function existsColumn(string $table, array $columns = []): bool { if (empty($table)) { return false; diff --git a/src/Database/Database.php b/src/Database/Database.php index fcc6f6337..fbdde000c 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -1366,16 +1366,16 @@ class Database /** * Retrieve a single record from a table and returns it in an associative array * - * @param string|array $table - * @param array $fields - * @param array $condition - * @param array $params + * @param string $table Table name or array [schema => table] + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * * @return bool|array * @throws \Exception * @see $this->select */ - public function selectFirst($table, array $fields = [], array $condition = [], array $params = []) + public function selectFirst(string $table, array $fields = [], array $condition = [], array $params = []) { $params['limit'] = 1; $result = $this->select($table, $fields, $condition, $params); @@ -1392,16 +1392,15 @@ class Database /** * Select rows from a table and fills an array with the data * - * @param string|array $table Table name or array [schema => table] - * @param array $fields Array of selected fields, empty for all - * @param array $condition Array of fields for condition - * @param array $params Array of several parameters - * + * @param string $table Table name or array [schema => table] + * @param array $fields Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters * @return array Data array * @throws \Exception * @see self::select */ - public function selectToArray($table, array $fields = [], array $condition = [], array $params = []) + public function selectToArray(string $table, array $fields = [], array $condition = [], array $params = []) { return $this->toArray($this->select($table, $fields, $condition, $params)); } diff --git a/src/Database/View.php b/src/Database/View.php index c8941167e..18db875ea 100644 --- a/src/Database/View.php +++ b/src/Database/View.php @@ -183,7 +183,7 @@ class View */ private static function isView(string $view): bool { - $status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'], + $status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES', ['TABLE_TYPE'], ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $view]); if (empty($status['TABLE_TYPE'])) { @@ -201,7 +201,7 @@ class View */ private static function isTable(string $table): bool { - $status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'], + $status = DBA::selectFirst('INFORMATION_SCHEMA.TABLES', ['TABLE_TYPE'], ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $table]); if (empty($status['TABLE_TYPE'])) { From 945cd1a2c22a43012086637651678ccb98a30f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 12:43:24 +0200 Subject: [PATCH 07/18] Fixed: - since $table can be now schema.table, this needs being taken care off - maybe this foreach(explode()) is a bit an overkill as only 1 or 2 entries can be found in it --- database.sql | 17 +++++++++++++++++ src/Database/DBA.php | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/database.sql b/database.sql index 62546556c..10b18d4ca 100644 --- a/database.sql +++ b/database.sql @@ -1673,6 +1673,7 @@ CREATE TABLE IF NOT EXISTS `worker-ipc` ( -- -- VIEW application-view -- +DROP VIEW IF EXISTS `application-view`; CREATE VIEW `application-view` AS SELECT `application`.`id` AS `id`, `application-token`.`uid` AS `uid`, @@ -1695,6 +1696,7 @@ CREATE VIEW `application-view` AS SELECT -- -- VIEW post-user-view -- +DROP VIEW IF EXISTS `post-user-view`; CREATE VIEW `post-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, @@ -1868,6 +1870,7 @@ CREATE VIEW `post-user-view` AS SELECT -- -- VIEW post-thread-user-view -- +DROP VIEW IF EXISTS `post-thread-user-view`; CREATE VIEW `post-thread-user-view` AS SELECT `post-user`.`id` AS `id`, `post-user`.`id` AS `post-user-id`, @@ -2040,6 +2043,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT -- -- VIEW post-view -- +DROP VIEW IF EXISTS `post-view`; CREATE VIEW `post-view` AS SELECT `item-uri`.`uri` AS `uri`, `post`.`uri-id` AS `uri-id`, @@ -2175,6 +2179,7 @@ CREATE VIEW `post-view` AS SELECT -- -- VIEW post-thread-view -- +DROP VIEW IF EXISTS `post-thread-view`; CREATE VIEW `post-thread-view` AS SELECT `item-uri`.`uri` AS `uri`, `post-thread`.`uri-id` AS `uri-id`, @@ -2310,6 +2315,7 @@ CREATE VIEW `post-thread-view` AS SELECT -- -- VIEW category-view -- +DROP VIEW IF EXISTS `category-view`; CREATE VIEW `category-view` AS SELECT `post-category`.`uri-id` AS `uri-id`, `post-category`.`uid` AS `uid`, @@ -2323,6 +2329,7 @@ CREATE VIEW `category-view` AS SELECT -- -- VIEW collection-view -- +DROP VIEW IF EXISTS `collection-view`; CREATE VIEW `collection-view` AS SELECT `post-collection`.`uri-id` AS `uri-id`, `post-collection`.`type` AS `type`, @@ -2343,6 +2350,7 @@ CREATE VIEW `collection-view` AS SELECT -- -- VIEW tag-view -- +DROP VIEW IF EXISTS `tag-view`; CREATE VIEW `tag-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-tag`.`type` AS `type`, @@ -2358,6 +2366,7 @@ CREATE VIEW `tag-view` AS SELECT -- -- VIEW network-item-view -- +DROP VIEW IF EXISTS `network-item-view`; CREATE VIEW `network-item-view` AS SELECT `post-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, @@ -2388,6 +2397,7 @@ CREATE VIEW `network-item-view` AS SELECT -- -- VIEW network-thread-view -- +DROP VIEW IF EXISTS `network-thread-view`; CREATE VIEW `network-thread-view` AS SELECT `post-thread-user`.`uri-id` AS `uri-id`, `parent-post`.`id` AS `parent`, @@ -2416,6 +2426,7 @@ CREATE VIEW `network-thread-view` AS SELECT -- -- VIEW owner-view -- +DROP VIEW IF EXISTS `owner-view`; CREATE VIEW `owner-view` AS SELECT `contact`.`id` AS `id`, `contact`.`uid` AS `uid`, @@ -2543,6 +2554,7 @@ CREATE VIEW `owner-view` AS SELECT -- -- VIEW account-view -- +DROP VIEW IF EXISTS `account-view`; CREATE VIEW `account-view` AS SELECT `contact`.`id` AS `id`, `contact`.`url` AS `url`, @@ -2628,6 +2640,7 @@ CREATE VIEW `account-view` AS SELECT -- -- VIEW account-user-view -- +DROP VIEW IF EXISTS `account-user-view`; CREATE VIEW `account-user-view` AS SELECT `ucontact`.`id` AS `id`, `contact`.`id` AS `pid`, @@ -2731,6 +2744,7 @@ CREATE VIEW `account-user-view` AS SELECT -- -- VIEW pending-view -- +DROP VIEW IF EXISTS `pending-view`; CREATE VIEW `pending-view` AS SELECT `register`.`id` AS `id`, `register`.`hash` AS `hash`, @@ -2752,6 +2766,7 @@ CREATE VIEW `pending-view` AS SELECT -- -- VIEW tag-search-view -- +DROP VIEW IF EXISTS `tag-search-view`; CREATE VIEW `tag-search-view` AS SELECT `post-tag`.`uri-id` AS `uri-id`, `post-user`.`uid` AS `uid`, @@ -2773,6 +2788,7 @@ CREATE VIEW `tag-search-view` AS SELECT -- -- VIEW workerqueue-view -- +DROP VIEW IF EXISTS `workerqueue-view`; CREATE VIEW `workerqueue-view` AS SELECT `process`.`pid` AS `pid`, `workerqueue`.`priority` AS `priority` @@ -2783,6 +2799,7 @@ CREATE VIEW `workerqueue-view` AS SELECT -- -- VIEW profile_field-view -- +DROP VIEW IF EXISTS `profile_field-view`; CREATE VIEW `profile_field-view` AS SELECT `profile_field`.`id` AS `id`, `profile_field`.`uid` AS `uid`, diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 38590eb56..68fb32f9a 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -530,7 +530,11 @@ class DBA foreach ($tables as $schema => $table) { if (is_numeric($schema)) { - $quotedTables[] = self::quoteIdentifier($table); + $str = ''; + foreach (explode('.', $table) as $part) { + $str .= self::quoteIdentifier($part) . '.'; + } + $quotedTables[] = rtrim($str, '.'); } else { $quotedTables[] = self::quoteIdentifier($schema) . '.' . self::quoteIdentifier($table); } From 1080a840f5b9178182976f157b9883af4bc86617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 13:04:05 +0200 Subject: [PATCH 08/18] Changes: - Database->$driver can no longer be NULL, an empty string is fine anyway --- src/Database/DBA.php | 2 +- src/Database/Database.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 68fb32f9a..d428f36f5 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -77,7 +77,7 @@ class DBA * * @return string with either "pdo" or "mysqli" */ - public static function getDriver() + public static function getDriver(): string { return DI::dba()->getDriver(); } diff --git a/src/Database/Database.php b/src/Database/Database.php index fbdde000c..a77494d69 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -64,7 +64,7 @@ class Database protected $server_info = ''; /** @var PDO|mysqli */ protected $connection; - protected $driver; + protected $driver = ''; protected $pdo_emulate_prepares = false; private $error = false; private $errorno = 0; @@ -181,7 +181,7 @@ class Database // No suitable SQL driver was found. if (!$this->connected) { - $this->driver = null; + $this->driver = ''; $this->connection = null; } @@ -233,7 +233,7 @@ class Database } } - $this->driver = null; + $this->driver = ''; $this->connected = false; } From a7651fa1d59b77d7dbf81744e0324df461c91b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 13:21:33 +0200 Subject: [PATCH 09/18] Changes: - let's at least log the error message, yes it does flood your logfile --- tests/Util/Database/StaticDatabase.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php index 0782a9745..5be4776ee 100644 --- a/tests/Util/Database/StaticDatabase.php +++ b/tests/Util/Database/StaticDatabase.php @@ -21,6 +21,7 @@ namespace Friendica\Test\Util\Database; +use Friendica\Core\Logger; use Friendica\Database\Database; use Friendica\Database\DatabaseException; use PDO; @@ -179,7 +180,8 @@ class StaticDatabase extends Database self::$staticConnection = @new ExtendedPDO($connect, $user, $pass); self::$staticConnection->setAttribute(PDO::ATTR_AUTOCOMMIT,0); } catch (PDOException $e) { - /// @TODO At least log exception, don't ignore it! + // Log exception + Logger::error('Cannot establish database connection', ['exception' => $e, 'host' => $server, 'dbname' => $db]); } } From 5fe428d3e4dc7e9745897e00838490a97286c042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 13:32:04 +0200 Subject: [PATCH 10/18] Fixed: - PHPUnit\Framework\Error\Notice: Undefined index: language in /.../src/Util/EMailer/MailBuilder.php on line 122 --- src/Util/EMailer/MailBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/EMailer/MailBuilder.php b/src/Util/EMailer/MailBuilder.php index e6b745b97..321bdc9e6 100644 --- a/src/Util/EMailer/MailBuilder.php +++ b/src/Util/EMailer/MailBuilder.php @@ -119,7 +119,7 @@ abstract class MailBuilder { $this->recipientUid = $user['uid'] ?? 0; try { - $this->l10n = $user['language'] ? $this->l10n->withLang($user['language']) : $this->l10n; + $this->l10n = isset($user['language']) ? $this->l10n->withLang($user['language']) : $this->l10n; } catch (Exception $e) { $this->logger->warning('cannot use language.', ['user' => $user, 'exception' => $e]); } From 5e57ad4d44306050f7a0641f2bc6625fd10115ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 13:45:13 +0200 Subject: [PATCH 11/18] Added simple wrapper script to run PHPUnit tests for you. To use this, you need to set at least 4 variables in your ~/.bashrc (recommended): export FRIENDICA_MYSQL_HOST="localhost" export FRIENDICA_MYSQL_DATABASE="friendica_test" export FRIENDICA_MYSQL_USER="friendica_test" export FRIENDICA_MYSQL_PASSWWORD="friendica_test" Then you can put ./bin/dev/run_tests.sh into your .git/hooks/pre-commit file --- bin/dev/run_tests.sh | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 bin/dev/run_tests.sh diff --git a/bin/dev/run_tests.sh b/bin/dev/run_tests.sh new file mode 100755 index 000000000..d36b8bac0 --- /dev/null +++ b/bin/dev/run_tests.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +PHPUNIT_BIN="./vendor/bin/phpunit" + +if [ -z "${FRIENDICA_MYSQL_HOST}" -o -z "${FRIENDICA_MYSQL_DATABASE}" -o -z "${FRIENDICA_MYSQL_USER}" ] +then + echo "$0: Please add this to your ~/.bashrc file: + +export FRIENDICA_MYSQL_HOST=\"localhost\" +export FRIENDICA_MYSQL_DATABASE=\"friendica_test\" +export FRIENDICA_MYSQL_USER=\"friendica_test\" +export FRIENDICA_MYSQL_PASSWWORD=\"friendica_test\" +# Optional: +#export FRIENDICA_MYSQL_PORT=\"\" +#export FRIENDICA_MYSQL_SOCKET=\"\" + +And create the user/password and database (schema). This script will map then all variables for you and call phpunit properly." + exit 255 +elif [ ! -e "${PHPUNIT_BIN}" ] +then + echo "$0: Cannot find '${PHPUNIT_BIN}' executable." + exit 255 +fi + +export MYSQL_HOST="${FRIENDICA_MYSQL_HOST}" +export MYSQL_DATABASE="${FRIENDICA_MYSQL_DATABASE}" +export MYSQL_USER="${FRIENDICA_MYSQL_USER}" +export MYSQL_PASSWORD="${FRIENDICA_MYSQL_PASSWORD}" +export MYSQL_PORT="${FRIENDICA_MYSQL_PORT}" +export MYSQL_SOCKET="${FRIENDICA_MYSQL_SOCKET}" + +echo "$0: Running unit tests ..." +${PHPUNIT_BIN} -v tests/ > /tmp/friendica-phpunit.log 2>/dev/null +STATUS=$? +echo "$0: Returned status: ${STATUS}" +exit ${STATUS} From dcedd2e5d96e8b88bf5ea668322d881a374672b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 13:53:30 +0200 Subject: [PATCH 12/18] Ops, WWORD ... --- bin/dev/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/dev/run_tests.sh b/bin/dev/run_tests.sh index d36b8bac0..adb139977 100755 --- a/bin/dev/run_tests.sh +++ b/bin/dev/run_tests.sh @@ -9,7 +9,7 @@ then export FRIENDICA_MYSQL_HOST=\"localhost\" export FRIENDICA_MYSQL_DATABASE=\"friendica_test\" export FRIENDICA_MYSQL_USER=\"friendica_test\" -export FRIENDICA_MYSQL_PASSWWORD=\"friendica_test\" +export FRIENDICA_MYSQL_PASSWORD=\"friendica_test\" # Optional: #export FRIENDICA_MYSQL_PORT=\"\" #export FRIENDICA_MYSQL_SOCKET=\"\" From 9ccb113530ddc4d717f8cf3467588fd03cf6bd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 17:47:11 +0200 Subject: [PATCH 13/18] Ops, autorun.sh is there but looks like lesser "multi-project" friendly as MYSQL_* must be defined. I might still use my version as that is project-specific. --- bin/dev/run_tests.sh | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100755 bin/dev/run_tests.sh diff --git a/bin/dev/run_tests.sh b/bin/dev/run_tests.sh deleted file mode 100755 index adb139977..000000000 --- a/bin/dev/run_tests.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -PHPUNIT_BIN="./vendor/bin/phpunit" - -if [ -z "${FRIENDICA_MYSQL_HOST}" -o -z "${FRIENDICA_MYSQL_DATABASE}" -o -z "${FRIENDICA_MYSQL_USER}" ] -then - echo "$0: Please add this to your ~/.bashrc file: - -export FRIENDICA_MYSQL_HOST=\"localhost\" -export FRIENDICA_MYSQL_DATABASE=\"friendica_test\" -export FRIENDICA_MYSQL_USER=\"friendica_test\" -export FRIENDICA_MYSQL_PASSWORD=\"friendica_test\" -# Optional: -#export FRIENDICA_MYSQL_PORT=\"\" -#export FRIENDICA_MYSQL_SOCKET=\"\" - -And create the user/password and database (schema). This script will map then all variables for you and call phpunit properly." - exit 255 -elif [ ! -e "${PHPUNIT_BIN}" ] -then - echo "$0: Cannot find '${PHPUNIT_BIN}' executable." - exit 255 -fi - -export MYSQL_HOST="${FRIENDICA_MYSQL_HOST}" -export MYSQL_DATABASE="${FRIENDICA_MYSQL_DATABASE}" -export MYSQL_USER="${FRIENDICA_MYSQL_USER}" -export MYSQL_PASSWORD="${FRIENDICA_MYSQL_PASSWORD}" -export MYSQL_PORT="${FRIENDICA_MYSQL_PORT}" -export MYSQL_SOCKET="${FRIENDICA_MYSQL_SOCKET}" - -echo "$0: Running unit tests ..." -${PHPUNIT_BIN} -v tests/ > /tmp/friendica-phpunit.log 2>/dev/null -STATUS=$? -echo "$0: Returned status: ${STATUS}" -exit ${STATUS} From 3b8d9a7248b04b3466339d812f2b978348e0c5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 17:54:23 +0200 Subject: [PATCH 14/18] Use protected $this->logger instead --- tests/Util/Database/StaticDatabase.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php index 5be4776ee..22c44affd 100644 --- a/tests/Util/Database/StaticDatabase.php +++ b/tests/Util/Database/StaticDatabase.php @@ -21,7 +21,6 @@ namespace Friendica\Test\Util\Database; -use Friendica\Core\Logger; use Friendica\Database\Database; use Friendica\Database\DatabaseException; use PDO; @@ -46,7 +45,7 @@ class StaticDatabase extends Database /** * Override the behaviour of connect, due there is just one, static connection at all * - * @return bool|void + * @return bool Success */ public function connect(): bool { @@ -181,7 +180,7 @@ class StaticDatabase extends Database self::$staticConnection->setAttribute(PDO::ATTR_AUTOCOMMIT,0); } catch (PDOException $e) { // Log exception - Logger::error('Cannot establish database connection', ['exception' => $e, 'host' => $server, 'dbname' => $db]); + $this->logger::error('Cannot establish database connection', ['exception' => $e, 'host' => $server, 'dbname' => $db]); } } From 0332a57bfdef29179b7962a7e06eba6f89e85a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 18:11:59 +0200 Subject: [PATCH 15/18] Rewrote to suggestions from @MrPetovan (I tried to maintain the old way of ['scheme' => 'table'] with my version). --- src/Database/DBA.php | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/Database/DBA.php b/src/Database/DBA.php index d428f36f5..3cd14766b 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -526,32 +526,25 @@ class DBA */ public static function buildTableString(array $tables): string { - $quotedTables = []; - - foreach ($tables as $schema => $table) { - if (is_numeric($schema)) { - $str = ''; - foreach (explode('.', $table) as $part) { - $str .= self::quoteIdentifier($part) . '.'; - } - $quotedTables[] = rtrim($str, '.'); - } else { - $quotedTables[] = self::quoteIdentifier($schema) . '.' . self::quoteIdentifier($table); - } - } - - return implode(', ', $quotedTables); + // Quote each entry + return implode(',', array_map(['self', 'quoteIdentifier'], $tables)); } /** - * Escape an identifier (table or field name) + * Escape an identifier (table or field name) optional with a schema like (schema.)table * - * @param $identifier - * @return string + * @param $identifier Table, field name + * @return string Quotes table or field name */ public static function quoteIdentifier(string $identifier): string { - return '`' . str_replace('`', '``', $identifier) . '`'; + return implode( + '.', + array_map( + function (string $identifier) { return '`' . str_replace('`', '``', $identifier) . '`'; }, + explode('.', $identifier) + ) + ); } /** From 80c8ec17c21422c3c7001fc53f6f16e8c09e3877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 18:42:51 +0200 Subject: [PATCH 16/18] Fixed documentation --- src/Database/DBA.php | 18 +++++++++--------- src/Database/Database.php | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 3cd14766b..9ce2b6147 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -218,7 +218,7 @@ class DBA /** * Check if data exists * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $condition Array of fields for condition * @return boolean Are there rows for that condition? * @throws \Exception @@ -289,7 +289,7 @@ class DBA /** * Insert a row into a table * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $param parameter array * @param int $duplicate_mode What to do on a duplicated entry * @return boolean was the insert successful? @@ -304,7 +304,7 @@ class DBA * Inserts a row with the provided data in the provided table. * If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead. * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $param parameter array * @return boolean was the insert successful? * @throws \Exception @@ -329,7 +329,7 @@ class DBA * * This function can be extended in the future to accept a table array as well. * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @return boolean was the lock successful? * @throws \Exception */ @@ -414,7 +414,7 @@ class DBA * Only set $old_fields to a boolean value when you are sure that you will update a single row. * When you set $old_fields to "true" then $fields must contain all relevant fields! * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields contains the fields that are updated * @param array $condition condition array with the key values * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields) @@ -431,7 +431,7 @@ class DBA /** * Retrieve a single record from a table and returns it in an associative array * - * @param string|array $table Table name or array [schema => table] + * @param string|array $table Table name in format schema.table (while scheme is optiona) * @param array $fields * @param array $condition * @param array $params @@ -447,7 +447,7 @@ class DBA /** * Select rows from a table and fills an array with the data * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields Array of selected fields, empty for all * @param array $condition Array of fields for condition * @param array $params Array of several parameters @@ -464,7 +464,7 @@ class DBA /** * Select rows from a table * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields Array of selected fields, empty for all * @param array $condition Array of fields for condition * @param array $params Array of several parameters @@ -492,7 +492,7 @@ class DBA /** * Counts the rows from a table satisfying the provided condition * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $condition array of fields for condition * @param array $params Array of several parameters * diff --git a/src/Database/Database.php b/src/Database/Database.php index a77494d69..1c9e24ade 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -820,7 +820,7 @@ class Database /** * Check if data exists * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $condition Array of fields for condition * * @return boolean Are there rows for that condition? @@ -1003,7 +1003,7 @@ class Database /** * Insert a row into a table. Field value objects will be cast as string. * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $param parameter array * @param int $duplicate_mode What to do on a duplicated entry * @@ -1054,7 +1054,7 @@ class Database * Inserts a row with the provided data in the provided table. * If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead. * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $param parameter array * @return boolean was the insert successful? * @throws \Exception @@ -1102,7 +1102,7 @@ class Database * * This function can be extended in the future to accept a table array as well. * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @return boolean was the lock successful? * @throws \Exception */ @@ -1300,7 +1300,7 @@ class Database * Only set $old_fields to a boolean value when you are sure that you will update a single row. * When you set $old_fields to "true" then $fields must contain all relevant fields! * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields contains the fields that are updated * @param array $condition condition array with the key values * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields) @@ -1366,7 +1366,7 @@ class Database /** * Retrieve a single record from a table and returns it in an associative array * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields Array of selected fields, empty for all * @param array $condition Array of fields for condition * @param array $params Array of several parameters @@ -1392,7 +1392,7 @@ class Database /** * Select rows from a table and fills an array with the data * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields Array of selected fields, empty for all * @param array $condition Array of fields for condition * @param array $params Array of several parameters @@ -1466,7 +1466,7 @@ class Database * * $data = DBA::select($table, $fields, $condition, $params); * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $fields Array of selected fields, empty for all * @param array $condition Array of fields for condition * @param array $params Array of several parameters @@ -1506,7 +1506,7 @@ class Database /** * Counts the rows from a table satisfying the provided condition * - * @param string $table Table name or array [schema => table] + * @param string $table Table name in format schema.table (while scheme is optiona) * @param array $condition Array of fields for condition * @param array $params Array of several parameters * From f38ad168f53639a932a63fec8ccf9a43e0c129a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 19:19:11 +0200 Subject: [PATCH 17/18] Reverted and improved TODO: ------ @nupplaphil: There is no easy possibility to add a logger here, that's why there isn't any yet and instead a placeholder.. This execution point is a critical state during a testrun, and tbh I'd like to leave here no further logic (yet) because I spent hours debugging cases, where transactions weren't fully closed and strange/unpredictable errors occur (sometimes -mainly during debugging other errors :) ...) ----- --- tests/Util/Database/StaticDatabase.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php index 22c44affd..2c05b921b 100644 --- a/tests/Util/Database/StaticDatabase.php +++ b/tests/Util/Database/StaticDatabase.php @@ -179,8 +179,7 @@ class StaticDatabase extends Database self::$staticConnection = @new ExtendedPDO($connect, $user, $pass); self::$staticConnection->setAttribute(PDO::ATTR_AUTOCOMMIT,0); } catch (PDOException $e) { - // Log exception - $this->logger::error('Cannot establish database connection', ['exception' => $e, 'host' => $server, 'dbname' => $db]); + /// @TODO Try to find a way to log this exception as it contains valueable information } } From 8092188991abe4bb234d7d8f40f31a9b1ab60e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20H=C3=A4der?= Date: Tue, 21 Jun 2022 21:12:43 +0200 Subject: [PATCH 18/18] Added important comment from @nupplaphil@github.com --- tests/Util/Database/StaticDatabase.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php index 2c05b921b..81bb5a996 100644 --- a/tests/Util/Database/StaticDatabase.php +++ b/tests/Util/Database/StaticDatabase.php @@ -179,7 +179,18 @@ class StaticDatabase extends Database self::$staticConnection = @new ExtendedPDO($connect, $user, $pass); self::$staticConnection->setAttribute(PDO::ATTR_AUTOCOMMIT,0); } catch (PDOException $e) { - /// @TODO Try to find a way to log this exception as it contains valueable information + /* + * @TODO Try to find a way to log this exception as it contains valueable information + * @nupplaphil@github.com comment: + * + * There is no easy possibility to add a logger here, that's why + * there isn't any yet and instead a placeholder.. This execution + * point is a critical state during a testrun, and tbh I'd like to + * leave here no further logic (yet) because I spent hours debugging + * cases, where transactions weren't fully closed and + * strange/unpredictable errors occur (sometimes -mainly during + * debugging other errors :) ...) + */ } }