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

Wn Test Plugin Laravel Package

winter/wn-test-plugin

A test plugin for Winter CMS that provides sample models, controllers, migrations, and backend features for exercising plugin behavior and automated tests. Useful as a reference when building or validating Winter CMS plugins.

View on GitHub
Deep Wiki
Context7

Getting Started

This is Winter CMS's own test/playground plugin — the fixture the core team uses to exercise backend forms, lists, relations, components and migrations. You don't "adopt" it; you install it into a development Winter instance and read it.

As of v3.0.0 it requires Winter v1.2.8 or newer. Check your core version first — on older cores the backend create/update/preview pages render empty, because the plugin no longer ships those view files and relies on the defaults added in v1.2.8.

Minimal setup:

composer require winter/wn-test-plugin --dev
php artisan winter:up      # runs migrations + update steps
php artisan serve

It installs to plugins/winter/test/ (Winter's composer installer maps the package name to the plugin path), and it should appear in the backend under its own navigation entry.

Look here first, in this order:

  1. Plugin.php — the whole registration surface: registerComponents(), registerNavigation(), registerSettings(), registerMarkupTags(), registerSchedule(). This file is effectively the table of contents for the plugin.
  2. models/ + updates/ — model definitions next to the migrations that create them, with $belongsTo/$belongsToMany/$attachMany declared alongside.
  3. controllers/ + controllers/<name>/config_form.yaml and config_list.yaml — the YAML-driven backend CRUD pattern, plus $formLayout = 'fancy' on the Pages and Records controllers. Note there are no create.htm/update.htm/preview.htm/reorder.htm or list-toolbar partials anymore; core supplies those.
  4. components/ — a component class plus its default.htm partial.

First use case: clone it into a fresh project as a working reference while you build your first real plugin. Run php artisan create:plugin Acme\Demo, then keep plugins/winter/test open side by side and copy the shape of each piece rather than inventing it. The second use case is a smoke test: if the test plugin's backend pages render and its migrations run, your Winter install, database and asset pipeline are healthy.

Implementation Patterns

Reference-driven scaffolding. The plugin is most valuable as a canonical example set. Grep for the pattern you need rather than reading docs:

grep -rn "belongsToMany" plugins/winter/test/models
grep -rn "registerComponents" plugins/winter/test/Plugin.php
grep -rn "type: fieldset" plugins/winter/test/controllers/*/config_form.yaml
grep -rn "formLayout" plugins/winter/test/controllers

Every Winter feature the core supports tends to have a minimal, working instance here — relations, file attachments, repeater widgets, list filters/scopes, backend permissions, and (new in v3.0.0) fieldset, url and sensitive form widgets.

Form field widgets as copy-paste references. The Records form is now the best single file to crib from. It demonstrates:

  • a fieldset grouping contact details under one legend, with a nested datepicker — note the fields still save to the model as top-level attributes, the fieldset is purely presentational;
  • a url field with suggestion options;
  • a sensitive widget inside a repeater (for values you want masked in the UI but still round-trip through the model);
  • taglist relation-mode examples, now grouped on the FormWidgets tab;
  • both a simple block group and a Complex group in the grouped repeater on the Repeater tab.

Copy the YAML shape, then adjust only the field names and tab structure.

Prefer $formLayout over controller overrides. v3.0.0 deleted the per-controller BackendMenu::setContext() constructors, $bodyClass overrides, and the Pages::index()/create()/update() overrides in favour of the declarative $formLayout = 'fancy' property. If your own controllers carry that scaffolding, this is the moment to delete it: set $formLayout on the controller and let core's default views handle context and chrome. Same for the 68 create/update/preview/reorder/toolbar views the plugin used to ship — don't reintroduce them.

Live sandbox for your own code. Because it ships models you can mutate freely, it's a safe target for experiments: attach one of your plugin's models to a test model via a relation, drop one of your components onto a test page, or point a backend widget at its controller. You get real data and real CRUD without polluting a client project.

Component smoke tests in pages/partials. If it registers components, drop one into a CMS page to verify the entire theme → component → partial chain works:

{% component 'testComponent' %}

This is the fastest way to confirm your theme's {% framework %}/{% scripts %} includes and AJAX handler registration are wired correctly.

Forking instead of depending. For day-to-day work, copy the plugin directory into your own repo as plugins/acme/playground and rename the namespace. It's a template, not a library — vendoring gives you a stable reference you control and lets you delete the parts you don't need. Keep in mind you'll now also need Winter v1.2.8+ in the target project, since the fork inherits the same reliance on core default views.

CI sanity fixture. In a pipeline that tests a Winter plugin, install this as a dev dependency and run php artisan winter:up before your own migrations. It exercises the plugin loader, the migration runner and the backend boot path — a cheap integration assertion that your CI environment is actually functional, not just that PHP starts. Pin the combination of plugin version and core version, since v3.0.0 raises the floor.

Upgrade verification. After bumping Winter core, boot an instance with this plugin installed and click through its backend pages. It touches enough of the framework that breakage surfaces here before it surfaces in your own plugin.

Gotchas and Tips

  • Minimum core is now v1.2.8. Upgrading the plugin without upgrading Winter gives you backend pages that render empty — not an error, just blank. If you see that after a composer update, check Winter core version before debugging your own code.
  • The view-file overrides are gone — deliberately. Don't copy the old create/update/preview/reorder or toolbar partials from an older tag into your project; they were removed because core's defaults now do the job. Any local fork that still carries them will silently shadow the new behaviour.
  • Remaining controller partials switched from .htm to .php. If you patched or extended a partial by path, your include will break. Re-grep for partial names after upgrading.
  • Custom models need label / label_plural translations. Core's default views use them to title pages, and v3.0.0 filled in the missing ones for the bundled models. Your own models will show raw or empty titles without them.
  • Not semver-stable, and not production-safe. It's a playground: methods get renamed, migrations get rewritten, and the release cadence follows core development rather than compatibility promises — v3.0.0 removing 68 files and bumping the core floor is exactly that pattern. Always --dev, and pin a version if you're relying on it in CI.
  • Migrations run against whatever DB you point at. Its updates/ will create real tables. Use a scratch database or SQLite in-memory for local experiments; don't install it against a shared dev database you care about.
  • Backend navigation pollution. If it registers navigation or settings, it will show up in the backend menu of every environment you install it in. That's fine locally, confusing for a teammate who pulls your composer.lock — hence --dev plus a note in the README.
  • Namespace collisions when copying. Copying files without a global rename leaves two classes claiming the same FQCN and two plugins with the same identifier. Rename Plugin.php's $plugin->name/author, the namespace, the composer package name, and the directory together — Winter will silently load only one of them otherwise.
  • Rebuild tables cheaply. Rather than dropping the database, use php artisan plugin:refresh Winter.Test to roll back and re-run its migrations, and php artisan cache:clear after touching Plugin.php if registrations seem stale.
  • Composer install placement. Winter plugin packages rely on the composer installer to land in plugins/. If your project overrides the plugin path, or if allow-plugins blocks the installer, the package ends up in vendor/ and Winter never sees it. Symptom: composer require succeeds, nothing appears in the backend. Check plugins/winter/test exists on disk.
  • Extension points, not overrides. If you want to reuse a pattern, extend the base class in your own plugin rather than editing the vendor copy — edits vanish on the next composer update. If you extend CustomFile, match the new return type declarations on getPartitionDirectory(), getStorageDirectory(), getPublicPath() and isLocalStorage() or PHP will throw a signature mismatch.
  • Debugging backend CRUD issues: enable debug => true in config/app.php and watch storage/logs/. The YAML configs (config_form.yaml, config_list.yaml) fail loudly on typos in field names but quietly on wrong list column names — a blank column usually means the attribute doesn't exist on the model, not that the widget is broken. Mislabelled or missing partial/hint paths also tend to fail silently; v3.0.0 fixed several of these in the Records form, so compare your paths against it.
  • Release metadata in this dataset is unreliable — the listed date can run ahead of the current date. Check the repository's branch activity and the core version requirement directly before assuming a tag is both current and compatible.
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