I'm creating a Booking form in Wordpress which will send the data to an external CRM (Airship in this case) whilst also storing the data inside the Wordpress CMS that can then be emailed automatically.
Currently I've tried Contact Form 7 and a few other plugins, but this requires its own action="/?page_id=1327&preview=true#wpcf7-f1326-p1327-o1" (just as a page preview whilst building).
Airship CRM also has it's own action="http://atwbar.com/linkitajax.php" required to submit data.
Any suggestions/advice would be HUGELY appreciated!
when I want to save some special data, process a form to a crm or just redirect all my forms, I use the Contact form 7 hook : wpcf7_before_send_mail
Here is an example to redirect any form to a page (extract from an utility plugin I've done, so, don't take care about unset and session lines, options...).
add_action('wpcf7_before_send_mail', 'mail_send_redirection');
function mail_send_redirection($contactform){
$submission = WPCF7_Submission::get_instance();
if($options['_redirect_all_forms'] == 'false' && $contact_form->prop( 'redirection_settings' ) == 'false'){
return;
}
$redirection_form_id = $contact_form->prop( 'redirection_settings' );
$redirection_page_id = (empty($redirection_form_id)) ? $options['_thank_you_url'] : $redirection_form_id;
$nonce = wp_create_nonce('redirect-user-action');
if($contact_form->prop( 'redirection_message' ) != ''){
$args = array(
'html' => false,
'exclude_blank' => false );
$message = wpcf7_mail_replace_tags( $contact_form->prop( 'redirection_message' ), $args );
unset($_SESSION['bcf7u_nonce']);
unset($_SESSION['bcf7u_message']);
unset($_SESSION['bcf7u_pageid']);
$_SESSION['_nonce'] = $nonce;
$_SESSION['_pageid'] = $redirection_page_id;
$_SESSION['_message'] = $message;
}
$contact_form->skip_mail = false;
$contact_form->set_properties(
array(
'additional_settings' => "on_sent_ok: \"location.replace('" . get_permalink($redirection_page_id) . "/?nonce=" . $nonce . "');\""));
}
To save a form field, just use update_post_meta.
There are other method to send a request base on wp_ajax_no_priv_{$action} action and js.
Tell me if it's helps you, or if you need some more hints !
Related
I would like to extend the woocommerce rest api to include data of its 'booking' extension plugin. Currently this extension does not have default endpoints provided by the rest api.
So far I have created a plugin, and I've added the following code;
add_filter( 'woocommerce_rest_prepare_product', 'custom_data');
function custom_data($response, $object) {
if( empty( $response->data ) )
return $response;
$response->data['meta_data'] = get_post_meta( $object[ID], 'availability', true);
return $response;
}
When I call the end point /products only the default data outlined by woocommerce is still called my little add on is no where to be found.
I don't even know where to find the above filter as I just saw this posted on a webpage and I tried to get it to do what I wanted, don't know if this is the correct direction to go down either. Webpage: https://francescocarlucci.com/woocommerce/woocommerce-api-custom-data-default-endpoints/#more-96
The above was me trying to extend the api but I also decided to try making a custom endpoint to see if I can get my desired outcome but so far I've just made a endpoint which calls but I have no idea what to write to retrieve the data I want.
custom end point code:
function register_custom_route() {
register_rest_route( 'ce/v1', '/bookable',
array(
'methods' => 'GET',
'callback' => 'get_bookable'
)
);
}
function get_bookable( ) {
return array( 'custom' => 'woocommerce here' );
//What code do I write here :(
}
Is there anyway I can achieve what I want under one of the above methods?
I'm quite new to dev and I'm familiar with javascript not PHP hence my need to want to use the rest api as I would like to use wordpress/woocommerce as a headless cms.
So far the closets example I've come to has been shown on this question Creating WooCommerce Custom API
Alternatively you can try the below code to extend product response of WooCommerce REST API without doing additionally, as your above hook "woocommerce_rest_prepare_product" is for v1 but currently it was v3 so the hook for the latest is below one(the below hook is from v2 controller of rest api which is extended by v3).
add_filter('woocommerce_rest_prepare_product_object', 'so54387226_custom_data', 10, 3);
function so54387226_custom_data($response, $object, $request) {
if (empty($response->data))
return $response;
$id = $object->get_id(); //it will fetch product id
$response->data['booking_meta_data'] = get_post_meta($id, 'availability', true);
return $response;
}
I tested the above code it works perfectly fine. Hope it may helps to someone who search for similar solution.
this is only part of my code. some variable not defined. and this just concept. hopefully, you can modify as per your requirement.
public function __construct() {
$this->template_url = apply_filters( 'woocommerce_template_url', 'woocommerce/'
);
$this->api_namespace = 'wc/v';
$this->base = 'home';
$this->api_version = '2';
add_action( 'woocommerce_loaded', array( $this, 'register_hooks' ) );
}
$namespace = $this->api_namespace . $this->api_version;
register_rest_route(
$namespace, '/wclogin/',
array(
'methods' => 'GET',
'callback' => array( $this, 'wc_login'),
)
);
function wc_login($request){
$user = get_user_by('email', $request["email"]);
//bad email
if(!$user){
$error = new WP_Error();
$error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
return $error;
}
else{ //check password
if(!wp_check_password($request["password"], $user->user_pass, $user->ID)){ //bad password
$error = new WP_Error();
$error->add('invalid', __('<strong>ERROR</strong>: Either the email or password you entered is invalid.'));
return $error;
}else{
return $user; //passed
}
}
}
Just an update for those that come to this question. Now, there is a rest api for the booking extension: https://docs.woocommerce.com/document/bookings-rest-api-reference/
I am using contact form 7 to submit a form and generate a reference number through soap client using the wpcf7_before_send_mail.
The code is
function wpcf7_do_something($WPCF7_ContactForm)
{
if (3490 == $WPCF7_ContactForm->id()) {
$client = new SoapClient('http://xxx.xxx.xxx.xxx:xxxxx/4dwsdl', array('trace' => 1));
$res_date = date("Y-m-d", strtotime('01 feb 2015'));
$enquiry_id = $client->__call('WS_AddContact',
array(
'narwal Devender',
null,
'Devender',
'narwal',
'hisar',
'Hisar',
'Haryana',
'125001',
'Australia',
'01662246138',
'9802260750',
'8529000369',
'vijaylal#webmastershisar.com',
true,
'google',
'google',
'Phone Call',
0,
'type of good should be strode.',
$res_date,
'2 to 6 Months',
'SSPSS',
null,//array('xxxxxxx'),
array('46.75'),
array('1 x 1 x 1 (1qm)'),
array('xxxxxxxxx'),
array('send print should be here to work.'),
null,
'xxxxxxxxxxxxx',
null
)
);
mail('vijaylal#webmastershisar.com', 'My Subject', $enquiry_id);
}
return $wpcf7;
}
This is working fine and sending email.
But I want to show the enquiry id to the custom on thankyou page or any page or by using some redirect and sending data to the url.
I am also trying to use this code in wpcf7_mail_sent this also work,
But when I am trying to use redirect It does nothing and contact form hangs simply.
add_action('wpcf7_mail_sent', 'wpcf7_redirect_on_submit');
function wpcf7_redirect_on_submit($wpcf7)
{
header( 'Location: http://www.google.com' );
exit;
}
How can I redirect contact form in wpcf7_mail_sent without using javascript or jQuery on_sent_ok?
or
How can I show this Enquiry id to the user on a page?
Can anybody please help to get this work done.
You can also used an available hook to change properties
add_filter( 'wpcf7_contact_form_properties', 'let_me_redirect', 10, 2 );
/**
* Add the code that will run when on_sent_ok is triggered;
*/
function let_me_redirect( $properties, $contact_form_obj){
$properties[ 'additional_settings' ] .="on_sent_ok: \"location.replace('http://www.google.com');\""
;
return $properties;
}
I have created a form in Drupal using its API. The theme is overridden by a template. In the template, I want to show errors where the form exists, I do not want to show the error using drupal's form_set_error() because it shows the error in a fixed default area of the page.
This is my implementation of hook_form()
function newsletter_box($form, &$form_state)
{
$form = array();
$form["newsletter-email"] = array(
"#type" => "textfield",
"#maxlength" => 32,
"#title" => "Your Email"
);
$form['send-email'] = array(
"#type" => "submit",
"#value" => t("Join Our Newsletter!")
);
return $form;
}
And this is my implementation of hook_submit()
function newsletter_box_submit($form, &$form_state)
{
if( !filter_var($form_state['values']["newsletter-email"], FILTER_VALIDATE_EMAIL) )
{
$form_state['build_info']['args'] = ['form-error' => t("Email not formatted correctly.") ];
// NOTE: here is the place where the error is set, rather I use to set a new variable, but this variable is not available in my template. Why?
}
$form_state['rebuild'] = TRUE;
drupal_form_submit("newsletter_box", $form_state);
}
Suggest adding the variable by implementing a hook_preprocess, and add the error message into form rather than form_state.
Example:
// Set in newsletter_box_submit or newsletter_box_validate
$form['#form_error'] = t("Email not formatted correctly.");
/**
* Implements hook_preprocess_HOOK().
*/
function [module_name]_preprocess_newsletter_box(&$vars) {
$form = $vars['form'];
$error_message = $form['#form_error'];
// Use $error_message in template.
}
It feels like a hack though, strongly recommend theming the form the Drupal way.
I have edit form for entity. There is element
$feedback = new FeedbackViewer('Feedback');
$feedback->setLabel('Feedback')->setRequired(false);
$feedback->setPostId($this->testimonialId);
$feedback->setAppId($this->config->testimonials->appId);
$feedback->setIgnore(true);
$this->addElement($feedback);
This feedback viewer loads iframe with another zf datagrid that shows feedbacks inside the form.
I use this form in ZF datagrid
$entityId = $this->getRequest()->getParam('edit');
if ($entityId) {
$entityForm = call_user_func($formCallback, $entityId);
$form->setUsePreDefinedFormElements(true);
$form->setForm($entityForm);
}
But ZF datagrid after saving action triggers error Validation failed. Removing the feedbacks element makes it saving correctly.
any suggestions?
$grid->setForm($form);
if($action != 'show') {
$form->getForm()->getElement('form_reset')->setLabel(null);
$form->getForm()->getElement('form_submit')->setLabel(null);
$gridParam = $this->getRequest()->getParam('grid');
$startParam = $this->getRequest()->getParam('start');
if ($gridParam) {
if ($gridParam == 'all') {
$gridParam = 'index';
}
// Attach to event listener custom redirect action
$grid->listenEvent('crud.after_update', array($this, 'setGridRedirectCallback'), array('action' => $gridParam, 'page' => $startParam));
$grid->listenEvent('crud.after_delete', array($this, 'setGridRedirectCallback'), array('action' => $gridParam));
$form->getForm()->getElement('form_reset')->setAttribs(array('onclick' => 'window.location.href = "/admin/' . $gridParam . (($startParam) ? '/start/' . $startParam : '') . '";'));
}
I solved this issue with putting this in If tags, couldn't find better solution.
We have built custom forms and at this stage are built very well with a lot of thought. Each class has its own responsibility and so far the basic principle of OOP concepts have been used i.e. inheritance, polymorphism, encapsulation, etc. Each element of the form is an object and all objects are collected and initiated on the fly.
Now weve got to the processing part of the forms we at a loss for a strategy to deal with this and would like to ask if anyone has any pointers please?
Is there an alternative, say for instance the creation of a class that could be responsible for checking if the form has been submit and methods to gather post data, validate, etc or do people still do the old way like a quick conditional in the client to check if form submit:
if(isset($_POST["var"])
{
//process form
} else {
//show form
}
And would it be best to use a separate action page to process?
Bascially what I dont want to do is have to write some awful code thats not reusable or make use of OOP concepts. We would like to achieve something WITHOUT USING ANY FRAMEWORKS.
I would try to go with structure like this :
// public function __construct( ValidatorInterface $validator )
$form = new Form( new Validator );
// public function add_field( $name , array $rules = array() )
$form->add_field(
'name',
// that would be $_POST['name'] , and in template file <?php echo $name ?>
array(
'required' => 'Full Name is required'
// for validator to execute is_required()
));
$form->add_field(
'email' ,
array(
'required' => 'Email Address is required',
'email' => 'A valid email address is required'
// for validator to execute is_email()
));
$form->add_field( 'country' );
//name of submit button
$for->add_submitter( 'submit' );
// etc
$page = new Template();
$page->use_file( 'contact.php' );
if( $form->is_submitted() )
{
// gathers all the $_POST's from registered fields
$form->collect();
if ($form->is_valid() )
{
$page->use_file( 'done.html' );
// do some stuff
}
else
{
// public function populate( TemplateInterface $template )
// assigns field values and error messages to the template
$form->populate( $page );
}
}
echo $page->render();
And the Template class based upon this code : http://codeangel.org/articles/simple-php-template-engine.html
update
Implementation for method that registers new fields
public function add_field( $name , array $rules = array() )
{
if ( !array_key_exists( $name , $this->_fields ))
{
$this->_fields[ $name ] = array();
}
$this->_fields[ $name ]['rules'] = $rules;
}
Implementation for method that finds values of all the registered fields
public function collect()
{
$field_names = array_keys( $this->_fields );
foreach ( $field_names as $name )
{
$this->_fields[ $name ]['value'] = $this->_collect_value( $name );
}
}
protected function _collect_value($name)
{
$value = null;
if ( isset( $_POST[ $name ] ) )
{
$value = $_POST[$name];
}
$value = trim( $value );
if ( empty( $value ) ){
$value = null;
}
return $value;
}
The data collection is pretty simple process.
And on the is_valid() method call if get the Validator instance from local variable and performs actions on each registered form field ( mostly with helpfule php filter_var() function.
You're all missing very important concept. You don't want to show form, you want to ask user for some input. You actually want something like this:
$rules = array(
"name" => array("not_empty"),
"email" => array("not_empty", "email")
);
$callback = array($this, "handle_valid_post_data");
$ui->request_input($rules, $callback);
Sadly, no framework does this so you have to implement it yourself.