Skip to content

Releases

v0.5.0

Choose a tag to compare

@etus-ephraitech etus-ephraitech released this 29 Oct 13:43

Documentation site with tested examples, themes that extend other themes, and genuine PUT,
PATCH and DELETE request bodies. No breaking changes.

Added

  • Documentation site, built from docs/ with Zensical (reading mkdocs.yml) and published
    to GitHub Pages on release tags by a new Docs workflow that builds in strict mode on every
    push and pull request. Code examples are real files in docs/examples/app/, included into
    the pages and run by a new tests/Docs suite, so published examples always work.
  • CONTRIBUTING.md with instructions for running the tests and previewing the documentation.
  • Getting started tutorial: appointment booking with a two-column layout, a business rule
    and editing, built from tested example files run over HTTP against a database.
  • Guides for layout, multiple choices, file uploads, custom field types and customising views,
    each with tested examples (a real app/Config/Forms.php example is tested in separate
    processes so it cannot affect other tests).
  • Themes can extend another theme ('extends' => 'bootstrap5'): templates missing from a
    theme's views folder are taken from the theme it extends, so a custom theme only needs the
    templates it changes. The parent must be a registered theme; loops are guarded against.
  • Guides for option providers, forms written by admins, showing submissions, testing your
    forms, and JavaScript and APIs, with tested example apps (an admin form editor and public
    form pages, a submissions screen, a JSON API) and example tests that use CodeIgniter's
    standard $migrate = true.
  • tests/bootstrap.php treats docs/examples/app as part of the test app, so example
    migrations and views work as they would in a real app.
  • Reference section: Form, Fields, Schemas, Configuration, and Helpers and commands, written
    by hand and checked by ApiReferenceTest (every public method, setting, theme class key,
    helper and command option must be documented, and everything documented must exist), plus
    a Schema keys page generated from FormSchema::describe() with composer docs:reference
    and checked by SchemaReferenceTest.
  • Concepts section explaining values, validation, security and architecture, with every
    statement checked by ConceptsClaimsTest (each test is named after the page section that
    makes the claim); Upgrading and Changelog pages (the changelog page includes this file).

Fixed

  • validate() ignored the data of genuine PUT, PATCH and DELETE requests (from
    JavaScript or API clients), whose URL-encoded body PHP does not put in $_POST. It now
    reads the raw body for those methods when $_POST is empty. Browser forms, which send
    POST with a hidden _method field, were not affected.

v0.4.0

Choose a tag to compare

@etus-ephraitech etus-ephraitech released this 28 Oct 21:23

Showing stored data, a forms helper, and FormSchema::describe() as groundwork for visual
builders. No breaking changes.

Added

  • Form::present($data) turns stored data, such as a saved submission, into readable rows:
    field labels, option labels instead of values (including groups and provider options),
    Yes/No for checkboxes and lists for multi-value fields. Values no longer among the options
    are shown as stored. Passwords, buttons and uploads are never included.
    Form::renderPresented($data) renders them with the new presented theme view.
  • Contracts\PresentableFieldInterface (isPresentable(), presentValue()), implemented by
    every field; custom fields can override presentValue(), for example to format amounts.
  • Config $presentYes, $presentNo, $presentEmpty and theme classes presented,
    presented_label, presented_value, presented_empty.
  • A forms helper (helper('forms')) with forms_load(), forms_check() and
    forms_present(). Functions are prefixed forms_ so they never clash with CodeIgniter's
    form helper.
  • FormSchema::describe($policy) describes what a schema may contain under a policy, as
    JSON-ready data: every allowed field type with its label, accepted keys, the kind of value
    each key takes and a one-line explanation, which keys are required (requires) or cannot be
    combined (exclusive), plus the allowed rules with their parameter kinds, attributes,
    option providers, upload types, size limits and forbidden names. Groundwork for visual
    builders and admin help pages; a test loads every described key through the loader under
    each policy, so the description and the loader cannot disagree.
  • SchemaLoader::keysFor() (the loader's own key lists, shared with describe()) and
    SchemaPolicy::getRules(), getAttributes(), getForbiddenNames(), getLimits().

v0.3.0

Choose a tag to compare

@etus-ephraitech etus-ephraitech released this 28 Oct 21:22

Forms from schemas: load forms from arrays or JSON written by developers or admins, with a
restricted policy by default, option providers, admin checks and export. No breaking changes.

Added

  • Schema loading: Form::fromSchema(), Form::fromJson() and $form->loadSchema() build
    forms from arrays or JSON (schema version 1): every built-in field type and option, rows and
    fieldsets, form settings, and registered custom types. Loading is all or nothing: the
    schema is first built on a scratch form and every error is collected with its location
    (fields[2].children[0].max_size: ...), including typo suggestions and hints for HTML
    habits such as maxlength. Keys are applied in schema order.
  • Schema\SchemaException with getErrors() and getMessages(); Schema\SchemaLoader::errors()
    checks a schema without loading it.
  • Contracts\SchemaConfigurableInterface lets custom field types accept extra schema keys.
  • Schema\SchemaPolicy: every schema is checked against a policy, restricted by default
    (Form::fromSchema(), fromJson() and loadSchema() all take an optional policy).
    SchemaPolicy::restricted(), for schemas written by admins or clients, blocks event-handler
    and behaviour attributes (on*, formaction, style, data-*), rules outside an
    allow-list with checked parameters (no is_unique, regex_match or custom rules), a
    schema-set form action, uploads without max_size (capped at 10 MB) or without an
    explicit mimes list from safe types (no SVG or HTML), protected field names such as
    role and is_admin, password and hidden fields, unlisted custom types, and oversized
    schemas. SchemaPolicy::trusted() is for developer-written schemas. Policies are immutable
    and can be customised (allowTypes(), allowRules(), allowAttributes(), allowMimes(),
    forbidNames(), allowNames(), withLimits(), withMaxUploadSize(), allowAction());
    unsafe allowances such as on* attributes or SVG uploads are refused.
  • Option providers: named sources of options registered in $optionProviders
    ([ClassName::class, 'method'] for static methods, CodeIgniter models or plain classes,
    'ClassName::method', or a Closure). Schemas use "options_from": "services"; code uses
    ->optionsFrom('services'). Providers run lazily, once per field, and never while a schema
    is loaded or checked; strict option checking uses their options. SchemaPolicy can narrow
    which providers admin schemas may use (onlyProviders(), disallowProviders()).
    Support\OptionProviders checks registrations; getOptionProvider() on choice fields.
  • Form::toSchema() and Form::toJson() export any form, including form classes, as a
    version 1 schema that loads back into an identical form (same schema, same HTML, same
    validation). Provider options are exported as options_from; attributes with their own key
    (autocomplete, rows, step, min, ...) are exported under it. Closure rules and
    unregistered custom field classes make the export fail with their location.
  • Schema\FormSchema::check() for admin screens: checks array or JSON input without throwing
    and returns a SchemaCheck (isValid(), getErrors(), getMessages(), getErrorsFor(),
    getSchema(), toArray() for JSON responses); restricted by default.
    FormSchema::load() and FormSchema::export() shortcuts.
  • php spark forms:schema check <file> [--trusted] and
    php spark forms:schema export <FormClass> [--output <file>].
  • SchemaConfigurableInterface::schemaValues() so custom fields can export their extra keys;
    Field::getExplicitId(), Field::getOwnAttributes(), Form::getExplicitId(),
    File::isUploadRequired(), File::getExtraRules().

Fixed

  • Forms could not be created on the command line (spark commands, queue workers, seeders):
    checking reserved field names called csrf_token(), which starts the Security service and
    needs a web request. The CSRF token name is now read from the Security config.
  • A source-integrity test that fails when a docblock missing its closing */ hides class
    members.

v0.2.0

Choose a tag to compare

@etus-ephraitech etus-ephraitech released this 28 Oct 21:21

Multi-value fields, strict option checking, file uploads, layout, new inputs and custom field
types. Read "Upgrading from 0.1" in the README before upgrading.

Added

  • Multi-value fields: select()->multiple() (with size()) and a new checkboxes() group
    field. Both submit as name[] and validated() returns a list, empty when nothing is
    chosen.
  • eachRules() for rules checked against every item of a multi-value field, using
    CodeIgniter's name.* wildcard. permit_empty is added automatically so an empty list
    passes; use rules('required') to require at least one item.
  • New field_checkboxes view; views receive $inputName, $values and $multiple.
  • Strict option checking: submitted values for selects, multi-selects, radios, checkbox
    groups and single checkboxes must be among the field's options (for a checkbox, its checked
    value). Controlled by $strictOptions and $strictOptionsMessage in config, per field with
    ->strictOptions(bool) and ->messages(['options' => '...']). Errors survive
    redirect()->withInput().
  • Contracts\ChoiceFieldInterface (getAllowedValues(), getStrictOptions()) for custom
    fields with a fixed set of values; Form::usesStrictOptions().
  • File uploads: file() field with required(), multiple(), maxSize() (kilobytes),
    extensions(), mimes(), image() and maxDimensions(), mapped to CodeIgniter's file
    rules, plus a generated accept attribute. Optional file fields are only validated when a
    file is uploaded. Uploads are never part of validated(); get them with
    Form::getFile(), Form::getFiles() and Form::hasUploadedFile().
  • Forms with a file field are sent as multipart automatically.
  • After a failed submission, file fields show a "choose the file again" hint
    ($fileReselectMessage, theme class reselect), since browsers cannot refill them.
  • Contracts\FileFieldInterface for custom upload fields; new field_file view.
  • Theme templates missing from a theme's views folder fall back to the package's bundled copy
    of that theme, so views published before an upgrade keep working with new field types.
    php spark forms:publish adds the missing templates without touching customised ones.
  • Layout: row() places fields side by side and fieldset() groups them under a titled
    section (description(), id()); both nest and take addClass(). Fields and fieldsets get
    width(1-12) for their column inside a row; fields without a width share the row. Layout is
    defined in the form class and rendered by <?= $form ?> and fields(); fields themselves
    stay a flat list, so values, validation and field() are unaffected.
  • Form::getLayout(), Layout\Row, Layout\Fieldset; new layout_row and
    layout_fieldset views and theme classes row, column ({width} placeholder),
    column_auto, section, section_legend, section_description.
  • New inputs: time(), datetimeLocal(), color() (values lower-cased) and search().
    date(), time() and datetimeLocal() share min(), max() and step() through the new
    Fields\DateTimeInputField base class.
  • Custom field type registry: $fieldTypes = ['money' => MoneyField::class] in config makes
    $this->money('price') a builder method, including inline chaining and inside groups.
    Registrations are checked: camelCase names, no clashes with built-in types or Form
    methods, and classes must implement FieldInterface.
  • Form::addField($type, $name, $label) creates any built-in or registered field by type key;
    Form::hasFieldType(); Support\FieldTypes::BUILT_IN lists the built-in keys.
  • Custom fields can render their own view: a VIEW containing a path (fields/money or
    Vendor\Package\Views\money) is loaded as given instead of from the theme. Field views can
    ask $class() for any theme class key.

Changed

  • Behaviour change: strict option checking is on by default. A form that accepted values
    outside a field's options in 0.1 now rejects them. Set $strictOptions = false in
    app/Config/Forms.php to restore the 0.1 behaviour, or opt single fields out with
    ->strictOptions(false). Existing in_list rules keep working; they are now optional for
    option fields.
  • FieldInterface has three new methods: getEachRules(), isMultiple() and getWidth(). Custom fields
    extending Fields\Field get both automatically; classes implementing the interface
    directly must add them.
  • getOptionId() moved from Radio into the shared HasOptions trait.
  • fields() with no arguments now renders the form's layout (rows and fieldsets) instead of
    a flat list. fields('a', 'b') with names is unchanged. Published form.php views get
    layouts automatically.
  • The field_select view uses $inputName and $values. Re-publish the views
    (php spark forms:publish --force) or apply the same change if you customised it.

Fixed

  • An array posted to a single-value field (for example nickname[]=x) could pass validation
    on fields without rules and reach validated() as an array. Single-value fields now treat
    a posted array as no value, and an unticked checkbox's array counts as unticked.

v0.1.0

Choose a tag to compare

@etus-ephraitech etus-ephraitech released this 27 Oct 20:11

First release of ephraitech/ci4-forms: a form builder for CodeIgniter 4.7+.

Define a form once in PHP and the package renders it with Bootstrap 5, validates it
with CodeIgniter's Validation service, repopulates input after errors, and returns
only clean data for the fields you defined.

Highlights

  • Form classes (define()) and inline forms (Form::make())
  • 13 field types: text, email, password, number, tel, url, date, hidden, textarea,
    select (with option groups), radio, checkbox, submit
  • validate() from POST, GET or JSON requests; validated() returns only defined fields,
    trimmed, with empty strings as null and unticked checkboxes as 0
  • Works with both re-rendering and redirect()->withInput(), including manual errors
    from setError()
  • fill() for edit screens from arrays or Entities; PUT/PATCH/DELETE spoofing
  • Escaped, accessible Bootstrap 5 markup; custom layouts with field() and control()
  • php spark forms:publish to customise the views

Requirements

PHP 8.2+ and CodeIgniter 4.7+.

See the README for full documentation.