Skip to content

[3.x] Support pages with more output file extensions (Remove overengineered code)#2547

Merged
emmadesilva merged 5 commits into
v3/non-html-pagesfrom
v3/non-html-pages-code-simplifications
Jul 14, 2026
Merged

[3.x] Support pages with more output file extensions (Remove overengineered code)#2547
emmadesilva merged 5 commits into
v3/non-html-pagesfrom
v3/non-html-pages-code-simplifications

Conversation

@emmadesilva

@emmadesilva emmadesilva commented Jul 14, 2026

Copy link
Copy Markdown
Member

1. The 4 InMemoryPage subclasses are YAGNI

The Epic explicitly states that the decision to use a thin subclass (SitemapPage extends InMemoryPage) instead of a plain InMemoryPage with a closure was made because the commands needed a concrete class to instantiate for the fallback: "must fall back to a fresh instance when the route is not registered".

However, the review notes state this fallback was removed: "an initial implementation fell back to a fresh page instance... the commands now fail with a generic error when the route is not registered".

Because the commands no longer instantiate the fallback, the sole justification for these subclasses is gone. We can delete SitemapPage, RssFeedPage, RobotsTxtPage, and LlmsTxtPage, and just register them as plain InMemoryPage instances with a bound closure/macro as originally proposed.

2. Overzealous config validation in RobotsTxtGenerator

if (! is_string($rule)) {
    throw new InvalidConfigurationException(...)
}

Throwing a hard exception if a user provides a non-string in the hyde.robots.disallow array (like 123 or 3.14) is overengineering. Just let PHP implicitly cast integers/floats to strings when building the output line, or cast it yourself with (string). We don't need a custom exception path for this.

3. Repeated runtime validation on static properties

public static function outputExtension(): string
{
    $extension = static::$outputExtension;
    if (! str_starts_with($extension, '.') || str_contains($extension, '/') || str_contains($extension, '\\')) {
        throw new InvalidArgumentException(...);
    }
    return $extension;
}

This validation runs on every single call (which happens constantly via RouteKey::fromPage). Validating a developer-defined static string property for slashes/dots at runtime on every route resolution is unnecessary overhead. If a developer sets a bad extension, the resulting file will just look weird or fail at the OS level. Drop the validation block entirely.

4. Reflection-based legacy guards on every boot

protected static function guardAgainstLegacyFileExtensionApi(string $pageClass): void
{
    if (property_exists($pageClass, 'fileExtension') || method_exists($pageClass, 'fileExtension') || method_exists($pageClass, 'setFileExtension')) {
        throw new RuntimeException(...);
    }
}

Running property_exists and two method_exists checks on every registered page class on every single boot just to catch users who haven't updated a V2 API is overengineering. We already documented this in UPGRADE.md and explicitly noted that a Rector script will handle the migration. Remove the runtime guard.

@emmadesilva
emmadesilva force-pushed the v3/non-html-pages-code-simplifications branch 2 times, most recently from 79bb0a8 to 7e4deb8 Compare July 14, 2026 22:17
@emmadesilva
emmadesilva force-pushed the v3/non-html-pages-code-simplifications branch from 7e4deb8 to 840324c Compare July 14, 2026 22:18
@emmadesilva
emmadesilva merged commit 9486d97 into v3/non-html-pages Jul 14, 2026
6 checks passed
@emmadesilva
emmadesilva deleted the v3/non-html-pages-code-simplifications branch July 14, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant