{"id":21739500,"url":"https://github.com/libreform/wp-libre-form","last_synced_at":"2025-10-08T08:19:29.256Z","repository":{"id":32050824,"uuid":"35622453","full_name":"libreform/wp-libre-form","owner":"libreform","description":"Easy native HTML5 forms for WordPress. Version 1.5 is unmaintained, but works without issue. 2.0 has been rewritten from the ground, and can be found at https://github.com/libreform/libreform","archived":false,"fork":false,"pushed_at":"2020-12-12T21:48:49.000Z","size":3793,"stargazers_count":67,"open_issues_count":16,"forks_count":27,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-09-15T05:34:58.594Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://wordpress.org/plugins/wp-libre-form","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libreform.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-14T16:28:04.000Z","updated_at":"2024-10-06T19:03:46.000Z","dependencies_parsed_at":"2022-07-30T05:37:53.989Z","dependency_job_id":null,"html_url":"https://github.com/libreform/wp-libre-form","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/libreform/wp-libre-form","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libreform%2Fwp-libre-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libreform%2Fwp-libre-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libreform%2Fwp-libre-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libreform%2Fwp-libre-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libreform","download_url":"https://codeload.github.com/libreform/wp-libre-form/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libreform%2Fwp-libre-form/sbom","scorecard":{"id":588250,"data":{"date":"2025-08-11","repo":{"name":"github.com/libreform/wp-libre-form","commit":"9fb4a7d19c4abb34191a407f01f724cd86244f78"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":3,"reason":"Found 9/27 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch 'release/1.5'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T21:08:25.649Z","repository_id":32050824,"created_at":"2025-08-20T21:08:25.650Z","updated_at":"2025-08-20T21:08:25.650Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278910521,"owners_count":26067088,"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","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-26T06:09:15.372Z","updated_at":"2025-10-08T08:19:29.241Z","avatar_url":"https://github.com/libreform.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WP Libre Form\n[![Build Status](https://travis-ci.org/libreform/wp-libre-form.svg?branch=master)](https://travis-ci.org/libreform/wp-libre-form) [![Latest Stable Version](https://poser.pugx.org/anttiviljami/wp-libre-form/v/stable)](https://packagist.org/packages/anttiviljami/wp-libre-form) [![Total Downloads](https://poser.pugx.org/anttiviljami/wp-libre-form/downloads)](https://packagist.org/packages/anttiviljami/wp-libre-form) [![Latest Unstable Version](https://poser.pugx.org/anttiviljami/wp-libre-form/v/unstable)](https://packagist.org/packages/anttiviljami/wp-libre-form) [![License](https://poser.pugx.org/anttiviljami/wp-libre-form/license)](https://packagist.org/packages/anttiviljami/wp-libre-form)\n\nUse standard HTML5 markup to create fully functional forms for WordPress\n\n## Features\n\n- Uses only HTML5 syntax to build forms. No GUIs, shortcodes, **no bullshit**\n- Works with any valid HTML form. Just copy any form from any website and it will work. **It's magic!**\n- Submissions are saved as custom post type posts. Form values are saved as custom fields.\n- Validates required fields tagged with the native HTML5 `required` attribute.\n- **It's hackable.** Add your own functionality with hooks and APIs.\n- Email notifications of received form submissions\n- Full file upload support to Media Library with input type=file\n- Multilingual support with Polylang\n- Predefined static HTML forms via filter hooks\n- Dynamic values, like %USER_EMAIL% for pre-populating form data\n\n## Why?\n\nModern HTML markup is already a great way to build forms. With Libre Form,\nthere's no need to learn clunky form builders that are hard to customise.\n\nJust use standard HTML inputs to build, or copy a form to your WordPress site\nthat will just magically work. No need to touch PHP code if you don't want to.\n\nRequired field validation, email notifications, file uploads to WP gallery and\nlots more are included by default in the core of the plugin, but you can also\nadd your own functionality with [hooks and APIs](#filter--action-api) provided\nby Libre Form.\n\n## Try it\n[TryoutWP](https://gettryout.com/) has provided us with a live demo, [which you can find here](http://gettryout.com/new/?template=libreform\u0026provider=demo\u0026redirect=wp-admin%2Fpost.php%3Fpost%3D4%26action%3Dedit ). It reflects the current release, not the master branch.\n\n## Screenshots\n\n### Editing a Form\n![Form edit](/assets/screenshot-1.png)\n\n### Form displayed in the default Twentysixteen theme\n![Submissions](/assets/screenshot-2.png)\n\n### Submissions view\n![Submissions](/assets/screenshot-3.png)\n\n### Single submission view\n![Submissions](/assets/screenshot-4.png)\n\n## Installation\n\n### The Composer Way (preferred)\n\nInstall the plugin via [Composer](https://getcomposer.org/)\n```\ncomposer require anttiviljami/wp-libre-form\n```\n\nActivate the plugin\n```\nwp plugin activate wp-libre-form\n```\n\n### The Old Fashioned Way\n\nThis plugin is available on the [official WordPress.org plugin directory](https://wordpress.org/plugins/wp-libre-form/).\n\nYou can also install the plugin by directly uploading the zip file as instructed below:\n\n1. [Download the plugin](https://github.com/anttiviljami/wp-libre-form/archive/master.zip)\n2. Upload to the plugin to /wp-content/plugins/ via the WordPress plugin uploader or your preferred method\n3. Activate the plugin\n\n## Filter / Action API\n\n### Filter: wplf_validate_submission\n\nUsed to add validation to your forms.\n\n#### Form specific hooks\n\nThis filter supports form specific hooks:\n\n- `wplf_{form_id}_validate_submission`\n- `wplf_{form_slug}_validate_submission`\n\nThese filters are only applied for the target form by ID or slug.\n\n#### Example: Google ReCaptcha integration\n\n```php\n/**\n * ReCaptcha for WP Libre Form\n */\nadd_filter( 'wplf_validate_submission', 'wplf_recaptcha' );\nfunction wplf_recaptcha( $return ) {\n  // skip this validation if submission has already failed\n  if ( ! $return-\u003eok ) {\n    return $return;\n  }\n\n  $secret = RECAPTCHA_KEY; // substitute with your own secret recaptcha key string\n  $options = [\n    'http' =\u003e [\n      'header'  =\u003e \"Content-type: application/x-www-form-urlencoded\\r\\n\",\n      'method'  =\u003e 'POST',\n      'content' =\u003e http_build_query([\n        'secret' =\u003e $secret,\n        'response' =\u003e $_POST['g-recaptcha-response'],\n      ])\n    ],\n  ];\n\n  $context  = stream_context_create( $options );\n  $result = file_get_contents( 'https://www.google.com/recaptcha/api/siteverify', false, $context );\n\n  $captcha_obj = json_decode( $result );\n\n  if ( false === $captcha_obj-\u003esuccess ) {\n    $return-\u003eok = 0;\n    $return-\u003eerror = __(\"Please prove you're not a robot before submitting.\");\n  }\n\n  return $return;\n}\n```\n\n### Action: wplf_post_validate_submission\n\nTriggers after the form validation is done.\n\n#### Form specific hooks\n\nThis action supports form specific hooks:\n\n- `wplf_{form_id}_post_validate_submission`\n- `wplf_{form_slug}_post_validate_submission`\n\nThese actions are only run for the target form by ID or slug.\n\n#### Example: Send a thank you email to the email in the submission\n\n```php\nadd_action( 'wplf_post_validate_submission', 'my_email_thankyou' );\nfunction my_email_thankyou( $return ) {\n  // recipient details from submission\n  $name = sanitize_text_field( $_POST['name'] );\n  $email = sanitize_email( $_POST['email'] );\n\n  // email subject\n  $subject = __( 'Thank You For Submitting A Form' );\n\n  // text body of email\n  $body = wp_sprintf( __('Thanks, %s for clicking Submit on this glorious HTML5 Form!'), $name );\n\n  // send the email\n  wp_mail( $email, $subject, $body );\n}\n```\n\n### Filter: wplf_disable_validate_additional_fields\n\nDynamically generated fields are disabled by default. If you want to allow fields that are not set in the form to be submitted you can use this filter.\n\n#### Form specific hooks\n\nThis filter supports form specific hooks:\n\n- `wplf_{form_id}_disable_validate_additional_fields`\n- `wplf_{form_slug}_disable_validate_additional_fields`\n\nThese filters are only applied for the target form by ID or slug.\n\nDisabling additonal fields validation for all forms:\n\n```php\nadd_filter( 'wplf_disable_validate_additional_fields' , '__return_true' );\n```\n\n### Filter: wplf_allowed_additional_form_fields\n\nYou can provide your own set of allowed field names, instead of disabling additional field validation entirely.\n\n#### Form specific hooks\n\nThis filter supports form specific hooks:\n\n- `wplf_{form_id}_allowed_additional_form_fields`\n- `wplf_{form_slug}_allowed_additional_form_fields`\n\nThese filters are only applied for the target form by ID or slug.\n\nDisabling additonal fields validation for all forms:\n\n```php\nadd_filter( 'wplf_allowed_additional_form_fields' , ['dynamic-field-name'] );\n```\n\n### Filter: wplf_dynamic_values\n\nAdd or customize dynamic values available in forms.\n\n#### Example: new value\n\n```php\nadd_filter('wplf_dynamic_values', function($values) {\n  $values['SOMETHING'] = [\n    'callback' =\u003e function() { return 'something'; },\n    'labels' =\u003e [\n      'name' =\u003e 'Something',\n      'description' =\u003e 'Something really useful.'\n    ],\n  ];\n\n  return $values;\n});\n\n// \u003cinput type=\"text\" placeholder=\"%SOMETHING%\" name=\"something\"\u003e\n```\n\n\n### Filter: wplf_uploaded_file_name\nIf you choose to not add uploaded files to the media library, you can change the file upload name.\n\n```php\nadd_filter('wplf_uploaded_file_name', function($name, $file, $id) {\n  return \"my_\".$name;\n}, 10, 3);\n```\n\n### Filter: wplf_uploaded_file_path\nIf you choose to not add uploaded files to the media library, you can change the file upload path.\n\n```php\nadd_filter('wplf_uploaded_file_path', function($name, $file, $id) {\n  return $name.\".userfile\";\n}, 10, 3);\n```\n\n## Plugins\n1.5 exposes a new function, `wplf()`. It simply returns the class instance of WP Libre Form.\n\nIt allows you to register your plugin as a WP Libre Form plugin, which in turn allows you to expose an API and a settings page for your plugin, should you want to.\n\n```php\n$wplf = wplf();\n$plugin = new YourPlugin();\n\n$wplf-\u003eplugins-\u003eregister([\n  \"name\" =\u003e \"YourPlugin\", // The name you wish to show on the WPLF plugin page. Willl also be used to access public methods in your plugin\n  \"description\" =\u003e \"What your plugin does in a sentence or two\",\n  \"link\" =\u003e \"https://toyourplugin.com\", // Plugin URL. Can be wordpress.org or pretty much any URL where you can download the plugin\n  \"version\" =\u003e YOUR_PLUGIN_VERSION, // Define a constant containing your plugin version\n  \"instance\" =\u003e $plugin, // Your plugin, instantiated. Users can access your public methods\n  \"settings_page\" =\u003e [$plugin, \"render_settings_page\"], // Function that renders your settings page, or a string that contains the link to it. Leave empty to disable.\n]);\n```\n\nIf you use spaces in the name, you can access the plugin instance like this:\n\n`wplf()-\u003eplugins-\u003e{\"Your plugin\"}-\u003esomePublicMethod()`\n\n## Javascript API\n\n### Client side callbacks\n\nWP Libre Form supports client side callbacks after form submission using window.wplf object. Example usage:\n\n```\nwindow.wplf.successCallbacks.push(res =\u003e alert('Form submission success: ' + res.form_id));\nwindow.wplf.errorCallbacks.push(() =\u003e alert('Form submission failed!'));\n```\n\nThese callbacks are executed in the order they appear.\n\nTo avoid running your JavaScript too early, add `wplf-form-js` to your enqueue dependencies:\n```php\nwp_enqueue_script( \"themejs\", \"/path/to/theme.js\", array( \"wplf-form-js\" ), ... );\n```\nOtherwise you might run into errors like \"Cannot read property 'push' of undefined\".\n\n## REST API driven sites\n\nYou can get forms out of the REST API. Just use `/wp/v2/wplf-form` to retrieve forms. You can get a singular form by using filters:\n\n`/wp/v2/wplf-form?slug=form-slug`\n\nHowever, if you're sending forms from a different domain than WP site URL, you'll run across a CORS issue submitting the form, which you can get around with this:\n\n```php\nadd_action('wplf_pre_validate_submission', function() {\n  $origin = $_SERVER['HTTP_ORIGIN'];\n  header(\"Access-Control-Allow-Origin: $origin\");\n  header(\"Access-Control-Allow-Credentials: true\");\n});\n```\nDo note that the above code snippet opens your form submissions to the world.\n\nYou can also use the \"official\" JS bundle if you want to.\n\n```javascript\nwindow.ajax_object = {\n  ajax_url: `${WP.url}/wp-admin/admin-ajax.php`,\n  ajax_credentials: 'include', // different origin\n  wplf_assets_dir: `${WP.url}/wp-content/plugins/wp-libre-form/assets`,\n}\n\nawait new Promise((resolve, reject) =\u003e {\n  const script = document.createElement('script')\n  const timeout = setTimeout(reject, 30000)\n  script.src = `${WP.url}/wp-content/plugins/wp-libre-form/assets/scripts/wplf-form.js`\n  script.onload = (e) =\u003e {\n    clearInterval(timeout)\n    resolve()\n  }\n\n  document.body.appendChild(script)\n})\n```\n\n## Multilingual\n\nYou can create multilingual forms using Polylang. WPLF will register and automatically fetch the translation when you use special template tags.\n\nExample:\n```html\n\u003cinput type=\"text\" placeholder=\"{{ Test string }}\" name=\"test\"\u003e\n```\n\nYou can also disable this feature, and create your own middleware for WPML, if you'd like.\n\n```php\nadd_filter( 'wplf_load_polylang' , __return_false );\n```\n\n## Adding extra classes to the form element\n\nYou can use the xclass attribute inside the shortcode to add your own extra classes for CSS.\n\n```\n[libre-form id=\"1\" xclass=\"extra\"]\n```\n\n## Adding extra attributes to the form element\n\nYou can add any custom attributes to the form element easily by adding them to the shortcode\n\n```\n[libre-form id=\"1\" data-custom-attr=\"contactme\"]\n```\n\nThe attribute will render as is on the `\u003cform\u003e` element\n\n```html\n\u003cform class=\"libre-form libre-form-1\" data-custom-attr=\"contactme\"\u003e\n```\n\n## Importing forms from a predefined HTML template\n\nSometimes a project might require static forms which are not supposed to\nbe editable in the admin panel.\n\nThis plugin allows you to define HTML forms in your project source code\nand import them into the form admin for specific forms.\n\n### Creating a static HTML template\n\nThe simplest way is to create a HTML5 file and read its contents. Other\noptions include using Twig to render HTML templates.\n\nRemember: WPLF will insert `form` tags on its own, meaning you only have\nto create the markup which sits directly inside the `form` tags.\n\n### Importing a template into WPLF\n\nOnce you're done creating a form template, you need to inform\nWPLF about it. You can use the `wplf_import_html_template`\nfilter hook for this:\n\n```php\n\u003c?php\n\nadd_filter( 'wplf_import_html_template', function ( $template, $form_id ) {\n    $some_form_id = 123;\n\n    if ( $form_id === $some_form_id ) {\n        // You can also render Twig templates and similar here\n        return file_get_contents( '/path/to/template/file.html' );\n    }\n\n    return $template;\n}, 10, 2 );\n```\n\nThe `$template` variable should be a raw HTML string. If it is set to\n`null` no template will be imported.\n\nAfter a template is imported for a certain form the form's editview will\nbe set to read only mode, meaning you must make changes to the static\nHTML template in code instead of editing the form inside the admin\npanel.\n\nOtherwise the form should function normally, meaning you can use WPLF\nfeatures as always.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibreform%2Fwp-libre-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibreform%2Fwp-libre-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibreform%2Fwp-libre-form/lists"}