diff --git a/.gitignore b/.gitignore index 3f19c74..16990f0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ # Ignore vendor lib vendor node_modules -dist +dist \ No newline at end of file diff --git a/README.md b/README.md index 6c215b2..ba16679 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,67 @@ if ( class_exists( '\Develtio\WP\Forms\Modules\Forms\CreateForm' ) ) { } ``` +## Use with AJAX ## +We use the Nette From library to building the forms (https://doc.nette.org/en/3.0/forms) + +Example +```php +if ( class_exists( '\Develtio\WP\Forms\Modules\Forms\CreateForm' ) ) { + $options = [ + 'send_mail' => false, // enables / disables sending an email, enabled by default + 'send_confirm_mail' => false, // enables / disables sending of confirmation email, disabled by default + 'rest_api' => true, // enables / disables WP REST API endpoint for form + 'create_cpt' => false, // enables / disables creation of CPT + ]; + + $instance = new \Develtio\WP\Forms\Modules\Forms\CreateForm('StepFirst', $options); + $instance->form->addText('client_id') + ->addRule($instance->form::REQUIRED, '%name is required'); + + $instance->form->addText('client_vat') + ->addRule($instance->form::REQUIRED, '%name is required'); + + $instance->form->addText('client_phone') + ->addRule($instance->form::REQUIRED, '%name is required') + ->addRule($instance->form::MAX_LENGTH, "%name shoud be not longer than 12 numbers', 12 "); + + $instance->save(); +} +``` + + +## Use with AJAX and Custom Handler ## +We use the Nette From library to building the forms (https://doc.nette.org/en/3.0/forms) + +Example +```php +if ( class_exists( '\Develtio\WP\Forms\Modules\Forms\CreateForm' ) ) { + $options = [ + 'send_mail' => false, // enables / disables sending an email, enabled by default + 'send_confirm_mail' => false, // enables / disables sending of confirmation email, disabled by default + 'rest_api' => true, // enables / disables WP REST API endpoint for form + 'create_cpt' => false, // enables / disables creation of CPT + 'custom_handler' => [ + 'StepFirstHandleRequest', + plugin_dir_path(dirname(__FILE__)) . '/handlers/' + ] + ]; + + $instance = new \Develtio\WP\Forms\Modules\Forms\CreateForm('Step1', $options); + $instance->form->addText('client_id') + ->addRule($instance->form::REQUIRED, '%name is required'); + + $instance->form->addText('client_vat') + ->addRule($instance->form::REQUIRED, '%name is required'); + + $instance->form->addText('client_phone') + ->addRule($instance->form::REQUIRED, '%name is required') + ->addRule($instance->form::MAX_LENGTH, "%name shoud be not longer than 12 numbers', 12 "); + + $instance->save(); +} +``` + ## Templates ## ##### Form template ##### diff --git a/composer.json b/composer.json deleted file mode 100644 index 9adb1d5..0000000 --- a/composer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "develtio/develtio-wp-forms", - "description": "Make forms doable", - "type": "wordpress-muplugin", - "license": "MIT", - "keywords": ["wordpress", "plugin", "forms", "nette"], - "homepage": "https://develtio.com", - "require": { - "composer/installers": "~1.0", - "nette/forms": "^3.0" - }, - "authors": [ - { - "name": "Develtio", - "homepage": "https://develtio.com" - }, - { - "name": "Michaล‚ Malinowski", - "email": "mki.malinowski@gmail.com" - } - ], - "autoload": { - "psr-4": { - "Develtio\\WP\\Forms\\": "./inc" - } - } -} diff --git a/composer.lock b/composer.lock deleted file mode 100644 index fdbaef7..0000000 --- a/composer.lock +++ /dev/null @@ -1,436 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "29e1cafce5905fac224e9d3c959a8ce3", - "packages": [ - { - "name": "composer/installers", - "version": "v1.9.0", - "source": { - "type": "git", - "url": "https://github.com/composer/installers.git", - "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/b93bcf0fa1fccb0b7d176b0967d969691cd74cca", - "reference": "b93bcf0fa1fccb0b7d176b0967d969691cd74cca", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0" - }, - "replace": { - "roundcube/plugin-installer": "*", - "shama/baton": "*" - }, - "require-dev": { - "composer/composer": "1.6.* || 2.0.*@dev", - "composer/semver": "1.0.* || 2.0.*@dev", - "phpunit/phpunit": "^4.8.36", - "sebastian/comparator": "^1.2.4", - "symfony/process": "^2.3" - }, - "type": "composer-plugin", - "extra": { - "class": "Composer\\Installers\\Plugin", - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Installers\\": "src/Composer/Installers" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kyle Robinson Young", - "email": "kyle@dontkry.com", - "homepage": "https://github.com/shama" - } - ], - "description": "A multi-framework Composer library installer", - "homepage": "https://composer.github.io/installers/", - "keywords": [ - "Craft", - "Dolibarr", - "Eliasis", - "Hurad", - "ImageCMS", - "Kanboard", - "Lan Management System", - "MODX Evo", - "MantisBT", - "Mautic", - "Maya", - "OXID", - "Plentymarkets", - "Porto", - "RadPHP", - "SMF", - "Thelia", - "Whmcs", - "WolfCMS", - "agl", - "aimeos", - "annotatecms", - "attogram", - "bitrix", - "cakephp", - "chef", - "cockpit", - "codeigniter", - "concrete5", - "croogo", - "dokuwiki", - "drupal", - "eZ Platform", - "elgg", - "expressionengine", - "fuelphp", - "grav", - "installer", - "itop", - "joomla", - "known", - "kohana", - "laravel", - "lavalite", - "lithium", - "magento", - "majima", - "mako", - "mediawiki", - "modulework", - "modx", - "moodle", - "osclass", - "phpbb", - "piwik", - "ppi", - "puppet", - "pxcms", - "reindex", - "roundcube", - "shopware", - "silverstripe", - "sydes", - "sylius", - "symfony", - "typo3", - "wordpress", - "yawik", - "zend", - "zikula" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2020-04-07T06:57:05+00:00" - }, - { - "name": "nette/component-model", - "version": "v3.0.1", - "source": { - "type": "git", - "url": "https://github.com/nette/component-model.git", - "reference": "66409cf5507c77edb46ffa88cf6a92ff58395601" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/component-model/zipball/66409cf5507c77edb46ffa88cf6a92ff58395601", - "reference": "66409cf5507c77edb46ffa88cf6a92ff58395601", - "shasum": "" - }, - "require": { - "nette/utils": "^2.5 || ^3.0", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "โš› Nette Component Model", - "homepage": "https://nette.org", - "keywords": [ - "components", - "nette" - ], - "time": "2020-04-21T13:48:20+00:00" - }, - { - "name": "nette/forms", - "version": "v3.0.6", - "source": { - "type": "git", - "url": "https://github.com/nette/forms.git", - "reference": "ecb5f7b8c82585c5fc4698ccb6815542fe6b2db4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/forms/zipball/ecb5f7b8c82585c5fc4698ccb6815542fe6b2db4", - "reference": "ecb5f7b8c82585c5fc4698ccb6815542fe6b2db4", - "shasum": "" - }, - "require": { - "nette/component-model": "^3.0", - "nette/http": "^3.0", - "nette/utils": "^3.0", - "php": ">=7.1" - }, - "conflict": { - "nette/di": "<3.0-stable" - }, - "require-dev": { - "latte/latte": "^2.8", - "nette/application": "^3.0", - "nette/di": "^3.0", - "nette/tester": "^2.0", - "phpstan/phpstan-nette": "^0.12", - "tracy/tracy": "^2.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "?? Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server & client side validation and mature design.", - "homepage": "https://nette.org", - "keywords": [ - "Forms", - "bootstrap", - "csrf", - "javascript", - "nette", - "validation" - ], - "time": "2020-07-13T12:29:50+00:00" - }, - { - "name": "nette/http", - "version": "v3.0.4", - "source": { - "type": "git", - "url": "https://github.com/nette/http.git", - "reference": "e4d8d360c66c8af9512ca13ab629d312af2b3ce3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/http/zipball/e4d8d360c66c8af9512ca13ab629d312af2b3ce3", - "reference": "e4d8d360c66c8af9512ca13ab629d312af2b3ce3", - "shasum": "" - }, - "require": { - "nette/utils": "^3.1", - "php": ">=7.1" - }, - "conflict": { - "nette/di": "<3.0.3" - }, - "require-dev": { - "nette/di": "^3.0", - "nette/security": "^3.0", - "nette/tester": "^2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.4" - }, - "suggest": { - "ext-fileinfo": "to detect type of uploaded files", - "nette/security": "allows use Nette\\Http\\UserStorage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "๐ŸŒ Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.", - "homepage": "https://nette.org", - "keywords": [ - "cookies", - "http", - "nette", - "proxy", - "request", - "response", - "security", - "session", - "url" - ], - "time": "2020-03-31T13:31:41+00:00" - }, - { - "name": "nette/utils", - "version": "v3.1.2", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "488f58378bba71767e7831c83f9e0fa808bf83b9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/488f58378bba71767e7831c83f9e0fa808bf83b9", - "reference": "488f58378bba71767e7831c83f9e0fa808bf83b9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "~2.0", - "phpstan/phpstan": "^0.12", - "tracy/tracy": "^2.3" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0-only", - "GPL-3.0-only" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "๐Ÿ›  Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "time": "2020-05-27T09:58:51+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "1.1.0" -} diff --git a/handlers/StepFirstHandleRequest.php b/handlers/StepFirstHandleRequest.php new file mode 100644 index 0000000..7feecb7 --- /dev/null +++ b/handlers/StepFirstHandleRequest.php @@ -0,0 +1,27 @@ +request = $request; + $this->form = $form; + } + + public static function handle() + { + /** + * Logic goes here + */ + + return [ + 'success' => 'true', + 'token' => 'generated_token' + ]; + } + + +} \ No newline at end of file diff --git a/inc/Init.php b/inc/Init.php index cbadc67..4ac9dde 100644 --- a/inc/Init.php +++ b/inc/Init.php @@ -18,7 +18,6 @@ public static function get_services() Core\Pages\Dashboard::class, Core\Base\Enqueue::class, Core\Base\SettingsLinks::class, - Modules\Forms\Init::class, ]; } diff --git a/inc/Modules/Forms/CreateForm.php b/inc/Modules/Forms/CreateForm.php index 35dc826..dee4f48 100644 --- a/inc/Modules/Forms/CreateForm.php +++ b/inc/Modules/Forms/CreateForm.php @@ -72,13 +72,23 @@ class CreateForm extends BaseController */ public $mail; + /** + * Rest Api class + * @var RestApi + */ + public $rest_api; + + public $custom_handler = null; + /** * Options form customizing features and properties * @var array */ public $options = [ 'send_mail' => true, - 'send_confirm_mail' => false + 'send_confirm_mail' => false, + 'rest_api' => false, + 'create_cpt' => true ]; /** @@ -96,8 +106,18 @@ public function __construct( $form_name, $options = [] ) $this->mail = new Mail($this); $this->form_name = $form_name; $this->form_slug = sanitize_title( $form_name ); - $this->custom_post_types = new CustomPostType(); + if($this->options['create_cpt']) { + $this->custom_post_types = new CustomPostType(); + } + + if($this->options['rest_api']) { + $this->rest_api = new RestApi(); + } + + if(isset($this->options['custom_handler'])) { + $this->custom_handler = $this->options['custom_handler']; + } } /** @@ -106,15 +126,22 @@ public function __construct( $form_name, $options = [] ) public function save() { $this->setShortcode(); - $this->custom_post_types->storeCustomPostTypes( $this ); + if($this->options['create_cpt']) { + $this->custom_post_types->storeCustomPostTypes($this); + } + + if($this->options['rest_api']) { + $this->rest_api->exposeObject($this, $this->custom_handler); + } if ( isset( $_POST ) && !is_admin() && $this->form->isSubmitted() && $this->form->isSuccess() ) { $this->form_values = $this->form->getValues(); if ( $this->options['send_mail'] ) $this->mail->proceed(); - add_action( 'init', [ $this, 'saveFormData' ] ); - + if($this->options['create_cpt']) { + add_action('init', [$this, 'saveFormData']); + } } } diff --git a/inc/Modules/Forms/CustomPostType.php b/inc/Modules/Forms/CustomPostType.php index 3edd988..5834bf2 100644 --- a/inc/Modules/Forms/CustomPostType.php +++ b/inc/Modules/Forms/CustomPostType.php @@ -50,7 +50,6 @@ class CustomPostType extends BaseController */ public function registerCustomPostTypes() { - foreach ( $this->custom_post_types as $post_type ) { register_post_type( $post_type['name'], $post_type['args'] ); } @@ -65,6 +64,7 @@ public function registerCustomPostTypes() */ public function storeCustomPostTypes( CreateForm $instance ) { + $this->form_instance = $instance; $this->post_type_name = $instance->post_type_prefix . $instance->form_slug; $this->form_components = $instance->form->getComponents(); @@ -74,6 +74,7 @@ public function storeCustomPostTypes( CreateForm $instance ) return; } + array_push( $this->custom_post_types, [ 'name' => $this->post_type_name, @@ -92,7 +93,7 @@ public function storeCustomPostTypes( CreateForm $instance ) ); if ( !empty( $this->custom_post_types ) ) { - add_action( 'init', [ $this, 'registerCustomPostTypes' ] ); + add_action( 'init', [ $this, 'registerCustomPostTypes' ], 100 ); $this->meta_box = new MetaBoxApi(); $this->meta_box->init( diff --git a/inc/Modules/Forms/Init.php b/inc/Modules/Forms/Init.php index 6dcdfe8..3ddadba 100644 --- a/inc/Modules/Forms/Init.php +++ b/inc/Modules/Forms/Init.php @@ -18,7 +18,7 @@ public function init() { $option = get_option('develtio_plugin'); - if(!$option['develtio_forms']) return; + if(!isset($option['develtio_forms'])) return; $this->register_services(); } diff --git a/inc/Modules/Forms/Mail.php b/inc/Modules/Forms/Mail.php index 544c51e..74888d6 100644 --- a/inc/Modules/Forms/Mail.php +++ b/inc/Modules/Forms/Mail.php @@ -98,7 +98,7 @@ public function __construct(CreateForm $form) protected function setMailer() { - if(SMTP_HOST && SMTP_PORT && SMTP_USERNAME && SMTP_PASSWORD) { + if(defined('SMTP_HOST') && defined('SMTP_PORT') && defined('SMTP_USERNAME') && defined('SMTP_PASSWORD')) { $this->mailer = new Swift_Mailer(( new Swift_SmtpTransport( SMTP_HOST, SMTP_PORT, SMTP_ENCRYPTION ) ) ->setUsername( SMTP_USERNAME ) ->setPassword( SMTP_PASSWORD )); diff --git a/inc/Modules/Forms/RestApi.php b/inc/Modules/Forms/RestApi.php new file mode 100644 index 0000000..f8195ed --- /dev/null +++ b/inc/Modules/Forms/RestApi.php @@ -0,0 +1,93 @@ +form_instance = $instance; + $this->post_type_name = $instance->post_type_prefix . $instance->form_slug; + + $this->custom_handler = $customHandler; + + add_action('rest_api_init', [$this,'registerAPIRoute']); + return $this; + } + + public function registerAPIRoute() + { + register_rest_route('develtio/v1', '/form/' . $this->post_type_name, + array( + 'methods' => 'POST', + 'callback' => [$this, 'handleRoute'], + 'permission_callback' => '__return_true', + ) + ); + } + + public function handleRoute(\WP_REST_Request $request) + { + $this->form_instance->form->validate(); + $errors = $this->form_instance->form->getErrors(); + + if(!empty($errors)){ + $response = new \WP_REST_Response([ + 'success' => 'false', + 'errors' => $errors + ]); + $response->set_headers(array('Cache-Control' => 'no-cache')); + return $response; + } + + if ( $this->form_instance->options['send_mail'] ){ + $this->form_instance->mail->proceed(); + + $response = new \WP_REST_Response([ + 'success' => 'true' + ]); + $response->set_headers(array('Cache-Control' => 'no-cache')); + return $response; + } + + $customResponse = []; + if($this->custom_handler){ + require_once $this->custom_handler[1].$this->custom_handler[0].'.php'; + $responseObject = new $this->custom_handler[0]($request, $this->form_instance); + $customResponse = $responseObject->handle(); + } + + $response = new \WP_REST_Response($customResponse); + $response->set_headers(array('Cache-Control' => 'no-cache')); + $response->set_status(200); + return $response; + } + +}