Jump to content

ICT:FinalConfig - AssetFileNormakizer extension

From Costa Sano MediaWiki
Revision as of 14:35, 18 February 2026 by Mngr (talk | contribs) (Created page with "= Final Configuration for Extension: AssetFileNormalizer = Document revision: {{#time:Y-m-d|{{REVISIONTIMESTAMP}}}} by {{REVISIONUSER}} This document defines the private MediaWiki extension '''AssetFileNormalizer'''. The extension enforces the archival invariant: <blockquote> '''One Asset = one File, both sharing the same immutable identifier.''' </blockquote> The extension is part of the Asset v2 architecture and must be considered normative infrastructure. Cate...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Final Configuration for Extension: AssetFileNormalizer

Document revision: 2026-02-18 by Mngr

This document defines the private MediaWiki extension AssetFileNormalizer.

The extension enforces the archival invariant:

One Asset = one File, both sharing the same immutable identifier.

The extension is part of the Asset v2 architecture and must be considered normative infrastructure.


1. Purpose and Scope

The AssetFileNormalizer extension automatically renames uploaded files associated with Asset pages so that:

  • The file name matches the Asset identifier
  • The original upload filename is removed
  • No redirect is created
  • No user intervention is required

This extension applies only to:

  • newly created Asset pages
  • files uploaded through the Asset form

It does not affect:

  • existing files
  • non-Asset pages
  • manual file moves

2. Design Principles

The extension is designed according to the following principles:

  • Minimal responsibility (one job only)
  • No dependency on Cargo internals
  • No dependency on Page Forms internals
  • Server-side authority (no JavaScript enforcement)
  • Upgrade-safe MediaWiki APIs
  • Non-blocking behavior on failure

The extension intentionally performs no validation of identifiers. It assumes that Asset v2 numbering logic has already produced a valid identifier.


3. Functional Behavior

3.1 Trigger

The extension runs when:

  • a page is saved
  • the page is newly created
  • the page is in the Asset namespace

3.2 Conditions

The extension proceeds only if:

  • the page contains a File field
  • the referenced file exists
  • the file name does not already match the Asset identifier

3.3 Action

If all conditions are met:

  • the file is moved to <AssetIdentifier>.<extension>
  • file history is preserved
  • redirect creation is suppressed

3.4 Failure Policy

If the file move fails:

  • the Asset page remains valid
  • the file remains under its original name
  • a debug log entry is written

The extension never blocks page saving.


4. Directory Structure

The extension is installed as a private extension under:

extensions/AssetFileNormalizer/
 ├─ extension.json
 └─ AssetFileNormalizer.php

5. Extension Registration

5.1 extension.json

{
  "name": "AssetFileNormalizer",
  "version": "1.0",
  "author": "Costa Sano Research",
  "description": "Automatically renames Asset files to match Asset identifiers",
  "type": "extension",
  "Hooks": {
    "PageSaveComplete": "AssetFileNormalizer::onPageSaveComplete"
  },
  "AutoloadClasses": {
    "AssetFileNormalizer": "AssetFileNormalizer.php"
  },
  "ManifestVersion": 2
}

6. Core Implementation

6.1 AssetFileNormalizer.php

<?php
use MediaWiki\MediaWikiServices;

class AssetFileNormalizer {

    public static function onPageSaveComplete(
        WikiPage $wikiPage,
        UserIdentity $user,
        string $summary,
        int $flags,
        RevisionRecord $revisionRecord,
        EditResult $editResult
    ) {
        $title = $wikiPage->getTitle();

        // Only Asset namespace (ID must match local configuration)
        if ( $title->getNamespace() !== 3014 ) {
            return;
        }

        // Only act on page creation
        if ( !$editResult->isNewPage() ) {
            return;
        }

        // Extract wikitext content
        $content = $revisionRecord->getContent( SlotRecord::MAIN );
        if ( !$content instanceof WikitextContent ) {
            return;
        }

        $text = $content->getText();

        // Extract File field
        if ( !preg_match( '/\|\s*File\s*=\s*(File:[^\|\n]+)/', $text, $m ) ) {
            return;
        }

        $fileTitle = Title::newFromText( trim( $m[1] ) );
        if ( !$fileTitle || !$fileTitle->inNamespace( NS_FILE ) ) {
            return;
        }

        $repo = MediaWikiServices::getInstance()
            ->getRepoGroup()
            ->getLocalRepo();

        $file = $repo->newFile( $fileTitle );
        if ( !$file->exists() ) {
            return;
        }

        // Compute target filename
        $assetCode = $title->getText();
        $extension = $file->getExtension();

        $targetTitle = Title::makeTitle(
            NS_FILE,
            $assetCode . '.' . $extension
        );

        // Already normalized
        if ( $fileTitle->equals( $targetTitle ) ) {
            return;
        }

        // Move file without redirect
        $status = $file->move(
            $targetTitle,
            'Automatic Asset file normalization',
            /* suppressRedirect */ true,
            $user
        );

        if ( !$status->isOK() ) {
            wfDebugLog(
                'AssetFileNormalizer',
                'File move failed for ' . $fileTitle->getPrefixedText()
            );
        }
    }
}

7. Enabling the Extension

Add the following line to LocalSettings.php:

wfLoadExtension( 'AssetFileNormalizer' );

Optionally, the extension may be wrapped in a feature flag for emergency disablement.


8. Security and Permissions

  • The file move is executed under the saving user context
  • Users creating Assets must have:
    • upload rights
    • movefile rights (or equivalent)
  • The extension does not escalate privileges

Deletion of Asset/File couples remains a sysop-only operation.


9. Relationship to Asset v2

This extension is a mandatory component of Asset v2.

Without it:

  • Asset creation still works
  • File upload still works
  • The archival invariant (name equality) is not enforced

With it:

  • Asset and File identity are strictly aligned
  • The Asset–File couple is sealed at creation time

10. Status

AssetFileNormalizer is complete and ready for deployment.

No database changes are required. No migration of existing files is performed.