diff --git a/src/Modules/Review/Http/ReviewController.php b/src/Modules/Review/Http/ReviewController.php
index 97a2b28ef..0c7a2ca26 100644
--- a/src/Modules/Review/Http/ReviewController.php
+++ b/src/Modules/Review/Http/ReviewController.php
@@ -5,7 +5,7 @@
*
* HTTP controller for word review interface.
*
- * PHP version 8.1
+ * PHP version 8.2
*
* @category Lwt
* @package Lwt\Modules\Review\Http
@@ -20,7 +20,6 @@
namespace Lwt\Modules\Review\Http;
use Lwt\Shared\Http\BaseController;
-use Lwt\Shared\Infrastructure\Exception\ValidationException;
use Lwt\Modules\Review\Application\ReviewFacade;
use Lwt\Modules\Review\Infrastructure\SessionStateManager;
use Lwt\Modules\Language\Application\LanguageFacade;
@@ -89,77 +88,6 @@ public function index(array $params): ?\Lwt\Shared\Infrastructure\Http\RedirectR
return null;
}
- /**
- * Render review header frame.
- *
- * @param array $params Route parameters
- *
- * @return void
- *
- * @psalm-suppress UnusedVariable Variables are used in included view files
- */
- public function header(array $params): void
- {
- $langId = $this->param('lang') !== '' ? (int) $this->param('lang') : null;
- $textId = $this->param('text') !== '' ? (int) $this->param('text') : null;
- $selection = $this->param('selection') !== '' ? (int) $this->param('selection') : null;
-
- // Get selection data from session criteria
- $sessReviewSql = null;
- if ($selection !== null && $this->sessionManager->hasCriteria()) {
- $sessReviewSql = $this->sessionManager->getSelectionString();
- }
-
- $testData = $this->reviewFacade->getReviewDataFromParams(
- $selection,
- $sessReviewSql,
- $langId,
- $textId
- );
-
- if ($testData === null) {
- throw ValidationException::forField(
- 'parameters',
- 'Review header requires valid lang, text, or selection parameter'
- )->setHttpStatusCode(400);
- }
-
- $languageName = $this->reviewFacade->getL2LanguageName(
- $langId,
- $textId,
- $selection,
- $sessReviewSql
- );
-
- // Initialize session
- $dueCount = (int) ($testData['counts']['due'] ?? 0);
- $this->reviewFacade->initializeReviewSession($dueCount);
-
- // Pre-compute service output for view
- $navLinksHtml = ($textId !== null)
- ? (new \Lwt\Modules\Text\Application\Services\TextNavigationService())
- ->getPreviousAndNextTextLinks($textId, '/review?text=', false, '')
- : '';
- $annotationLinkHtml = ($textId !== null)
- ? (new \Lwt\Modules\Text\Application\Services\AnnotationService())->getAnnotationLink($textId)
- : '';
-
- // Render header views
- include __DIR__ . '/../Views/header.php';
-
- // Prepare variables for header content
- /** @var mixed $titleRaw */
- $titleRaw = $testData['title'] ?? '';
- $title = is_string($titleRaw) ? $titleRaw : '';
- /** @var mixed $propertyRaw */
- $propertyRaw = $testData['property'] ?? '';
- $property = is_string($propertyRaw) ? $propertyRaw : '';
- $totalDue = $dueCount;
- $totalCount = (int) ($testData['counts']['total'] ?? 0);
-
- include __DIR__ . '/../Views/header_content.php';
- }
-
/**
* Get review property from request parameters.
*
diff --git a/src/Modules/Review/Views/footer.php b/src/Modules/Review/Views/footer.php
deleted file mode 100644
index a081986f9..000000000
--- a/src/Modules/Review/Views/footer.php
+++ /dev/null
@@ -1,80 +0,0 @@
-
- * @license Unlicense
- * @link https://hugofara.github.io/lwt/developer/api
- * @since 3.0.0
- *
- * @var int $remaining
- * @var int $wrong
- * @var int $correct
- */
-
-namespace Lwt\Views\Review;
-
-use Lwt\Shared\UI\Helpers\IconHelper;
-
-// Ensure variables are integers
-$remainingInt = (int) ($remaining ?? 0);
-$wrongInt = (int) ($wrong ?? 0);
-$correctInt = (int) ($correct ?? 0);
-
-$total = $wrongInt + $correctInt + $remainingInt;
-$divisor = $total > 0 ? $total / 100.0 : 1.0;
-$lRemaining = (int) round($remainingInt / $divisor, 0);
-$lWrong = (int) round($wrongInt / $divisor, 0);
-$lCorrect = (int) round($correctInt / $divisor, 0);
-?>
-
-
diff --git a/src/Modules/Review/Views/header.php b/src/Modules/Review/Views/header.php
deleted file mode 100644
index 92aa969c7..000000000
--- a/src/Modules/Review/Views/header.php
+++ /dev/null
@@ -1,65 +0,0 @@
-
- * @license Unlicense
- * @link https://hugofara.github.io/lwt/developer/api
- * @since 3.0.0
- *
- * @var int|null $textId
- */
-
-namespace Lwt\Views\Review;
-
-use Lwt\Shared\UI\Helpers\PageLayoutHelper;
-
-/** @var int|null $textId */
-assert(is_string($navLinksHtml));
-assert(is_string($annotationLinkHtml));
-
-?>
-
diff --git a/src/Modules/Review/Views/header_content.php b/src/Modules/Review/Views/header_content.php
deleted file mode 100644
index 1638af9dc..000000000
--- a/src/Modules/Review/Views/header_content.php
+++ /dev/null
@@ -1,90 +0,0 @@
-
- * @license Unlicense
- * @link https://hugofara.github.io/lwt/developer/api
- * @since 3.0.0
- *
- * @var string $title
- * @var string $property
- * @var int $totalDue
- * @var int $totalCount
- * @var string $languageName
- */
-
-namespace Lwt\Views\Review;
-
-// Validate and cast injected variables
-assert(isset($title) && is_string($title));
-assert(isset($property) && is_string($property));
-assert(isset($totalDue) && is_int($totalDue));
-assert(isset($totalCount) && is_int($totalCount));
-assert(isset($languageName) && is_string($languageName));
-
-?>
- $title]),
- ENT_QUOTES,
- 'UTF-8'
-); ?>
-
- 1
- ? __('review.header.words_due_today_many')
- : __('review.header.words_due_today_one'),
- ENT_QUOTES,
- 'UTF-8'
- ); ?>
- ,
-
-
-
-
diff --git a/src/Modules/Text/Application/Services/TextReadingService.php b/src/Modules/Text/Application/Services/TextReadingService.php
deleted file mode 100644
index 33c4836fb..000000000
--- a/src/Modules/Text/Application/Services/TextReadingService.php
+++ /dev/null
@@ -1,333 +0,0 @@
-
- * @license Unlicense
- * @link https://hugofara.github.io/lwt/developer/api
- * @since 3.0.0 Migrated from Core/Text/text_display.php
- */
-
-declare(strict_types=1);
-
-namespace Lwt\Modules\Text\Application\Services;
-
-use Lwt\Shared\Infrastructure\Globals;
-use Lwt\Shared\Infrastructure\Utilities\StringUtils;
-use Lwt\Shared\Infrastructure\Database\Connection;
-use Lwt\Shared\Infrastructure\Database\QueryBuilder;
-use Lwt\Modules\Vocabulary\Application\Services\ExportService;
-use Lwt\Modules\Tags\Application\TagsFacade;
-
-/**
- * Service class for text reading display.
- *
- * @category Lwt
- * @package Lwt\Modules\Text\Application\Services
- * @author HugoFara
- * @license Unlicense
- * @link https://hugofara.github.io/lwt/developer/api
- * @since 3.0.0
- *
- * @psalm-suppress UnusedClass - Service class for text reading functionality
- */
-class TextReadingService
-{
- /**
- * Print the output when the word is a term.
- *
- * @param int $actcode Action code, > 1 for multiword
- * @param bool $showAll Show all words or not
- * @param string $spanid ID for this span element
- * @param string $hidetag Hide tag string
- * @param int $currcharcount Current number of characters
- * @param array $record Various data from database
- * @param array $exprs Current expressions (passed by reference)
- *
- * @return void
- */
- public function echoTerm(
- int $actcode,
- bool $showAll,
- string $spanid,
- string $hidetag,
- int $currcharcount,
- array $record,
- array &$exprs = array()
- ): void {
- $actcode = (int)$record['Code'];
- if ($actcode > 1) {
- // A multiword, $actcode is the number of words composing it
- $tiText = (string)($record['TiText'] ?? '');
- $lastExpr = !empty($exprs) ? $exprs[sizeof($exprs) - 1] : null;
- if ($lastExpr === null || $lastExpr[1] != $tiText) {
- $exprs[] = array($actcode, $tiText, $actcode);
- }
-
- if (isset($record['WoID'])) {
- $woId = (int)$record['WoID'];
- $woStatus = (int)$record['WoStatus'];
- $ti2Order = (int)$record['Ti2Order'];
- $tiTextLC = (string)($record['TiTextLC'] ?? '');
- $attributes = array(
- 'id' => $spanid,
- 'class' => implode(
- " ",
- [
- $hidetag, "click", "mword", ($showAll ? 'mwsty' : 'wsty'),
- "order" . $ti2Order,
- 'word' . $woId, 'status' . $woStatus
- ]
- ),
- 'data_hex' => StringUtils::toClassName($tiTextLC),
- 'data_pos' => $currcharcount,
- 'data_order' => $ti2Order,
- 'data_wid' => $woId,
- 'data_trans' => htmlspecialchars(
- ExportService::replaceTabNewline((string)($record['WoTranslation'] ?? '')) .
- (($tags = TagsFacade::getWordTagList($woId, false)) ? ' [' . $tags . ']' : ''),
- ENT_QUOTES,
- 'UTF-8'
- ),
- 'data_rom' => htmlspecialchars((string)($record['WoRomanization'] ?? ''), ENT_QUOTES, 'UTF-8'),
- 'data_status' => $woStatus,
- 'data_code' => $actcode,
- 'data_text' => htmlspecialchars($tiText, ENT_QUOTES, 'UTF-8')
- );
- $span = ' $val) {
- $span .= ' ' . $attr_name . '="' . (string)$val . '"';
- }
- $span .= '>';
- if ($showAll) {
- $span .= $actcode;
- } else {
- $span .= htmlspecialchars($tiText, ENT_QUOTES, 'UTF-8');
- }
- $span .= '';
- echo $span;
- }
- } else {
- // Single word
- $tiText = (string)($record['TiText'] ?? '');
- $tiTextLC = (string)($record['TiTextLC'] ?? '');
- $ti2Order = (int)$record['Ti2Order'];
- if (isset($record['WoID'])) {
- // Word found status 1-5|98|99
- $woId = (int)$record['WoID'];
- $woStatus = (int)$record['WoStatus'];
- $attributes = array(
- 'id' => $spanid,
- 'class' => implode(
- " ",
- [
- $hidetag, "click", "word", "wsty", "word" . $woId,
- 'status' . $woStatus
- ]
- ),
- 'data_hex' => StringUtils::toClassName($tiTextLC),
- 'data_pos' => $currcharcount,
- 'data_order' => $ti2Order,
- 'data_wid' => $woId,
- 'data_trans' => htmlspecialchars(
- ExportService::replaceTabNewline((string)($record['WoTranslation'] ?? '')) .
- (($tags = TagsFacade::getWordTagList($woId, false)) ? ' [' . $tags . ']' : ''),
- ENT_QUOTES,
- 'UTF-8'
- ),
- 'data_rom' => htmlspecialchars((string)($record['WoRomanization'] ?? ''), ENT_QUOTES, 'UTF-8'),
- 'data_status' => $woStatus
- );
- } else {
- // Not registered word (status 0)
- $attributes = array(
- 'id' => $spanid,
- 'class' => implode(
- " ",
- [
- $hidetag, "click", "word", "wsty", "status0"
- ]
- ),
- 'data_hex' => StringUtils::toClassName($tiTextLC),
- 'data_pos' => $currcharcount,
- 'data_order' => $ti2Order,
- 'data_trans' => '',
- 'data_rom' => '',
- 'data_status' => '0',
- 'data_wid' => ''
- );
- }
- foreach ($exprs as $expr) {
- $attributes['data_mw' . $expr[0]] = htmlspecialchars($expr[1], ENT_QUOTES, 'UTF-8');
- }
- $span = ' $val) {
- $span .= ' ' . $attr_name . '="' . (string)$val . '"';
- }
- $span .= '>' . htmlspecialchars($tiText, ENT_QUOTES, 'UTF-8') . '';
- echo $span;
- for ($i = sizeof($exprs) - 1; $i >= 0; $i--) {
- /**
- * @var array{0: int, 1: string, 2: int} $currentExpr
-*/
- $currentExpr = $exprs[$i];
- $currentExpr[2]--;
- $exprs[$i] = $currentExpr;
- if ($currentExpr[2] < 1) {
- unset($exprs[$i]);
- $exprs = array_values($exprs);
- }
- }
- }
- }
-
- /**
- * Check if a new sentence SPAN should be started.
- *
- * @param int $sid Sentence ID
- * @param int $old_sid Old sentence ID
- *
- * @return int Sentence ID
- */
- public function parseSentence(int $sid, int $old_sid): int
- {
- if ($sid == $old_sid) {
- return $sid;
- }
- if ($sid != 0) {
- echo '';
- }
- $sid = $old_sid;
- echo '';
- return $sid;
- }
-
- /**
- * Process each text item (can be punctuation, term, etc...)
- *
- * @param array $record Text item information
- * @param int $showAll Show all words or not (0 or 1)
- * @param int $currcharcount Current number of characters
- * @param bool $hide Should some item be hidden,
- * depends on $showAll
- * @param array $exprs Current expressions
- *
- * @return void
- */
- public function parseItem(
- array $record,
- int $showAll,
- int $currcharcount,
- bool $hide,
- array &$exprs = array()
- ): void {
- $actcode = (int)$record['Code'];
- $order = (int)$record['Ti2Order'];
- $spanid = 'ID-' . $order . '-' . $actcode;
-
- // Check if item should be hidden
- $hidetag = $hide ? ' hide' : '';
-
- if ($record['TiIsNotWord'] != 0) {
- // The current item is not a term (likely punctuation)
- $text = (string)($record['TiText'] ?? '');
- // Add 'punc' class for punctuation (non-whitespace non-words)
- $puncClass = (trim($text) !== '' && !ctype_space($text)) ? 'punc' : '';
- $classes = trim($hidetag . ' ' . $puncClass);
- echo "" .
- str_replace("ΒΆ", '
', htmlspecialchars($text, ENT_QUOTES, 'UTF-8')) . '';
- } else {
- // A term (word or multi-word)
- $this->echoTerm(
- $actcode,
- (bool)$showAll,
- $spanid,
- $hidetag,
- $currcharcount,
- $record,
- $exprs
- );
- }
- }
-
- /**
- * Get all words and start the iterate over them.
- *
- * @param int $textId ID of the text
- * @param int $showAll Show all words or not (0 or 1)
- *
- * @return void
- */
- public function mainWordLoop(int $textId, int $showAll): void
- {
- $res = QueryBuilder::table('word_occurrences')
- ->selectRaw('CASE WHEN `Ti2WordCount`>0 THEN Ti2WordCount ELSE 1 END AS Code')
- ->selectRaw('CASE WHEN CHAR_LENGTH(Ti2Text)>0 THEN Ti2Text ELSE `WoText` END AS TiText')
- ->selectRaw('CASE WHEN CHAR_LENGTH(Ti2Text)>0 THEN LOWER(Ti2Text) ELSE `WoTextLC` END AS TiTextLC')
- ->select(['Ti2Order', 'Ti2SeID'])
- ->selectRaw('CASE WHEN `Ti2WordCount`>0 THEN 0 ELSE 1 END AS TiIsNotWord')
- ->selectRaw(
- 'CASE WHEN CHAR_LENGTH(Ti2Text)>0 THEN CHAR_LENGTH(Ti2Text) ' .
- 'ELSE CHAR_LENGTH(`WoTextLC`) END AS TiTextLength'
- )
- ->select(['WoID', 'WoText', 'WoStatus', 'WoTranslation', 'WoRomanization'])
- ->leftJoin('words', 'Ti2WoID', '=', 'WoID')
- ->where('Ti2TxID', '=', $textId)
- ->orderBy('Ti2Order', 'ASC')
- ->orderBy('Ti2WordCount', 'DESC')
- ->getPrepared();
- $currcharcount = 0;
- $hidden_items = array();
- $exprs = array();
- $cnt = 1;
- $sid = 0;
- $last = -1;
-
- // Loop over words and punctuation
- foreach ($res as $record) {
- $sid = $this->parseSentence($sid, (int) $record['Ti2SeID']);
- if ($cnt < $record['Ti2Order']) {
- echo '';
- }
- if ($showAll) {
- $hide = isset($record['WoID'])
- && array_key_exists((int) $record['WoID'], $hidden_items);
- } else {
- $hide = $record['Ti2Order'] <= $last;
- }
-
- $this->parseItem($record, $showAll, $currcharcount, $hide, $exprs);
- if ((int)$record['Code'] == 1) {
- $currcharcount += (int)$record['TiTextLength'];
- $cnt++;
- }
- $last = max(
- $last,
- (int) $record['Ti2Order'] + ((int)$record['Code'] - 1) * 2
- );
- if ($showAll) {
- if (
- isset($record['WoID'])
- && !array_key_exists((int) $record['WoID'], $hidden_items)
- ) {
- $hidden_items[(int) $record['WoID']] = (int) $record['Ti2Order']
- + ((int)$record['Code'] - 1) * 2;
- }
- // Clean the already finished items
- $hidden_items = array_filter(
- $hidden_items,
- fn ($val) => $val >= $record['Ti2Order'],
- );
- }
- }
-
- echo '' . $currcharcount . '';
- }
-}
diff --git a/src/Shared/UI/Helpers/PageLayoutHelper.php b/src/Shared/UI/Helpers/PageLayoutHelper.php
index 777872944..0590421b7 100644
--- a/src/Shared/UI/Helpers/PageLayoutHelper.php
+++ b/src/Shared/UI/Helpers/PageLayoutHelper.php
@@ -4,7 +4,7 @@
* \file
* \brief Helper for page layout generation (headers, footers, navigation).
*
- * PHP version 8.1
+ * PHP version 8.2
*
* @category View
* @package Lwt
@@ -840,35 +840,6 @@ public static function renderPageEnd(): void
echo '