create-controller-form-actions — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited create-controller-form-actions (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Read @.ai/Component/Controller/CONTEXT.md for controller conventions (base class, DI, security attributes, error mapping). Read @.ai/Component/Forms/CONTEXT.md for form patterns (FormBuilder, FormHandler, FormDataProvider, FormDataHandler).
FormBuilderInterface and FormHandlerInterface are injected as action arguments (preferred DI mode — see Controller/CONTEXT.md), each with an explicit #[Autowire(service: '…')] so the action picks up the domain-specific form services:
#[AdminSecurity("is_granted('create', request.get('_legacy_controller'))")]
public function createAction(
Request $request,
#[Autowire(service: 'prestashop.core.form.identifiable_object.builder.{domain}_form_builder')]
FormBuilderInterface ${domain}FormBuilder,
#[Autowire(service: 'prestashop.core.form.identifiable_object.handler.{domain}_form_handler')]
FormHandlerInterface ${domain}FormHandler,
): ResponseFormBuilderInterface::getForm(), render form templateFormHandlerInterface::handle() — it internally calls FormDataHandler::create() which dispatches the Add commandgetIdentifiableObjectId())Reference: TaxController::createAction(), ManufacturerController::createAction()
Same injection mode — FormBuilderInterface and FormHandlerInterface as action arguments:
#[AdminSecurity("is_granted('update', request.get('_legacy_controller'))")]
public function editAction(
Request $request,
int ${domain}Id,
#[Autowire(service: 'prestashop.core.form.identifiable_object.builder.{domain}_form_builder')]
FormBuilderInterface ${domain}FormBuilder,
#[Autowire(service: 'prestashop.core.form.identifiable_object.handler.{domain}_form_handler')]
FormHandlerInterface ${domain}FormHandler,
): Response${domain}FormBuilder->getFormFor(${domain}Id) — FormDataProvider::getData($id) is called internally to pre-fill the form${domain}FormHandler->handle($form) — calls FormDataHandler::update() which dispatches Edit command{Domain}NotFoundException → error flash, redirect to index (entity may have been deleted concurrently)Reference: TaxController::editAction(), ManufacturerController::editAction()
Some entities require additional actions beyond create/edit:
deleteCoverImageAction(int $id)exportAction(Request $request) — generates CSV/PDFviewAction(int $id) — read-only detail page (e.g. Customer, Order)updatePositionAction(Request $request) — handled by PositionDefinitionFor these single-purpose actions, skip FormBuilder/FormHandler — they exist to bridge a Symfony form lifecycle to a CQRS command, which is overkill for an action that just dispatches one command or query. Inject the bus (or specific handler) and dispatch directly:
#[AdminSecurity("is_granted('delete', request.get('_legacy_controller'))")]
public function deleteCoverImageAction(int ${domain}Id): RedirectResponse
{
try {
$this->dispatchCommand(new DeleteCoverImageCommand(${domain}Id));
$this->addFlash('success', /* … */);
} catch ({Domain}NotFoundException $e) {
$this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessages()));
}
return $this->redirectToRoute('admin_{domain}s_edit', ['{domain}Id' => ${domain}Id]);
}The FormBuilder/FormHandler pair is required for the create/edit form lifecycle — not for every controller action.
@.ai/Component/Controller/CONTEXT.md for all controller conventions (DI order, security attributes, error mapping)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.