PHPackages                             fonda/f-status - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. fonda/f-status

ActiveTypo3-cms-extension[Utility &amp; Helpers](/categories/utility)

fonda/f-status
==============

Tracks and displays the status of registered system processes (imports, commands, etc.) in the TYPO3 Dashboard and Reports module

033↑990.9%PHP

Since May 30Pushed 1w agoCompare

[ Source](https://github.com/fonda-gmbh/f_status)[ Packagist](https://packagist.org/packages/fonda/f-status)[ RSS](/packages/fonda-f-status/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

f\_status — Custom Status Dashboard Widget
==========================================

[](#f_status--custom-status-dashboard-widget)

Provides a TYPO3 Dashboard widget that shows the status of registered system processes (imports, scheduled commands, etc.).

Typical use cases are scheduler commands that should run regularly but have stopped running.

[![example.png](Resources/Public/Screenshots/example.png)](Resources/Public/Screenshots/example.png)

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

[](#requirements)

- TYPO3 14.3.3+

📦 Installation
--------------

[](#-installation)

```
composer require fonda/f-status:@dev
```

The extension provides two integration points:

- **Dashboard widget** — add via the TYPO3 Dashboard interface (widget group: *System Info*, identifier: `fstatus_status`)
- **Reports module** — visible automatically under *Admin Tools &gt; Reports* as *System Status*

🔌 1 — Registering a StatusReporter
----------------------------------

[](#-1--registering-a-statusreporter)

Implement `StatusReporterInterface` in your extension. TYPO3's DI container auto-tags it — no further configuration needed.

```
class MyImportStatusReporter implements StatusReporterInterface
{
    public function getIdentifier(): string
    {
        return 'my_extension.import';
    }

    public function getLabel(): string
    {
        // Plain string or LLL: label reference
        return 'My Import';
    }

    public function getExpectedMaxAge(): ?\DateInterval
    {
        // Return an interval to enable stale detection.
        // Return null if there is no regularity expectation (no stale warning).
        return \DateInterval::createFromDateString('1 day');
    }
}
```

That's it — the class is auto-discovered and appears in the widget immediately.

✍️ 2 — Writing the status
-------------------------

[](#️-2--writing-the-status)

There are two approaches depending on the situation.

### 🤖 Approach A — Automatic via SchedulerCommandStatusListener (3rd-party commands, status only)

[](#-approach-a--automatic-via-schedulercommandstatuslistener-3rd-party-commands-status-only)

`f_status` ships a built-in `AfterTaskExecutionEvent` listener that automatically writes success/failure for any registered reporter. Use this when you cannot or do not want to modify the command itself.

The only requirement: the reporter's `getIdentifier()` must return the scheduler command identifier.

```
class MyCommandStatusReporter implements StatusReporterInterface
{
    public function getIdentifier(): string
    {
        return 'vendor:package:command'; // must match the scheduler command identifier
    }

    public function getLabel(): string
    {
        return 'My Command';
    }

    public function getExpectedMaxAge(): ?\DateInterval
    {
        return \DateInterval::createFromDateString('1 day');
    }
}
```

A working example is provided in `Resources/Private/Example/SchedulerCommandStatusReporter.php`.

### 🛠️ Approach B — Manual set() (own commands, rich messages)

[](#️-approach-b--manual-set-own-commands-rich-messages)

Inject `StatusService` directly into your command and call `set()` with the result. Use this when you own the command and want to include a meaningful message (e.g. record counts, import details).

```
use Fonda\FStatus\Service\StatusService;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;

class MyImportCommand extends Command
{
    public function __construct(
        private readonly MyImportService $importService,
        private readonly StatusService $statusService,
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        try {
            $info = $this->importService->run();

            $this->statusService->set(
                identifier: 'my_extension.import',
                message: sprintf('%d inserted, %d updated', $info->inserted, $info->updated),
                severity: ContextualFeedbackSeverity::OK,
            );

            return Command::SUCCESS;
        } catch (\Throwable $e) {
            $this->statusService->set(
                identifier: 'my_extension.import',
                message: $e->getMessage(),
                severity: ContextualFeedbackSeverity::ERROR,
            );

            return Command::FAILURE;
        }
    }
}
```

📊 Widget display logic
----------------------

[](#-widget-display-logic)

The widget determines the displayed state from the reporter and the stored status:

Condition`getExpectedMaxAge()`Displayed stateBadge colourNo DB entry`null`Never runinfo (blue)No DB entryinterval setNever runerror (red)Entry exists, within max ageanySeverity from `set()`ok / warning / errorEntry exists, older than max ageinterval setStalewarning (yellow)`getExpectedMaxAge()` returning `null` means "this process has no regularity expectation" — the widget will show the actual stored severity without any stale check.

The *max age* interval is shown in the widget next to the badge (e.g. `1 day`, `2 hours`).

🔧 StatusService API
-------------------

[](#-statusservice-api)

```
// Write or update a status entry
$statusService->set(string $identifier, string $message, ContextualFeedbackSeverity $severity): void;

// Remove a status entry
$statusService->remove(string $identifier): void;

// Read a single entry (returns null if not found)
$statusService->get(string $identifier): ?Status;

// Get all entries for a given severity
$statusService->getBySeverity(ContextualFeedbackSeverity $severity): Status[];

// Check whether a reporter is registered for the given identifier
$statusReporterRegistry->has(string $identifier): bool;
```

###  Health Score

24

—

LowBetter than 31% of packages

Maintenance64

Regular maintenance activity

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/1d08c176686c8914d32c70d4af388887d738930fdfdf07c7ca9c841ad10ed683?d=identicon)[georgringer](/maintainers/georgringer)

---

Top Contributors

[![georgringer](https://avatars.githubusercontent.com/u/1905663?v=4)](https://github.com/georgringer "georgringer (2 commits)")

### Embed Badge

![Health badge](/badges/fonda-f-status/health.svg)

```
[![Health](https://phpackages.com/badges/fonda-f-status/health.svg)](https://phpackages.com/packages/fonda-f-status)
```

PHPackages © 2026

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