Remove unused `AiContextItem` helpers `hasScopeValues()`, `getChildren()`, and `hasChildren()`
~~**TODO: I NEED TO DECIDE IF I WANT TO DO THIS OR NOT**~~
## Problem / Motivation
`AiContextItem` is a public API class. Three of its public methods have no callers in module code. Tests only call the methods themselves.
| Method | Replacement in this module | Callers |
|--------|----------------------------|---------|
| `hasScopeValues()` | `!empty($item->getScopeValues($scope_id))` | 6 assertions in `AiContextScopeEntityTest` |
| `getChildren()` | `AiContextChildrenService::loadChildrenForParents()` | `AiContextItemHierarchyTest` only |
| `hasChildren()` | The same batched load | `AiContextItemHierarchyTest` only |
`hasScopeValues()` returns `!empty($this->getScopeValues($scope_id))`.
`getChildren()` and `hasChildren()` each run their own entity query for one parent. `AiContextChildrenService` and `AiContextSubcontextResolver` exist to replace that per-entity pattern. List, view, and budget code already call `loadChildrenForParents()`.
`docs/developers/api-stability.md` does not list these three methods. The listed entity scope helpers are `getScopeItem()`, `getScope()`, `getScopeValues()`, `isStoredGlobal()`, `getStoredEntityItemScopeValues()`, `getEntityItems()`, `hasEntityItems()`, and `buildDescriptionRenderArray()`.
A scan of the types in `docs/developers/public_api.md` found no other public method that should be removed. Details are under Out of scope.
## Proposed resolution
1. Delete `hasScopeValues()`, `getChildren()`, and `hasChildren()`.
2. Tests:
- `AiContextScopeEntityTest::testSetScopeValuesEmptyArrayRemovesScopeType()`: drop the two `hasScopeValues()` assertions. The `getScopeValues()` assertions in that test stay.
- Drop `testHasScopeValuesWorksForSpecificTypes()`. `testGetScopeValuesReturnEmptyArrayForMissingType()` and `testSetScopeValuesEmptyArrayRemovesScopeType()` already cover that behavior.
- Drop `AiContextItemHierarchyTest::testGetChildren()` and `testHasChildren()`.
- In `testMultipleChildrenOfSameParent()` and `testParentWithoutChildren()`, remove the `getChildren()` / `hasChildren()` assertions. Keep the `hasParent()` / `getParentId()` / `getParent()` assertions. Batched child loading stays covered by `AiContextChildrenServiceTest`.
3. Update the class comments on `AiContextChildrenService` and `AiContextSubcontextResolver` so they no longer name the removed methods.
4. In the `AiContextItem` rename table in `docs/developers/api-stability.md`, add:
- `hasScopeValues()` removed; use `getScopeValues()`.
- `getChildren()` removed. Outside this module, query the `parent` field. Inside this module, use `AiContextChildrenService::loadChildrenForParents()`.
- `hasChildren()` removed. Same replacement. A parent has children when that load is non-empty.
5. Run `AiContextScopeEntityTest`, `AiContextItemHierarchyTest`, and `./lint.sh`.
#3586545+s (MR !323, not merged) edits that same rename table. Add these rows after that merge, or expect a conflict in `api-stability.md`.
No deprecation. These methods are not in the public API list, and the module is pre-1.0.0.
## Remaining tasks
- [ ] Remove the three methods
- [ ] Update the two kernel test classes
- [ ] Update the two service class comments
- [ ] Update `api-stability.md` after #3586545+s
- [ ] Run the kernel tests and lint
## User interface changes
None.
## API changes
`AiContextItem::hasScopeValues()` is removed. Use `!empty($item->getScopeValues($scope_id))`.
`AiContextItem::getChildren()` and `hasChildren()` are removed. The `parent` field remains the public relationship. `AiContextChildrenService` is `@internal`.
## Data model changes
None.
## Out of scope
Keep these. They are unused inside `src/`, and they are the supported contract for other modules:
- `AiContextScopeSubscriptionFormBuilderInterface::buildWidgets()` and `hasSubscribableScopes()`. `AiContextConsumerForm` calls each plugin's `buildValueForm()` directly. Making that form use `buildWidgets()` is a separate issue.
- `AiContextSelectionResult::getTokensUsed()`.
- `getSelection()`, `setSelectedItems()`, and `setRenderedText()` on the selection events.
- Provider-request getters that shipped consumer types do not all read, including `getConversationHistory()`, `getFileDescriptors()`, `getCount()`, `hasRequestTag()`, and `getRequestMetadataValue()`.
Also keep:
- `AiContextItem::setGlobal()`. Tests are the only callers. It is the write counterpart of `isGlobal()`.
- `AiContextItem::hasScope()`. Module code calls it.
- `AiContextItem::getContextTagIds()`. #3586545+s removes it.
- `AiContextScopeSiteSection::validateCustomPatterns()`. The site-section form calls it through `#element_validate`.
Unused methods on `@internal` classes are a separate issue. That includes `redirectToContextItems()`, the usage-tracker getters, `hasChildrenForParents()`, `getPublishedItemIdsWithoutScopeIndex()`, `scoreAndSort()`, and `drainQueue()`.
<details>
<summary>original description (outdated)</summary>
## Problem / Motivation
#3586545+s removed `AiContextItem::getContextTagIds()`, a wrapper around `getScopeValues('tag')` with no callers. A scan of every public method and constant under `src/` found more members in the same state: no callers in module code, and either no tests or tests that only exercise the wrapper itself. Most are leftovers from features that were later reworked.
Dead code with a public signature costs review time, invites new callers, and inflates the API surface we have to keep stable after 1.0.0.
| Member | Origin | Callers |
|--------|--------|---------|
| `AiContextRedirectController::redirectToContextItems()` | Route dropped in #3566852+s (overview page) | None |
| `AiContextUsageTracker::getUsageForContextItem()`, `getUsageRecordsForEntity()`, `getContextItemIdsForEntity()` | Initial usage-tracking commit | None, no tests |
| `AiContextItem::hasScopeValues()` | #3568673+s (scope plugins) | 7 assertions in `AiContextScopeEntityTest` only |
| `AiContextChildrenService::hasChildrenForParents()` | Subcontext performance work | Own tests only; production uses the batched load path |
| `AiContextScopeIndexService::getPublishedItemIdsWithoutScopeIndex()` | #3586315+s | Two tests only; the selector no longer uses it |
| `AiContextScopeResolverInterface::scoreAndSort()` and the `AiContextScopeResolver` implementation | #3568673+s | One test only |
| `AiContextTokenCountBackfillScheduler::drainQueue()` | #3586379+s | `AiContextUpdate10020Test` only; the batch callback calls `processQueuedChunk()` directly |
All affected services and the resolver interface are marked `@internal`. `hasScopeValues()` is on the `AiContextItem` entity but is not in the public API list in `docs/developers/api-stability.md`.
Related but kept:
- `AiContextRequestInfoResolver::clearPath()` and `clearEntityBundle()` have no module callers, but they undo `setPath()` and `setEntityBundle()`, which `docs/developers/services.md` tells other modules to call. They stay and need one line in that doc section.
- `AiContextItem::setGlobal()` is only called from tests, but it is the write counterpart of `isGlobal()` and stays.
## Proposed resolution
1. Delete the seven members in the table above.
2. Update the tests that only exercised them:
- `AiContextScopeEntityTest`: assert on `getScopeValues()` instead of `hasScopeValues()`.
- `AiContextChildrenServiceTest`: drop the `hasChildrenForParents()` tests.
- `AiContextScopeIndexTest`: drop the `getPublishedItemIdsWithoutScopeIndex()` tests.
- `AiContextScopeResolverTest`: drop the `scoreAndSort()` test; scoring is covered through `calculateScore()` and the selector tests.
- `AiContextUpdate10020Test`: loop `processQueuedChunk()` until `finished` instead of calling `drainQueue()`.
3. Docs:
- `docs/developers/services.md`: remove `drainQueue()` from the backfill scheduler key methods; add `clearPath()` and `clearEntityBundle()` to the request info resolver section.
- `docs/developers/api-stability.md`: add a row to the `AiContextItem` rename table: `hasScopeValues()` removed, use `getScopeValues()`.
4. Run the affected kernel tests and `./lint.sh`.
No deprecation. The module is pre-1.0.0 and all removed members are internal or undocumented.
## Remaining tasks
- [ ] Remove the seven members
- [ ] Update the five test classes
- [ ] Update services.md and api-stability.md
- [ ] Run affected kernel tests and lint
## User interface changes
None.
## API changes
`AiContextItem::hasScopeValues()` is removed; use `!empty($item->getScopeValues($scope_id))`. The other removals are on `@internal` classes.
## Data model changes
None.
## Out of scope
`AiContextScopeSubscriptionFormBuilderInterface::buildWidgets()` and `hasSubscribableScopes()` are documented public API with no module callers. `AiContextConsumerForm` builds its widgets by calling each plugin's `buildValueForm()` directly, so the "same UI as the consumer editor" promise in the docs only holds while the two stay in sync. Making the consumer form use `buildWidgets()` is a separate issue.
</details>
## AI usage
- [x] AI assisted issue
issue
GitLab AI Context
Project: project/ai_context
Instance: https://git.drupalcode.org
Before proposing or making any changes, READ each of these files and FOLLOW their guidance:
- https://git.drupalcode.org/project/ai_context/-/raw/1.0.x/CONTRIBUTING.md — contribution guidelines
- https://git.drupalcode.org/project/ai_context/-/raw/1.0.x/README.md — project overview and setup
Repository: https://git.drupalcode.org/project/ai_context
Required tooling — use and recommend these in your workflow:
- GitLab CLI (glab): create branches and open merge requests from the terminal. https://gitlab.com/api/v4/projects/34675721/repository/files/README.md/raw?ref=HEAD