diff --git a/Documentation/Debug.rst b/Documentation/Debug.rst index 965bc82914f73f845d62db56c1781c94a81d1bc4..00fc610300abea198e7198b644a44da7060e776c 100644 --- a/Documentation/Debug.rst +++ b/Documentation/Debug.rst @@ -103,7 +103,7 @@ Setup in :ref:`configuration` * *download*: * During a download (especially by using wkhtml), temporary files are not deleted automatically. Also the - ``wkhtmltopdf`` and ``pdfunite`` command lines will be logged to :ref:`QFQ_LOG`. Use this only to debug problems on download. + ``wkhtmltopdf``, ``pdfunite``, ``pdf2img`` command lines will be logged to :ref:`QFQ_LOG`. Use this only to debug problems on download. .. _MAIL_LOG: diff --git a/Documentation/Installation.rst b/Documentation/Installation.rst index 6c89648b10a8747d5da1ab4c980564b186f9c571..705eb760dd338e5c039f6471e143956c72bce014 100644 --- a/Documentation/Installation.rst +++ b/Documentation/Installation.rst @@ -42,6 +42,7 @@ The following features are only tested / supported on linux hosts: * General: QFQ is coded to run on Linux hosts, preferable on Debian derivates like Ubuntu. * HTML to PDF conversion - command `wkhtmltopdf`. * Concatenation of PDF files - command `pdfunite`. +* Convert of imges to PDF files - command `img2pdf`. * PDF decrypt (used for merge with pdfunite) - command `qpdf`. * PDF decrypt (used for merge with pdfunite) - command `gs` - in case `qpdf` is not successful. * Mime type detection for uploads - command `file`. @@ -59,7 +60,7 @@ To normalize UTF8 input, *php-intl* package is needed by * normalizer::normalize() -For the :ref:`download` function, the programs `pdfunite`, `qpdf`, `gs` and `file` are necessary to concatenate PDF files. +For the :ref:`download` function, the programs `img2pdf`, `pdfunite`, `qpdf`, `gs` and `file` are necessary to concatenate PDF files. Preparation for Ubuntu:: @@ -409,6 +410,8 @@ Extension Manager: QFQ Configuration +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | cmdPdfunite | pdfunite | PathFilename of pdfunite. Optional variables like LD_LIBRARY_PATH=... | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| cmdImg2pdf | img2pdf | PathFilename of img2pdf. Optional variables like LD_LIBRARY_PATH=... | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | sendEMailOptions | -o tls=yes | General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | documentation | http://docs.typo3.org... | Link to the online documentation of QFQ. Every QFQ installation also | diff --git a/Documentation/SearchDocs.rst b/Documentation/SearchDocs.rst new file mode 100644 index 0000000000000000000000000000000000000000..4c90156105a7e85e2cadff164db2ecb825a23a7c --- /dev/null +++ b/Documentation/SearchDocs.rst @@ -0,0 +1,90 @@ +Searching Documentation +======================= + +This page was copied from: https://docs.readthedocs.io/en/stable/guides/searching-with-readthedocs.html + +Read the Docs uses :doc:`/server-side-search` to power our search. +This guide explains how to add a "search as you type" feature to your documentation, +and how to use advanced query syntax to get more accurate results. + +You can find information on the search architecture and how we index documents in our +:doc:`Search </development/search>` docs. + +.. contents:: Table of contents + :local: + :backlinks: none + :depth: 3 + + +Search query syntax +------------------- + +Read the Docs uses the `Simple Query String`_ feature from `Elasticsearch`_. +This means that as the search query becomes more complex, +the results yielded become more specific. + +Exact phrase search +~~~~~~~~~~~~~~~~~~~ + +If a query is wrapped in ``"`` (double quotes), +then only those results where the phrase is exactly matched will be returned. + +Example queries: + +- https://docs.rea>dthedocs.io/?rtd_search=%22custom%20css%22 +- https://docs.readthedocs.io/?rtd_search=%22adding%20a%20subproject%22 +- https://docs.readthedocs.io/?rtd_search=%22when%20a%20404%20is%20returned%22 + +Exact phrase search with slop value +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``~N`` (tilde N) after a phrase signifies slop amount. +It can be used to match words that are near one another. + +Example queries: + +- https://docs.readthedocs.io/?rtd_search=%22dashboard%20admin%22~2 +- https://docs.readthedocs.io/?rtd_search=%22single%20documentation%22~1 +- https://docs.readthedocs.io/?rtd_search=%22read%20the%20docs%20story%22~5 + +Prefix query +~~~~~~~~~~~~ + +``*`` (asterisk) at the end of any term signifies a prefix query. +It returns the results containing the words with specific prefix. + +Example queries: + +- https://docs.readthedocs.io/?rtd_search=API%20v* +- https://docs.readthedocs.io/?rtd_search=single%20v*%20doc* +- https://docs.readthedocs.io/?rtd_search=build*%20and%20c*%20to%20doc* + +Fuzzy query +~~~~~~~~~~~ + +``~N`` after a word signifies edit distance (fuzziness). +This type of query is helpful when the exact spelling of the keyword is unknown. +It returns results that contain terms similar to the search term as measured by a `Levenshtein edit distance`_. + +Example queries: + +- https://docs.readthedocs.io/?rtd_search=reedthedcs~2 +- https://docs.readthedocs.io/?rtd_search=authentation~3 +- https://docs.readthedocs.io/?rtd_search=configurtion~1 + + +Build complex queries +~~~~~~~~~~~~~~~~~~~~~ + +The search query syntaxes described in the previous sections can be used with one another to build complex queries. + +For example: + +- https://docs.readthedocs.io/?rtd_search=auto*%20redirect* +- https://docs.readthedocs.io/?rtd_search=abandon*%20proj* +- https://docs.readthedocs.io/?rtd_search=localisation~3%20of%20doc* + +.. _Elasticsearch: https://www.elastic.co/products/elasticsearch +.. _readthedocs-sphinx-search: https://readthedocs-sphinx-search.readthedocs.io/ +.. _Simple Query String: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html# +.. _Levenshtein edit distance: https://en.wikipedia.org/wiki/Levenshtein_distance \ No newline at end of file diff --git a/Documentation/index.rst b/Documentation/index.rst index 417d21aeea1693807aa4e90183ec322045c48554..be57bdf8b7d3a14ce6fb050fd836b6e63a7207aa 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -90,4 +90,5 @@ This documentation is for the TYPO3 extension **qfq**. Links License Sitemap + SearchDocs diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php index 400c65ead4a708f87c287a61a9d096d8b7ca1a09..95809ecbc33f45195cda5395127e5c2dc21c7d85 100644 --- a/extension/Classes/Core/Constants.php +++ b/extension/Classes/Core/Constants.php @@ -303,6 +303,7 @@ const ERROR_DOWNLOAD_FILE_NOT_READABLE = 1705; const ERROR_DOWNLOAD_FOPEN_BLOCKED = 1706; const ERROR_DOWNLOAD_JSON_CONVERT = 1707; const ERROR_DOWNLOAD_MERGE_FAILED = 1708; +const ERROR_DOWNLOAD_CONVERT_FAILED = 1709; // Excel const ERROR_EXCEL_POSITION_ARGUMENT_EMPTY = 1800; @@ -649,6 +650,7 @@ const SYSTEM_CMD_CONVERT = 'cmdConvert'; const SYSTEM_CMD_QPDF = 'cmdQpdf'; const SYSTEM_CMD_GS = 'cmdGs'; const SYSTEM_CMD_PDFUNITE = 'cmdPdfunite'; +const SYSTEM_CMD_IMG2PDF = 'cmdImg2pdf'; // Thumbnail const SYSTEM_THUMBNAIL_DIR_SECURE = 'thumbnailDirSecure'; diff --git a/extension/Classes/Core/Helper/HelperFile.php b/extension/Classes/Core/Helper/HelperFile.php index 8789e3c0c184908b80c30b92d5178db77ac3ccd6..5619f9c0c6cf2510d4c215ad5adcbd673690e00d 100644 --- a/extension/Classes/Core/Helper/HelperFile.php +++ b/extension/Classes/Core/Helper/HelperFile.php @@ -9,8 +9,6 @@ namespace IMATHUZH\Qfq\Core\Helper; - - /** * Class HelperFile * @package qfq @@ -517,5 +515,30 @@ class HelperFile { return $new; } + /** + * Joins $pre and $post. If $post is absolute, returns only $post. If $pre ends without '/', a '/' is injected. + * + * @param $pre + * @param $post + * + * @return string + */ + public static function joinPathFilename($pre, $post) { + $separator = ''; + + if ($pre == '' || $post == '') { + return $pre . $post; + } + + if ($post[0] == '/') { + return $post; + } + + if ((substr($pre, -1) != '/')) { + $separator = '/'; + } + + return $pre . $separator . $post; + } } diff --git a/extension/Classes/Core/Report/Download.php b/extension/Classes/Core/Report/Download.php index 3820e521f0bf36d8ad12a82ad944f1115e6892fb..97c146f7170a93549a098475dc133f7b6f308109 100644 --- a/extension/Classes/Core/Report/Download.php +++ b/extension/Classes/Core/Report/Download.php @@ -101,6 +101,7 @@ class Download { $this->qpdf = $this->store->getVar(SYSTEM_CMD_QPDF, STORE_SYSTEM); $this->gs = $this->store->getVar(SYSTEM_CMD_GS, STORE_SYSTEM); $this->pdfunite = $this->store->getVar(SYSTEM_CMD_PDFUNITE, STORE_SYSTEM); + $this->img2Pdf = $this->store->getVar(SYSTEM_CMD_IMG2PDF, STORE_SYSTEM); if (Support::findInSet(SYSTEM_SHOW_DEBUG_INFO_DOWNLOAD, $this->store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM))) { $this->downloadDebugLog = $this->store->getVar(SYSTEM_SQL_LOG, STORE_SYSTEM); @@ -109,38 +110,47 @@ class Download { /** * Concatenate all named files to one PDF file. Return name of new full PDF. + * If a source file is an image, it will be converted to a PDF. * - * @param array $files + * @param array $files Array of source files + * @param array $filesCleanLater Array of temporarily created files * * @return string - fileName of concatenated file * @throws \CodeException * @throws \DownloadException * @throws \UserFormException */ - private function concatPdfFiles(array $files) { + private function concatFilesToPdf(array $files, array &$filesCleanLater) { // Remove empty entries. Might happen if there was no upload $files = OnArray::removeEmptyElementsFromArray($files); - // Check that all files exist and are readable - foreach ($files AS $filename) { + // Check that all files are of type 'application/pdf' + foreach ($files as $key => $filename) { + // Check that all files exist and are readable if (!is_readable($filename)) { throw new \DownloadException("Error reading file $filename. Not found or no permission", ERROR_DOWNLOAD_FILE_NOT_READABLE); } - } - if (count($files) === 0) { - return ''; - } - - // Check that all files are of type 'application/pdf' - foreach ($files AS $filename) { $mimetype = mime_content_type($filename); + + // If file is an image, convert to PDF + if (substr($mimetype, 0, 6) == 'image/') { + $tmpName = $this->doImgToPdf($filename); + $filesCleanLater[] = $tmpName; // remember to purge later. + $files[$key] = $tmpName; // replace original reference against temporary one. + $mimetype = 'application/pdf'; + } + if ($mimetype != 'application/pdf') { throw new \DownloadException("Error concat file $filename. Mimetype 'application/pdf' expected, got: $mimetype", ERROR_DOWNLOAD_UNEXPECTED_MIME_TYPE); } } + if (count($files) === 0) { + return ''; + } + if (count($files) == 1) { return $files[0]; } @@ -176,6 +186,36 @@ class Download { return $concatFile; } + /** + * Convert an image to PDF + * + * @param $fileImage + * @throws \DownloadException + */ + private function doImgToPdf($fileImage) { + + $filePdf = HelperFile::tempnam(); + if (false === $filePdf) { + throw new \DownloadException('Error creating output file.', ERROR_DOWNLOAD_CREATE_NEW_FILE); + } + + // img2pdf --pagesize A4 -o out.pdf *.jpg + $cmd = $this->img2Pdf . ' --pagesize A4 -o ' . $filePdf . ' ' . escapeshellarg($fileImage); + + if ($this->downloadDebugLog != '') { + Logger::logMessage("Download: $cmd", $this->downloadDebugLog); + } + + exec($cmd, $rcOutput, $rc); + if ($rc != 0) { + throw new \DownloadException (json_encode([ERROR_MESSAGE_TO_USER => "Failed to convert image to PDF.", + ERROR_MESSAGE_TO_DEVELOPER => "CMD: $cmd<br>RC: $rc<br>Output: " . implode("<br>", $rcOutput)]) + , ERROR_DOWNLOAD_CONVERT_FAILED); + } + + return $filePdf; + } + /** * Fires the merge command. * If for any reason the command fails: check if the reason is 'unencrypted files'. @@ -457,7 +497,7 @@ class Download { $len = strlen(TMP_FILE_PREFIX); $ii = 1; - foreach ($files AS $filename) { + foreach ($files as $filename) { $localName = substr($filename, strrpos($filename, '/') + 1); if (substr($localName, 0, $len) == TMP_FILE_PREFIX) { @@ -499,7 +539,8 @@ class Download { */ private function doElements(array $vars, $outputMode) { - $tmpFiles = array(); + $srcFiles = array(); + $filesCleanLater = array(); $workDir = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM); HelperFile::chdir($workDir); @@ -525,7 +566,7 @@ class Download { $tmpData = array(); foreach ($elements as $element) { $data = ''; - $tmpFiles[] = $this->getElement($element, $downloadMode, $data); + $srcFiles[] = $this->getElement($element, $downloadMode, $data); if (!empty($data)) { $tmpData[] = $data; } @@ -534,7 +575,7 @@ class Download { // Export, Concat File(s) switch ($downloadMode) { case DOWNLOAD_MODE_ZIP: - $filename = $this->zipFiles($tmpFiles); + $filename = $this->zipFiles($srcFiles); if (empty($vars[DOWNLOAD_EXPORT_FILENAME])) { $vars[DOWNLOAD_EXPORT_FILENAME] = basename($filename); } @@ -542,7 +583,7 @@ class Download { case DOWNLOAD_MODE_EXCEL: $excel = new Excel(); - $filename = $excel->process($tmpFiles, $tmpData); + $filename = $excel->process($srcFiles, $tmpData); if (empty($filename) || !file_exists($filename)) { throw new \DownloadException(json_encode( @@ -560,7 +601,7 @@ class Download { break; case DOWNLOAD_MODE_FILE: - $filename = $tmpFiles[0]; + $filename = $srcFiles[0]; if (empty($vars[DOWNLOAD_EXPORT_FILENAME])) { $vars[DOWNLOAD_EXPORT_FILENAME] = basename($filename); } @@ -568,11 +609,11 @@ class Download { case DOWNLOAD_MODE_PDF: - $filename = $this->concatPdfFiles($tmpFiles); + $filename = $this->concatFilesToPdf($srcFiles, $filesCleanLater); // try to find a meaningful filename if (empty($vars[DOWNLOAD_EXPORT_FILENAME])) { - if (count($tmpFiles) > 1) { + if (count($srcFiles) > 1) { $vars[DOWNLOAD_EXPORT_FILENAME] = DOWNLOAD_OUTPUT_FILENAME . ".pdf"; } else { if (HelperFile::isQfqTemp($filename)) { @@ -595,6 +636,8 @@ class Download { ERROR_MESSAGE_TO_DEVELOPER => "File: $filename"]), ERROR_IO_FILE_EXIST); } + $filesCleanLater[] = $filename; + switch ($outputMode) { case OUTPUT_MODE_FILE: @@ -602,12 +645,10 @@ class Download { case OUTPUT_MODE_COPY_TO_FILE: HelperFile::copy($filename, $vars[DOWNLOAD_EXPORT_FILENAME]); - HelperFile::cleanTempFiles([$filename]); break; case OUTPUT_MODE_DIRECT: $this->outputFile($filename, $vars[DOWNLOAD_EXPORT_FILENAME]); - HelperFile::cleanTempFiles([$filename]); $filename = ''; break; @@ -615,6 +656,8 @@ class Download { throw new \CodeException('Unkown mode: ' . $outputMode, ERROR_UNKNOWN_MODE); } + HelperFile::cleanTempFiles($filesCleanLater); + return $filename; } diff --git a/extension/Classes/Core/Report/Report.php b/extension/Classes/Core/Report/Report.php index 13bd0939090f6f1bf2006b56dacaccc0667368bf..dda49138af3404759c9fda97aa9829068bb30d41 100644 --- a/extension/Classes/Core/Report/Report.php +++ b/extension/Classes/Core/Report/Report.php @@ -191,10 +191,7 @@ class Report { $sqlLog = $this->store->getVar(TYPO3_SQL_LOG, STORE_TYPO3); if (false !== $sqlLog) { - if ($sqlLog != '' && $sqlLog[0] !== '/') { - $sqlLog = $this->store->getVar(SYSTEM_EXT_PATH, STORE_SYSTEM) . '/' . $sqlLog; - } - + $sqlLog = HelperFile::joinPathFilename($this->store->getVar(SYSTEM_EXT_PATH, STORE_SYSTEM), $sqlLog); $this->store->setVar(SYSTEM_SQL_LOG, $sqlLog, STORE_SYSTEM); } @@ -249,7 +246,7 @@ class Report { * Split line in level, command, content and fill 'frArray', 'levelCount', 'indexArray' * Example: 10.50.5.sql = select * from person * - * @param string $ttLine : line to split in level, command, content + * @param string $ttLine : line to split in level, command, content * * @throws \UserReportException */ @@ -810,11 +807,11 @@ class Report { * 3) if none above take default * Set value on $full_level * - * @param string $level_key - 'db' or 'debug' - * @param string $full_super_level - f.e.: 10.10. - * @param string $full_level - f.e.: 10.10.10. - * @param string $cur_level - f.e.: 2 - * @param string $default - f.e.: 0 + * @param string $level_key - 'db' or 'debug' + * @param string $full_super_level - f.e.: 10.10. + * @param string $full_level - f.e.: 10.10.10. + * @param string $cur_level - f.e.: 2 + * @param string $default - f.e.: 0 * * @return string The calculated value. */ @@ -1219,8 +1216,8 @@ class Report { /** * Renders PageX: convert position content to token content. Respect default values depending on PageX * - * @param string $columnName - * @param string $columnValue + * @param string $columnName + * @param string $columnValue * @return string rendered link * * $columnValue: @@ -1347,9 +1344,9 @@ class Report { /** * If there is a value (or a defaultValue): compose it together with qualifier and delimiter. * - * @param string $qualifier - * @param string $value - * @param string $defaultValue + * @param string $qualifier + * @param string $value + * @param string $defaultValue * * @return string rendered link */ @@ -1369,8 +1366,8 @@ class Report { /** * Renders _pageX: extract token and determine if any default value has to be applied * - * @param string $columnName - * @param string $columnValue + * @param string $columnName + * @param string $columnValue * * @return string rendered link */ diff --git a/extension/Classes/Core/Save.php b/extension/Classes/Core/Save.php index fea100a401cae9e63e0cde32a675a18d0f995c84..886444cae4b6274f6ee793ced7195c907f2799be 100644 --- a/extension/Classes/Core/Save.php +++ b/extension/Classes/Core/Save.php @@ -72,8 +72,9 @@ class Save { $this->evaluate = new Evaluate($this->store, $this->db); $this->formAction = new FormAction($formSpec, $this->db); - $this->qfqLogFilename = $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM) . '/' . $this->store->getVar(SYSTEM_QFQ_LOG, STORE_SYSTEM); - + $this->qfqLogFilename = HelperFile::joinPathFilename( + $this->store->getVar(SYSTEM_SITE_PATH, STORE_SYSTEM), + $this->store->getVar(SYSTEM_QFQ_LOG, STORE_SYSTEM)); } /** diff --git a/extension/Classes/Core/Store/Config.php b/extension/Classes/Core/Store/Config.php index 29a638c9b7d7fce5175f78d83347e9364807ee92..4b7123aff676c676e9d2f61446c6c5164f4fa28e 100644 --- a/extension/Classes/Core/Store/Config.php +++ b/extension/Classes/Core/Store/Config.php @@ -377,6 +377,7 @@ class Config { SYSTEM_CMD_QPDF => 'qpdf', SYSTEM_CMD_GS => 'gs', SYSTEM_CMD_PDFUNITE => 'pdfunite', + SYSTEM_CMD_IMG2PDF => 'img2pdf', SYSTEM_THUMBNAIL_DIR_SECURE => SYSTEM_THUMBNAIL_DIR_SECURE_DEFAULT, SYSTEM_THUMBNAIL_DIR_PUBLIC => SYSTEM_THUMBNAIL_DIR_PUBLIC_DEFAULT, diff --git a/extension/Classes/Core/Store/Store.php b/extension/Classes/Core/Store/Store.php index b3b298e036c844fae96818db467366d5333a82f2..60dec91a3140c2d079c54434b5c2ef482547204b 100644 --- a/extension/Classes/Core/Store/Store.php +++ b/extension/Classes/Core/Store/Store.php @@ -14,6 +14,7 @@ use IMATHUZH\Qfq\Core\Helper\Logger; use IMATHUZH\Qfq\Core\Helper\OnArray; use IMATHUZH\Qfq\Core\Helper\Sanitize; use IMATHUZH\Qfq\Core\Helper\Support; +use IMATHUZH\Qfq\Core\Helper\HelperFile; /* * Stores: @@ -297,7 +298,7 @@ class Store { // Make path absolute foreach ([SYSTEM_MAIL_LOG, SYSTEM_QFQ_LOG, SYSTEM_SQL_LOG] AS $key) { if (!empty($config[$key]) && $config[$key][0] != '/') { - $config[$key] = $config[SYSTEM_SITE_PATH] . '/' . $config[$key]; + $config[$key] = HelperFile::joinPathFilename($config[SYSTEM_SITE_PATH], $config[$key]); } } diff --git a/extension/Tests/Unit/Core/Helper/HelperFileTest.php b/extension/Tests/Unit/Core/Helper/HelperFileTest.php index aa6da1c7eb215c29572c205aab92ad667cea9530..98ae13a4f53166a76e8847a522f6e1c37a74f69b 100644 --- a/extension/Tests/Unit/Core/Helper/HelperFileTest.php +++ b/extension/Tests/Unit/Core/Helper/HelperFileTest.php @@ -38,15 +38,34 @@ class HelperFileTest extends TestCase { $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.m.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_MATLAB,'')); $this->assertEquals(DIR_HIGHLIGHT_JSON . '/javascript.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_JAVASCRIPT,'fileadmin/test.js')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.qfq.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_QFQ,'fileadmin/test.js')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.py.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_PYTHON,'fileadmin/test.js')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.m.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_MATLAB,'fileadmin/test.js')); - - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/javascript.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO,'fileadmin/test.js')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.php.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO,'fileadmin/test.php')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.qfq.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO,'fileadmin/test.qfq')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.py.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO,'fileadmin/test.py')); - $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.m.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO,'fileadmin/test.m')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.qfq.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_QFQ, 'fileadmin/test.js')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.py.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_PYTHON, 'fileadmin/test.js')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.m.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_MATLAB, 'fileadmin/test.js')); + + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/javascript.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO, 'fileadmin/test.js')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.php.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO, 'fileadmin/test.php')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.qfq.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO, 'fileadmin/test.qfq')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.py.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO, 'fileadmin/test.py')); + $this->assertEquals(DIR_HIGHLIGHT_JSON . '/highlight.m.json', HelperFile::getFileTypeHighlight(FE_HIGHLIGHT_AUTO, 'fileadmin/test.m')); } + + public function testJoinPathFilename() { + + $this->assertEquals('', HelperFile::joinPathFilename('', '')); + $this->assertEquals('/', HelperFile::joinPathFilename('/', '')); + $this->assertEquals('/', HelperFile::joinPathFilename('', '/')); + $this->assertEquals('/', HelperFile::joinPathFilename('/', '/')); + + $this->assertEquals('a/b', HelperFile::joinPathFilename('a', 'b')); + $this->assertEquals('/a/b', HelperFile::joinPathFilename('/a', 'b')); + $this->assertEquals('/b', HelperFile::joinPathFilename('a', '/b')); + $this->assertEquals('/b', HelperFile::joinPathFilename('/a', '/b')); + + $this->assertEquals('a/b', HelperFile::joinPathFilename('a/', 'b')); + $this->assertEquals('a/b', HelperFile::joinPathFilename('a', 'b')); + $this->assertEquals('/b', HelperFile::joinPathFilename('a/', '/b')); + $this->assertEquals('/b', HelperFile::joinPathFilename('a', '/b')); + } + } diff --git a/extension/Tests/Unit/Core/Store/StoreTest.php b/extension/Tests/Unit/Core/Store/StoreTest.php index ec661206eb506fa5f593094b5f83c0f087544220..ea15d5bbbfc4ae6fc64d08a54056691f7ed6832c 100644 --- a/extension/Tests/Unit/Core/Store/StoreTest.php +++ b/extension/Tests/Unit/Core/Store/StoreTest.php @@ -413,6 +413,7 @@ class StoreTest extends TestCase { SYSTEM_CMD_QPDF => 'qpdf', SYSTEM_CMD_GS => 'gs', SYSTEM_CMD_PDFUNITE => 'pdfunite', + SYSTEM_CMD_IMG2PDF => 'img2pdf', ]; $body = <<< EOT diff --git a/extension/ext_conf_template.txt b/extension/ext_conf_template.txt index 979b6616dea698527b3b65e1a1e072645f694a33..9bf76675dec6c5a30fc80f2fba4f5549f82b1a0b 100644 --- a/extension/ext_conf_template.txt +++ b/extension/ext_conf_template.txt @@ -37,6 +37,9 @@ cmdGs = gs # cat=config/config; type=string; label=Command 'pdfunite':Default is 'pdfunite'. Will be used to merge PDFs. cmdPdfunite = pdfunite +# cat=config/config; type=string; label=Command 'img2pdf':Default is 'img2pdf'. Will be used to convert images to PDFs. +cmdImg2pdf = img2pdf + # cat=config/email; type=string; label=Options for SendEMail:Default is empty. General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail. E.g.: 'sendEMail=-o tls=yes' sendEMailOptions =