Exception:
Array
(
    [message] => Vvveb\System\Import\Xml::__construct(): Argument #6 ($port) must be of type string, null given, called in /home/colonichecom/Vvveb/admin/controller/tools/export.php on line 38
    [file] => /home/colonichecom/Vvveb/system/import/xml.php
    [line_no] => 86
    [line] => 	public function __construct(string $driver = DB_ENGINE, string $host = DB_HOST, string $dbname = DB_NAME, string $user = DB_USER, string $pass = DB_PASS, string $port = DB_PORT, string $prefix = DB_PREFIX) {	 // <==

    [lines] => Array
        (
            [0] => 	 * @param string $dbname

            [1] => 	 * @param string $user

            [2] => 	 * @param string $pass

            [3] => 	 * @param string $port

            [4] => 	 * @param string $prefix

            [5] => 	 * @return void

            [6] => 	 */

            [7] => 	public function __construct(string $driver = DB_ENGINE, string $host = DB_HOST, string $dbname = DB_NAME, string $user = DB_USER, string $pass = DB_PASS, string $port = DB_PORT, string $prefix = DB_PREFIX) {	 // <==

            [8] => 		$this->sqlPath = DIR_ROOT . "install/sql/$driver/";

            [9] => 		$engine        = '\Vvveb\System\Db\\' . ucfirst($driver);

            [10] => 

            [11] => 		$this->prefix = $prefix;

            [12] => 

            [13] => 		$this->db = new $engine($host, $dbname, $user, $pass, $port, $prefix);

        )

    [trace] => #0 /home/colonichecom/Vvveb/admin/controller/tools/export.php(38): Vvveb\System\Import\Xml->__construct()
#1 /home/colonichecom/Vvveb/system/core/frontcontroller.php(199): Vvveb\Controller\Tools\Export->__construct()
#2 /home/colonichecom/Vvveb/system/core/frontcontroller.php(338): Vvveb\System\Core\FrontController::call()
#3 /home/colonichecom/Vvveb/system/core/frontcontroller.php(427): Vvveb\System\Core\FrontController::redirect()
#4 /home/colonichecom/Vvveb/system/core/startup.php(514): Vvveb\System\Core\FrontController::dispatch()
#5 /home/colonichecom/Vvveb/index.php(173): Vvveb\System\Core\start()
#6 /home/colonichecom/Vvveb/admin/index.php(45): include('/home/coloniche...')
#7 /home/colonichecom/Vvveb/public/admin/index.php(26): include('/home/coloniche...')
#8 {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\Import;

            [23] => 

            [24] => #[\AllowDynamicProperties]

            [25] => class Xml {

            [26] => 	/**

            [27] => 	 * @var mixed Database driver object

            [28] => 	 */

            [29] => 	private mixed $db;

            [30] => 

            [31] => 	/**

            [32] => 	 * @var \DOMDocument

            [33] => 	 */

            [34] => 	private \DOMDocument $dom;

            [35] => 

            [36] => 	/**

            [37] => 	 * @var \DOMXPath

            [38] => 	 */

            [39] => 	private \DOMXPath $xpath;

            [40] => 

            [41] => 	/**

            [42] => 	 * @var string

            [43] => 	 */

            [44] => 	private string $sqlPath;

            [45] => 

            [46] => 	/**

            [47] => 	 * @var string

            [48] => 	 */

            [49] => 	private string $prefix;

            [50] => 

            [51] => 	/**

            [52] => 	 * @var array

            [53] => 	 */

            [54] => 	private array $idsMap;

            [55] => 

            [56] => 	/**

            [57] => 	 * @var int

            [58] => 	 */

            [59] => 	private int $importXMLOptions = LIBXML_NOBLANKS |

            [60] => 		LIBXML_COMPACT |

            [61] => 		LIBXML_NOCDATA |

            [62] => 		LIBXML_PARSEHUGE |

            [63] => 		LIBXML_NOWARNING |

            [64] => 		LIBXML_BIGLINES;

            [65] => 

            [66] => 	/**

            [67] => 	 * @var array

            [68] => 	 */

            [69] => 	private array $tableOrder = [];

            [70] => 

            [71] => 	/**

            [72] => 	 * @var array

            [73] => 	 */

            [74] => 	private array $cDataColumns = ['content', 'excerpt', 'name', 'title', 'description', 'meta_title', 'meta_description', 'slug'];

            [75] => 

            [76] => 	/**

            [77] => 	 * @param string $driver

            [78] => 	 * @param string $host

            [79] => 	 * @param string $dbname

            [80] => 	 * @param string $user

            [81] => 	 * @param string $pass

            [82] => 	 * @param string $port

            [83] => 	 * @param string $prefix

            [84] => 	 * @return void

            [85] => 	 */

            [86] => 	public function __construct(string $driver = DB_ENGINE, string $host = DB_HOST, string $dbname = DB_NAME, string $user = DB_USER, string $pass = DB_PASS, string $port = DB_PORT, string $prefix = DB_PREFIX) {	 // <==

            [87] => 		$this->sqlPath = DIR_ROOT . "install/sql/$driver/";

            [88] => 		$engine        = '\Vvveb\System\Db\\' . ucfirst($driver);

            [89] => 

            [90] => 		$this->prefix = $prefix;

            [91] => 

            [92] => 		$this->db = new $engine($host, $dbname, $user, $pass, $port, $prefix);

            [93] => 

            [94] => 		$this->tableOrder = include 'table-order.php';

            [95] => 	}

            [96] => 

            [97] => 	/**

            [98] => 	 * Get all table names for the database

            [99] => 	 *

            [100] => 	 * @param string $db

            [101] => 	 * @return array

            [102] => 	 */

            [103] => 	public function getTableNames(string $db = DB_NAME): array {

            [104] => 		return $this->db->getTableNames();

            [105] => 	}

            [106] => 

            [107] => 	/**

            [108] => 	 * @param array $tables

            [109] => 	 * @return string

            [110] => 	 */

            [111] => 	public function export(array $tables = []): string {

            [112] => 		$this->dom                     = new \DOMDocument('1.0', 'utf-8');

            [113] => 		$this->dom->formatOutput       = true;

            [114] => 		$this->dom->preserveWhiteSpace = false;

            [115] => 

            [116] => 		if (empty($tables)) {

            [117] => 			$tables = $this->getTableNames();

            [118] => 		}

            [119] => 

            [120] => 		$root         = $this->dom->createElement('root');

            [121] => 		$database     = $this->dom->createElement('database');

            [122] => 

            [123] => 		foreach ($tables as $tableName) {

            [124] => 			$table = $this->dom->createElement($tableName);

            [125] => 			$q     = '`';

            [126] => 

            [127] => 			if (DB_ENGINE == 'pgsql') {

            [128] => 				$q = '"';

            [129] => 			}

            [130] => 

            [131] => 			$stmt   = $this->db->query("SELECT * FROM $q$tableName$q");

            [132] => 			//$result = $stmt->get_result();

            [133] => 

            [134] => 			while ($row = $this->db->fetchArray($stmt)) {

            [135] => 				$item = $this->dom->createElement('item');

            [136] => 

            [137] => 				foreach ($row as $key => $value) {

            [138] => 					$isString = is_string($value);

            [139] => 

            [140] => 					if ($value === null) {

            [141] => 						$value = 'NULL';

            [142] => 					}

            [143] => 

            [144] => 					if ($value === 0) {

            [145] => 						$value = '0';

            [146] => 					}

            [147] => 

            [148] => 					if (! $value && $value !== '0') {

            [149] => 						$value = '';

            [150] => 					}

            [151] => 

            [152] => 					if (in_array($key,$this->cDataColumns) || $isString) {

            [153] => 						//$element = $this->dom->createElement($key, $value);

            [154] => 

            [155] => 						$cdata   = $this->dom->createCDataSection($value);

            [156] => 						$element = $this->dom->createElement($key);

            [157] => 						$element->appendChild($cdata);

            [158] => 					} else {

            [159] => 						$element = $this->dom->createElement($key, $value);

            [160] => 					}

            [161] => 

            [162] => 					$item->appendChild($element);

            [163] => 				}

            [164] => 				$table->appendChild($item);

            [165] => 			}

            [166] => 

            [167] => 			if ($table->hasChildNodes()) {

            [168] => 				$database->appendChild($table);

            [169] => 			}

            [170] => 		}

            [171] => 

            [172] => 		$root->appendChild($database);

            [173] => 		$this->dom->appendChild($root);

            [174] => 

            [175] => 		return $this->dom->saveXML();

            [176] => 	}

            [177] => 

            [178] => 	/**

            [179] => 	 * @param \LibXMLError $error

            [180] => 	 * @param array $xml

            [181] => 	 * @return string

            [182] => 	 */

            [183] => 	public function displayXmlError(\LibXMLError $error, array $xml): string {

            [184] => 		$return  = $xml[$error->line - 1] . "\n";

            [185] => 		$return .= str_repeat('-', $error->column) . "^\n";

            [186] => 

            [187] => 		switch ($error->level) {

            [188] => 			case LIBXML_ERR_WARNING:

            [189] => 				$return .= "Warning $error->code: ";

            [190] => 

            [191] => 				break;

            [192] => 

            [193] => 			case LIBXML_ERR_ERROR:

            [194] => 				$return .= "Error $error->code: ";

            [195] => 

            [196] => 				break;

            [197] => 

            [198] => 			case LIBXML_ERR_FATAL:

            [199] => 				$return .= "Fatal Error $error->code: ";

            [200] => 

            [201] => 				break;

            [202] => 		}

            [203] => 

            [204] => 		$return .= trim($error->message) .

            [205] => 				   "\n  Line: $error->line" .

            [206] => 				   "\n  Column: $error->column";

            [207] => 

            [208] => 		if ($error->file) {

            [209] => 			$return .= "\n  File: $error->file";

            [210] => 		}

            [211] => 

            [212] => 		return "$return\n\n--------------------------------------------\n\n";

            [213] => 	}

            [214] => 

            [215] => 	/**

            [216] => 	 * @param string $xml

            [217] => 	 * @param array $tables

            [218] => 	 * @return bool

            [219] => 	 */

            [220] => 	public function import(string $xml, array $tables = []): bool {

            [221] => 		if ($tables) {

            [222] => 			//sort tables by table order

            [223] => 			$tableOrder = array_flip($this->tableOrder);

            [224] => 			usort($tables, function ($left, $right) use ($tableOrder) {

            [225] => 				return  $tableOrder[$left] <=> $tableOrder[$right];

            [226] => 			});

            [227] => 		} else {

            [228] => 			$tables = $this->tableOrder;

            [229] => 		}

            [230] => 

            [231] => 		$this->dom                      = new \DOMDocument('1.0', 'utf-8');

            [232] => 		$this->dom->formatOutput        = false;

            [233] => 		$this->dom->preserveWhiteSpace  = false;

            [234] => 		$this->dom->strictErrorChecking = false;

            [235] => 		libxml_use_internal_errors(true);

            [236] => 		$result = $this->dom->loadXML($xml, $this->importXMLOptions);

            [237] => 

            [238] => 		if (! $result) {

            [239] => 			$error   = libxml_get_last_error();

            [240] => 			$message = $this->displayXmlError($error, explode("\n", $xml));

            [241] => 

            [242] => 			throw new \Exception(sprintf("Unable to load XML content, check if valid XML!\n\t%s", $message), 1);

            [243] => 		}

            [244] => 

            [245] => 		$this->dom->normalize();

            [246] => 

            [247] => 		$this->xpath  = new \DOMXpath($this->dom);

            [248] => 

            [249] => 		$domTables       = $this->xpath->query('//root/database/*');

            [250] => 

            [251] => 		//map ids

            [252] => 		foreach ($domTables as $table) {

            [253] => 			$tableName = $table->nodeName;

            [254] => 			$rows = $table->childNodes;

            [255] => 

            [256] => 			if (! is_null($rows)) {

            [257] => 				foreach ($rows as $row) {

            [258] => 					$columns = $row->childNodes;

            [259] => 

            [260] => 					if ($columns) {

            [261] => 						foreach ($columns as $column) {

            [262] => 							//if ($column->nodeName == '#text') continue;

            [263] => 							$columnName  = $column->nodeName;

            [264] => 							$columnValue = $column->nodeValue;

            [265] => 

            [266] => 							$data[$columnName] = $columnValue;

            [267] => 							$idColumn          = $tableName . '_id';

            [268] => 

            [269] => 							if ($columnName == $idColumn) {

            [270] => 								$this->idsMap[$idColumn][$columnValue] = $columnValue;

            [271] => 							}

            [272] => 						}

            [273] => 					}

            [274] => 				}

            [275] => 			}

            [276] => 		}

            [277] => 

            [278] => 		if (DB_ENGINE == 'mysqli') {

            [279] => 			$stmt   = $this->db->execute('SET sql_mode = "";');

            [280] => 		}

            [281] => 

            [282] => 		$q = '`';

            [283] => 

            [284] => 		if (DB_ENGINE == 'pgsql') {

            [285] => 			$q = '"';

            [286] => 		}

            [287] => 

            [288] => 		foreach ($tables as $tableName) {

            [289] => 			$rows       = $this->xpath->query("//root/database/$tableName/item");

            [290] => 

            [291] => 			if (! is_null($rows)) {

            [292] => 				foreach ($rows as $row) {

            [293] => 					$columns = $row->childNodes;

            [294] => 

            [295] => 					$update            = '';

            [296] => 					$data              = [];

            [297] => 					$idColumn          = $tableName . '_id';

            [298] => 

            [299] => 					foreach ($columns as $column) {

            [300] => 						//if ($column->nodeName == '#text') continue;

            [301] => 						$columnName  = $column->nodeName;

            [302] => 						$columnValue = $column->nodeValue;

            [303] => 

            [304] => 						if ($columnName == 'parent_id' && $columnValue > 0) {

            [305] => 							//self refrence table id

            [306] => 							$oldId       = $columnValue;

            [307] => 							$columnValue = $this->idsMap[$idColumn][$columnValue] ?? $columnValue;

            [308] => 						}

            [309] => 

            [310] => 						if ($columnName == $idColumn) {

            [311] => 							$idValue                           = $columnValue;

            [312] => 							$this->idsMap[$idColumn][$idValue] = $idValue;

            [313] => 						} else {

            [314] => 							if (isset($this->idsMap[$columnName]) && $columnValue > 0) {

            [315] => 								$oldId       = $columnValue;

            [316] => 

            [317] => 								if (isset($this->idsMap[$columnName][$columnValue])) {

            [318] => 									$columnValue = $this->idsMap[$columnName][$columnValue];

            [319] => 								} else {

            [320] => 									error_log("$tableName - $columnName with value `$columnValue` does not map, probably missing data");

            [321] => 								}

            [322] => 							}

            [323] => 

            [324] => 							$data[$columnName] = $columnValue;

            [325] => 

            [326] => 							if ($update) {

            [327] => 								$update .= ',';

            [328] => 							}

            [329] => 							$update .= "$q$columnName$q = :$columnName";

            [330] => 						}

            [331] => 					}

            [332] => 

            [333] => 					$cols   = implode("$q, $q",array_keys($data));

            [334] => 					$values = implode(', :',array_keys($data));

            [335] => 

            [336] => 					$duplicate = "ON DUPLICATE KEY UPDATE $update\n\n";

            [337] => 

            [338] => 					if (DB_ENGINE == 'sqlite' || DB_ENGINE == 'pgsql') {

            [339] => 						//$duplicate = "ON CONFLICT($q$cols$q) DO UPDATE SET $update\n\n";

            [340] => 						$duplicate = '';

            [341] => 					}

            [342] => 

            [343] => 					$sql = "INSERT INTO $q$tableName$q ($q$cols$q) VALUES (:$values)" . $duplicate;

            [344] => 

            [345] => 					$stmt   = $this->db->execute($sql, $data);

            [346] => 					$lastId = $this->db->insert_id;

            [347] => 

            [348] => 					if ($idColumn != 'site_id' && $idColumn != 'language_id') {

            [349] => 						$this->idsMap[$idColumn][$idValue] = $lastId;

            [350] => 					}

            [351] => 

            [352] => 					//$result = $stmt->get_result();

            [353] => 				}

            [354] => 			}

            [355] => 		}

            [356] => 

            [357] => 		return true;

            [358] => 	}

            [359] => }

        )

)