diff --git a/application/Html2Text.php b/application/Html2Text.php deleted file mode 100644 index 6b3c898a6..000000000 --- a/application/Html2Text.php +++ /dev/null @@ -1,331 +0,0 @@ - - * @copyright Copyright 2012 Sean Murphy. All rights reserved. - * @license http://creativecommons.org/publicdomain/zero/1.0/ - * @link http://php.net/manual/function.str-replace.php - * - * @param mixed $search - * @param mixed $replace - * @param mixed $subject - * @param int $count - * @return mixed - */ -function mb_str_replace($search, $replace, $subject, &$count = 0) { - if (!is_array($subject)) { - // Normalize $search and $replace so they are both arrays of the same length - $searches = is_array($search) ? array_values($search) : array($search); - $replacements = is_array($replace) ? array_values($replace) : array($replace); - $replacements = array_pad($replacements, count($searches), ''); - foreach ($searches as $key => $search) { - $parts = mb_split(preg_quote($search), $subject); - if (is_array($parts)) - { - $count += count($parts) - 1; - $subject = implode($replacements[$key], $parts); - } - } - } else { - // Call mb_str_replace for each subject in array, recursively - foreach ($subject as $key => $value) { - $subject[$key] = mb_str_replace($search, $replace, $value, $count); - } - } - return $subject; -} - -/****************************************************************************** - * Copyright (c) 2010 Jevon Wright and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * or - * - * LGPL which is available at http://www.gnu.org/licenses/lgpl.html - * - * - * Contributors: - * Jevon Wright - initial API and implementation - * Denis Flaven - some fixes for properly handling UTF-8 characters - ****************************************************************************/ - -class Html2Text { - - /** - * Tries to convert the given HTML into a plain text format - best suited for - * e-mail display, etc. - * - *

In particular, it tries to maintain the following features: - *

- * - * @param string html the input HTML - * @return string the HTML converted, as best as possible, to text - * @throws Html2TextException if the HTML could not be loaded as a {@link DOMDocument} - */ - static function convert($html) { - // replace   with spaces - - $html = str_replace(" ", " ", $html); - $html = mb_str_replace("\xc2\xa0", " ", $html); // DO NOT USE str_replace since it breaks the "à" character which is \xc3 \xa0 in UTF-8 - - $html = static::fixNewlines($html); - - $doc = new \DOMDocument(); - if (!@$doc->loadHTML(''.$html)) // Forces the UTF-8 character set for HTML fragments - { - throw new Html2TextException("Could not load HTML - badly formed?", $html); - } - - $output = static::iterateOverNode($doc); - - // remove leading and trailing spaces on each line - $output = preg_replace("/[ \t]*\n[ \t]*/im", "\n", $output); - $output = preg_replace("/ *\t */im", "\t", $output); - - // remove unnecessary empty lines - $output = preg_replace("/\n\n\n*/im", "\n\n", $output); - - // remove leading and trailing whitespace - $output = trim($output); - - return $output; - } - - /** - * Unify newlines; in particular, \r\n becomes \n, and - * then \r becomes \n. This means that all newlines (Unix, Windows, Mac) - * all become \ns. - * - * @param string text text with any number of \r, \r\n and \n combinations - * @return string the fixed text - */ - static function fixNewlines($text) { - // replace \r\n to \n - $text = str_replace("\r\n", "\n", $text); - // remove \rs - $text = str_replace("\r", "\n", $text); - - return $text; - } - - static function nextChildName($node) { - // get the next child - $nextNode = $node->nextSibling; - while ($nextNode != null) { - if ($nextNode instanceof \DOMElement) { - break; - } - $nextNode = $nextNode->nextSibling; - } - $nextName = null; - if ($nextNode instanceof \DOMElement && $nextNode != null) { - $nextName = strtolower($nextNode->nodeName); - } - - return $nextName; - } - - static function prevChildName($node) { - // get the previous child - $nextNode = $node->previousSibling; - while ($nextNode != null) { - if ($nextNode instanceof \DOMElement) { - break; - } - $nextNode = $nextNode->previousSibling; - } - $nextName = null; - if ($nextNode instanceof \DOMElement && $nextNode != null) { - $nextName = strtolower($nextNode->nodeName); - } - - return $nextName; - } - - static function iterateOverNode($node) { - if ($node instanceof \DOMText) { - // Replace whitespace characters with a space (equivilant to \s) - return preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $node->wholeText); - } - if ($node instanceof \DOMDocumentType) { - // ignore - return ""; - } - - $nextName = static::nextChildName($node); - $prevName = static::prevChildName($node); - - $name = strtolower($node->nodeName); - - // start whitespace - switch ($name) { - case "hr": - return "---------------------------------------------------------------\n"; - - case "style": - case "head": - case "title": - case "meta": - case "script": - // ignore these tags - return ""; - - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": - case "ol": - case "ul": - // add two newlines, second line is added below - $output = "\n"; - break; - - case "td": - case "th": - // add tab char to separate table fields - $output = "\t"; - break; - - case "tr": - case "p": - case "div": - // add one line - $output = "\n"; - break; - - case "li": - $output = "- "; - break; - - default: - // print out contents of unknown tags - $output = ""; - break; - } - - // debug - //$output .= "[$name,$nextName]"; - - if (isset($node->childNodes)) { - for ($i = 0; $i < $node->childNodes->length; $i++) { - $n = $node->childNodes->item($i); - - $text = static::iterateOverNode($n); - - $output .= $text; - } - } - - // end whitespace - switch ($name) { - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": - $output .= "\n"; - break; - - case "p": - case "br": - // add one line - if ($nextName != "div") - $output .= "\n"; - break; - - case "div": - // add one line only if the next child isn't a div - if ($nextName != "div" && $nextName != null) - $output .= "\n"; - break; - - case "a": - // links are returned in [text](link) format - $href = $node->getAttribute("href"); - - $output = trim($output); - - // remove double [[ ]] s from linking images - if (substr($output, 0, 1) == "[" && substr($output, -1) == "]") { - $output = substr($output, 1, strlen($output) - 2); - - // for linking images, the title of the overrides the title of the - if ($node->getAttribute("title")) { - $output = $node->getAttribute("title"); - } - } - - // if there is no link text, but a title attr - if (!$output && $node->getAttribute("title")) { - $output = $node->getAttribute("title"); - } - - if ($href == null) { - // it doesn't link anywhere - if ($node->getAttribute("name") != null) { - $output = "[$output]"; - } - } else { - if ($href == $output || $href == "mailto:$output" || $href == "http://$output" || $href == "https://$output") { - // link to the same address: just use link - $output; - } else { - // replace it - if ($output) { - $output = "[$output]($href)"; - } else { - // empty string - $output = $href; - } - } - } - - // does the next node require additional whitespace? - switch ($nextName) { - case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": - $output .= "\n"; - break; - } - break; - - case "img": - if ($node->getAttribute("title")) { - $output = "[" . $node->getAttribute("title") . "]"; - } elseif ($node->getAttribute("alt")) { - $output = "[" . $node->getAttribute("alt") . "]"; - } else { - $output = ""; - } - break; - - case "li": - $output .= "\n"; - break; - - default: - // do nothing - } - - return $output; - } - -} diff --git a/application/Html2TextException.php b/application/Html2TextException.php deleted file mode 100644 index ddfa86586..000000000 --- a/application/Html2TextException.php +++ /dev/null @@ -1,28 +0,0 @@ -more_info = $more_info; - } -} diff --git a/application/utils.inc.php b/application/utils.inc.php index 48e53f4bd..887df1ab2 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -26,6 +26,7 @@ use Combodo\iTop\Service\Module\ModuleService; use ScssPhp\ScssPhp\Compiler; use ScssPhp\ScssPhp\OutputStyle; use ScssPhp\ScssPhp\ValueConverter; +use Soundasleep\Html2Text; /** @@ -2067,7 +2068,7 @@ SQL; { try { //return ''.$sHtml; - return \Html2Text\Html2Text::convert(''.$sHtml); + return Html2Text::convert(''.$sHtml); } catch (Exception $e) { return $e->getMessage(); diff --git a/composer.json b/composer.json index 8adc82473..ffacc9955 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ "symfony/yaml": "~6.4.0", "tecnickcom/tcpdf": "^6.6.0", "thenetworg/oauth2-azure": "^2.0", - "masterminds/html5": "^2.8.0" + "masterminds/html5": "^2.8.0", + "soundasleep/html2text": "~2.1" }, "require-dev": { "symfony/debug-bundle": "~6.4.0", diff --git a/composer.lock b/composer.lock index b093c2cd5..01d78be94 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c8ab1de6659dd4fa2ded6043615b86e6", + "content-hash": "d2f27adf8df98b0e8b1fdc19d514197f", "packages": [ { "name": "apereo/phpcas", @@ -2041,6 +2041,61 @@ }, "time": "2024-01-13T12:36:40+00:00" }, + { + "name": "soundasleep/html2text", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/soundasleep/html2text.git", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/soundasleep/html2text/zipball/83502b6f8f1aaef8e2e238897199d64f284b4af3", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.3|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Soundasleep\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jevon Wright", + "homepage": "https://jevon.org", + "role": "Developer" + } + ], + "description": "A PHP script to convert HTML into a plain text format", + "homepage": "https://github.com/soundasleep/html2text", + "keywords": [ + "email", + "html", + "php", + "text" + ], + "support": { + "email": "support@jevon.org", + "issues": "https://github.com/soundasleep/html2text/issues", + "source": "https://github.com/soundasleep/html2text/tree/2.1.0" + }, + "time": "2023-01-06T09:28:15+00:00" + }, { "name": "symfony/cache", "version": "v6.4.2", diff --git a/js/ckeditor/package.json b/js/ckeditor/package.json index 88c007a8e..4e970ab16 100644 --- a/js/ckeditor/package.json +++ b/js/ckeditor/package.json @@ -53,6 +53,7 @@ "scripts": { "styles": "cp -r src/resources/styles/ build/styles", "build": "webpack --mode production && npm run styles", + "dev": "webpack --mode development --watch && npm run styles", "postbuild": "tsc --declaration --declarationDir build --stripInternal --emitDeclarationOnly" } } diff --git a/js/ckeditor/src/plugins/disabler/disabler.plugin.ts b/js/ckeditor/src/plugins/disabler/disabler.plugin.ts index 9ad8ccfa3..a51bac3be 100644 --- a/js/ckeditor/src/plugins/disabler/disabler.plugin.ts +++ b/js/ckeditor/src/plugins/disabler/disabler.plugin.ts @@ -1,12 +1,6 @@ import { Plugin } from '@ckeditor/ckeditor5-core'; import {ClassicEditor} from "@ckeditor/ckeditor5-editor-classic"; -interface BlockFieldInterface{ - (element:HTMLElement, isBlocked: boolean):any; -} - -declare var BlockFieldElement: BlockFieldInterface; - export default class Disabler extends Plugin { static get pluginName() { @@ -42,7 +36,11 @@ export default class Disabler extends Plugin { // @ts-ignore const oElement = $(oEditor.ui.element); if(typeof oElement.block === 'function') { - BlockFieldElement(oElement, oInputElement.disabled); + if (oInputElement.disabled) { + oElement.block({message: '', blockMsgClass: '', enableValidation : true, baseZ: 9999, overlayCSS: { backgroundColor: '#ccd6e066'}}); + } else { + oElement.unblock(); + } } // handle ckeditor read only mode diff --git a/js/utils.js b/js/utils.js index 5bb9fc24f..042e118fa 100644 --- a/js/utils.js +++ b/js/utils.js @@ -314,14 +314,6 @@ function BlockField(field_id, bBlocked) { } } -function BlockFieldElement(element, bBlocked) { - if (bBlocked) { - element.block({message: '', enableValidation : true, baseZ: 9999, overlayCSS: { backgroundColor: '#ccd6e066'}}); - } else { - element.unblock(); - } -} - /** * Updates (enables/disables) a "duration" field */ diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index f16c24d02..0fc4c1b90 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -746,8 +746,6 @@ return array( 'HTMLDOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', 'HTMLNullSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', 'HTMLSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', - 'Html2Text\\Html2Text' => $baseDir . '/application/Html2Text.php', - 'Html2Text\\Html2TextException' => $baseDir . '/application/Html2TextException.php', 'ITopArchiveTar' => $baseDir . '/core/tar-itop.class.inc.php', 'InlineImage' => $baseDir . '/core/inlineimage.class.inc.php', 'InlineImageGC' => $baseDir . '/core/inlineimage.class.inc.php', @@ -1045,13 +1043,16 @@ return array( 'Laminas\\Validator\\GpsPoint' => $vendorDir . '/laminas/laminas-validator/src/GpsPoint.php', 'Laminas\\Validator\\GreaterThan' => $vendorDir . '/laminas/laminas-validator/src/GreaterThan.php', 'Laminas\\Validator\\Hex' => $vendorDir . '/laminas/laminas-validator/src/Hex.php', + 'Laminas\\Validator\\HostWithPublicIPv4Address' => $vendorDir . '/laminas/laminas-validator/src/HostWithPublicIPv4Address.php', 'Laminas\\Validator\\Hostname' => $vendorDir . '/laminas/laminas-validator/src/Hostname.php', 'Laminas\\Validator\\Iban' => $vendorDir . '/laminas/laminas-validator/src/Iban.php', 'Laminas\\Validator\\Identical' => $vendorDir . '/laminas/laminas-validator/src/Identical.php', 'Laminas\\Validator\\InArray' => $vendorDir . '/laminas/laminas-validator/src/InArray.php', 'Laminas\\Validator\\Ip' => $vendorDir . '/laminas/laminas-validator/src/Ip.php', + 'Laminas\\Validator\\IsArray' => $vendorDir . '/laminas/laminas-validator/src/IsArray.php', 'Laminas\\Validator\\IsCountable' => $vendorDir . '/laminas/laminas-validator/src/IsCountable.php', 'Laminas\\Validator\\IsInstanceOf' => $vendorDir . '/laminas/laminas-validator/src/IsInstanceOf.php', + 'Laminas\\Validator\\IsJsonString' => $vendorDir . '/laminas/laminas-validator/src/IsJsonString.php', 'Laminas\\Validator\\Isbn' => $vendorDir . '/laminas/laminas-validator/src/Isbn.php', 'Laminas\\Validator\\Isbn\\Isbn10' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn10.php', 'Laminas\\Validator\\Isbn\\Isbn13' => $vendorDir . '/laminas/laminas-validator/src/Isbn/Isbn13.php', @@ -1067,7 +1068,10 @@ return array( 'Laminas\\Validator\\Step' => $vendorDir . '/laminas/laminas-validator/src/Step.php', 'Laminas\\Validator\\StringLength' => $vendorDir . '/laminas/laminas-validator/src/StringLength.php', 'Laminas\\Validator\\Timezone' => $vendorDir . '/laminas/laminas-validator/src/Timezone.php', + 'Laminas\\Validator\\Translator\\DummyTranslator' => $vendorDir . '/laminas/laminas-validator/src/Translator/DummyTranslator.php', + 'Laminas\\Validator\\Translator\\Translator' => $vendorDir . '/laminas/laminas-validator/src/Translator/Translator.php', 'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php', + 'Laminas\\Validator\\Translator\\TranslatorFactory' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorFactory.php', 'Laminas\\Validator\\Translator\\TranslatorInterface' => $vendorDir . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php', 'Laminas\\Validator\\UndisclosedPassword' => $vendorDir . '/laminas/laminas-validator/src/UndisclosedPassword.php', 'Laminas\\Validator\\Uri' => $vendorDir . '/laminas/laminas-validator/src/Uri.php', @@ -1152,11 +1156,11 @@ return array( 'ModuleHandlerApiInterface' => $baseDir . '/core/modulehandler.class.inc.php', 'MonthlyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', 'MyHelpers' => $baseDir . '/core/MyHelpers.class.inc.php', - 'MySQLException' => $baseDir . '/application/exceptions/mysql/MySQLException.php', - 'MySQLHasGoneAwayException' => $baseDir . '/application/exceptions/mysql/MySQLHasGoneAwayException.php', - 'MySQLNoTransactionException' => $baseDir . '/application/exceptions/mysql/MySQLNoTransactionException.php', - 'MySQLQueryHasNoResultException' => $baseDir . '/application/exceptions/mysql/MySQLQueryHasNoResultException.php', - 'MySQLTransactionNotClosedException' => $baseDir . '/application/exceptions/mysql/MySQLTransactionNotClosedException.php', + 'MySQLException' => $baseDir . '/core/cmdbsource.class.inc.php', + 'MySQLHasGoneAwayException' => $baseDir . '/core/cmdbsource.class.inc.php', + 'MySQLNoTransactionException' => $baseDir . '/core/cmdbsource.class.inc.php', + 'MySQLQueryHasNoResultException' => $baseDir . '/core/cmdbsource.class.inc.php', + 'MySQLTransactionNotClosedException' => $baseDir . '/core/cmdbsource.class.inc.php', 'NestedQueryExpression' => $baseDir . '/core/oql/expression.class.inc.php', 'NestedQueryOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', 'NewObjectMenuNode' => $baseDir . '/application/menunode.class.inc.php', @@ -1538,6 +1542,7 @@ return array( 'SQLObjectQueryBuilder' => $baseDir . '/core/sqlobjectquerybuilder.class.inc.php', 'SQLQuery' => $baseDir . '/core/sqlquery.class.inc.php', 'SQLUnionQuery' => $baseDir . '/core/sqlunionquery.class.inc.php', + 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'SVGDOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', @@ -1549,6 +1554,7 @@ return array( 'Sabberworm\\CSS\\OutputFormat' => $vendorDir . '/sabberworm/php-css-parser/src/OutputFormat.php', 'Sabberworm\\CSS\\OutputFormatter' => $vendorDir . '/sabberworm/php-css-parser/src/OutputFormatter.php', 'Sabberworm\\CSS\\Parser' => $vendorDir . '/sabberworm/php-css-parser/src/Parser.php', + 'Sabberworm\\CSS\\Parsing\\Anchor' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/Anchor.php', 'Sabberworm\\CSS\\Parsing\\OutputException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/OutputException.php', 'Sabberworm\\CSS\\Parsing\\ParserState' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/ParserState.php', 'Sabberworm\\CSS\\Parsing\\SourceException' => $vendorDir . '/sabberworm/php-css-parser/src/Parsing/SourceException.php', @@ -1646,6 +1652,8 @@ return array( 'SimpleCryptSodiumEngine' => $baseDir . '/core/simplecrypt.class.inc.php', 'SimpleGraph' => $baseDir . '/core/simplegraph.class.inc.php', 'SimpleGraphException' => $baseDir . '/core/simplegraph.class.inc.php', + 'Soundasleep\\Html2Text' => $vendorDir . '/soundasleep/html2text/src/Html2Text.php', + 'Soundasleep\\Html2TextException' => $vendorDir . '/soundasleep/html2text/src/Html2TextException.php', 'SpreadsheetBulkExport' => $baseDir . '/core/spreadsheetbulkexport.class.inc.php', 'StimulusChecker' => $baseDir . '/core/userrights.class.inc.php', 'StimulusInternal' => $baseDir . '/core/stimulus.class.inc.php', @@ -1937,6 +1945,7 @@ return array( 'Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => $vendorDir . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', 'Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => $vendorDir . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', 'Symfony\\Component\\Config\\Exception\\LoaderLoadException' => $vendorDir . '/symfony/config/Exception/LoaderLoadException.php', + 'Symfony\\Component\\Config\\Exception\\LogicException' => $vendorDir . '/symfony/config/Exception/LogicException.php', 'Symfony\\Component\\Config\\FileLocator' => $vendorDir . '/symfony/config/FileLocator.php', 'Symfony\\Component\\Config\\FileLocatorInterface' => $vendorDir . '/symfony/config/FileLocatorInterface.php', 'Symfony\\Component\\Config\\Loader\\DelegatingLoader' => $vendorDir . '/symfony/config/Loader/DelegatingLoader.php', @@ -2095,11 +2104,13 @@ return array( 'Symfony\\Component\\CssSelector\\Node\\ElementNode' => $vendorDir . '/symfony/css-selector/Node/ElementNode.php', 'Symfony\\Component\\CssSelector\\Node\\FunctionNode' => $vendorDir . '/symfony/css-selector/Node/FunctionNode.php', 'Symfony\\Component\\CssSelector\\Node\\HashNode' => $vendorDir . '/symfony/css-selector/Node/HashNode.php', + 'Symfony\\Component\\CssSelector\\Node\\MatchingNode' => $vendorDir . '/symfony/css-selector/Node/MatchingNode.php', 'Symfony\\Component\\CssSelector\\Node\\NegationNode' => $vendorDir . '/symfony/css-selector/Node/NegationNode.php', 'Symfony\\Component\\CssSelector\\Node\\NodeInterface' => $vendorDir . '/symfony/css-selector/Node/NodeInterface.php', 'Symfony\\Component\\CssSelector\\Node\\PseudoNode' => $vendorDir . '/symfony/css-selector/Node/PseudoNode.php', 'Symfony\\Component\\CssSelector\\Node\\SelectorNode' => $vendorDir . '/symfony/css-selector/Node/SelectorNode.php', 'Symfony\\Component\\CssSelector\\Node\\Specificity' => $vendorDir . '/symfony/css-selector/Node/Specificity.php', + 'Symfony\\Component\\CssSelector\\Node\\SpecificityAdjustmentNode' => $vendorDir . '/symfony/css-selector/Node/SpecificityAdjustmentNode.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\CommentHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/CommentHandler.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HandlerInterface' => $vendorDir . '/symfony/css-selector/Parser/Handler/HandlerInterface.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HashHandler' => $vendorDir . '/symfony/css-selector/Parser/Handler/HashHandler.php', @@ -2150,10 +2161,13 @@ return array( 'Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => $vendorDir . '/symfony/dependency-injection/Attribute/Autowire.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireCallable.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireDecorated.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireInline' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireInline.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireIterator.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireLocator.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireMethodOf' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireMethodOf.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => $vendorDir . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => $vendorDir . '/symfony/dependency-injection/Attribute/Exclude.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\Lazy' => $vendorDir . '/symfony/dependency-injection/Attribute/Lazy.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => $vendorDir . '/symfony/dependency-injection/Attribute/MapDecorated.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedIterator.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => $vendorDir . '/symfony/dependency-injection/Attribute/TaggedLocator.php', @@ -2169,6 +2183,7 @@ return array( 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowirePass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', + 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckAliasValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckAliasValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => $vendorDir . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', @@ -2193,6 +2208,7 @@ return array( 'Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', + 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveAutowireInlineAttributesPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveAutowireInlineAttributesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => $vendorDir . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', @@ -2231,6 +2247,7 @@ return array( 'Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarLoaderInterface.php', 'Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessor.php', 'Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => $vendorDir . '/symfony/dependency-injection/EnvVarProcessorInterface.php', + 'Symfony\\Component\\DependencyInjection\\Exception\\AutoconfigureFailedException' => $vendorDir . '/symfony/dependency-injection/Exception/AutoconfigureFailedException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => $vendorDir . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/dependency-injection/Exception/BadMethodCallException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => $vendorDir . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', @@ -2303,6 +2320,7 @@ return array( 'Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/GlobFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/IniFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/PhpFileLoader.php', + 'Symfony\\Component\\DependencyInjection\\Loader\\UndefinedExtensionHandler' => $vendorDir . '/symfony/dependency-injection/Loader/UndefinedExtensionHandler.php', 'Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/XmlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/dependency-injection/Loader/YamlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Parameter' => $vendorDir . '/symfony/dependency-injection/Parameter.php', @@ -2315,6 +2333,7 @@ return array( 'Symfony\\Component\\DependencyInjection\\Reference' => $vendorDir . '/symfony/dependency-injection/Reference.php', 'Symfony\\Component\\DependencyInjection\\ReverseContainer' => $vendorDir . '/symfony/dependency-injection/ReverseContainer.php', 'Symfony\\Component\\DependencyInjection\\ServiceLocator' => $vendorDir . '/symfony/dependency-injection/ServiceLocator.php', + 'Symfony\\Component\\DependencyInjection\\StaticEnvVarLoader' => $vendorDir . '/symfony/dependency-injection/StaticEnvVarLoader.php', 'Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => $vendorDir . '/symfony/dependency-injection/TaggedContainerInterface.php', 'Symfony\\Component\\DependencyInjection\\TypedReference' => $vendorDir . '/symfony/dependency-injection/TypedReference.php', 'Symfony\\Component\\DependencyInjection\\Variable' => $vendorDir . '/symfony/dependency-injection/Variable.php', @@ -2657,6 +2676,7 @@ return array( 'Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/routing/Exception/ExceptionInterface.php', 'Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/routing/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => $vendorDir . '/symfony/routing/Exception/InvalidParameterException.php', + 'Symfony\\Component\\Routing\\Exception\\LogicException' => $vendorDir . '/symfony/routing/Exception/LogicException.php', 'Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => $vendorDir . '/symfony/routing/Exception/MethodNotAllowedException.php', 'Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => $vendorDir . '/symfony/routing/Exception/MissingMandatoryParametersException.php', 'Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => $vendorDir . '/symfony/routing/Exception/NoConfigurationException.php', @@ -2797,6 +2817,7 @@ return array( 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php', + 'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => $vendorDir . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', @@ -2858,7 +2879,9 @@ return array( 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', @@ -2924,6 +2947,7 @@ return array( 'TriggerOnStateLeave' => $baseDir . '/core/trigger.class.inc.php', 'TriggerOnThresholdReached' => $baseDir . '/core/trigger.class.inc.php', 'TrueExpression' => $baseDir . '/core/oql/expression.class.inc.php', + 'Twig\\Attribute\\YieldReady' => $vendorDir . '/twig/twig/src/Attribute/YieldReady.php', 'Twig\\Cache\\CacheInterface' => $vendorDir . '/twig/twig/src/Cache/CacheInterface.php', 'Twig\\Cache\\FilesystemCache' => $vendorDir . '/twig/twig/src/Cache/FilesystemCache.php', 'Twig\\Cache\\NullCache' => $vendorDir . '/twig/twig/src/Cache/NullCache.php', @@ -2947,6 +2971,7 @@ return array( 'Twig\\Extension\\SandboxExtension' => $vendorDir . '/twig/twig/src/Extension/SandboxExtension.php', 'Twig\\Extension\\StagingExtension' => $vendorDir . '/twig/twig/src/Extension/StagingExtension.php', 'Twig\\Extension\\StringLoaderExtension' => $vendorDir . '/twig/twig/src/Extension/StringLoaderExtension.php', + 'Twig\\Extension\\YieldNotReadyExtension' => $vendorDir . '/twig/twig/src/Extension/YieldNotReadyExtension.php', 'Twig\\FileExtensionEscapingStrategy' => $vendorDir . '/twig/twig/src/FileExtensionEscapingStrategy.php', 'Twig\\Lexer' => $vendorDir . '/twig/twig/src/Lexer.php', 'Twig\\Loader\\ArrayLoader' => $vendorDir . '/twig/twig/src/Loader/ArrayLoader.php', @@ -2962,10 +2987,12 @@ return array( 'Twig\\NodeVisitor\\OptimizerNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php', 'Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php', 'Twig\\NodeVisitor\\SandboxNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php', + 'Twig\\NodeVisitor\\YieldNotReadyNodeVisitor' => $vendorDir . '/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php', 'Twig\\Node\\AutoEscapeNode' => $vendorDir . '/twig/twig/src/Node/AutoEscapeNode.php', 'Twig\\Node\\BlockNode' => $vendorDir . '/twig/twig/src/Node/BlockNode.php', 'Twig\\Node\\BlockReferenceNode' => $vendorDir . '/twig/twig/src/Node/BlockReferenceNode.php', 'Twig\\Node\\BodyNode' => $vendorDir . '/twig/twig/src/Node/BodyNode.php', + 'Twig\\Node\\CaptureNode' => $vendorDir . '/twig/twig/src/Node/CaptureNode.php', 'Twig\\Node\\CheckSecurityCallNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityCallNode.php', 'Twig\\Node\\CheckSecurityNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityNode.php', 'Twig\\Node\\CheckToStringNode' => $vendorDir . '/twig/twig/src/Node/CheckToStringNode.php', @@ -3060,6 +3087,7 @@ return array( 'Twig\\RuntimeLoader\\ContainerRuntimeLoader' => $vendorDir . '/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php', 'Twig\\RuntimeLoader\\FactoryRuntimeLoader' => $vendorDir . '/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php', 'Twig\\RuntimeLoader\\RuntimeLoaderInterface' => $vendorDir . '/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php', + 'Twig\\Runtime\\EscaperRuntime' => $vendorDir . '/twig/twig/src/Runtime/EscaperRuntime.php', 'Twig\\Sandbox\\SecurityError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityError.php', 'Twig\\Sandbox\\SecurityNotAllowedFilterError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php', 'Twig\\Sandbox\\SecurityNotAllowedFunctionError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php', @@ -3068,6 +3096,7 @@ return array( 'Twig\\Sandbox\\SecurityNotAllowedTagError' => $vendorDir . '/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php', 'Twig\\Sandbox\\SecurityPolicy' => $vendorDir . '/twig/twig/src/Sandbox/SecurityPolicy.php', 'Twig\\Sandbox\\SecurityPolicyInterface' => $vendorDir . '/twig/twig/src/Sandbox/SecurityPolicyInterface.php', + 'Twig\\Sandbox\\SourcePolicyInterface' => $vendorDir . '/twig/twig/src/Sandbox/SourcePolicyInterface.php', 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index 632d6d2df..594907f1a 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -46,6 +46,7 @@ return array( 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), 'Symfony\\Bundle\\DebugBundle\\' => array($vendorDir . '/symfony/debug-bundle'), 'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'), + 'Soundasleep\\' => array($vendorDir . '/soundasleep/html2text/src'), 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'), 'Sabberworm\\CSS\\' => array($vendorDir . '/sabberworm/php-css-parser/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 8f1e52d1c..bc9bece45 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -74,6 +74,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Bundle\\FrameworkBundle\\' => 31, 'Symfony\\Bundle\\DebugBundle\\' => 27, 'Symfony\\Bridge\\Twig\\' => 20, + 'Soundasleep\\' => 12, 'ScssPhp\\ScssPhp\\' => 16, 'Sabberworm\\CSS\\' => 15, ), @@ -275,6 +276,10 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f array ( 0 => __DIR__ . '/..' . '/symfony/twig-bridge', ), + 'Soundasleep\\' => + array ( + 0 => __DIR__ . '/..' . '/soundasleep/html2text/src', + ), 'ScssPhp\\ScssPhp\\' => array ( 0 => __DIR__ . '/..' . '/scssphp/scssphp/src', @@ -1129,8 +1134,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'HTMLDOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', 'HTMLNullSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', 'HTMLSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', - 'Html2Text\\Html2Text' => __DIR__ . '/../..' . '/application/Html2Text.php', - 'Html2Text\\Html2TextException' => __DIR__ . '/../..' . '/application/Html2TextException.php', 'ITopArchiveTar' => __DIR__ . '/../..' . '/core/tar-itop.class.inc.php', 'InlineImage' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', 'InlineImageGC' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', @@ -1428,13 +1431,16 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Laminas\\Validator\\GpsPoint' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GpsPoint.php', 'Laminas\\Validator\\GreaterThan' => __DIR__ . '/..' . '/laminas/laminas-validator/src/GreaterThan.php', 'Laminas\\Validator\\Hex' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hex.php', + 'Laminas\\Validator\\HostWithPublicIPv4Address' => __DIR__ . '/..' . '/laminas/laminas-validator/src/HostWithPublicIPv4Address.php', 'Laminas\\Validator\\Hostname' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Hostname.php', 'Laminas\\Validator\\Iban' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Iban.php', 'Laminas\\Validator\\Identical' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Identical.php', 'Laminas\\Validator\\InArray' => __DIR__ . '/..' . '/laminas/laminas-validator/src/InArray.php', 'Laminas\\Validator\\Ip' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Ip.php', + 'Laminas\\Validator\\IsArray' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsArray.php', 'Laminas\\Validator\\IsCountable' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsCountable.php', 'Laminas\\Validator\\IsInstanceOf' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsInstanceOf.php', + 'Laminas\\Validator\\IsJsonString' => __DIR__ . '/..' . '/laminas/laminas-validator/src/IsJsonString.php', 'Laminas\\Validator\\Isbn' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn.php', 'Laminas\\Validator\\Isbn\\Isbn10' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn10.php', 'Laminas\\Validator\\Isbn\\Isbn13' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Isbn/Isbn13.php', @@ -1450,7 +1456,10 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Laminas\\Validator\\Step' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Step.php', 'Laminas\\Validator\\StringLength' => __DIR__ . '/..' . '/laminas/laminas-validator/src/StringLength.php', 'Laminas\\Validator\\Timezone' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Timezone.php', + 'Laminas\\Validator\\Translator\\DummyTranslator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/DummyTranslator.php', + 'Laminas\\Validator\\Translator\\Translator' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/Translator.php', 'Laminas\\Validator\\Translator\\TranslatorAwareInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php', + 'Laminas\\Validator\\Translator\\TranslatorFactory' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorFactory.php', 'Laminas\\Validator\\Translator\\TranslatorInterface' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Translator/TranslatorInterface.php', 'Laminas\\Validator\\UndisclosedPassword' => __DIR__ . '/..' . '/laminas/laminas-validator/src/UndisclosedPassword.php', 'Laminas\\Validator\\Uri' => __DIR__ . '/..' . '/laminas/laminas-validator/src/Uri.php', @@ -1535,11 +1544,11 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'ModuleHandlerApiInterface' => __DIR__ . '/../..' . '/core/modulehandler.class.inc.php', 'MonthlyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'MyHelpers' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', - 'MySQLException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLException.php', - 'MySQLHasGoneAwayException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLHasGoneAwayException.php', - 'MySQLNoTransactionException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLNoTransactionException.php', - 'MySQLQueryHasNoResultException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLQueryHasNoResultException.php', - 'MySQLTransactionNotClosedException' => __DIR__ . '/../..' . '/application/exceptions/mysql/MySQLTransactionNotClosedException.php', + 'MySQLException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', + 'MySQLHasGoneAwayException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', + 'MySQLNoTransactionException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', + 'MySQLQueryHasNoResultException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', + 'MySQLTransactionNotClosedException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', 'NestedQueryExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', 'NestedQueryOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', 'NewObjectMenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', @@ -1921,6 +1930,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'SQLObjectQueryBuilder' => __DIR__ . '/../..' . '/core/sqlobjectquerybuilder.class.inc.php', 'SQLQuery' => __DIR__ . '/../..' . '/core/sqlquery.class.inc.php', 'SQLUnionQuery' => __DIR__ . '/../..' . '/core/sqlunionquery.class.inc.php', + 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'SVGDOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', @@ -1932,6 +1942,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Sabberworm\\CSS\\OutputFormat' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/OutputFormat.php', 'Sabberworm\\CSS\\OutputFormatter' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/OutputFormatter.php', 'Sabberworm\\CSS\\Parser' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parser.php', + 'Sabberworm\\CSS\\Parsing\\Anchor' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/Anchor.php', 'Sabberworm\\CSS\\Parsing\\OutputException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/OutputException.php', 'Sabberworm\\CSS\\Parsing\\ParserState' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/ParserState.php', 'Sabberworm\\CSS\\Parsing\\SourceException' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/Parsing/SourceException.php', @@ -2029,6 +2040,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'SimpleCryptSodiumEngine' => __DIR__ . '/../..' . '/core/simplecrypt.class.inc.php', 'SimpleGraph' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', 'SimpleGraphException' => __DIR__ . '/../..' . '/core/simplegraph.class.inc.php', + 'Soundasleep\\Html2Text' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2Text.php', + 'Soundasleep\\Html2TextException' => __DIR__ . '/..' . '/soundasleep/html2text/src/Html2TextException.php', 'SpreadsheetBulkExport' => __DIR__ . '/../..' . '/core/spreadsheetbulkexport.class.inc.php', 'StimulusChecker' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', 'StimulusInternal' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', @@ -2320,6 +2333,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLoaderImportCircularReferenceException.php', 'Symfony\\Component\\Config\\Exception\\FileLocatorFileNotFoundException' => __DIR__ . '/..' . '/symfony/config/Exception/FileLocatorFileNotFoundException.php', 'Symfony\\Component\\Config\\Exception\\LoaderLoadException' => __DIR__ . '/..' . '/symfony/config/Exception/LoaderLoadException.php', + 'Symfony\\Component\\Config\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/config/Exception/LogicException.php', 'Symfony\\Component\\Config\\FileLocator' => __DIR__ . '/..' . '/symfony/config/FileLocator.php', 'Symfony\\Component\\Config\\FileLocatorInterface' => __DIR__ . '/..' . '/symfony/config/FileLocatorInterface.php', 'Symfony\\Component\\Config\\Loader\\DelegatingLoader' => __DIR__ . '/..' . '/symfony/config/Loader/DelegatingLoader.php', @@ -2478,11 +2492,13 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\CssSelector\\Node\\ElementNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/ElementNode.php', 'Symfony\\Component\\CssSelector\\Node\\FunctionNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/FunctionNode.php', 'Symfony\\Component\\CssSelector\\Node\\HashNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/HashNode.php', + 'Symfony\\Component\\CssSelector\\Node\\MatchingNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/MatchingNode.php', 'Symfony\\Component\\CssSelector\\Node\\NegationNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/NegationNode.php', 'Symfony\\Component\\CssSelector\\Node\\NodeInterface' => __DIR__ . '/..' . '/symfony/css-selector/Node/NodeInterface.php', 'Symfony\\Component\\CssSelector\\Node\\PseudoNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/PseudoNode.php', 'Symfony\\Component\\CssSelector\\Node\\SelectorNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/SelectorNode.php', 'Symfony\\Component\\CssSelector\\Node\\Specificity' => __DIR__ . '/..' . '/symfony/css-selector/Node/Specificity.php', + 'Symfony\\Component\\CssSelector\\Node\\SpecificityAdjustmentNode' => __DIR__ . '/..' . '/symfony/css-selector/Node/SpecificityAdjustmentNode.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\CommentHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/CommentHandler.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/HandlerInterface.php', 'Symfony\\Component\\CssSelector\\Parser\\Handler\\HashHandler' => __DIR__ . '/..' . '/symfony/css-selector/Parser/Handler/HashHandler.php', @@ -2533,10 +2549,13 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\Attribute\\Autowire' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Autowire.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireCallable' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireCallable.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireDecorated.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireInline' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireInline.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireIterator.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireLocator.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireMethodOf' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireMethodOf.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\AutowireServiceClosure' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/AutowireServiceClosure.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\Exclude' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Exclude.php', + 'Symfony\\Component\\DependencyInjection\\Attribute\\Lazy' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/Lazy.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\MapDecorated' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/MapDecorated.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedIterator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedIterator.php', 'Symfony\\Component\\DependencyInjection\\Attribute\\TaggedLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/Attribute/TaggedLocator.php', @@ -2552,6 +2571,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowirePass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowirePass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredMethodsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\AutowireRequiredPropertiesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/AutowireRequiredPropertiesPass.php', + 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckAliasValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckAliasValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckArgumentsValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php', @@ -2576,6 +2596,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php', + 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveAutowireInlineAttributesPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveAutowireInlineAttributesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveBindingsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveBindingsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveChildDefinitionsPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveClassPass' => __DIR__ . '/..' . '/symfony/dependency-injection/Compiler/ResolveClassPass.php', @@ -2614,6 +2635,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\EnvVarLoaderInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarLoaderInterface.php', 'Symfony\\Component\\DependencyInjection\\EnvVarProcessor' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessor.php', 'Symfony\\Component\\DependencyInjection\\EnvVarProcessorInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/EnvVarProcessorInterface.php', + 'Symfony\\Component\\DependencyInjection\\Exception\\AutoconfigureFailedException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/AutoconfigureFailedException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\AutowiringFailedException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/AutowiringFailedException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/BadMethodCallException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => __DIR__ . '/..' . '/symfony/dependency-injection/Exception/EnvNotFoundException.php', @@ -2686,6 +2708,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\Loader\\GlobFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/GlobFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/IniFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/PhpFileLoader.php', + 'Symfony\\Component\\DependencyInjection\\Loader\\UndefinedExtensionHandler' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/UndefinedExtensionHandler.php', 'Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/XmlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/Loader/YamlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Parameter' => __DIR__ . '/..' . '/symfony/dependency-injection/Parameter.php', @@ -2698,6 +2721,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\DependencyInjection\\Reference' => __DIR__ . '/..' . '/symfony/dependency-injection/Reference.php', 'Symfony\\Component\\DependencyInjection\\ReverseContainer' => __DIR__ . '/..' . '/symfony/dependency-injection/ReverseContainer.php', 'Symfony\\Component\\DependencyInjection\\ServiceLocator' => __DIR__ . '/..' . '/symfony/dependency-injection/ServiceLocator.php', + 'Symfony\\Component\\DependencyInjection\\StaticEnvVarLoader' => __DIR__ . '/..' . '/symfony/dependency-injection/StaticEnvVarLoader.php', 'Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => __DIR__ . '/..' . '/symfony/dependency-injection/TaggedContainerInterface.php', 'Symfony\\Component\\DependencyInjection\\TypedReference' => __DIR__ . '/..' . '/symfony/dependency-injection/TypedReference.php', 'Symfony\\Component\\DependencyInjection\\Variable' => __DIR__ . '/..' . '/symfony/dependency-injection/Variable.php', @@ -3040,6 +3064,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\Routing\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/symfony/routing/Exception/ExceptionInterface.php', 'Symfony\\Component\\Routing\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Routing\\Exception\\InvalidParameterException' => __DIR__ . '/..' . '/symfony/routing/Exception/InvalidParameterException.php', + 'Symfony\\Component\\Routing\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/routing/Exception/LogicException.php', 'Symfony\\Component\\Routing\\Exception\\MethodNotAllowedException' => __DIR__ . '/..' . '/symfony/routing/Exception/MethodNotAllowedException.php', 'Symfony\\Component\\Routing\\Exception\\MissingMandatoryParametersException' => __DIR__ . '/..' . '/symfony/routing/Exception/MissingMandatoryParametersException.php', 'Symfony\\Component\\Routing\\Exception\\NoConfigurationException' => __DIR__ . '/..' . '/symfony/routing/Exception/NoConfigurationException.php', @@ -3180,6 +3205,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php', + 'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', @@ -3241,7 +3267,9 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', @@ -3307,6 +3335,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'TriggerOnStateLeave' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', 'TriggerOnThresholdReached' => __DIR__ . '/../..' . '/core/trigger.class.inc.php', 'TrueExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', + 'Twig\\Attribute\\YieldReady' => __DIR__ . '/..' . '/twig/twig/src/Attribute/YieldReady.php', 'Twig\\Cache\\CacheInterface' => __DIR__ . '/..' . '/twig/twig/src/Cache/CacheInterface.php', 'Twig\\Cache\\FilesystemCache' => __DIR__ . '/..' . '/twig/twig/src/Cache/FilesystemCache.php', 'Twig\\Cache\\NullCache' => __DIR__ . '/..' . '/twig/twig/src/Cache/NullCache.php', @@ -3330,6 +3359,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\Extension\\SandboxExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/SandboxExtension.php', 'Twig\\Extension\\StagingExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/StagingExtension.php', 'Twig\\Extension\\StringLoaderExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/StringLoaderExtension.php', + 'Twig\\Extension\\YieldNotReadyExtension' => __DIR__ . '/..' . '/twig/twig/src/Extension/YieldNotReadyExtension.php', 'Twig\\FileExtensionEscapingStrategy' => __DIR__ . '/..' . '/twig/twig/src/FileExtensionEscapingStrategy.php', 'Twig\\Lexer' => __DIR__ . '/..' . '/twig/twig/src/Lexer.php', 'Twig\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/twig/twig/src/Loader/ArrayLoader.php', @@ -3345,10 +3375,12 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\NodeVisitor\\OptimizerNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php', 'Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php', 'Twig\\NodeVisitor\\SandboxNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php', + 'Twig\\NodeVisitor\\YieldNotReadyNodeVisitor' => __DIR__ . '/..' . '/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php', 'Twig\\Node\\AutoEscapeNode' => __DIR__ . '/..' . '/twig/twig/src/Node/AutoEscapeNode.php', 'Twig\\Node\\BlockNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockNode.php', 'Twig\\Node\\BlockReferenceNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockReferenceNode.php', 'Twig\\Node\\BodyNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BodyNode.php', + 'Twig\\Node\\CaptureNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CaptureNode.php', 'Twig\\Node\\CheckSecurityCallNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityCallNode.php', 'Twig\\Node\\CheckSecurityNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityNode.php', 'Twig\\Node\\CheckToStringNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckToStringNode.php', @@ -3443,6 +3475,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\RuntimeLoader\\ContainerRuntimeLoader' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php', 'Twig\\RuntimeLoader\\FactoryRuntimeLoader' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php', 'Twig\\RuntimeLoader\\RuntimeLoaderInterface' => __DIR__ . '/..' . '/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php', + 'Twig\\Runtime\\EscaperRuntime' => __DIR__ . '/..' . '/twig/twig/src/Runtime/EscaperRuntime.php', 'Twig\\Sandbox\\SecurityError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityError.php', 'Twig\\Sandbox\\SecurityNotAllowedFilterError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php', 'Twig\\Sandbox\\SecurityNotAllowedFunctionError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php', @@ -3451,6 +3484,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\Sandbox\\SecurityNotAllowedTagError' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php', 'Twig\\Sandbox\\SecurityPolicy' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityPolicy.php', 'Twig\\Sandbox\\SecurityPolicyInterface' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SecurityPolicyInterface.php', + 'Twig\\Sandbox\\SourcePolicyInterface' => __DIR__ . '/..' . '/twig/twig/src/Sandbox/SourcePolicyInterface.php', 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index 44d865ac7..bc2c481d8 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -2128,6 +2128,64 @@ }, "install-path": "../scssphp/scssphp" }, + { + "name": "soundasleep/html2text", + "version": "2.1.0", + "version_normalized": "2.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/soundasleep/html2text.git", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/soundasleep/html2text/zipball/83502b6f8f1aaef8e2e238897199d64f284b4af3", + "reference": "83502b6f8f1aaef8e2e238897199d64f284b4af3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.3|^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "time": "2023-01-06T09:28:15+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Soundasleep\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jevon Wright", + "homepage": "https://jevon.org", + "role": "Developer" + } + ], + "description": "A PHP script to convert HTML into a plain text format", + "homepage": "https://github.com/soundasleep/html2text", + "keywords": [ + "email", + "html", + "php", + "text" + ], + "support": { + "email": "support@jevon.org", + "issues": "https://github.com/soundasleep/html2text/issues", + "source": "https://github.com/soundasleep/html2text/tree/2.1.0" + }, + "install-path": "../soundasleep/html2text" + }, { "name": "symfony/cache", "version": "v6.4.2", diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 16887e28c..c0cea0397 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'combodo/itop', 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '0036c70fbd34e0bfbdfdbaf26d497d8e1ed7bd04', + 'reference' => '71e36d264e098583e31c752528c815d1f9e29032', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,7 +22,7 @@ 'combodo/itop' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '0036c70fbd34e0bfbdfdbaf26d497d8e1ed7bd04', + 'reference' => '71e36d264e098583e31c752528c815d1f9e29032', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -359,6 +359,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'soundasleep/html2text' => array( + 'pretty_version' => '2.1.0', + 'version' => '2.1.0.0', + 'reference' => '83502b6f8f1aaef8e2e238897199d64f284b4af3', + 'type' => 'library', + 'install_path' => __DIR__ . '/../soundasleep/html2text', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/cache' => array( 'pretty_version' => 'v6.4.2', 'version' => '6.4.2.0', diff --git a/lib/composer/platform_check.php b/lib/composer/platform_check.php index dee74e173..425c21e9f 100644 --- a/lib/composer/platform_check.php +++ b/lib/composer/platform_check.php @@ -11,13 +11,10 @@ if (!(PHP_VERSION_ID >= 80100)) { $missingExtensions = array(); extension_loaded('curl') || $missingExtensions[] = 'curl'; extension_loaded('dom') || $missingExtensions[] = 'dom'; -extension_loaded('gd') || $missingExtensions[] = 'gd'; extension_loaded('iconv') || $missingExtensions[] = 'iconv'; extension_loaded('json') || $missingExtensions[] = 'json'; extension_loaded('libxml') || $missingExtensions[] = 'libxml'; -extension_loaded('mysqli') || $missingExtensions[] = 'mysqli'; extension_loaded('openssl') || $missingExtensions[] = 'openssl'; -extension_loaded('soap') || $missingExtensions[] = 'soap'; extension_loaded('tokenizer') || $missingExtensions[] = 'tokenizer'; extension_loaded('xml') || $missingExtensions[] = 'xml'; diff --git a/lib/soundasleep/html2text/.editorconfig b/lib/soundasleep/html2text/.editorconfig new file mode 100644 index 000000000..7974b6a8a --- /dev/null +++ b/lib/soundasleep/html2text/.editorconfig @@ -0,0 +1,23 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab +indent_size = 4 + +[*.md] +indent_style = space +indent_size = 2 + +# don't add newlines to test files +[tests/*] +indent_style = tabs +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/lib/soundasleep/html2text/.gitignore b/lib/soundasleep/html2text/.gitignore new file mode 100644 index 000000000..a41c6bab9 --- /dev/null +++ b/lib/soundasleep/html2text/.gitignore @@ -0,0 +1,7 @@ +tests/*.output +*.sublime-project +*.sublime-workspace +vendor/ +**/*.DS_Store +.phpunit.result.cache +composer.lock diff --git a/lib/soundasleep/html2text/CHANGELOG.md b/lib/soundasleep/html2text/CHANGELOG.md new file mode 100644 index 000000000..a1bda0954 --- /dev/null +++ b/lib/soundasleep/html2text/CHANGELOG.md @@ -0,0 +1,37 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.1.0] - 2019-02-15 +### Added +- Zero-width non-joiners are now stripped to prevent output issues, similar to non-breaking whitespace + +### Fixed +- Fix namespace in composer [#67](https://github.com/soundasleep/html2text/pull/67) + +## [1.0.0] - 2019-02-14 +### Added +- Added `drop_links` option to render links without the target href [#65](https://github.com/soundasleep/html2text/pull/65) + +### Changed +- **Important:** Changed namespace from `\Html2Text\Html2Text` to `\Soundasleep\Html2text` [#45](https://github.com/soundasleep/html2text/issues/45) +- Treat non-breaking spaces consistently: never include them in output text [#64](https://github.com/soundasleep/html2text/pull/64) +- Second argument to `convert()` is now an array, rather than boolean [#65](https://github.com/soundasleep/html2text/pull/65) +- Optimise/improve newline & whitespace handling [#47](https://github.com/soundasleep/html2text/pull/47) +- Upgrade PHP support to PHP 7.3+ +- Upgrade PHPUnit to 7.x +- Re-release project under MIT license [#58](https://github.com/soundasleep/html2text/issues/58) + +## [0.5.0] - 2017-04-20 +### Added +- Add ignore_error optional argument [#63](https://github.com/soundasleep/html2text/pull/63) +- Blockquote support [#50](https://github.com/soundasleep/html2text/pull/50) + +[Unreleased]: https://github.com/soundasleep/html2text/compare/1.1.0...HEAD +[1.1.0]: https://github.com/soundasleep/html2text/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/soundasleep/html2text/compare/0.5.0...1.0.0 +[0.5.0]: https://github.com/soundasleep/html2text/compare/0.5.0...0.3.4 diff --git a/lib/soundasleep/html2text/LICENSE.md b/lib/soundasleep/html2text/LICENSE.md new file mode 100644 index 000000000..d8613be25 --- /dev/null +++ b/lib/soundasleep/html2text/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Jevon Wright + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/soundasleep/html2text/README.md b/lib/soundasleep/html2text/README.md new file mode 100644 index 000000000..3055234a7 --- /dev/null +++ b/lib/soundasleep/html2text/README.md @@ -0,0 +1,102 @@ +![example workflow](https://github.com/soundasleep/html2text/actions/workflows/test.yml/badge.svg) [![Total Downloads](https://poser.pugx.org/soundasleep/html2text/downloads.png)](https://packagist.org/packages/soundasleep/html2text) +========= + +html2text is a very simple script that uses DOM methods to convert HTML into a format similar to what would be +rendered by a browser - perfect for places where you need a quick text representation. For example: + +```html + +Ignored Title + +

Hello, World!

+ +

This is some e-mail content. + Even though it has whitespace and newlines, the e-mail converter + will handle it correctly. + +

Even mismatched tags.

+ +
A div
+
Another div
+
A div
within a div
+ +
A link + + + +``` + +Will be converted into: + +```text +Hello, World! + +This is some e-mail content. Even though it has whitespace and newlines, the e-mail converter will handle it correctly. + +Even mismatched tags. + +A div +Another div +A div +within a div + +[A link](http://foo.com) +``` + +See the [original blog post](http://journals.jevon.org/users/jevon-phd/entry/19818) or the related [StackOverflow answer](http://stackoverflow.com/a/2564472/39531). + +## Installing + +You can use [Composer](http://getcomposer.org/) to add the [package](https://packagist.org/packages/soundasleep/html2text) to your project: + +```json +{ + "require": { + "soundasleep/html2text": "~1.1" + } +} +``` + +And then use it quite simply: + +```php +$text = \Soundasleep\Html2Text::convert($html); +``` + +You can also include the supplied `html2text.php` and use `$text = convert_html_to_text($html);` instead. + +### Options + +| Option | Default | Description | +|--------|---------|-------------| +| **ignore_errors** | `false` | Set to `true` to ignore any XML parsing errors. | +| **drop_links** | `false` | Set to `true` to not render links as `[http://foo.com](My Link)`, but rather just `My Link`. | +| **char_set** | `'auto'` | Specify a specific character set. Pass multiple character sets (comma separated) to detect encoding, default is ASCII,UTF-8 | + +Pass along options as a second argument to `convert`, for example: + +```php +$options = array( + 'ignore_errors' => true, + // other options go here +); +$text = \Soundasleep\Html2Text::convert($html, $options); +``` + +## Tests + +Some very basic tests are provided in the `tests/` directory. Run them with `composer install && vendor/bin/phpunit`. + +## Troubleshooting + +### Class 'DOMDocument' not found + +You need to [install the PHP XML extension](https://github.com/soundasleep/html2text/issues/55) for your PHP version. e.g. `apt-get install php7.4-xml` + +## License + +`html2text` is [licensed under MIT](LICENSE.md), making it suitable for both Eclipse and GPL projects. + +## Other versions + +Also see [html2text_ruby](https://github.com/soundasleep/html2text_ruby), a Ruby implementation. diff --git a/lib/soundasleep/html2text/composer.json b/lib/soundasleep/html2text/composer.json new file mode 100644 index 000000000..fb662c18a --- /dev/null +++ b/lib/soundasleep/html2text/composer.json @@ -0,0 +1,32 @@ +{ + "name": "soundasleep/html2text", + "description": "A PHP script to convert HTML into a plain text format", + "type": "library", + "keywords": [ "php", "html", "text", "email" ], + "homepage": "https://github.com/soundasleep/html2text", + "license": "MIT", + "authors": [ + { + "name": "Jevon Wright", + "homepage": "https://jevon.org", + "role": "Developer" + } + ], + "autoload": { + "psr-4": { + "Soundasleep\\": "src" + } + }, + "support": { + "email": "support@jevon.org" + }, + "require": { + "php": "^7.3|^8.0", + "ext-dom": "*", + "ext-libxml": "*" + }, + "require-dev": { + "phpunit/phpunit": "^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.9" + } +} diff --git a/lib/soundasleep/html2text/convert.php b/lib/soundasleep/html2text/convert.php new file mode 100644 index 000000000..48094eb21 --- /dev/null +++ b/lib/soundasleep/html2text/convert.php @@ -0,0 +1,21 @@ + + + + + tests + + + diff --git a/lib/soundasleep/html2text/src/Html2Text.php b/lib/soundasleep/html2text/src/Html2Text.php new file mode 100644 index 000000000..1763cb4a4 --- /dev/null +++ b/lib/soundasleep/html2text/src/Html2Text.php @@ -0,0 +1,540 @@ + */ + public static function defaultOptions(): array { + return [ + 'ignore_errors' => false, + 'drop_links' => false, + 'char_set' => 'auto' + ]; + } + + /** + * Tries to convert the given HTML into a plain text format - best suited for + * e-mail display, etc. + * + *

In particular, it tries to maintain the following features: + *

+ * + * @param string $html the input HTML + * @param boolean|array $options if boolean, Ignore xml parsing errors, else ['ignore_errors' => false, 'drop_links' => false, 'char_set' => 'auto'] + * @return string the HTML converted, as best as possible, to text + * @throws Html2TextException if the HTML could not be loaded as a {@link \DOMDocument} + */ + public static function convert(string $html, $options = []): string { + + if ($options === false || $options === true) { + // Using old style (< 1.0) of passing in options + $options = ['ignore_errors' => $options]; + } + + $options = array_merge(static::defaultOptions(), $options); + + // check all options are valid + foreach ($options as $key => $value) { + if (!in_array($key, array_keys(static::defaultOptions()))) { + throw new \InvalidArgumentException("Unknown html2text option '$key'. Valid options are " . implode(',', static::defaultOptions())); + } + } + + $is_office_document = self::isOfficeDocument($html); + + if ($is_office_document) { + // remove office namespace + $html = str_replace(["", ""], "", $html); + } + + $html = self::fixNewlines($html); + + // use mb_convert_encoding for legacy versions of php + if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION < 81 && mb_detect_encoding($html, "UTF-8", true)) { + $html = mb_convert_encoding($html, "HTML-ENTITIES", "UTF-8"); + } + + $doc = self::getDocument($html, $options); + + $output = self::iterateOverNode($doc, null, false, $is_office_document, $options); + + // process output for whitespace/newlines + $output = self::processWhitespaceNewlines($output); + + return $output; + } + + /** + * Unify newlines; in particular, \r\n becomes \n, and + * then \r becomes \n. This means that all newlines (Unix, Windows, Mac) + * all become \ns. + * + * @param string $text text with any number of \r, \r\n and \n combinations + * @return string the fixed text + */ + public static function fixNewlines(string $text): string { + // replace \r\n to \n + $text = str_replace("\r\n", "\n", $text); + // remove \rs + $text = str_replace("\r", "\n", $text); + + return $text; + } + + /** @return array */ + public static function nbspCodes(): array { + return [ + "\xc2\xa0", + "\u00a0", + ]; + } + + /** @return array */ + public static function zwnjCodes(): array { + return [ + "\xe2\x80\x8c", + "\u200c", + ]; + } + + /** + * Remove leading or trailing spaces and excess empty lines from provided multiline text + * + * @param string $text multiline text any number of leading or trailing spaces or excess lines + * @return string the fixed text + */ + public static function processWhitespaceNewlines(string $text): string { + + // remove excess spaces around tabs + $text = preg_replace("/ *\t */im", "\t", $text); + + // remove leading whitespace + $text = ltrim($text); + + // remove leading spaces on each line + $text = preg_replace("/\n[ \t]*/im", "\n", $text); + + // convert non-breaking spaces to regular spaces to prevent output issues, + // do it here so they do NOT get removed with other leading spaces, as they + // are sometimes used for indentation + $text = self::renderText($text); + + // remove trailing whitespace + $text = rtrim($text); + + // remove trailing spaces on each line + $text = preg_replace("/[ \t]*\n/im", "\n", $text); + + // unarmor pre blocks + $text = self::fixNewLines($text); + + // remove unnecessary empty lines + $text = preg_replace("/\n\n\n*/im", "\n\n", $text); + + return $text; + } + + /** + * Can we guess that this HTML is generated by Microsoft Office? + */ + public static function isOfficeDocument(string $html): bool { + return strpos($html, "urn:schemas-microsoft-com:office") !== false; + } + + public static function isWhitespace(string $text): bool { + return strlen(trim(self::renderText($text), "\n\r\t ")) === 0; + } + + /** + * Parse HTML into a DOMDocument + * + * @param string $html the input HTML + * @param array $options + * @return \DOMDocument the parsed document tree + */ + private static function getDocument(string $html, array $options): \DOMDocument { + + $doc = new \DOMDocument(); + + $html = trim($html); + + if (!$html) { + // DOMDocument doesn't support empty value and throws an error + // Return empty document instead + return $doc; + } + + if ($html[0] !== '<') { + // If HTML does not begin with a tag, we put a body tag around it. + // If we do not do this, PHP will insert a paragraph tag around + // the first block of text for some reason which can mess up + // the newlines. See pre.html test for an example. + $html = '' . $html . ''; + } + + $header = ''; + // use char sets for modern versions of php + if (PHP_MAJOR_VERSION * 10 + PHP_MINOR_VERSION >= 81) { + // use specified char_set, or auto detect if not set + $char_set = ! empty($options['char_set']) ? $options['char_set'] : 'auto'; + if ('auto' === $char_set) { + $char_set = mb_detect_encoding($html); + } else if (strpos($char_set, ',')) { + mb_detect_order($char_set); + $char_set = mb_detect_encoding($html); + } + // turn off error detection for Windows-1252 legacy html + if (strpos($char_set, '1252')) { + $options['ignore_errors'] = true; + } + $header = ''; + } + + if (! empty($options['ignore_errors'])) { + $doc->strictErrorChecking = false; + $doc->recover = true; + $doc->xmlStandalone = true; + $old_internal_errors = libxml_use_internal_errors(true); + $load_result = $doc->loadHTML($header . $html, LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NONET | LIBXML_PARSEHUGE); + libxml_use_internal_errors($old_internal_errors); + } + else { + $load_result = $doc->loadHTML($header . $html); + } + + if (!$load_result) { + throw new Html2TextException("Could not load HTML - badly formed?", $html); + } + + return $doc; + } + + /** + * Replace any special characters with simple text versions, to prevent output issues: + * - Convert non-breaking spaces to regular spaces; and + * - Convert zero-width non-joiners to '' (nothing). + * + * This is to match our goal of rendering documents as they would be rendered + * by a browser. + */ + private static function renderText(string $text): string { + $text = str_replace(self::nbspCodes(), " ", $text); + $text = str_replace(self::zwnjCodes(), "", $text); + return $text; + } + + private static function nextChildName(?\DOMNode $node): ?string { + // get the next child + $nextNode = $node->nextSibling; + while ($nextNode != null) { + if ($nextNode instanceof \DOMText) { + if (!self::isWhitespace($nextNode->wholeText)) { + break; + } + } + + if ($nextNode instanceof \DOMElement) { + break; + } + + $nextNode = $nextNode->nextSibling; + } + + $nextName = null; + if (($nextNode instanceof \DOMElement || $nextNode instanceof \DOMText) && $nextNode != null) { + $nextName = strtolower($nextNode->nodeName); + } + + return $nextName; + } + + /** @param array $options */ + private static function iterateOverNode(\DOMNode $node, ?string $prevName, bool $in_pre, bool $is_office_document, array $options): string { + if ($node instanceof \DOMText) { + // Replace whitespace characters with a space (equivilant to \s) + if ($in_pre) { + $text = "\n" . trim(self::renderText($node->wholeText), "\n\r\t ") . "\n"; + + // Remove trailing whitespace only + $text = preg_replace("/[ \t]*\n/im", "\n", $text); + + // armor newlines with \r. + return str_replace("\n", "\r", $text); + + } + $text = self::renderText($node->wholeText); + $text = preg_replace("/[\\t\\n\\f\\r ]+/im", " ", $text); + + if (!self::isWhitespace($text) && ($prevName == 'p' || $prevName == 'div')) { + return "\n" . $text; + } + return $text; + } + + if ($node instanceof \DOMDocumentType || $node instanceof \DOMProcessingInstruction) { + // ignore + return ""; + } + + $name = strtolower($node->nodeName); + $nextName = self::nextChildName($node); + + // start whitespace + switch ($name) { + case "hr": + $prefix = ''; + if ($prevName != null) { + $prefix = "\n"; + } + return $prefix . "---------------------------------------------------------------\n"; + + case "style": + case "head": + case "title": + case "meta": + case "script": + // ignore these tags + return ""; + + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + case "ol": + case "ul": + case "pre": + // add two newlines + $output = "\n\n"; + break; + + case "td": + case "th": + // add tab char to separate table fields + $output = "\t"; + break; + + case "p": + // Microsoft exchange emails often include HTML which, when passed through + // html2text, results in lots of double line returns everywhere. + // + // To fix this, for any p element with a className of `MsoNormal` (the standard + // classname in any Microsoft export or outlook for a paragraph that behaves + // like a line return) we skip the first line returns and set the name to br. + // @phpstan-ignore-next-line + if ($is_office_document && $node->getAttribute('class') == 'MsoNormal') { + $output = ""; + $name = 'br'; + break; + } + + // add two lines + $output = "\n\n"; + break; + + case "tr": + // add one line + $output = "\n"; + break; + + case "div": + $output = ""; + if ($prevName !== null) { + // add one line + $output .= "\n"; + } + break; + + case "li": + $output = "- "; + break; + + default: + // print out contents of unknown tags + $output = ""; + break; + } + + // debug + //$output .= "[$name,$nextName]"; + + if (isset($node->childNodes)) { + + $n = $node->childNodes->item(0); + $previousSiblingNames = []; + $previousSiblingName = null; + + $parts = []; + $trailing_whitespace = 0; + + while ($n != null) { + + $text = self::iterateOverNode($n, $previousSiblingName, $in_pre || $name == 'pre', $is_office_document, $options); + + // Pass current node name to next child, as previousSibling does not appear to get populated + if ($n instanceof \DOMDocumentType + || $n instanceof \DOMProcessingInstruction + || ($n instanceof \DOMText && self::isWhitespace($text))) { + // Keep current previousSiblingName, these are invisible + $trailing_whitespace++; + } + else { + $previousSiblingName = strtolower($n->nodeName); + $previousSiblingNames[] = $previousSiblingName; + $trailing_whitespace = 0; + } + + $node->removeChild($n); + $n = $node->childNodes->item(0); + + $parts[] = $text; + } + + // Remove trailing whitespace, important for the br check below + while ($trailing_whitespace-- > 0) { + array_pop($parts); + } + + // suppress last br tag inside a node list if follows text + $last_name = array_pop($previousSiblingNames); + if ($last_name === 'br') { + $last_name = array_pop($previousSiblingNames); + if ($last_name === '#text') { + array_pop($parts); + } + } + + $output .= implode('', $parts); + } + + // end whitespace + switch ($name) { + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + case "pre": + case "p": + // add two lines + $output .= "\n\n"; + break; + + case "br": + // add one line + $output .= "\n"; + break; + + case "div": + break; + + case "a": + // links are returned in [text](link) format + // @phpstan-ignore-next-line + $href = $node->getAttribute("href"); + + $output = trim($output); + + // remove double [[ ]] s from linking images + if (substr($output, 0, 1) == "[" && substr($output, -1) == "]") { + $output = substr($output, 1, strlen($output) - 2); + + // for linking images, the title of the overrides the title of the + // @phpstan-ignore-next-line + if ($node->getAttribute("title")) { + // @phpstan-ignore-next-line + $output = $node->getAttribute("title"); + } + } + + // if there is no link text, but a title attr + // @phpstan-ignore-next-line + if (!$output && $node->getAttribute("title")) { + // @phpstan-ignore-next-line + $output = $node->getAttribute("title"); + } + + if ($href == null) { + // it doesn't link anywhere + // @phpstan-ignore-next-line + if ($node->getAttribute("name") != null) { + if ($options['drop_links']) { + $output = "$output"; + } else { + $output = "[$output]"; + } + } + } else { + if ($href == $output || $href == "mailto:$output" || $href == "http://$output" || $href == "https://$output") { + // link to the same address: just use link + $output = "$output"; + } else { + // replace it + if ($output) { + if ($options['drop_links']) { + $output = "$output"; + } else { + $output = "[$output]($href)"; + } + } else { + // empty string + $output = "$href"; + } + } + } + + // does the next node require additional whitespace? + switch ($nextName) { + case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": + $output .= "\n"; + break; + } + break; + + case "img": + // @phpstan-ignore-next-line + if ($node->getAttribute("title")) { + // @phpstan-ignore-next-line + $output = "[" . $node->getAttribute("title") . "]"; + // @phpstan-ignore-next-line + } elseif ($node->getAttribute("alt")) { + // @phpstan-ignore-next-line + $output = "[" . $node->getAttribute("alt") . "]"; + } else { + $output = ""; + } + break; + + case "li": + $output .= "\n"; + break; + + case "blockquote": + // process quoted text for whitespace/newlines + $output = self::processWhitespaceNewlines($output); + + // add leading newline + $output = "\n" . $output; + + // prepend '> ' at the beginning of all lines + $output = preg_replace("/\n/im", "\n> ", $output); + + // replace leading '> >' with '>>' + $output = preg_replace("/\n> >/im", "\n>>", $output); + + // add another leading newline and trailing newlines + $output = "\n" . $output . "\n\n"; + break; + default: + // do nothing + } + + return $output; + } +} diff --git a/lib/soundasleep/html2text/src/Html2TextException.php b/lib/soundasleep/html2text/src/Html2TextException.php new file mode 100644 index 000000000..fe919f357 --- /dev/null +++ b/lib/soundasleep/html2text/src/Html2TextException.php @@ -0,0 +1,15 @@ +more_info = $more_info; + } + +} diff --git a/lib/tecnickcom/tcpdf/fonts/droidsansfallback.php b/lib/tecnickcom/tcpdf/fonts/droidsansfallback.php index 83b9bdd1c..4a61e19f2 100644 --- a/lib/tecnickcom/tcpdf/fonts/droidsansfallback.php +++ b/lib/tecnickcom/tcpdf/fonts/droidsansfallback.php @@ -1,6 +1,6 @@ aChoices)) { - $aErrorMessages[] = "Value ({$sValue}) is not part of the field possible values list"; + $sValue = utils::HtmlEntities($sValue); + $aErrorMessages[] = "Value ({$sValue}) is not part of the field possible values list"; } } } \ No newline at end of file diff --git a/sources/Form/Validator/SelectObjectValidator.php b/sources/Form/Validator/SelectObjectValidator.php index a4d0c69cd..3794a353e 100644 --- a/sources/Form/Validator/SelectObjectValidator.php +++ b/sources/Form/Validator/SelectObjectValidator.php @@ -37,6 +37,7 @@ class SelectObjectValidator extends AbstractValidator $iObjectsCount = $oSetForExistingCurrentValue->CountWithLimit(1); if ($iObjectsCount === 0) { + $value = utils::HtmlEntities($value); return ["Value $value does not match the corresponding filter set"]; } diff --git a/tests/php-unit-tests/unitary-tests/application/query/QueryTest.php b/tests/php-unit-tests/unitary-tests/application/query/QueryTest.php index ece49c6a3..7751ab798 100644 --- a/tests/php-unit-tests/unitary-tests/application/query/QueryTest.php +++ b/tests/php-unit-tests/unitary-tests/application/query/QueryTest.php @@ -25,6 +25,7 @@ use Combodo\iTop\Test\UnitTest\ItopDataTestCase; use MetaModel; use Query; use QueryOQL; +use utils; /** * This test creates call export on requests and check request usage counter. @@ -48,6 +49,7 @@ class QueryTest extends ItopDataTestCase public function setUp(): void { parent::setUp(); + $this->SetNonPublicStaticProperty(utils::class, 'sAbsoluteUrlAppRootCache', null); // create export user $this->CreateExportUser(); @@ -184,7 +186,15 @@ class QueryTest extends ItopDataTestCase // execute curl $result = curl_exec($curl); - + if (curl_errno($curl)) { + $info = curl_getinfo($curl); + var_export($info); + var_dump([ + 'url' => $url, + 'app_root_url:' => MetaModel::GetConfig()->Get('app_root_url'), + 'GetAbsoluteUrlAppRoot:' => \utils::GetAbsoluteUrlAppRoot(), + ]); + } // close curl curl_close($curl); diff --git a/tests/php-unit-tests/unitary-tests/application/utilsTest.php b/tests/php-unit-tests/unitary-tests/application/utilsTest.php index c122db8aa..ca9283d31 100644 --- a/tests/php-unit-tests/unitary-tests/application/utilsTest.php +++ b/tests/php-unit-tests/unitary-tests/application/utilsTest.php @@ -29,6 +29,19 @@ use utils; */ class utilsTest extends ItopTestCase { + protected function setUp(): void + { + parent::setUp(); + $this->SetNonPublicStaticProperty(utils::class, 'sAbsoluteUrlAppRootCache', 'https://localhost/itop/'); + } + + protected function tearDown(): void + { + $this->SetNonPublicStaticProperty(utils::class, 'sAbsoluteUrlAppRootCache', null); + parent::tearDown(); + } + + public function testEndsWith() { $this->assertFalse(utils::EndsWith('a', 'bbbb')); @@ -632,21 +645,21 @@ class utilsTest extends ItopTestCase } /** + * @dataProvider GetMentionedObjectsFromTextProvider * @covers utils::GetMentionedObjectsFromText * * @throws \Exception */ - public function testGetMentionedObjectsFromText() + public function testGetMentionedObjectsFromText($sInput, $sFormat, $aExceptedMentionedObjects) { // Emulate the "Case provider mechanism" (reason: the data provider requires utils constants not available before the application startup) - foreach ($this->GetMentionedObjectsFromTextProvider() as $sCase => list($sInput, $sFormat, $aExceptedMentionedObjects)) { - $aTestedMentionedObjects = utils::GetMentionedObjectsFromText($sInput, $sFormat); + echo "testGetMentionedObjectsFromText: input = $sInput\n"; + $aTestedMentionedObjects = utils::GetMentionedObjectsFromText($sInput, $sFormat); - $sExpectedAsString = print_r($aExceptedMentionedObjects, true); - $sTestedAsString = print_r($aTestedMentionedObjects, true); + $sExpectedAsString = print_r($aExceptedMentionedObjects, true); + $sTestedAsString = print_r($aTestedMentionedObjects, true); - $this->assertEquals($sTestedAsString, $sExpectedAsString, "Case '$sCase': Found mentioned objects don't match. Got: $sTestedAsString, expected $sExpectedAsString"); - } + $this->assertEquals($sTestedAsString, $sExpectedAsString, "Found mentioned objects don't match. Got: $sTestedAsString, expected $sExpectedAsString"); } /** @@ -666,7 +679,7 @@ class utilsTest extends ItopTestCase ], '1 UserRequest' => [ "Begining - Before link R-012345 After link + Before link R-012345 After link End", utils::ENUM_TEXT_FORMAT_HTML, [ @@ -675,8 +688,8 @@ class utilsTest extends ItopTestCase ], '2 UserRequests' => [ "Begining - Before link R-012345 After link - And R-987654 + Before link R-012345 After link + And R-987654 End", utils::ENUM_TEXT_FORMAT_HTML, [ @@ -685,8 +698,8 @@ class utilsTest extends ItopTestCase ], '1 UserRequest, 1 Person' => [ "Begining - Before link R-012345 After link - And Claude Monet + Before link R-012345 After link + And Claude Monet End", utils::ENUM_TEXT_FORMAT_HTML, [ diff --git a/tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php b/tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php index 41901e46e..afca36584 100644 --- a/tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php +++ b/tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php @@ -4,10 +4,10 @@ namespace Combodo\iTop\Test\UnitTest\Core; use ActionEmail; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; +use Dict; use Exception; use MetaModel; use utils; -use Dict; /** * @covers \ActionEmail @@ -35,8 +35,6 @@ class ActionEmailTest extends ItopDataTestCase { parent::setUp(); - $this->RequireOnceItopFile('application/Html2Text.php'); - static::$oActionEmail = MetaModel::NewObject('ActionEmail', [ 'name' => 'Test action', 'status' => 'disabled',