From 45b629e39f4bbd8738e29ab28e7676c3e6d5a89f Mon Sep 17 00:00:00 2001
From: jhaller <jan.haller@math.uzh.ch>
Date: Wed, 5 Jul 2023 14:20:40 +0200
Subject: [PATCH] F8975 WIP: Previously the notation mode was not set correctly
 because statements such as 'form={{form:SE}}' were not considered while
 determining the first token. This should now be fixed. The first token gets
 determined earlier on while joining the lines. Based on this first token the
 notation mode will be set like before. Added an error "Invalid level
 detected" which tells the user that an alias was used where it is not
 allowed. refs #8975

---
 extension/Classes/Core/BodytextParser.php | 23 +++++++++++++----------
 extension/Classes/Core/Constants.php      |  2 ++
 extension/Classes/Core/Report/Report.php  |  6 ++++++
 3 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/extension/Classes/Core/BodytextParser.php b/extension/Classes/Core/BodytextParser.php
index f1a91d3cb..84e15d138 100644
--- a/extension/Classes/Core/BodytextParser.php
+++ b/extension/Classes/Core/BodytextParser.php
@@ -180,6 +180,7 @@ class BodytextParser {
         $data = array();
         $reportLines = $this->reportLinesTemp;
         $bodytextArray = explode(PHP_EOL, $bodyText);
+        $firstToken = '';
 
         $nestingOpenRegexp = $nestingOpen;
         if ($nestingOpen === '(' || $nestingOpen === '[') {
@@ -206,7 +207,6 @@ class BodytextParser {
                 // E.g. myAlias { ...
                 || (1 === preg_match('/^\w*(\s*' . $nestingOpenRegexp . ')+$/', $row))
             ) {
-
                 // if there is already something: save this.
                 if ($full !== '') {
                     $data[] = $full;
@@ -215,6 +215,13 @@ class BodytextParser {
                 // start new line
                 $full = $row;
 
+                // This later determines the notation mode
+                // Possible values for $firstToken: '10', '10.20', '10.sql=...', '10.head=...', 'myAlias {', 'myAlias{'
+                // Values such as 'form={{form:SE}}' are disregarded
+                if (empty($firstToken) && 1 !== preg_match('/^(' . TOKEN_VALID_LIST . ')\s*=/', $row)) {
+                    $firstToken = (strpos($row, $nestingOpen) !== false) ? trim(substr($row, 0, strpos($row, $nestingOpen))) : $row;
+                }
+
             // If the open delimiter is missing while using an alias, this is necessary to get the correct error message later on
             // Starts a new line if the previous line only contained '}'
             // It prevents that the lines '}' and 'myAlias' will be joined
@@ -259,6 +266,7 @@ class BodytextParser {
             }
         }
         $this->reportLinesTemp = $reportLines;
+        $this->firstToken = $firstToken;
 
         return implode(PHP_EOL, $data);
     }
@@ -336,13 +344,11 @@ class BodytextParser {
         $reportLines = $this->reportLinesTemp;
         $alias = null;
         $aliases = null;
-        // $firstToken determines the notation mode of the whole tt_content record
-        $firstToken = explode(NESTING_TOKEN_OPEN, $bodytext, 2);
-        $firstToken = trim($firstToken[0]);
+        $firstToken = $this->firstToken;
 
         // No first token or non-numeric first token implies report notation 2.0 is used
         // It supports auto numbering of blocks and aliases
-        if ((empty($firstToken) || !is_numeric($firstToken)) && !strpos($firstToken, '.')) {
+        if (empty($firstToken) || (!is_numeric($firstToken) && !strpos($firstToken, '='))) {
             $notationMode = 'other';
             $aliases = array();
             $levels = array();
@@ -379,9 +385,6 @@ class BodytextParser {
             $levelStartPos = ($levelStartPos === false) ? 0 : $levelStartPos + 1;  // Skip PHP_EOL
 
             $level = trim(substr($pre, $levelStartPos));
-//            if($level==='') {
-//                $pre=
-//            }
 
             // Report Notation 2.0
             // Count open brackets in front of current level
@@ -394,12 +397,12 @@ class BodytextParser {
 
                 // $firstToken === $level checks if we are in the 'first loop'
                 // $adjustLength is used later while extracting a substring and has to be zero in the first loop
-                ($firstToken === $level) ? $adjustLength = 0 : $adjustLength = 1;
+                $adjustLength = ($firstToken === $level && strpos($pre, PHP_EOL) === false) ? 0 : 1;
 
                 // If the $level, from which the $alias is extracted, contains whitespace, $alias is empty
                 // E.g. no alias or number is used: $level = "1.sql = SELECT ..."
                 // E.g. alias is used: $level = "myAlias"
-                (strpos($level, ' ')) ? $alias = '' : $alias = $level;
+                $alias = (strpos($level, ' ')) ? '' : $level;
 
                 // If no alias is set, then nothing gets saved
                 if (!empty($alias)) {
diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php
index b15930292..ee0222b7f 100644
--- a/extension/Classes/Core/Constants.php
+++ b/extension/Classes/Core/Constants.php
@@ -255,6 +255,8 @@ const ERROR_TWIG_COLUMN_NOT_UNIQUE = 1411;
 const ERROR_DOUBLE_DEFINITION = 1412;
 const ERROR_INVALID_SAVE_ZIP_FILENAME = 1413;
 const ERROR_NUMERIC_ALIAS = 1414;
+const ERROR_INVALID_LEVEL = 1415;
+
 
 // Upload
 const ERROR_UPLOAD = 1500;
diff --git a/extension/Classes/Core/Report/Report.php b/extension/Classes/Core/Report/Report.php
index 67f9186f0..ebf0a6f37 100644
--- a/extension/Classes/Core/Report/Report.php
+++ b/extension/Classes/Core/Report/Report.php
@@ -323,6 +323,12 @@ class Report {
         $alias = TOKEN_ALIAS . "." . $level;
         $alias = $this->store->getVar($alias, STORE_TYPO3);
 
+        // Throw exception if level is not numeric
+        // E.g. myAlias
+        if (1 !== preg_match('/([0-9\.])+/', $level)) {
+            throw new \UserReportException ("Invalid level detected: $level is not a valid level.", ERROR_INVALID_LEVEL);
+        }
+
         // Throw exception if alias is numeric
         // E.g. 10, 10.20
         if (is_numeric($alias)) {
-- 
GitLab