azure-devops · Solcom-website · PR #164388
ASP → XML-Feeds (Freelancermap, Freelance.de)
feature/P2503-112→develop
Author: Philipps, Marc
4 Commits · 19 Files · +1372/-9 LOC
Build: succeeded
Findings: standards = 3 (1 hard, 2 judgement) · spec = 2 partials (P2503-165 AK3 Config-Name-Drift, freelancermap UTM = toter Code) · canvas-axis = inactive.
Worst: Test-Klassen unter tests/src/Functional/ erweitern KernelTestBase — PSR-4-Namespace-Drift, blockiert phpunit-Suite-Discovery.
Standards
Hard Violations
-
Hard
tests/src/Functional/LegacyRedirectSubscriberTest.php:5 +
tests/src/Functional/VendorFeedRouteTest.php:5 — Beide Klassen liegen physisch unter tests/src/Functional/ (PSR-4-Namespace \Functional) und deklarieren namespace Drupal\Tests\solcom_project_offer_feeds\Functional, erweitern aber KernelTestBase statt BrowserTestBase. Das drupal-testing/SKILL.md-Mapping ist explizit: Functional/ → BrowserTestBase. Kommentar im Code sagt "KernelTestBase HTTP harness" — Intent ist Kernel-Tests mit HTTP-Harness, aber das Verzeichnis ist falsch.
Fix: Beide Klassen nach tests/src/Kernel/ verschieben und Namespace auf Drupal\Tests\solcom_project_offer_feeds\Kernel anpassen.
Judgement Calls
-
Judge
VendorFeedBuilder.php:215 — $jobTitle = (string) ($offer->get('field_sf_job_title')->value ?? $offer->label() ?? ''). ADR-0032 Regel 2 (Migrate-Title-Pflicht) sagt: kein ID-Fallback. Wenn das Migrate-Modul ADR-0032-konform ist (skip_on_empty + SOQL-Filter), enthält label() nie eine SF-ID. Vertretbar — engere Defensive wäre field_sf_job_title ohne Fallback + Leer-Zeile im Feed statt Risiko eines SF-ID-Leaks.
-
Judge
templates/solcom-feed-freelancermap.html.twig:21-28 + templates/solcom-feed-freelance.html.twig:25-31 — |raw-Filter auf p.jobTitle, p.jobDescription, etc. Sicher, weil VendorFeedBuilder::stripTagsKeepBr() vorher nur <br /> behält und alles andere via strip_tags() entfernt. Kein Sicherheitsproblem — aber kein Twig-Kommentar erklärt die Kausalkette. Lesbarkeits-Schuld.
-
Judge
solcom_project_offer_feeds.routing.yml:7,16 — Beide Routen haben _access: 'TRUE'. Vendor-XML-Feeds sind Public-by-Design. Controller setzt X-Robots-Tag: noindex, nofollow. Kein Verstoß — aber eine Inline-Notiz zur Intentionalität (warum Public OK) würde Routine-Reviewer beruhigen.
Pass-Items
- Pass PHP-Architektur sauber:
VendorFeedBuilder nutzt vollständiges Constructor-Injection, VendorContext ist typsicheres Value-Object, Controller delegiert ohne Logik. Kein statisches \Drupal::service().
- Pass Caching korrekt:
CacheableResponse mit entity-Level Cache-Tags (node:X, node_list:project_offer) + url.site-Context.
- Pass ADR-0032 Outbound-Field-Binding eingehalten:
field_sf_application_url wird nicht direkt aus dem Node-Field gelesen; Minggo-URL wird programmatisch aus field_sf_id + Config-Workspace-ID gebaut.
Spec
Spec-Compliance (AK-Mapping)
- ✓ Story-AK1: Automatische Übergabe via XML-Feed —
VendorFeedBuilder::getEligibleOffers() filtert field_sf_pub_status='Online', status=1, Publish-Window — VendorFeedBuilder.php:47-66.
- ✓ Story-AK2: Kanal-individuelle Steuerung via
field_sf_channel_freelancermap / field_sf_channel_freelance — VendorFeedController.php:35,42.
- ✓ Story-AK3/4: Publish-Window + pub_status-Filter in
getEligibleOffers(); Feed verändert sich beim nächsten Poll — VendorFeedBuilder.php:52-62.
- ✓ Story-AK5:
jobDescriptionURL via entity.toUrl('canonical', ['absolute' => TRUE]) — VendorFeedBuilder.php:233.
- ✓ Story-AK6 UTM (freelance.de): Doppel-CDATA mit UTM-URL —
VendorFeedBuilder.php:240-245, solcom-feed-freelance.html.twig:30.
- ✓ P2503-167:
LegacyRedirectSubscriber mit LEGACY_REDIRECTS-Map — LegacyRedirectSubscriber.php:34-44.
- ✓ P2503-165 AK4/AK5: HTTP 200,
Content-Type: application/xml, X-Robots-Tag, alle 11 Pflicht-Kinder + CDATA-Wraps — VendorFeedController.php:53-59, solcom-feed-freelancermap.html.twig:22-34.
- ✓ P2503-165 AK6/AK7/AK8:
dd.mm.yyyy-Format, jobApplicationURL optional, jobDescriptionURL = canonical — VendorFeedBuilder.php:232-238,279-284.
- ✓ P2503-165 AK9: Cache-Tags
node_list:project_offer + node:<nid> — VendorFeedBuilder.php:146-148.
- ✓ P2503-165 AK10: Empty-Feed → HTTP 200 mit
<openPositions/>.
- ✓ P2503-165 AK11/12: Kernel-Test (7 Fixtures: happy, status=0, pub_status≠Online, channel=FALSE, publish_start Zukunft, publish_end Vergangenheit, mixed) + Functional-Test.
- ✓ P2503-166 AK3: jobNumber-Suffix '-298' konfigurierbar —
VendorFeedBuilder.php:171, settings.yml:9.
- ✓ P2503-166 AK4: Doppel-CDATA in
<jobDescriptionURL> — solcom-feed-freelance.html.twig:30.
- ✓ P2503-166 AK5: Config-Schema für
feeds.freelance.job_number_suffix + feeds.freelance.utm — schema.yml:32-47.
- ✓ P2503-167 AK3/AK4: Subscriber greift nur für die zwei exakten Pfade, Map als Klassen-Konstante (kein
match()-Duplikat) — LegacyRedirectSubscriber.php:34-44.
Spec-Gaps (partial / Drift)
-
Drift
P2503-165 AK3 (partial): Sub-Task-AK fordert wörtlich, dass
config/install/solcom_project_offer.settings.yml (Parent-Modul) um Sektion feeds: erweitert wird. Tatsächlich liefert das Sub-Modul eine eigenständige solcom_project_offer_feeds.settings.yml. Funktionell konsistenter (saubere Config-Objekt-Grenze pro Sub-Modul), aber AK-Wortlaut weicht ab. Follow-up: Sub-Task-AK in Jira auf "eigene solcom_project_offer_feeds.settings.yml" korrigieren.
-
Toter Code
freelancermap UTM:
feeds.freelancermap.utm existiert in settings.yml + Schema, wird in VendorContext::utmParamsFromConfig gebaut, aber Freelancermap-Twig rendert keinen UTM-URL-Tag. Spec-konform (P2503-165 fordert kein UTM für Freelancermap), aber UTM-Config ist toter Code. Aufräum-Kandidat oder Schema-Entfernung.
Scope Creep (im Diff, nicht in Spec)
-
Scope
scripts/prompts/implement-prompt.md, merge-prompt.md, review-prompt.md + .hooks/pre-commit — Ralph-Loop-Prompt-Engineering und pre-commit-Hook-Änderungen. Nichts davon gehört zu F-340. Erhöht Review-Rauschen, aber unkritisch. Note: in einem sauberen PR-Flow als separater Infrastruktur-Commit auf eigenen Branch.
Sub-Task-Status
- P2503-165 Vollständig implementiert. Kleiner Formalia-Drift bei AK3 (Config-Name).
- P2503-166 Vollständig implementiert.
- P2503-167 Vollständig implementiert (incl. out-of-scope-Guard für
detail.aspx).
Empfohlene Korrekturen (Post-Merge)
- Blocker (Follow-up) Test-Verzeichnis-Drift fixen:
LegacyRedirectSubscriberTest.php + VendorFeedRouteTest.php nach tests/src/Kernel/ verschieben, Namespace anpassen. Sub-Task-Ticket im selben Sprint einplanen.
- Note P2503-165 AK3 in Jira an die Implementierung anpassen (eigene Settings-Datei statt Parent-Erweiterung).
- Note Freelancermap-UTM-Config: entweder im Twig nutzen oder aus Schema entfernen.
- Note Twig-Kommentar bei
|raw ergänzen ("safe weil stripTagsKeepBr").
- Note Routing-Kommentar zu
_access: 'TRUE' ergänzen (Public-by-Design + X-Robots-Tag).
- Note Scope-Creep-Files (Ralph-Prompts, pre-commit) in nächstem PR als separater Commit aufräumen.