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] => }
)
)