{"id":18779362,"url":"https://github.com/zostay/formfactory","last_synced_at":"2025-04-13T10:33:59.569Z","repository":{"id":737745,"uuid":"388087","full_name":"zostay/FormFactory","owner":"zostay","description":"Yet another generic forms processing system for Perl","archived":false,"fork":false,"pushed_at":"2015-06-12T03:37:55.000Z","size":551,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-08-20T22:28:48.257Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://search.cpan.org/dist/Form-Factory/","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zostay.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2009-11-28T04:38:24.000Z","updated_at":"2015-02-16T04:48:38.000Z","dependencies_parsed_at":"2022-07-08T00:10:33.913Z","dependency_job_id":null,"html_url":"https://github.com/zostay/FormFactory","commit_stats":null,"previous_names":[],"tags_count":21,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2FFormFactory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2FFormFactory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2FFormFactory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2FFormFactory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zostay","download_url":"https://codeload.github.com/zostay/FormFactory/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223583042,"owners_count":17168786,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T20:19:44.966Z","updated_at":"2024-11-07T20:19:45.595Z","avatar_url":"https://github.com/zostay.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nForm::Factory - a general-purpose form handling API\n\n# VERSION\n\nversion 0.022\n\n# SYNOPSIS\n\n    ### CGI, HTML example\n    my $interface = Form::Factory-\u003enew_interface('HTML');\n    my $action  = $interface-\u003enew_action('MyApp::Action::Login');\n\n    ### Drawing the form contents\n    $action-\u003eunstash('login');\n    $action-\u003eglobals-\u003e{after_login} = '/index.html';\n    $action-\u003estash('login');\n    $action-\u003erender;\n    $action-\u003erender_control(button =\u003e {\n        name  =\u003e 'submit',\n        label =\u003e 'Login',\n    });\n    $action-\u003eresults-\u003eclear_all;\n    \n    ### Processing the form result\n    my $q = CGI-\u003enew;\n    $action-\u003eunstash('login');\n    $action-\u003econsume_and_clean_and_check_and_process( request =\u003e $q-\u003eVars );\n\n    if ($action-\u003eis_valid and $action-\u003eis_success) {\n        $action-\u003estash('login');\n        print $q-\u003eredirect($action-\u003eglobals-\u003e{after_login});\n    }\n    else {\n        print q{\u003cp class=\"errors\"\u003e};\n        print $action-\u003eerror_messages;\n        print q{\u003c/p\u003e};\n    }\n\n# DESCRIPTION\n\n**ALPHA API**. This code is not fully tested (if you look in the test files you will see a long list of tests planned, but no yet implemented). It is currently being employed on a non-production project. The API _will_ change. See [\"TODO\"](#todo) for more.\n\nThis API is designed to be a general purpose API for showing and processing forms. This has been done before. I know. However, I believe this provides some distinct advantages. \n\nYou should check out the alternatives because this might be more complex than you really need. That said, why would you want this?\n\n## MODULAR AND EXTENSIBLE\n\nThis forms processor makes heavy use of [Moose](https://metacpan.org/pod/Moose). Nearly every class is replaceable or extensible in case it does not work the way you need it to. It is initially implemented to support HTML forms and command-line interfaces, but I would like to see it support XForms, XUL, PDF forms, GUI forms via Wx or Curses, etc.\n\n## ENCAPSULATED ACTIONS\n\nThe centerpiece of this API is the way an action is encapsulated in a single object. In a way, a form object is a glorified functor with a `run` method responsible for taking the action. Wrapped around that is the ability to describe what kind of inputs are expected, how to clean up and verify the inputs, how to report errors so that they can be used, how entered values can be sent back to the orignal user, etc.\n\nThe goal here is to create self-contained actions that specify what they are in fairly generic terms, take specific action when the input checks out, to handle exceptions in a way that is convenient in forms processing (where exceptions are often more common than not) and send back output cleanly.\n\n## MULTIPLE IMPLEMENTATIONS\n\nAn action presents a blueprint for the data it needs to run. A form interface takes that blueprint and builds the UI to present to the user and consume input from the user and notify the action.\n\nA form interface could be any kind of UI. The way the form interface and action is used will depend on the form interface implementation. The action itself should not need to care (much) about what interface it is used in.\n\n## CONTROLS VERSUS WIDGETS\n\nSo far, the attempt has been made to keep controls pretty generic. A control specifies the kind of inputs an action expects for some input, but the interface is responsible for rendering that control as a suitable widget and consuming data from that widget.\n\n## FORM AND CONTROL FEATURES\n\nForms and controls can be extended with common features. These features can clean up the input, check the input for errors, and provide additional processing to forms. Features can be added to an action class or even to a specific instance to modify the form on the fly.\n\n# METHODS\n\n## new\\_interface\n\n    my $interface = Form::Factory-\u003enew_interface($name, \\%options);\n\nThis creates a [Form::Factory::Interface](https://metacpan.org/pod/Form::Factory::Interface) object with the given options. This is, more or less, a shortcut for:\n\n    my $interface_class = Form::Factory-\u003einterface_class($name);\n    my $interface       = $interface_class-\u003enew(\\%options);\n\n## interface\\_class\n\n    my $class_name = Form::Factory-\u003einterface_class('HTML');\n\nReturns the interface class for the named interface. This loads the interface class from the [Form::Factory::Interface](https://metacpan.org/pod/Form::Factory::Interface) namespace. \n\nSee [\"CLASS LOADING\"](#class-loading).\n\n## control\\_class\n\n    my $class_name = Form::Factory-\u003econtrol_class('full_text');\n\nReturns the control class for the named control. This loads the control class from the [Form::Factory::Control](https://metacpan.org/pod/Form::Factory::Control) namespace.\n\nSee [\"CLASS LOADING\"](#class-loading).\n\n## feature\\_class\n\n    my $class_name = Form::Factory-\u003efeature_class('functional');\n\nReturns the feature class for the named feature. This loads the feature class from the [Form::Factory::Feature](https://metacpan.org/pod/Form::Factory::Feature) namespace.\n\nSee [\"CLASS LOADING\"](#class-loading).\n\n## control\\_feature\\_class\n\n    my $class_name = Form::Factory-\u003econtrol_feature_class('required');\n\nReturns the control feature class for the named control feature. This loads the control feature class from the [Form::Factory::Feature::Control](https://metacpan.org/pod/Form::Factory::Feature::Control) namespace.\n\nSee [\"CLASS LOADING\"](#class-loading).\n\n# CLASS LOADING\n\nThis package features a few class loading methods. These methods each load a type of class. The type of class depends on the namespace they are based upon (which is mentioned in the documentation for each class loading method).\n\nEach namespace is divided into two segments: the reserved namespace and the custom namespace. The reserved namespace is reserved for use by the [Form::Factory](https://metacpan.org/pod/Form::Factory) library itself. These will be any class directly under the namespace given. \n\nFor example, interface classes will always be directly under [Form::Factory::Interface](https://metacpan.org/pod/Form::Factory::Interface), such as [Form::Factory::Interface::HTML](https://metacpan.org/pod/Form::Factory::Interface::HTML) and [Form::Factory::Interface::CLI](https://metacpan.org/pod/Form::Factory::Interface::CLI).\n\nThe custom namespaces are implemented as an alias under the `Custom` package namespace. You first define a custom package, which contains a `register_implementation`, which returns the name of a package that actually implements that class.\n\nFor example, you might create an interface class specific to your app. You might define a class as follows:\n\n    package Form::Factory::Interface::Custom::MyAppHTML;\n    sub register_implementation { 'MyApp::Form::Factory::Interface::HTML' }\n\n    package MyApp::Form::Factory::Interface::HTML;\n    use Moose;\n\n    extends qw( Form::Factory::Interface::HTML );\n\n    # implementation here...\n\nAny custom name is similar. You could then retrieve your custom name via:\n\n    my $class = Form::Factory-\u003einterface_class('MyAppHTML');\n\nThough, you probably actually want:\n\n    my $interface = Form::Factory-\u003enew_interface('MyAppHTML');\n\n# TODO\n\nThis is not definite, but some things I know as of right now I'm not happy with:\n\n- There are lots of tweaks coming to controls.\n- Features do not do very much yet, but they must do more, especially control features. I want features to be able to modify control construction, add interface-specific functionality for rendering and consuming, etc. They will be bigger and badder, but this might mean who knows what needs to change elsewhere.\n- The interfaces are kind of stupid at this point. They probably need a place to put their brains so they can some more interesting work.\n\n# CODE REPOSITORY\n\nIf you would like to take a look at the latest progress on this software, please see the Github repository: [http://github.com/zostay/FormFactory](http://github.com/zostay/FormFactory)\n\n# BUGS\n\nPlease report any bugs you find to the Github issue tracker: [http://github.com/zostay/FormFactory/issues](http://github.com/zostay/FormFactory/issues)\n\nIf you need help getting started or something (the documentation was originally thrown together over my recent vacation, so it's probably lacking and wonky), you can also contact me on Twitter ([http://twitter.com/zostay](http://twitter.com/zostay)) or by [email](#author).\n\n# SEE ALSO\n\n[Form::Factory::Interface::CLI](https://metacpan.org/pod/Form::Factory::Interface::CLI), [Form::Factory::Interface::HTML](https://metacpan.org/pod/Form::Factory::Interface::HTML)\n\n# AUTHOR\n\nAndrew Sterling Hanenkamp \u003chanenkamp@cpan.org\u003e\n\n# COPYRIGHT AND LICENSE\n\nThis software is copyright (c) 2015 by Qubling Software LLC.\n\nThis is free software; you can redistribute it and/or modify it under\nthe same terms as the Perl 5 programming language system itself.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzostay%2Fformfactory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzostay%2Fformfactory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzostay%2Fformfactory/lists"}