Skip to content

Commit fb83413

Browse files
committed
Fix Tracker::remove not actually removing
1 parent 6754967 commit fb83413

File tree

4 files changed

+101
-1
lines changed

4 files changed

+101
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ mix-manifest.json
77
package-lock.json
88
yarn.lock
99
.idea/*
10+
.claude/*

CLAUDE.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Commands
6+
7+
```bash
8+
# Run all tests
9+
vendor/bin/pest
10+
11+
# Run a single test file
12+
vendor/bin/pest tests/Unit/TrackerTest.php
13+
14+
# Run a specific test by name
15+
vendor/bin/pest --filter "test name"
16+
17+
# Lint (Laravel Pint)
18+
vendor/bin/pint
19+
20+
# Build CP assets
21+
npm run build
22+
23+
# Dev CP assets
24+
npm run dev
25+
```
26+
27+
## Architecture
28+
29+
This is a Statamic addon (`thoughtco/statamic-cache-tracker`) that tracks which content items are rendered on each page, then automatically clears those pages from the static cache when content is updated.
30+
31+
### Core Flow
32+
33+
1. **Tracking**`Http/Middleware/CacheTracker` runs on every GET request. It hooks into Statamic's augmentation lifecycle (via `Asset::hook`, `Entry::hook`, `LocalizedTerm::hook`, etc.) to collect "tags" for each content item rendered during the request. After a successful response, it stores a `URL → [tags]` mapping in cache.
34+
35+
2. **Invalidation**`Listeners/Subscriber` subscribes to Statamic save/delete events (entries, assets, terms, navs, forms, globals). When content changes, it dispatches `Jobs/InvalidateTags` which calls `Tracker::invalidate($tags)` to find all URLs containing those tags and clear them from the static cache.
36+
37+
3. **Tag format** — Tags follow patterns like `asset:{id}`, `collection:{handle}:{id}`, `term:{id}`, `form:{handle}`, `nav:{handle}`, `global:{handle}`. Wildcard matching is supported via `*` prefix notation (e.g., `collection:blog:*`).
38+
39+
### Key Classes
40+
41+
- **`Tracker/Manager`** — Core logic. Stores `URL → tags[]` in cache under key `tracker::urls`. Handles `add`, `get`, `invalidate`, and `flush`. Tag matching supports wildcards.
42+
- **`Http/Middleware/CacheTracker`** — Hooks into Statamic augmentation to collect tags during rendering. Also fires `TrackContentTags` event for custom integrations.
43+
- **`Listeners/Subscriber`** — Maps Statamic events to tag generation and queues invalidation.
44+
- **`Facades/Tracker`** — Facade for `Manager` (bound as `cache-tracker`).
45+
46+
### Extending
47+
48+
Custom tag sources can be registered via `Tracker::addAdditionalTracker()`, which accepts a closure or class with an `__invoke(Request $request, array &$tags)` signature and runs in a pipeline.
49+
50+
The `TrackContentTags` event can be fired from custom code to inject additional tags into the current request's tracking.
51+
52+
### CP Features
53+
54+
- **Utility** — "Cache Tracker" utility in the CP for manually clearing URLs or wildcards.
55+
- **Bulk Actions** — "View Cache Tags" and "Clear Cache" actions available on entry/term listings.
56+
- **Permissions**`view cache tracker tags` and `clear cache tracker tags`.
57+
58+
### Testing Notes
59+
60+
Tests use Pest with an `AddonTestCase` base that:
61+
- Enables static caching with `half` strategy
62+
- Creates a default `pages` collection with a `home` entry
63+
- Disables stache disk writes
64+
- Uses SQLite in-memory database
65+
66+
Fixture views live in `tests/__fixtures__/resources/views/`.

src/Tracker/Manager.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ public function remove(string $url)
135135
{
136136
$this->invalidateUrls([$url]);
137137

138-
$this->cacheStore()->forget(md5($url));
138+
$storeData = $this->all();
139+
unset($storeData[md5($url)]);
140+
$this->cacheStore()->forever($this->cacheKey, $storeData);
139141
}
140142
}

tests/Unit/TrackerTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,37 @@ public function it_flushes()
9292
Event::assertDispatched(UrlInvalidated::class);
9393
}
9494

95+
#[Test]
96+
public function it_removes_a_url()
97+
{
98+
Tracker::add('/page1', ['products:1']);
99+
Tracker::add('/page2', ['products:2']);
100+
101+
$this->assertCount(2, Tracker::all());
102+
103+
Tracker::remove('/page1');
104+
105+
$this->assertCount(1, Tracker::all());
106+
$this->assertNull(Tracker::get('/page1'));
107+
$this->assertNotNull(Tracker::get('/page2'));
108+
}
109+
110+
#[Test]
111+
public function it_removes_a_url_and_does_not_retrack_on_next_visit()
112+
{
113+
$this->get('/');
114+
115+
$this->assertCount(1, Tracker::all());
116+
117+
Tracker::remove(collect(Tracker::all())->first()['url']);
118+
119+
$this->assertCount(0, Tracker::all());
120+
121+
$this->get('/');
122+
123+
$this->assertCount(1, Tracker::all());
124+
}
125+
95126
#[Test]
96127
public function it_invalidates_by_exact_tag_match()
97128
{

0 commit comments

Comments
 (0)