Skip to content

Context review#4429

Open
riccio82 wants to merge 113 commits intodevelopfrom
context-review
Open

Context review#4429
riccio82 wants to merge 113 commits intodevelopfrom
context-review

Conversation

@riccio82
Copy link
Copy Markdown
Collaborator

No description provided.

riccio82 and others added 24 commits March 17, 2026 14:24
… and collection

Introduce SegmentMetadataMarshaller enum as single source of truth for
valid metadata keys with marshall/unmarshall type conversion.

Add SegmentMetadataMapper to map XLIFF trans-unit attributes to DB-ready
SegmentMetadataStruct entries, and SegmentMetadataCollection as a
purpose-built read-only collection with typed find() lookup.

Refactor all consumers (SegmentExtractor, SegmentStorageService,
SizeRestrictionChecker, QA, controllers) to use the centralized
components instead of scattered constants and inline logic.
…Type enum

Add resname and restype attributes to the segment metadata pipeline, enabling XLIFF context mapping storage with validated lookup strategies.
GetSegmentsController now calls jsonSerialize() on SegmentMetadataCollection,
returning typed values (int, string) instead of raw DB strings.
- Add proper error reporting: check isValid() and throw with aggregated
  exception messages instead of silently accepting invalid metadata
- Remove unused imports (InjectableFiltersTags, HandlersSorter,
  JobsMetadataDao, MetadataDao)
…nstraints

- XLIFF 2.0 test fixture: use matecat: namespace prefix (matecat:resname,
  matecat:restype) with proper xmlns:matecat declaration per spec
- Feature spec Section 8: clean constraints from 16 → 13 active items,
  remove implemented/outdated entries, add new architecture decisions
- Section 7.2: context-url pipeline task list (7 items) — FilesMetadataMarshaller,
  CONTEXT_URL cases, fallback resolver, 3 APIs, GetSegmentsController
- Section 11: full architecture — three-level storage, dual ingestion paths,
  read-time fallback resolution, FilesMetadataMarshaller Pattern B design
- Section 8: three new constraints (naming convention, dual ingestion, fallback order)
…lers

Add 'context-url' as a new metadata key recognized at both segment
level (SegmentMetadataMarshaller, 9th case) and project level
(ProjectsMetadataMarshaller, 31st case). Both use simple string
pass-through for marshall/unMarshall. TDD: +8 tests.
Ostico and others added 13 commits April 7, 2026 13:37
…hModel and UserDao

- parameterize status, job, and password in all 3 SearchModel
  query builders
- remove dead regexp-escape assignments
  (regexpEscapedSrc/Trg never read)
- remove redundant escape() in UserDao::sanitize(), downstream
  queries already use :named PDO parameters
…Statement()

- Change buildInsertStatement() return type from string to array
- Return [$sql, $dupBindValues] to surface bind values to callers
- Update Database::insert() to merge dupBindValues before execute()
- Update AbstractDao::insertStruct() to merge dupBindValues into data
- Add 6 unit tests + 4 integration tests covering all branches
- Mark TF-1 as done in remaining-actionable-items.md
…ions, type propagateTranslation, remove dead escape()

QW-3: Replace $_POST direct access with $this->params in FilesController,
DeepLGlossaryController, and ModernMTController (16 replacements across 3 files).
Replace $_FILES direct access with Klein $this->request->files() DataCollection
in XliffToTargetConverterController, ModernMTController, DeepLGlossaryController,
TMXFileController, and GlossaryFilesController. Refactor TMSService::uploadFile()
to accept injected file array. Add constructor injection to UploadHandler for
file array (single boundary: index.php passes $_FILES).
QW-4: Add @return array shape docblock to VersionHandlerInterface::propagateTranslation().
QW-2 cleanup: Remove dead escape() method from Database.php and IDatabase.php
after all callers were migrated to parameterized queries.

All tests pass: 2278 tests, 17481 assertions, 0 failures.
…rglobals with Klein abstractions in 6 controllers
…b->commit(), fix PHPStan level 8

TF-3: Decompose the 279-line SetTranslationController::translate() into
5 focused private methods (prepareTranslation, buildNewTranslation,
persistTranslation, buildResult, finalizeTranslation) with transaction
boundaries ($db->begin/$db->commit) visible in the orchestrator.

Post-extraction: removed Database $db from persistTranslation() params,
fixed all 80 PHPStan level 8 errors including filter_var string|false
handling, nullable property guards, typed method signatures, and
accurate array shape PHPDocs.

25 unit tests for canUpdateSuggestion (10), isSplittedSegment (4),
setStatusForSplittedSegment (3), buildNewTranslation (8) via
TestableSetTranslationController subclass + 6 structural guards.
2310 tests, 17701 assertions, 0 failures. PHPStan level 8: 0 errors.
…tureStruct, and OwnerFeatureDao

- Type __construct($features) param as ?array<BasicFeatureStruct>
- Add iterable value types to getCodes(), splitString(), getAutoloadPlugins(), merge(), runOnFeature()
- Narrow BasicFeatureStruct::toNewObject() return from IBaseFeature to BaseFeature
- Replace call_user_func_array() with first-class callable syntax ($obj->$method(...$args))
- Remove dead property_exists() check (always true for typed BasicFeatureStruct)
- Fix OwnerFeatureDao: narrow getByIdCustomer/getByUserId return types, type destroyCacheByIdCustomer param, cast lastInsertId to int, remove dead ?? [] (non-nullable _fetchObjectMap)
- Type BasicFeatureStruct::$options as array<string, mixed>|string|null
…ming convention

- Align rewriteContributionContexts @method param $contextData → $requestData
- Reclassify filterProjectNameModified, handleTUContextGroups,
  alter_chunk_review_struct from filter → run (return values were discarded)
- Move @method annotations to run section with void return type
- Document hook naming convention: ~45 camelCase vs ~17 snake_case,
  policy: keep existing, new hooks use camelCase (PSR-1)
- Update roadmap inconsistencies section with resolutions
- Update remaining-actionable-items.md SR-5 status
…case to camelCase

Remove 20 hook dispatch sites that have zero handler implementations across
all plugins (uber, airbnb, translated, aligner) and internal features.
Rename 5 remaining snake_case hooks to camelCase for PSR-1 consistency.

Removed hooks (filter): filterCreationStatus, overrideConversionResult,
filterGlobalWarnings, filterSegmentWarnings, filterSetTranslationResult,
prepareAllNotes, processExtractedJsonNotes, filterIsChunkCompletionUndoable,
doNotManageAlternativeTranslations, filter_team_for_project_creation,
filterProjectDependencies, filterFeaturesMerged

Removed hooks (run): project_password_changed, processZIPDownloadPreview,
checkSplitAccess, afterTMAnalysisCloseProject, fastAnalysisComplete,
bootstrapCompleted, postProjectCommit, handleTUContextGroups

Renamed: filter_job_password_to_review_password → filterJobPasswordToReviewPassword,
job_password_changed → jobPasswordChanged, review_password_changed → reviewPasswordChanged,
project_completion_event_saved → projectCompletionEventSaved,
alter_chunk_review_struct → alterChunkReviewStruct
Ostico added 4 commits April 9, 2026 01:22
…et hooks

- Add FilterEvent/RunEvent minimal base classes (single hookName() method)
- Add dispatchFilter()/dispatchRun() on FeatureSet with matching error handling
- Create 44 typed event DTO classes (29 filter + 15 run) in Hook/Event/
- Migrate all 44 call sites from string filter()/run() to typed dispatchFilter()/dispatchRun()
- Migrate all handler methods in Uber, Airbnb, Translated, AbstractRevisionFeature, ProjectCompletion
- Remove @method annotations from FeatureSet (superseded by event classes)
- Clean stale handler docblocks, remove union type hacks from Translated
- Add @see dispatch-site annotations on all 43 event classes
- Add @template T on dispatchFilter()/dispatchRun() for PHPStan inference
- Extract Translated::checkInternalEmail() static utility from hook handler
- Add phpstan.neon with bootstrap autoloader for plugin analysis
- Fix 58 PHPStan missingType errors with annotations (no code changes)
- Fix 8 PHPStan doc-only errors (@var/@return/@param type narrowing)
- Fix 15 PHPStan code errors in Airbnb plugin (false guards, null coalesce, dead code)
- Fix 7 PHPUnit notices (createMock → createStub where no expectations set)
- Legacy filter()/run() retained only for 5 vendor SubFiltering hooks

No BC bridge — all plugins controlled, handlers updated atomically per-hook.
Zero string dispatch remaining in lib/ (verified via grep).
2323 tests, 0 failures, 0 notices.
…ed plugins

Airbnb: 19 → 4 errors (15 fixed, 4 require interface/struct changes in lib/)
Translated: 16 → 0 errors (all fixed)

2323 tests, 0 failures.
…yped pipeline customization

- Implement 6 customizeFrom*() methods on FeatureSet (FeatureSetInterface v4.0)
- customizeFromLayer0ToLayer1 wraps event dispatch (Uber + Airbnb handlers)
- Other 5 are no-ops (YAGNI — no handlers exist)
- Delete filter(string, mixed): mixed
- Delete run(string): void
- Delete runOnFeature() private helper
- Migrate Uber + Airbnb fromLayer0ToLayer1 handlers to event DTO (was still Pipeline)
- Remove reflection bridge added by subagent — clean direct dispatch only

Zero string dispatch remaining. 2325 tests, 0 failures.
Ostico and others added 9 commits April 10, 2026 09:36
- Add screenshot metadata extraction to contextReviewUtils
- Create HtmlContextPanel and ScreenshotContextPanel components
- Implement zoom controls (50%-200%) for both HTML and screenshot views
- Add toolbar toggle to switch between HTML and screenshot content views
- Fix scrolling behavior for zoomed content in both views
- Prevent nested scrollbars in HTML view with overflow:visible enforcement
- Add responsive zoom with dynamic margin for proper scroll bounds
- All 235 tests passing
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Rename all frontend JS/SCSS files, utilities, hooks, components, and
sample files from context-review to context-preview. Add
_context_preview.html template (served via the existing
/context-review route) with updated body/div class names matching the
renamed frontend selectors. Webpack entry point updated accordingly.
…calls

On incremental calls to tagSegments, tier1 elements (resolved via the
strategy pass using resname/restype) were not added to tier1Nodes.
This allowed Pass 2 to append other segments to those elements via
text match, causing tier1 segments to appear on multiple nodes and
showing spurious navigation buttons.

Fix: in the alreadyTagged branch of the strategy pass, re-find the
element via findElementByMetadata and add it to tier1Nodes so Pass 2
correctly excludes it on subsequent calls.

Add regression test covering the incremental call scenario.
Copilot AI review requested due to automatic review settings April 17, 2026 09:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a “context preview/review” capability and modernizes several backend/plugin hook integrations by introducing typed hook event objects, while also cleaning up legacy test assets and tightening data-handling in a few critical paths.

Changes:

  • Introduce Context Preview UI building blocks (new panels, resizing hook, layout styles) and wire segment highlight/translation updates to a ContextPreview channel.
  • Replace multiple FeatureSet filter()/run() calls with typed dispatchFilter()/dispatchRun() events across controllers, workers, and LQA components.
  • Update segment/file/project metadata handling (new metadata marshallers/collections, context-url support) and enforce a unique constraint on segment_metadata.

Reviewed changes

Copilot reviewed 268 out of 328 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
public/js/hooks/useSegmentsLoader.js Remove unused import from segments loader hook.
public/js/hooks/useResizable.js New hook for draggable vertical resizing.
public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js Adjust tag placeholder handling during text transform.
public/js/components/segments/SegmentsContainer.js Recalculate viewport height with context preview wrapper + send highlight messages.
public/js/components/segments/Editarea.js Send translation updates to context preview channel.
public/js/components/contextPreview/index.js Export context preview panels.
public/js/components/contextPreview/ScreenshotContextPanel.js New screenshot-based context preview panel.
public/js/components/contextPreview/LivePreviewPanel.js New live preview container panel with zoom scaling.
public/img/icons/ChangePassword.js Fix React SVG attribute casing (clipPath).
public/css/sass/cattool.scss Add context preview header/container/resize-handle styles.
plugins/uber Bump submodule pointer.
plugins/translated Bump submodule pointer.
plugins/airbnb Bump submodule pointer.
phpstan.neon Add PHPStan configuration.
old_tests/support/lib/Utils/ZipArchiveExtendedTest.php Remove legacy test placeholder.
old_tests/support/lib/UnitTestInitializer.php Remove legacy integration test initializer.
old_tests/support/lib/IntegrationTest.php Remove legacy integration test base class.
old_tests/support/lib/Factory/User.php Remove legacy factory.
old_tests/support/lib/Factory/OwnerFeature.php Remove legacy factory.
old_tests/support/lib/Factory/Base.php Remove legacy factory base.
old_tests/support/lib/Factory/ApiKey.php Remove legacy factory.
old_tests/support/fixtures/users.yml Remove legacy fixtures.
old_tests/support/fixtures/segments.yml Remove legacy fixtures.
old_tests/support/fixtures/segment_translations.yml Remove legacy fixtures.
old_tests/support/fixtures/segment_translation_versions.yml Remove legacy fixtures.
old_tests/support/fixtures/qa_models.yml Remove legacy fixtures.
old_tests/support/fixtures/qa_chunk_reviews.yml Remove legacy fixtures.
old_tests/support/fixtures/qa_categories.yml Remove legacy fixtures.
old_tests/support/fixtures/projects.yml Remove legacy fixtures.
old_tests/support/fixtures/jobs.yml Remove legacy fixtures.
old_tests/support/fixtures/files_job.yml Remove legacy fixtures.
old_tests/support/fixtures/files.yml Remove legacy fixtures.
old_tests/support/files/zip-with-model-json/amex-test.docx.xlf Remove legacy test file.
old_tests/support/files/zip-with-model-json/__meta/qa_model.json Remove legacy test metadata file.
old_tests/support/files/xliff/sdlxliff-with-mrk-and-note.xlf.sdlxliff Remove legacy test file.
old_tests/support/files/xliff/file-with-preserve-white-space.xliff Remove legacy test file.
old_tests/support/files/xliff/file-with-notes-nobase64.po.sdlxliff Remove legacy test file.
old_tests/support/files/xliff/file-with-hello-world.xliff Remove legacy test file.
old_tests/support/files/xliff/amex-test.docx.xlf Remove legacy test file.
old_tests/support/files/txt/hello.txt Remove legacy test file.
old_tests/support/files/tmx/exampleForTestOriginal.tmx Remove legacy test file.
old_tests/support/files/test-propagation.xlf Remove legacy test file.
old_tests/support/files/small-with-notes.sdlxliff Remove legacy test file.
old_tests/support/files/json/schema/schema_1.json Remove legacy schema fixture.
old_tests/support/files/json/schema/invalid.json Remove legacy invalid schema fixture.
old_tests/support/files/json/files/valid.json Remove legacy JSON fixture.
old_tests/support/files/json/files/invalid_maxItems.json Remove legacy JSON fixture.
old_tests/support/files/json/files/invalid.json Remove legacy JSON fixture.
old_tests/support/files/glossary/GlossaryInvalidHeader.csv Remove legacy glossary fixture.
old_tests/support/files/glossary/Final-Matecat-new_glossary_format-InvalidTargetLang.csv Remove legacy glossary fixture.
old_tests/support/files/glossary/Final-Matecat-new_glossary_format-Glossary.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/mixed-valid.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/minimal-valid.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/minimal-invalid.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/invalid-structure.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/invalid-language.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/full-structure-valid.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Header-vuoti.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato solo blacklist language-specific.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato solo blacklist combinata.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato semplice solo lingue.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato lingue + campi termine.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato lingue + campi termine (non per tutte le lingue).csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/V - Formato completo.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV -Formato solo blacklist generale.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Header vuoto.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato una sola lingua solo note.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato una sola lingua solo esempi.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato una sola lingua completa.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato completo con colonne lingua spostate.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato campi concetto + una sola lingua.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato campi concetto + una sola lingua solo note.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Formato campi concetto + una sola lingua solo esempi.csv Remove legacy glossary fixture.
old_tests/support/files/csv/glossary/NV - Campi concetto + una sola lingua solo termini.csv Remove legacy glossary fixture.
old_tests/integration/Features/TranslationVersions/setTranslationWithVersioningDisabledTest.php Remove legacy integration test.
old_tests/integration/Features/ReviewImproved/AssignQualityModelToProjectTest.php Remove legacy integration test.
old_tests/integration/Features/ProjectCompletion/JobStatusTest.php Remove legacy integration test.
old_tests/integration/CreateProjectController/sourceAndTargetLangValidationTest.php Remove legacy integration test.
old_tests/integration/CreateProjectController/setPrivateTMKeyTest.php Remove legacy integration test.
old_tests/integration/Converters/ConversionsTest.php Remove legacy integration test.
old_tests/integration/API/V2/SegmentVersionTest.php Remove legacy integration test.
old_tests/integration/API/V2/SegmentTranslationIssueTest.php Remove legacy integration test placeholder.
old_tests/integration/API/V2/ProjectUrlsTest.php Remove legacy integration test.
old_tests/integration/API/V2/ProjectUpdateTest.php Remove legacy integration test.
old_tests/integration/API/V2/JobMergeTest.php Remove legacy integration test.
old_tests/integration/API/V2/CreateTeamTest.php Remove legacy integration test.
old_tests/integration/API/V1/ValidateSourceAndTargetLanguagesTest.php Remove legacy integration test.
old_tests/integration/API/V1/StatusTest.php Remove legacy integration test.
old_tests/integration/API/V1/NewWithTeamTest.php Remove legacy integration test.
old_tests/integration/API/V1/NewWithRevisionTypeTest.php Remove legacy integration test.
old_tests/integration/API/V1/NewWithPrivateTMKeyTest.php Remove legacy integration test.
old_tests/integration/API/V1/NewWithOwnershipTest.php Remove legacy integration test.
old_tests/README.md Remove legacy test documentation.
old_tests/.htaccess Remove legacy directory access restriction file.
migrations/20260326190000_alter_table_segment_metadata_add_unique_index.php Add migration for unique segment metadata key per segment.
lib/View/templates/_context_preview.html Add new context preview view template.
lib/View/fileupload/index.php Instantiate upload handler with injected files array.
lib/View/fileupload/UploadHandler.php Decouple upload handler from superglobals by injecting files.
lib/View/API/V2/Json/Job.php Use typed hook events for outsource info + project URLs.
lib/View/API/V2/Json/Activity.php Use typed hook event for activity log entry filtering.
lib/View/API/App/Json/Analysis/AnalysisFile.php Guard/encode non-string metadata keys/values.
lib/Utils/TMS/TMSService.php Accept request files array instead of using $_FILES.
lib/Utils/LQA/SizeRestriction/SizeRestriction.php Use typed event for character length counting.
lib/Utils/LQA/QA/TagChecker.php Use typed events for tag mismatch/position checks.
lib/Utils/LQA/QA/SizeRestrictionChecker.php Use metadata marshaller constant for size restriction key.
lib/Utils/LQA/QA/DomHandler.php Use typed event for excluded tags injection.
lib/Utils/LQA/QA.php Remove legacy constant alias for size restriction.
lib/Utils/Engines/MyMemory.php Use typed event for MyMemory parameter filtering.
lib/Utils/AsyncTasks/Workers/Analysis/TMAnalysisWorker.php Use typed event for analysis-before-MT hook; remove after-close-project hook.
lib/Utils/AsyncTasks/Workers/Analysis/FastAnalysis.php Use typed run event; remove fast-analysis completion hook.
lib/Utils/AsyncTasks/Workers/AIAssistantWorker.php Clean up comment and blank line.
lib/Utils/AIAssistant/GeminiClient.php Remove unused AppConfig import.
lib/Routes/view_routes.php Add route for context preview view.
lib/Routes/api_v3_routes.php Add API v3 endpoints for context-url configuration.
lib/Plugins/Features/TranslationVersions/VersionHandlerInterface.php Clarify return array shape in docblock.
lib/Plugins/Features/ReviewExtended/ReviewedWordCountModel.php Use typed event for revision-change email filtering.
lib/Plugins/Features/ReviewExtended/ChunkReviewModel.php Use typed run event for chunk review updates.
lib/Plugins/Features/ProjectCompletion/Model/ProjectCompletionStatusModel.php Use typed event for review password mapping.
lib/Plugins/Features/ProjectCompletion/Model/EventModel.php Use typed run event on completion event save.
lib/Plugins/Features/ProjectCompletion.php Switch to typed hook event methods for job password + translation events.
lib/Model/matecat.sql Make segment_metadata index unique in schema.
lib/Model/Users/UserDao.php Add result type checks; remove legacy escaping.
lib/Model/Translators/TranslatorsModel.php Dispatch typed job-password-changed run event.
lib/Model/Segments/SegmentUIStruct.php Add context_url to UI struct.
lib/Model/Segments/SegmentMetadataMarshaller.php New enum for allowed segment metadata keys and marshalling rules.
lib/Model/Segments/SegmentMetadataMapper.php Map trans-unit attributes into metadata collection.
lib/Model/Segments/SegmentMetadataCollection.php New collection helper for segment metadata.
lib/Model/Segments/ContextUrlResolver.php Resolve segment/file/project-level context URL precedence.
lib/Model/Segments/ContextResType.php Add enum for context resource type.
lib/Model/Projects/ProjectsMetadataMarshaller.php Add project-level context-url metadata.
lib/Model/ProjectCreation/SegmentStorageService.php Store segment metadata via collection; replace hooks with typed events.
lib/Model/ProjectCreation/ProjectManagerModel.php Use SegmentMetadataMarshaller allowlist for segment metadata detection.
lib/Model/ProjectCreation/JobCreationService.php Use typed events for payable rates and job creation validation.
lib/Model/OwnerFeatures/OwnerFeatureDao.php Tighten types; remove null coalescing defaults; adjust signatures.
lib/Model/JobSplitMerge/JobSplitMergeService.php Dispatch typed run events post-split and post-merge.
lib/Model/Files/MetadataStruct.php Allow mixed values for file metadata.
lib/Model/Files/FilesMetadataMarshaller.php New enum for allowed file metadata keys and marshalling.
lib/Model/FeaturesBase/Hook/RunEvent.php New base class for typed run hook events.
lib/Model/FeaturesBase/Hook/FilterEvent.php New base class for typed filter hook events.
lib/Model/FeaturesBase/Hook/Event/Run/ValidateProjectCreationEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/ValidateJobCreationEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/TmAnalysisDisabledEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/SetTranslationCommittedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/ReviewPasswordChangedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/ProjectCompletionEventSavedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/PostProjectCreateEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/PostJobSplittedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/PostJobMergedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/PostAddSegmentTranslationEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/JobPasswordChangedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/FilterProjectNameModifiedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/ChunkReviewUpdatedEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/BeforeProjectCreationEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Run/AlterChunkReviewStructEvent.php New run hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/WordCountEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/SanitizeOriginalDataMapEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/RewriteContributionContextsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/ProjectUrlsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/PrepareNotesForRenderingEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/PopulatePreTranslationsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/OutsourceAvailableInfoEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/IsAnInternalUserEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/InjectExcludedTagsInQaEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/HandleJsonNotesBeforeInsertEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FromLayer0ToLayer1Event.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterRevisionChangeNotificationListEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterPayableRatesEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterMyMemoryGetParametersEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterJobPasswordToReviewPasswordEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterGetSegmentsResultEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterCreateProjectFeaturesEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterContributionStructOnSetTranslationEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterContributionStructOnMTSetEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/FilterActivityLogEntryEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/EncodeInstructionsEvent New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/DecodeInstructionsEvent New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/CorrectTagErrorsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/CheckTagPositionsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/CheckTagMismatchEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/CharacterLengthCountEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/AppendInitialTemplateVarsEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/AppendFieldToAnalysisObjectEvent.php New filter hook event class.
lib/Model/FeaturesBase/Hook/Event/Filter/AnalysisBeforeMTGetContributionEvent.php New filter hook event class.
lib/Model/FeaturesBase/BasicFeatureStruct.php Tighten options docblock and return type.
lib/Model/DataAccess/XFetchEnvelope.php Add value object for XFetch cache metadata.
lib/Model/DataAccess/IDatabase.php Remove legacy escape() method.
lib/Model/DataAccess/Database.php Fix ON DUPLICATE KEY UPDATE binding + remove escape().
lib/Model/DataAccess/AbstractDao.php Track query compute delta and propagate duplicate bind values.
lib/Model/Conversion/Upload.php Update docs to use request files array.
lib/Model/Analysis/AbstractStatus.php Use typed outsource-available event.
lib/Controller/Views/OutsourceTo/AbstractController.php Avoid logging raw superglobals; log request params.
lib/Controller/Views/ContextReviewController.php New view controller for context preview route.
lib/Controller/Views/CattoolController.php Use typed event for template vars hook.
lib/Controller/Views/AnalyzeController.php Use typed event for template vars hook.
lib/Controller/Abstracts/BaseKleinViewController.php Use typed internal-user filter hook event.
lib/Controller/Abstracts/Authentication/SessionTokenStoreHandler.php Disable XFetch semantics for session tokens.
lib/Controller/API/V3/FileInfoController.php Use typed decode-instructions event.
lib/Controller/API/V3/DeepLGlossaryController.php Avoid $_POST/$_FILES; use request object.
lib/Controller/API/V2/UrlsController.php Use typed project URLs event.
lib/Controller/API/V2/SplitJobController.php Simplify split access check signature; remove feature hook call.
lib/Controller/API/V2/ProjectCreationStatusController.php Remove plugin filtering of creation status result.
lib/Controller/API/V2/GlossaryFilesController.php Pass request files array into uploadFile().
lib/Controller/API/V2/DownloadOriginalController.php Avoid logging raw $_POST; log request post params.
lib/Controller/API/V2/DownloadController.php Remove conversion override hook and zip preview hook; avoid logging $_REQUEST.
lib/Controller/API/V2/ChangeProjectNameController.php Dispatch typed run event instead of filter.
lib/Controller/API/V2/ChangePasswordController.php Dispatch typed job/review password changed run events; remove project password hook.
lib/Controller/API/V1/NewController.php Replace several hooks with typed events; adjust metadata validation.
lib/Controller/API/Commons/Validators/IsOwnerInternalUserValidator.php Use typed internal-user event; improve readability.
lib/Controller/API/Commons/Validators/InternalUserValidator.php Use typed internal-user event; improve readability.
lib/Controller/API/App/XliffToTargetConverterController.php Use request files array instead of $_FILES.
lib/Controller/API/App/TMXFileController.php Pass request files into uploadFile().
lib/Controller/API/App/GetWarningController.php Remove feature-driven warning filters and size restriction lookup change.
lib/Controller/API/App/GetTagProjectionController.php Avoid logging raw $_POST.
lib/Controller/API/App/GetSearchController.php Dispatch typed set-translation-committed event; normalize queryParams type.
lib/Controller/API/App/GetContributionController.php Convert rewriteContributionContexts hook to typed event.
lib/Controller/API/App/FilesController.php Avoid $_POST; use controller params.
lib/Controller/API/App/CreateProjectController.php Convert filterCreateProjectFeatures hook to typed event.
lib/Controller/API/App/CompletionEventController.php Load features from chunk project; dispatch typed alter-chunk-review run event.
lib/Controller/API/App/ChangeJobsStatusController.php Avoid logging raw $_POST.
lib/Bootstrap.php Remove bootstrapCompleted plugin hook invocation.
composer.json Add Gemini client; bump matecat/subfiltering major version.
INSTALL/matecat.sql Make segment_metadata index unique in installer schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +38
const handleMouseUp = () => {
if (!isDraggingRef.current) return
isDraggingRef.current = false
setIsDragging(false)
document.body.style.cursor = ''
document.body.style.userSelect = ''
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the component unmounts while dragging, the cleanup removes listeners but never resets document.body.style.cursor / userSelect, leaving the whole app in row-resize / non-selectable state. In the cleanup function, also set isDraggingRef.current = false, setIsDragging(false) (if needed), and restore the body styles (optionally guarding so you only reset if you set them).

Copilot uses AI. Check for mistakes.

return () => {
window.removeEventListener('mousemove', handleMouseMove)
window.removeEventListener('mouseup', handleMouseUp)
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the component unmounts while dragging, the cleanup removes listeners but never resets document.body.style.cursor / userSelect, leaving the whole app in row-resize / non-selectable state. In the cleanup function, also set isDraggingRef.current = false, setIsDragging(false) (if needed), and restore the body styles (optionally guarding so you only reset if you set them).

Suggested change
window.removeEventListener('mouseup', handleMouseUp)
window.removeEventListener('mouseup', handleMouseUp)
if (isDraggingRef.current) {
isDraggingRef.current = false
setIsDragging(false)
document.body.style.cursor = ''
document.body.style.userSelect = ''
}

Copilot uses AI. Check for mistakes.
Comment on lines +65 to 71

if(!is_string($metadatum->key) or !is_string($metadatum->value)) {
$metadatum->value = json_encode($metadatum->value);
$metadatum->key = json_encode($metadatum->key);
}

$this->metadata[] = new AnalysisFileMetadata($metadatum->key, $metadatum->value);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition uses or, so if either key or value is non-string you JSON-encode both. That corrupts valid string keys (e.g. \"instructions\") when only the value is non-string. Encode/cast key and value independently (e.g., only JSON-encode value when it’s non-scalar) and avoid JSON-encoding keys unless you explicitly support non-string key types.

Suggested change
if(!is_string($metadatum->key) or !is_string($metadatum->value)) {
$metadatum->value = json_encode($metadatum->value);
$metadatum->key = json_encode($metadatum->key);
}
$this->metadata[] = new AnalysisFileMetadata($metadatum->key, $metadatum->value);
$key = is_string($metadatum->key) ? $metadatum->key : (string)$metadatum->key;
if (is_string($metadatum->value)) {
$value = $metadatum->value;
} elseif (is_scalar($metadatum->value) || $metadatum->value === null) {
$value = (string)$metadatum->value;
} else {
$value = json_encode($metadatum->value);
}
$this->metadata[] = new AnalysisFileMetadata($key, $value);

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +27
public array $sql_down = [
'
ALTER TABLE `segment_metadata` REMOVE PARTITIONING;
ALTER TABLE `segment_metadata`
DROP INDEX `idx_id_segment_meta_key`,
ADD INDEX `idx_id_segment_meta_key` (`id_segment`, `meta_key`);
'
];
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The down migration is not a safe inverse of the up migration: REMOVE PARTITIONING is unrelated to the index change and will fail on non-partitioned tables (or change table structure unexpectedly). Also, multiple statements in a single string may not be supported by the migration runner/DB driver. Down should strictly revert the unique index back to a non-unique index (and omit partition operations).

Copilot uses AI. Check for mistakes.
Comment on lines 67 to +69
return $thisDao->setCacheTTL($ttl)->_fetchObjectMap($stmt, OwnerFeatureStruct::class, [
'id_customer' => $id_customer
]) ?? [];
]);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both methods declare a return type of array, but they now directly return _fetchObjectMap(...) without the previous ?? [] fallback. If _fetchObjectMap can return null (as the old code implied), this will raise a TypeError. Restore the ?? [] fallback or ensure _fetchObjectMap always returns an array (including when there are no results).

Copilot uses AI. Check for mistakes.
Comment on lines +452 to +471
// const rawMetadata = seg.get('metadata')
// const metadataArr = rawMetadata
// ? typeof rawMetadata.toJS === 'function'
// ? rawMetadata.toJS()
// : rawMetadata
// : []
// const findMeta = (key) =>
// metadataArr.find((m) => m.meta_key === key)?.meta_value ?? null
// segmentsList.push({
// sid: seg.get('sid'),
// source: seg.get('segment'),
// target: seg.get('translation'),
// context_url: seg.get('context_url') ?? null,
// resname: findMeta('resname'),
// restype: findMeta('restype'),
// })
// }
// ContextPreviewChannel.sendMessage({type: 'segments', segments: segmentsList})
// }, [segments])

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large commented-out logic in production code makes the intent unclear and is easy to let drift out-of-date. If this is intentionally deferred, prefer removing it and tracking via an issue/PR, or reintroduce it behind a feature flag/config so it stays executable and testable.

Suggested change
// const rawMetadata = seg.get('metadata')
// const metadataArr = rawMetadata
// ? typeof rawMetadata.toJS === 'function'
// ? rawMetadata.toJS()
// : rawMetadata
// : []
// const findMeta = (key) =>
// metadataArr.find((m) => m.meta_key === key)?.meta_value ?? null
// segmentsList.push({
// sid: seg.get('sid'),
// source: seg.get('segment'),
// target: seg.get('translation'),
// context_url: seg.get('context_url') ?? null,
// resname: findMeta('resname'),
// restype: findMeta('restype'),
// })
// }
// ContextPreviewChannel.sendMessage({type: 'segments', segments: segmentsList})
// }, [segments])

Copilot uses AI. Check for mistakes.
Comment on lines +96 to 98
const {placeholderRegex, decodeNeeded, encodedPlaceholder, regex, type} =
tagSignatures[key]
const shouldExcludeTag = excludeTags.some((value) => value === type)
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the destructured property from placeholder to encodedPlaceholder. If tagSignatures[...] entries still provide placeholder (and not encodedPlaceholder), the transform will stop substituting placeholders and will fall back to match. To make this robust, either update the tagSignatures definition consistently or support both keys (e.g., prefer encodedPlaceholder but fallback to placeholder).

Copilot uses AI. Check for mistakes.
!shouldExcludeTag
? (match) => {
return placeholder ? placeholder : match
return encodedPlaceholder ? encodedPlaceholder : match
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the destructured property from placeholder to encodedPlaceholder. If tagSignatures[...] entries still provide placeholder (and not encodedPlaceholder), the transform will stop substituting placeholders and will fall back to match. To make this robust, either update the tagSignatures definition consistently or support both keys (e.g., prefer encodedPlaceholder but fallback to placeholder).

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +23
public function __construct(
private mixed $segmentsList,
private readonly array $requestData,
) {
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The event exposes requestData as readonly with only a getter. In the previous hook usage (filter('rewriteContributionContexts', $segmentsList, $request)), plugins could influence both the segments list and the request context. With this design, plugins can only alter segmentsList (via a setter) but cannot update request data at all. If request mutation is still required, add setRequestData(array $requestData): void (and drop readonly) or clarify by removing the unused request reassignment at the call site.

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +37
public function getRequestData(): array
{
return $this->requestData;
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The event exposes requestData as readonly with only a getter. In the previous hook usage (filter('rewriteContributionContexts', $segmentsList, $request)), plugins could influence both the segments list and the request context. With this design, plugins can only alter segmentsList (via a setter) but cannot update request data at all. If request mutation is still required, add setRequestData(array $requestData): void (and drop readonly) or clarify by removing the unused request reassignment at the call site.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants