PHPackages                             helsingborg-stad/s3-local-index - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. helsingborg-stad/s3-local-index

ActiveWordpress-plugin[File &amp; Storage](/categories/file-storage)

helsingborg-stad/s3-local-index
===============================

1.2.0(3mo ago)0828↓42.1%[1 issues](https://github.com/helsingborg-stad/s3-local-index/issues)[2 PRs](https://github.com/helsingborg-stad/s3-local-index/pulls)MITPHPCI passing

Since Sep 15Pushed 3mo agoCompare

[ Source](https://github.com/helsingborg-stad/s3-local-index)[ Packagist](https://packagist.org/packages/helsingborg-stad/s3-local-index)[ RSS](/packages/helsingborg-stad-s3-local-index/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (125)Used By (0)

S3 Local Index
==============

[](#s3-local-index)

A WordPress plugin that provides local indexing of S3 files with CLI commands and cache flushing capabilities. This plugin improves performance when working with large S3 buckets by creating local indexes that enable fast file existence checks and directory listings without expensive S3 API calls.

This plugin is tested with a bucket of over 1 000 000 files.

Description
-----------

[](#description)

The S3 Local Index plugin creates and maintains local JSON index files that mirror the structure of your S3 bucket. This enables WordPress to quickly determine if files exist on S3 without making API calls for every check. The plugin supports both single-site and multisite WordPress installations.

### Key Features

[](#key-features)

- **Fast File Operations**: Local indexes eliminate the need for S3 API calls during file existence checks
- **WordPress Integration**: Seamless integration with WordPress's filesystem API through stream wrappers
- **CLI Management**: WP-CLI commands for index management
- **Cache Support**: Multiple caching strategies including WordPress object cache and static memory cache
- **Multisite Support**: Full support for WordPress multisite networks
- **Cached Delegation**: Sometimes delegation to original wrapper must occur, but fear not. This is cached!

Index maintanaince
------------------

[](#index-maintanaince)

The plugin will maintain the index when files are deleted and uploaded to reflect the changes. This functionality is designed using WordPress standard hooks. This plugin requires that you manage files "the right way", not registering files in WordPress will cause not\_found errors. Although you may lessen the issue by running the create command often (this reflects everyting in the bucket).

The flowing file changes will be captured:

- When a image file is resized.
- When a file is deleted
- When a file is uploaded

Good to know &amp; limitations
------------------------------

[](#good-to-know--limitations)

- The indexing cron / cli should only run on one of the sites in a multisite environment.
- All sites in a network MUST share a bucket. Multiple buckets is not yet supported.
- This plugin does not index directories, a lookup delegation will be made on is\_dir querys.

Requirements
------------

[](#requirements)

- WordPress 5.0 or higher
- PHP 8.0 or higher
- [S3 Uploads Plugin](https://github.com/humanmade/S3-Uploads) (required dependency)
- WP-CLI (for command-line operations)
- Composer (for dependency management)

Installation
------------

[](#installation)

1. **Install via Composer** (recommended):

    ```
    composer require helsingborg-stad/s3-local-index
    ```
2. **Manual Installation**:

    - Download the plugin files
    - Upload to `/wp-content/plugins/s3-local-index/`
    - Run `composer install` in the plugin directory
3. **Activate the Plugin**:

    - Through WordPress admin: Plugins → Installed Plugins → Activate "S3 Local Index"
    - Via WP-CLI: `wp plugin activate s3-local-index`

Configuration
-------------

[](#configuration)

The plugin is enabled by default when the S3 Uploads plugin is active. You can customize behavior using WordPress filters:

### Available Filters

[](#available-filters)

```
// Enable/disable the plugin
add_filter('S3_Local_Index/Config/IsEnabled', '__return_false');

// Set CLI command priority (default: 10)
add_filter('S3_Local_Index/Config/GetCliPriority', function() {
    return 15;
});

// Set plugin initialization priority (default: 20)
add_filter('S3_Local_Index/Config/GetPluginPriority', function() {
    return 25;
});

// Set custom cache directory (default: temp directory with unique site identifier)
add_filter('S3_Local_Index/Config/GetCacheDirectory', function() {
    return '/path/to/custom/cache/directory';
});
```

### Cache Directory Configuration

[](#cache-directory-configuration)

The plugin automatically prevents collisions between multiple sites on the same server by using unique cache directories. Each site gets its own cache directory based on its document root:

```
/tmp/s3-index-{8-character-uuid}/

```

**Examples:**

- Site 1: `/tmp/s3-index-0f256ede/`
- Site 2: `/tmp/s3-index-b9ba97a4/`

You can override this behavior using the `S3_Local_Index/Config/GetCacheDirectory` filter to specify a custom cache directory location.

CLI Commands
------------

[](#cli-commands)

The plugin provides a WP-CLI command for managing S3 indexes:

### Create Full Index

[](#create-full-index)

Creates a complete index by scanning all objects in the S3 bucket. It is recommended to setup this action as a daily cron, to eshure that the index is as accurate as possible over time (it is however maintained when a file is deleted or added in realtime).

```
wp s3-index create
```

This command:

- Scans the entire S3 bucket
- Groups files by blog ID, year, and month
- Creates JSON index files in the temporary directory
- Clears existing cache before starting
- Provides progress updates during execution

How It Works
------------

[](#how-it-works)

### Index Structure

[](#index-structure)

The plugin creates JSON index files organized by:

- **Blog ID**: `1` for single-site, specific ID for multisite
- **Year**: 4-digit year (e.g., `2023`)
- **Month**: 2-digit month (e.g., `01`)

Index files are stored as: `{cache-directory}/s3-index-{blogId}-{year}-{month}.json`

The cache directory is automatically generated to be unique per site (e.g., `/tmp/s3-index-0f256ede/`) to prevent collisions when multiple sites run on the same server.

### File Path Patterns

[](#file-path-patterns)

The plugin recognizes these S3 path patterns:

**Single Site:**

```
uploads/2023/01/image.jpg

```

**Multisite:**

```
uploads/sites/2/2023/01/image.jpg

```

**Multisite Multi Network:**

```
uploads/networks/1/sites/2/2023/01/image.jpg

```

### Caching Strategy

[](#caching-strategy)

The plugin uses a multi-layer caching approach:

1. **Static Cache**: In-memory cache for the current request
2. **WordPress Object Cache**: Persistent cache using WordPress's object cache system
3. **Composite Cache**: Combines both strategies for optimal performance

Cache keys follow the pattern: `index_{blogId}_{year}_{month}`

### Stream Wrapper Integration

[](#stream-wrapper-integration)

The plugin registers a custom S3 stream wrapper that:

- Intercepts S3 file operations
- Checks local indexes before making S3 API calls
- Provides transparent integration with WordPress filesystem functions. If any error occurs, it will delegate to the standard s3 wrapper.
- It only should cache file\_exist check. This is sufficient to make a noticable performance improvement.

### Running Tests

[](#running-tests)

If tests are available, run them with:

```
# Install test dependencies
composer install --dev

# Run PHPUnit tests (if configured)
vendor/bin/phpunit

# Run PHP Code Sniffer (if configured)
vendor/bin/phpcs
```

### Code Standards

[](#code-standards)

The plugin follows PSR-4 autoloading and PSR-12 coding standards. All classes use dependency injection and implement appropriate interfaces for testability.

Troubleshooting
---------------

[](#troubleshooting)

### Common Issues

[](#common-issues)

**Plugin not working:**

- Ensure S3 Uploads plugin is installed and active
- Check that S3 credentials are properly configured
- Verify WordPress has write permissions to the cache directory

**Index files not created:**

- Run `wp s3-index create` to generate initial indexes
- Check error logs for permission issues
- Ensure sufficient disk space in the cache directory

**Performance issues:**

- Verify cache is working: check WordPress object cache status
- Consider increasing cache TTL for static content
- Monitor cache directory size and clean up old indexes periodically

**Multiple sites on same server:**

- Each site automatically gets its own cache directory to prevent collisions
- Cache directories are generated as `/tmp/s3-index-{8-char-uuid}/`
- You can verify your site's cache directory with: `wp eval "echo (new S3_Local_Index\Config\Config(new WpService\WpService()))->getCacheDirectory();"`

### Debug Logging

[](#debug-logging)

The plugin logs important events to the WordPress error log:

```
[S3 Local Index] Stream wrapper registered.
[S3 Local Index] Cache cleared.
[S3 Local Index] Indexed 1000 objects...

```

Enable WordPress debug logging in `wp-config.php`:

```
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
```

Contributing
------------

[](#contributing)

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Make your changes with proper documentation
4. Add or update tests as needed
5. Submit a pull request

Please ensure all new code includes proper PHPDoc blocks and follows the existing code style.

License
-------

[](#license)

This plugin is licensed under the MIT License. See the `composer.json` file for details.

Authors
-------

[](#authors)

- **Sebastian Thulin** -

Support
-------

[](#support)

For issues and questions:

- Create an issue on the GitHub repository
- Contact the development team at Helsingborg Stad

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance80

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Recently: every ~27 days

Total

98

Last Release

104d ago

Major Versions

0.2.105 → 1.0.12025-10-03

### Community

Maintainers

![](https://www.gravatar.com/avatar/f46fe64973c3e89d15c745c0bf601c25983bafea81d30e64d4bf813a6f8c8c7c?d=identicon)[sebastianthulin](/maintainers/sebastianthulin)

---

Top Contributors

[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (35 commits)")[![sebastianthulin](https://avatars.githubusercontent.com/u/797129?v=4)](https://github.com/sebastianthulin "sebastianthulin (23 commits)")[![nRamstedt](https://avatars.githubusercontent.com/u/16800993?v=4)](https://github.com/nRamstedt "nRamstedt (8 commits)")[![thorbrink](https://avatars.githubusercontent.com/u/1064724?v=4)](https://github.com/thorbrink "thorbrink (5 commits)")[![petter-a](https://avatars.githubusercontent.com/u/40427478?v=4)](https://github.com/petter-a "petter-a (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/helsingborg-stad-s3-local-index/health.svg)

```
[![Health](https://phpackages.com/badges/helsingborg-stad-s3-local-index/health.svg)](https://phpackages.com/packages/helsingborg-stad-s3-local-index)
```

###  Alternatives

[knplabs/gaufrette

PHP library that provides a filesystem abstraction layer

2.5k39.8M123](/packages/knplabs-gaufrette)[superbalist/flysystem-google-storage

Flysystem adapter for Google Cloud Storage

26320.6M30](/packages/superbalist-flysystem-google-storage)[illuminate/filesystem

The Illuminate Filesystem package.

15161.6M2.6k](/packages/illuminate-filesystem)[creocoder/yii2-flysystem

The flysystem extension for the Yii framework

2931.7M62](/packages/creocoder-yii2-flysystem)[flowjs/flow-php-server

PHP library for handling chunk uploads. Works with flow.js html5 file uploads.

2451.6M15](/packages/flowjs-flow-php-server)[madnest/madzipper

Easier zip file handling for Laravel applications.

1382.3M6](/packages/madnest-madzipper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
