Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions resources/boost/skills/crud-redirects/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
name: CRUD Redirects and Query Strings
description: The ability to CRUD redirects and query strings within the Alt Redirect addon.
---

### Domain Description
The Alt Redirect addon provides a flexible way to manage redirects and query strings in Statamic. It supports both file-based and database-based storage via a repository pattern.

### Key Components
- `AltDesign\AltRedirect\Contracts\RepositoryInterface`: The primary interface for data operations.
- `AltDesign\AltRedirect\Repositories\RepositoryManager`: Handles driver resolution.

### Basic CRUD Operations
You can perform operations on two types: `redirects` and `query-strings`.

#### Injecting the Repository
The `RepositoryInterface` is automatically bound to the active driver. You can inject it into your classes:

```php
use AltDesign\AltRedirect\Contracts\RepositoryInterface;

public function __construct(protected RepositoryInterface $repository)
{
}
```

#### Fetching All Data
To get all redirects or query strings:

```php
$redirects = $this->repository->all('redirects');
$queryStrings = $this->repository->all('query-strings');
```

#### Finding a Specific Item
To find a redirect by its `from` path:

```php
$redirect = $this->repository->find('redirects', 'from', '/old-url');
```

To find a query string by its key:

```php
$queryString = $this->repository->find('query-strings', 'query_string', 'utm_source');
```

#### Creating or Updating
To save data, pass the type and an array containing the item data.
**IMPORTANT:** Always provide an `id` (e.g., using `uniqid()`) when creating new items to ensure compatibility across all storage drivers and to allow for future updates.

**Redirect Example:**
```php
$this->repository->save('redirects', [
'id' => uniqid(),
'from' => '/example-from',
'to' => '/example-to',
'redirect_type' => '301',
'sites' => ['default']
]);
```

**Query String Example:**
```php
$this->repository->save('query-strings', [
'id' => uniqid(),
'query_string' => 'new_param',
'strip' => true,
'sites' => ['default']
]);
```

#### Deleting
To delete an item, pass the type and an array containing at least the `id`, `from`, or `query_string` key.

```php
// Delete redirect by ID
$this->repository->delete('redirects', ['id' => '69d767de74f05']);
Comment on lines +77 to +78

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The FileRepository::delete() method silently fails to delete non-regex redirects when only an id is provided, as it only searches the directory for regex redirects.
Severity: MEDIUM

Suggested Fix

Update the FileRepository::delete() method to correctly handle the deletion of non-regex redirects by id. This may require a lookup mechanism to find the redirect's from value based on its id to construct the correct file path, or searching all possible storage locations. The documentation should also be clarified to reflect the repository's behavior.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: resources/boost/skills/crud-redirects/SKILL.md#L77-L78

Potential issue: When using the `FileRepository` driver, attempting to delete a
non-regex redirect by providing only its `id` will silently fail. The `delete()`
method's logic for handling deletions by `id` exclusively checks the directory
designated for regex redirects (`content/alt-redirect/alt-regex/`). Non-regex redirects
are stored elsewhere, with filenames based on a hash of their `from` value.
Consequently, the file is never found and deleted, leading to orphaned redirect records.
This issue is likely to occur as the `SKILL.md` documentation explicitly provides an
example of deleting a redirect using only its `id`.


// Delete redirect by path
$this->repository->delete('redirects', ['from' => '/example-from']);

// Delete query string by name
$this->repository->delete('query-strings', ['query_string' => 'new_param']);
```

### Advanced Operations
#### Regex Redirects
To get only the redirects that are intended for regex matching (often those containing regex patterns in the `from` field):

```php
$regexRedirects = $this->repository->getRegex('redirects');
```

#### Bulk Saving
To save multiple items at once:

```php
$this->repository->saveAll('redirects', [
['from' => '/a', 'to' => '/b', 'redirect_type' => '301', 'sites' => ['default']],
['from' => '/c', 'to' => '/d', 'redirect_type' => '302', 'sites' => ['default']],
]);
```
Comment on lines +99 to +103

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Calling saveAll() with a regex redirect that lacks an id causes a fatal error in FileRepository due to an attempt to access the undefined id key.
Severity: HIGH

Suggested Fix

In FileRepository::save(), before attempting to use $data['id'] for a regex redirect, check if it exists. If it is not set, generate a unique ID, similar to how DatabaseRepository handles missing IDs. This will prevent the crash when users follow the saveAll() documentation.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: resources/boost/skills/crud-redirects/SKILL.md#L99-L103

Potential issue: When using the `FileRepository` driver, calling `saveAll()` with an
array of redirects that includes a regex-based redirect without an `id` key will cause a
fatal error. The `saveAll()` method iterates and calls `save()` for each item. Inside
`save()`, if `URISupport::isRegex()` identifies the `from` value as a regular
expression, the code attempts to access `$data['id']` to construct the file path. Since
the `id` is not provided, this results in an `Undefined array key "id"` error, crashing
the process. This scenario is likely as the `SKILL.md` documentation for `saveAll()`
explicitly shows an example where `id` keys are omitted.


### Verifying Operations
After creating or modifying a redirect, you can verify it in several ways:

#### 1. Direct Storage Check
- **File Driver**: Check for a YAML file in `content/alt-redirect/`. The filename is typically a hash of the `from` URL or its base64 encoding.
- **Database Driver**: Use a database tool to query the `alt_redirects` or `alt_query_strings` tables.

#### 2. Using CURL
You can test if the redirect is working by making a request to the `from` path:
```bash
curl -I http://your-site.test/old-url
```
A successful redirect should return a `301 Moved Permanently` or `302 Found` status with a `Location` header pointing to the new URL.

#### 3. Repository Check
You can also use the repository's `find` or `all` methods in a test or via Tinker to confirm the data was saved correctly.

### Site Configuration
Redirects and query strings are site-specific. You must provide a list of site handles in the `sites` array.

#### Obtaining Site List
To get the list of available site handles in the current Statamic installation, you can use Tinker:
```php
php artisan tinker --execute="print_r(Statamic\Facades\Site::all()->map->handle()->toArray())"
```
Or within your code:
```php
use Statamic\Facades\Site;
$siteHandles = Site::all()->map->handle()->all();
```

### Implementation Details
- **File Driver**: Stores data as YAML files in `content/alt-redirect/`.
- **Database Driver**: Uses `alt_redirects` and `alt_query_strings` tables.
- **Multisite**: Both types include a `sites` array which should contain the handles of the Statamic sites where the redirect or query string rule applies.
Loading