Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Toolforge Bundle Laravel Package

wikimedia/toolforge-bundle

Symfony bundle for running applications on Wikimedia Toolforge. Provides ready-made integration with Toolforge services like MySQL, Redis, and Kubernetes, plus configuration helpers that simplify deploying and operating Symfony apps on the platform.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: wikimedia/toolforge-bundle is a Symfony 4/5 bundle, not a Laravel package. There is no service provider, no facade, no config publish tag. composer require in a Laravel app will install the code but you cannot boot it — it depends on Symfony\Component\HttpKernel\Bundle\Bundle, the Symfony DI container, the Security component, and Twig bundle conventions. For a Laravel developer, day-to-day leverage comes in one of two forms:

  1. You are maintaining (or inheriting) a Symfony-based Toolforge tool, and this bundle is the fastest path to Wikimedia login + Toolforge plumbing.
  2. You are building the same thing in Laravel and want to use this package as a reference implementation for the OAuth handshake, the user model, and the Toolforge-specific edge cases.

Minimal steps (Symfony path):

composer require wikimedia/toolforge-bundle
  1. Register the bundle in config/bundles.php (Symfony 4/5 Flex) or AppKernel.php.
  2. Register an OAuth consumer on Meta-Wiki (https://meta.wikimedia.org/wiki/Special:OAuthConsumerRegistration) — you need the consumer key/secret and an exact callback URL. Do this before writing config; nothing works without it.
  3. Publish/author the bundle config and wire the security firewall to the bundle's user provider and authenticator. Read the README for the exact service IDs; confirm the option names against src/DependencyInjection/Configuration.php in the version you installed, since they have churned between releases.
  4. Create (or subclass) the bundle's user entity so you can attach your own fields, then point the user_class config at it and run a Doctrine migration.

Where to look first, in order:

  • README.md — the only real documentation; expect it to be short.
  • src/DependencyInjection/Configuration.php — the authoritative list of config keys. README drift is common here.
  • src/Security/ — user provider, authenticator, and the ToolforgeUser/ToolforgeUserInterface contract.
  • src/EventSubscriber/ — how the current user is attached to the request.
  • Resources/config/ — service definitions, so you know what to decorate rather than fork.
  • composer.json — confirms which Symfony majors and which OAuth client (mediawiki/oauthclient for 1.0a, or an OAuth2 client) you actually got.

First use case to ship: a single protected route that logs a user in via Wikimedia and renders their username plus global groups in Twig. That exercises config, the OAuth callback, the user provider, session persistence, and the Twig integration in one pass — and it's exactly the shape 90% of Toolforge tools need.

Implementation Patterns

Gate a controller on Wikimedia identity. Don't hand-roll session checks; let the Security component do it and read the user from the token:

#[Route('/dashboard', name: 'dashboard')]
public function dashboard(): Response
{
    $user = $this->getUser(); // ToolforgeUserInterface
    return $this->render('dashboard.html.twig', [
        'username' => $user->getUsername(),
        'groups'   => $user->getGlobalGroups(),
    ]);
}

Authorize on CentralAuth groups, not local roles. This is the pattern that makes the bundle worth using. Toolforge tools typically gate admin actions on Wikimedia global groups (sysop, global-sysop, steward, accountcreator) rather than maintaining a local role table:

$isSysop = in_array('sysop', $user->getGlobalGroups(), true);

Wrap this in a Symfony voter (ToolforgeGroupVoter) so templates and controllers share one rule instead of scattering in_array calls.

Subclass the user entity for app-specific data. The bundle gives you the Wikimedia identity; it does not give you your app's data model. Extend the provided user class (or implement its interface), join your own tables to it, and let the bundle's provider hydrate the Wikimedia half. This keeps a clean split: bundle owns identity, you own application state.

Keep secrets in env, never in toolforge.yaml. Toolforge deploys are typically git-checkout-based, and the OAuth consumer secret is the whole ballgame:

# config/packages/toolforge.yaml
toolforge:
    oauth:
        consumer_key: '%env(WIKIMEDIA_OAUTH_KEY)%'
        consumer_secret: '%env(WIKIMEDIA_OAUTH_SECRET)%'
    user_class: App\Entity\User

Handle anonymous gracefully. Toolforge tools are usually public-read/write-authenticated. Don't force the OAuth dance on every visitor — leave the firewall lazy/anonymous and only challenge on the write actions.

For the Laravel port, use this bundle's structure as the spec. The three moving parts map cleanly:

// config/services.php
'wikimedia' => [
    'client_id'     => env('WIKIMEDIA_OAUTH_KEY'),
    'client_secret' => env('WIKIMEDIA_OAUTH_SECRET'),
    'redirect'      => env('WIKIMEDIA_REDIRECT_URI'),
],

Then a Socialite provider hitting the MediaWiki REST endpoints (/w/rest.php/oauth2/authorize, /w/rest.php/oauth2/access_token, /w/rest.php/oauth2/resource/profile on meta.wikimedia.org), a WikimediaIdentity value object mirroring ToolforgeUser, and a EnsureWikimediaUser middleware. Store the access token on the user row — you'll need it to call the Action API on the user's behalf. If your installed bundle version targets OAuth 1.0a instead, that's a different signing story; decide up front which protocol your tool needs.

Testing. In Symfony, mock the user provider or inject a test ToolforgeUser into the token storage. In a Laravel port, Socialite::shouldReceive('driver->user') gives you the same isolation. Either way, never let tests reach Meta-Wiki.

Gotchas and Tips

  • Symfony 4/5 only. No Symfony 6/7 support in the published line. If you're on a modern Symfony, budget for a fork or an upgrade PR. In Laravel, treat it strictly as reference code.
  • GPL-3.0. Copying its source into a Laravel app makes your app GPL. Reading it for the protocol details (OAuth endpoints, parameter names, group semantics) is fine; pasting its classes is a licensing decision, not a technical one.
  • Low adoption, thin docs. 15 stars and zero dependents means you are the QA. Expect to read src/ for anything beyond the happy path, and pin an exact version — there is no ecosystem to catch regressions for you.
  • OAuth callback URL must match exactly, including scheme, trailing slash, and host. Toolforge tools commonly live at https://<tool>.toolforge.org/; a mismatch produces an opaque rejection on Meta-Wiki that looks like a bundle bug but isn't.
  • HTTPS and proxies. Toolforge terminates TLS at the ingress. Configure trusted_proxies and framework.trusted_hosts so Symfony sees the real scheme and host; otherwise generated callback URLs silently come out as http:// and the OAuth round-trip fails.
  • Session/cookie scope. Run behind the Toolforge ingress with a proper cookie_domain/cookie_secure setting. Multiple tools on *.toolforge.org sharing a cookie name will clobber each other.
  • CentralAuth lookups are network calls. If the bundle does a live lookup per request, cache the user's global groups in the session or a short-TTL cache; the profile endpoint is not a local DB read.
  • Debugging toolkit: bin/console debug:router, debug:container --tag=security.authenticator, debug:event-dispatcher security.*, and var/log/dev.log. If login loops, it's almost always session persistence or a trusted-proxy issue, not the OAuth exchange.
  • Extension points beat forking. Prefer user_class config, a decorating service over the user provider, a security voter for group rules, and Twig template overrides in templates/bundles/ToolforgeBundle/. Forking a 15-star GPL bundle is a maintenance trap.
  • Don't assume the README matches your version. Config keys and service IDs have moved. When a "documented" option is rejected by the container, Configuration.php is the truth.
  • Budget a real spike. For a Laravel team the honest estimate is: half a day to read the bundle and extract the protocol contract, one to two days to implement and test a Socialite provider + middleware. That's usually cheaper, and far more maintainable, than trying to run a Symfony bundle inside Laravel.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons