anomaly/local_storage_adapter-extension
An extension for the Anomaly Local Storage Adapter that adds extra driver capabilities and configuration options for Laravel-based Streams applications, making it easier to manage local filesystem disks and storage behavior.
This is a PyroCMS 3 / Streams Platform addon, not a standalone Laravel package. It registers a local storage adapter so the Files module can back a disk with a directory on the server. There is no ServiceProvider you wire up by hand — installation is managed by the Streams addon system.
Minimal steps:
Install into the same project as the anomaly/files-module:
composer require anomaly/local_storage_adapter-extension
Check composer.lock immediately — this addon was last released in 2015 and expects Flysystem 1.x / PHP 5.6–7.x. On modern Laravel/Flysystem 3 it will fail dependency resolution. Do not force-install it; if it resolves you are on an old PyroCMS 3.x stack.
Register the addon:
php artisan addon:install anomaly.local_storage_adapter-extension
(or Addons → Local Storage Adapter → Install in the control panel). This runs the addon's migrations and registers the adapter extension.
Verify the extension is present — it should appear as an available Adapter when creating a disk (Files → Disks → Create, "Adapter" dropdown shows "Local").
First real use case: create a disk in the UI pointing at storage/app/files (or public/uploads), save it, then upload a file through Files → Files. If the upload lands on disk and file($entry)->url() returns a working URL, the addon is doing its job.
Where to look first in the codebase: the addon's src/LocalStorageAdapterExtension.php (or similarly named extension class) plus its resources/config/ and resources/lang/. The important contract is the Adapter extension type from the Files module — the class returns a Flysystem League\Flysystem\Adapter\Local instance and a display name. Everything else (paths, URLs, permissions) is delegated to Flysystem and the Files module.
Configure disks, not code. The intended workflow is entirely control-panel driven. Each disk record stores a driver/adapter handle plus an options array (path, permissions, etc.) that the extension passes to new Local($path, $writeFlags, $linkHandling, $permissions). Create one disk for app storage (private) and one for public assets if you serve media directly.
Reference the disk by slug from your own code. Once a disk exists, use the Files module API rather than Flysystem directly, so file records stay in the database:
// Resolve a disk by slug and write through the Files module
$disk = app(\Anomaly\FilesModule\Disk\Contract\DiskRepositoryInterface::class)
->findBySlug('local');
$file = $files->disk('local')->put('invoices/2024/acme.pdf', $contents);
Keeping writes inside the module means you get File entries, thumbnails, and field-type integration for free.
Programmatic disk creation in a seeder/migration. For reproducible deploys, don't click — seed the disk record so staging and production match:
DiskModel::create([
'name' => 'Local Files',
'slug' => 'local',
'adapter' => 'anomaly.extension.local_storage_adapter',
'options' => ['path' => base_path('storage/app/files')],
]);
Use it as a plain Flysystem adapter in tests. The class is a thin wrapper; you can instantiate the underlying Local adapter directly for unit tests of path/permission logic without booting the full addon.
Pair with the Files field type. In your own modules, define a files field and point it at the local disk — this is the most common day-to-day use: attaching documents/images to Streams entries. The adapter choice is invisible to the field.
Extension point for your own adapters. Copy this addon's structure as the template if you need an internal adapter (e.g. an encrypted local disk or an NFS mount). Register a new Adapter extension class, add the composer.json extra.streams block, and the Files module will list it alongside Local.
league/flysystem-local, and the Files module covers local storage without this addon. Treat it as a reference implementation, not a dependency, on any current stack.League\Flysystem\Adapter\Local (namespace removed in Flysystem 2) and PHP 5.x signatures. Any attempt to run it on Laravel 9+ will fatal on class-not-found before you reach runtime.anomaly.extension.local_storage_adapter). If the addon is uninstalled or renamed, existing disks silently resolve to no adapter and uploads fail with opaque "adapter not found" errors. Grep your disks table for the handle before/after upgrades.Local accepts relative paths but resolves against the PHP working directory, not base_path(). Always store absolute paths in disk options; otherwise artisan (cwd = project root) and queue workers (cwd can differ) write to different directories.storage/app are not web-accessible — you need a route or a symlink (php artisan storage:link) for downloads.permissions in the disk options rather than patching the class.options.path is absolute and writable by the PHP user, (2) storage/logs/laravel.log for Flysystem exceptions, (3) php artisan addon:list to confirm the extension is installed and enabled. Files module caching of disks can mask config changes — clear the addon cache after edits.Adapter extension against the current Files module contract and copy only the ~30 lines of registration boilerplate from this repo.How can I help you explore Laravel packages today?