CCC: Refactor to convert entity HTML helpers to data-only methods and render arrays
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3574908. --> Reported by: [kristen pol](https://www.drupal.org/user/8389) Related to !85 >>> <p>[Tracker]<br> <strong>Update Summary: </strong>[One-line status update for stakeholders]<br> <strong>Check-in Date: </strong>MM/DD/YYYY<br> <strong>Blocked by: </strong>[#XXXXXX] (New issues on new lines)<br> <strong>Additional Collaborators: </strong> @username1, @username2<br> <em>Metadata is used by the <a href="https://www.drupalstarforge.ai/" title="AI Tracker">AI Tracker.</a> Docs and additional fields <a href="https://www.drupalstarforge.ai/ai-dashboard/docs" title="AI Issue Tracker Documentation">here</a>.</em><br> [/Tracker]</p> <h3 id="summary-problem-motivation">Problem/Motivation</h3> <p>Follow-up to:</p> <p><span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/ai_context/issues/3573713" title="Status: Closed (fixed)">#3573713: Full architecture review of CCC in prep for 1.0</a></span></p> <p><strong>Summary / goal</strong></p> <p>Refactor entity presentation helpers (getTargetMarkup(), getDescriptionMarkup()) so they return data structures or render arrays instead of raw HTML strings; move markup generation into templates/preprocess or controllers. This improves testability, escaping, theming, and caching.</p> <p><strong>Why this matters</strong></p> <p>Entities returning HTML mix presentation with domain logic, increase XSS/escaping risk, and make unit assertions brittle. Render arrays integrate with Drupal&rsquo;s cache metadata system and are easier to test and theme.</p> <p><strong>Acceptance criteria (measurable)</strong></p> <ul> <li>AiContextItem no longer exposes HTML-returning methods. New API: `getTargetData()` / `getDescriptionSummary()` for data consumers, `buildTargetRenderArray()` / `buildDescriptionRenderArray()` for display. Render arrays include proper `#cache` metadata.</li> <li>ai_context_preprocess_views_view_field() and any callers consume the new data and render via templates or #markup built in preprocess, preserving visual output.</li> <li>All existing Views outputs remain visually equivalent (pixel-tolerant), and unit tests assert data shape rather than raw HTML fragments.</li> <li>No unescaped HTML is returned from entity methods; automated linter/static checks pass.</li> </ul> <h3 id="summary-proposed-resolution">Proposed resolution</h3> <p><strong>Files to change</strong></p> <ul> <li>src/Entity/AiContextItem.php &mdash; replace getTargetMarkup(), getDescriptionMarkup() implementations</li> <li>ai_context.module &mdash; ai_context_preprocess_views_view_field() and any other hooks that call those helpers</li> <li>Twig templates or preprocess functions where the HTML will be assembled/rendered (templates in module/theme)</li> </ul> <p><strong>Recommended implementation approach</strong></p> <ol> <li>Change getTargetMarkup() &rarr; getTargetData() returning array of items: [{ label, url?, type_label? }...] or a render array (preferred).</li> <li>Change getDescriptionMarkup() &rarr; getDescriptionSummary() returning { full_text, truncated, title } or a render array with #plain_text.</li> <li>Update preprocess and Views field handlers to build the final markup from the data or to render the provided render array directly. Add #cache metadata when returning a render array.</li> <li>&gt; Remove the old HTML-returning methods (`getTargetMarkup()`, `getDescriptionMarkup()`) once all internal callers are migrated to the new data or render array methods.</li> </ol> <p><strong>Subtasks</strong></p> <ul> <li>Extract data-returning versions of the helpers and unit-test their return shapes.</li> <li>Update preprocess/views code to consume new shapes and produce identical output.</li> <li>Replace direct HTML-return uses across codebase and remove the old methods.</li> <li>Add tests asserting data formats and that Views render output remains acceptable.</li> <li>Add cache metadata to render arrays where appropriate.</li> </ul> <p><strong>Testing strategy</strong></p> <ul> <li>Unit tests for new getTargetData() and getDescriptionSummary() to verify output shapes and truncation logic.</li> <li>Kernel/functional test to render the ai_context_items view and assert expected textual content (not raw HTML exactness).</li> <li>Security check ensuring no unescaped HTML flows from entity methods.</li> </ul> <p><strong>Risks &amp; mitigations</strong></p> <ul> <li>Risk: Visual regression in Views/UI. Mitigate by snapshotting before/after in functional tests and doing small manual QA of admin list.</li> <li>Risk: Missed callers still expecting HTML strings. Mitigate by running a grep to confirm all uses are updated before removing the old methods.</li> </ul> <h3 id="summary-remaining-tasks">Target date or deadline</h3> <p>March 2026</p> <h3 id="summary-remaining-tasks">Remaining tasks</h3> <ul> <li>Review AI findings</li> <li>Decide if they are correct</li> <li>Decide if the proposed approach is best or propose alternative</li> <li>Update code</li> <li>Review and test</li> </ul> <h3 id="summary-ai-usage">AI usage (if applicable)</h3> <p>[ ] AI Assisted Issue<br> This issue was generated with AI assistance, but was reviewed and refined by the creator.</p> <p>[ ] AI Assisted Code<br> This code was mainly generated by a human, with AI autocompleting or parts AI generated, but under full human supervision.</p> <p>[ ] AI Generated Code<br> This code was mainly generated by an AI with human guidance, and reviewed, tested, and refined by a human.</p> <p>[ ] Vibe Coded<br> This code was generated by an AI and has only been functionally tested.</p> > Related issue: [Issue #3573713](https://www.drupal.org/node/3573713)
issue