diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf37c7..54daf0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fix PDF export of tabs renamed in GLPI 11 +- Prevent PDF exports from failing when a network port has no instantiation type + or has multiple IP addresses. +- Prevent software and software-version PDF exports from failing when an + installation has no associated user. +- Use entity restriction criteria compatible with the GLPI query builder when + exporting software versions. ## [4.1.4] - 2026-07-30 diff --git a/inc/computer_softwareversion.class.php b/inc/computer_softwareversion.class.php index 306ba5a..cff99a5 100644 --- a/inc/computer_softwareversion.class.php +++ b/inc/computer_softwareversion.class.php @@ -246,7 +246,6 @@ public static function pdfForItem(PluginPdfSimplePDF $pdf, CommonDBTM $item) $tmp[] = $licname; } } - $linkUser = User::canView(); $pdf->displayLine( $data['version'], $compname, @@ -255,13 +254,14 @@ public static function pdfForItem(PluginPdfSimplePDF $pdf, CommonDBTM $item) $data['location'], $data['state'], $data['groupe'], - formatUserName( - $data['userid'], - $data['username'], - $data['userrealname'], - $data['userfirstname'], - $linkUser ? 1 : 0, - ), + ($data['userid'] === null + ? '' + : formatUserName( + (int) $data['userid'], + $data['username'], + $data['userrealname'], + $data['userfirstname'], + )), implode(', ', $tmp), Html::convDate($data['date_install']), ); @@ -307,7 +307,10 @@ public static function pdfForVersionByEntity(PluginPdfSimplePDF $pdf, SoftwareVe } $sql = ['SELECT' => ['id', 'completename'], 'FROM' => 'glpi_entities', - 'WHERE' => $dbu->getEntitiesRestrictRequest('glpi_entities'), + // getEntitiesRestrictRequest() returns a raw SQL string; feeding it to the + // array query builder produced "WHERE glpi_entities ( 1 )" and a MySQL + // error 1305. The criteria variant returns the array the builder expects. + 'WHERE' => $dbu->getEntitiesRestrictCriteria('glpi_entities'), 'ORDER' => 'completename']; foreach ($DB->request($sql) as $ID => $data) { diff --git a/inc/item_softwareversion.class.php b/inc/item_softwareversion.class.php index a67b47c..54b0fc1 100644 --- a/inc/item_softwareversion.class.php +++ b/inc/item_softwareversion.class.php @@ -284,7 +284,6 @@ public static function pdfForSoftware(PluginPdfSimplePDF $pdf, CommonDBTM $item) $tmp[] = $licname; } } - $linkUser = User::canView(); $pdf->displayLine( $data['version'], $data['item_type'], @@ -294,13 +293,14 @@ public static function pdfForSoftware(PluginPdfSimplePDF $pdf, CommonDBTM $item) $data['location'], $data['state'], $data['groupe'], - formatUserName( - $data['userid'], - $data['username'], - $data['userrealname'], - $data['userfirstname'], - $linkUser ? 1 : 0, - ), + ($data['userid'] === null + ? '' + : formatUserName( + (int) $data['userid'], + $data['username'], + $data['userrealname'], + $data['userfirstname'], + )), implode(', ', $tmp), ); } @@ -342,7 +342,10 @@ public static function pdfForVersionByEntity(PluginPdfSimplePDF $pdf, SoftwareVe } $sql = ['SELECT' => ['id', 'completename'], 'FROM' => 'glpi_entities', - 'WHERE' => $dbu->getEntitiesRestrictRequest('glpi_entities'), + // getEntitiesRestrictRequest() returns a raw SQL string; feeding it to the + // array query builder produced "WHERE glpi_entities ( 1 )" and a MySQL + // error 1305. The criteria variant returns the array the builder expects. + 'WHERE' => $dbu->getEntitiesRestrictCriteria('glpi_entities'), 'ORDER' => 'completename']; foreach ($DB->request($sql) as $ID => $data) { diff --git a/inc/networkport.class.php b/inc/networkport.class.php index 1d5a0ee..9a96040 100644 --- a/inc/networkport.class.php +++ b/inc/networkport.class.php @@ -73,8 +73,15 @@ public static function pdfForItem(PluginPdfSimplePDF $pdf, CommonDBTM $item) foreach ($result as $devid) { $netport = new NetworkPort(); $netport->getfromDB(current($devid)); - $instantiation_type = $netport->fields['instantiation_type']; - $instname = call_user_func([$instantiation_type, 'getTypeName']); + // Ports created by the inventory may carry no instantiation type at + // all; call_user_func(['', 'getTypeName']) then raised a TypeError and + // aborted the whole document. + $instantiation_type = $netport->fields['instantiation_type'] ?? ''; + if (!empty($instantiation_type) && is_a($instantiation_type, CommonDBTM::class, true)) { + $instname = call_user_func([$instantiation_type, 'getTypeName']); + } else { + $instname = NetworkPort::getTypeName(1); + } $pdf->displayTitle('' . $instname . ''); $pdf->displayLine('' . sprintf( @@ -138,26 +145,35 @@ public static function pdfForItem(PluginPdfSimplePDF $pdf, CommonDBTM $item) $netport->fields['mac'], )); - $sqlip = ['LEFT JOIN' => ['glpi_networknames' - => ['FKEY' => ['glpi_ipaddresses' => 'items_id', - 'glpi_networknames' => 'id'], - ['glpi_ipaddresses.entities_id' - => $_SESSION['glpiactive_entity']]]], - 'WHERE' => ['glpi_networknames.items_id' => $netport->fields['id']]]; - - $ipname = ''; - $ip = new IPAddress(); - if ($ip->getFromDBByRequest($sqlip)) { - $ipname = $ip->fields['name']; - - $pdf->displayLine('' . sprintf(__s('%1$s: %2$s'), __s('ip') . '', $ipname)); + // A network port usually carries several addresses (IPv4 + IPv6). + // IPAddress::getFromDBByRequest() expects a single result and throws + // a TooManyResultsException as soon as there are two, which aborted + // the whole PDF. Iterate over every address instead. + $sqlip = ['SELECT' => ['glpi_ipaddresses.id AS id', + 'glpi_ipaddresses.name AS name'], + 'FROM' => 'glpi_ipaddresses', + 'LEFT JOIN' => ['glpi_networknames' + => ['FKEY' => ['glpi_ipaddresses' => 'items_id', + 'glpi_networknames' => 'id']]], + 'WHERE' => ['glpi_networknames.items_id' => $netport->fields['id'], + 'glpi_ipaddresses.itemtype' => 'NetworkName', + 'glpi_ipaddresses.is_deleted' => 0] + + $dbu->getEntitiesRestrictCriteria('glpi_ipaddresses'), + 'ORDER' => 'glpi_ipaddresses.name']; + + foreach ($DB->request($sqlip) as $ipdata) { + $pdf->displayLine('' . sprintf( + __s('%1$s: %2$s'), + __s('ip') . '', + $ipdata['name'], + )); $sql = ['SELECT' => 'glpi_ipaddresses_ipnetworks.ipnetworks_id', 'FROM' => 'glpi_ipaddresses_ipnetworks', 'LEFT JOIN' => ['glpi_ipnetworks' => ['FKEY' => ['glpi_ipaddresses_ipnetworks' => 'ipnetworks_id', 'glpi_ipnetworks' => 'id']]], - 'WHERE' => ['glpi_ipaddresses_ipnetworks.ipaddresses_id' => $ip->getID()] + 'WHERE' => ['glpi_ipaddresses_ipnetworks.ipaddresses_id' => $ipdata['id']] + $dbu->getEntitiesRestrictCriteria('glpi_ipnetworks')]; $res = $DB->request($sql);