Ajaxify WP Options - Problems with using jquery serialize and checkboxes - wordpress

i've been working on a theme options panel for wordpress. but i've run into a bug when i start using more than 1 checkbox as an option.
my code uses jquery to serialize all the form data and then submit it to wp's ajax-url. then i add a callback function and WP knows to send the data to the function i have set up to save the options to the DB.
it works when i check the boxes ON, hit save and no problem. the values are saved. but now that the boxes are checked if i try to uncheck 1 or 2 of the 3 and click save... then on refresh the boxes are still checked. the values are still 'ON' in the DB. I think this is b/c jquery doesn't serialize unchecked checkboxes, so they aren't be passed to the update_option array. since they aren't in the update_option array the values for those keys stays the same as is currently in the DB. hence, no change. strangely (to me atleast) if i uncheck all 3 of my test checkboxes then it does update properly.
so, i am looking for a work around that will update the options with the correct values and remove checkbox values that have been unchecked.
<?php
add_action('admin_menu', 'test_add_theme_page');
function test_add_theme_page() {
if ( isset( $_GET['page'] ) && $_GET['page'] == basename(__FILE__) ) {
add_action('admin_head', 'test_theme_page_head');
}
add_theme_page(__('Test Admin'), __('Test Admin'), 'edit_themes', basename(__FILE__), 'test_theme_page');
}
function test_theme_page_head() {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
jQuery('form#test_form').submit(function() {
var data = jQuery(this).serialize();
alert(data);
jQuery.post(ajaxurl, data, function(response) {
if(response == 1) {
show_message(1);
t = setTimeout('fade_message()', 2000);
} else {
show_message(2);
t = setTimeout('fade_message()', 2000);
}
});
return false;
});
});
function show_message(n) {
if(n == 1) {
jQuery('#saved').html('<div id="message" class="updated fade"><p><strong><?php _e('Options saved.'); ?></strong></p></div>').show();
} else {
jQuery('#saved').html('<div id="message" class="error fade"><p><strong><?php _e('Options could not be saved.'); ?></strong></p></div>').show();
}
}
function fade_message() {
jQuery('#saved').fadeOut(1000);
clearTimeout(t);
}
</script>
<?php
}
function test_theme_page() {
?>
<div class="wrap">
<h2><?php _e('Test Admin'); ?></h2>
<div id="saved"></div>
<?php $options = get_option('test_theme');
echo "<br>";
print_r($options);
echo"<br>";
?>
<form action="/" name="test_form" id="test_form">
Text<input type="text" name="test_text" value="<?php echo $options['test_text']; ?>" /><br />
Check1<input type="checkbox" name="test_check1" <?php echo ($options['test_check1'] == 'on') ? 'checked' : ''; ?> /><br />
Check2<input type="checkbox" name="test_check2" <?php echo ($options['test_check2'] == 'on') ? 'checked' : ''; ?> /><br />
Check3<input type="checkbox" name="test_check3" <?php echo ($options['test_check3'] == 'on') ? 'checked' : ''; ?> /><br />
<input type="hidden" name="action" value="test_theme_data_save" />
<input type="hidden" name="security" value="<?php echo wp_create_nonce('test-theme-data'); ?>" />
<input type="submit" value="Submit" />
</form>
</div>
<?php
}
add_action('wp_ajax_test_theme_data_save', 'test_theme_save_ajax');
function test_theme_save_ajax() {
check_ajax_referer('test-theme-data', 'security');
$data = $_POST;
unset($data['security'], $data['action']);
if(!is_array(get_option('test_theme'))) {
$options = array();
} else {
$options = get_option('test_theme');
}
if(!empty($data)) {
$diff = array_diff($options, $data);
$diff2 = array_diff($data, $options);
$diff = array_merge($diff, $diff2);
} else {
$diff = array();
}
if(!empty($diff)) {
if(update_option('test_theme', $data)) {
die('1');
} else {
die('0');
}
} else {
die('1');
}
}
you can see the full code here
http://pastebin.com/BCHwsBi5

was apparently 1. over-complicating things and 2. not understanding that update_option returns TRUE on an update and returns FALSE if there is no change and NOT on failure.
here's the corrected test_theme_save_ajax() function:
function test_theme_save_ajax() {
check_ajax_referer('test-theme-data', 'security');
$data = $_POST;
unset($data['security'], $data['action']);
update_option('test_theme', $data);
die('1');
}

Related

Wordpress backend form returns JSON

I developed a small one-file plugin for a wordpress site. It's just adds an upload form for a file that POSTs to itself and then does some stuff with the file's contents once submitted.
It works fine on the staging environment, but on the live server there is a strange problem. Once I submit the form with the file the server does not bring me back to the same page but instead returns the following JSON:
{"success":false,"message":"Please enter a message."}
I am at loss what could be causing this. Has anybody come across such a problem?
The (simplified plugin):
function show_upload_form() {
if ($_FILES['userfile']) {
echo "<p>file received</p>";
$file = fopen($_FILES['userfile']['tmp_name'], "r");
$data = [];
while (!feof($file)) {
$data[] = fgetcsv($file,null,';');
}
foreach ($data as $line) {
$pid = $line[0];
if (isset($line[1])) {
$price = trim(str_replace(',', '.', $line[1]));
} else {
$price = "";
}
if (isset($line[2])) {
$title = trim(iconv("ISO-8859-1", "UTF-8", $line[2]));
} else {
$title = "";
}
global $wpdb;
$product_ids = $wpdb->get_results($wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s'", $pid));
foreach ($product_ids as $product_id) {
$elem = $product_id->post_id;
if ($price != "") {
update_post_meta($elem, '_price', $price);
update_post_meta($elem, '_sale_price', $price);
update_post_meta($elem, '_regular_price', $price);
}
if ($title != "") {
wp_update_post(array(
'ID' => $elem,
'post_title' => $title,
));
}
}
echo "<p>Produkt #".$pid;
if ($price != "") {
echo " - new price: ".$price."€";
}
if ($title != "") {
echo "- new title: ".$title;
}
}
} else {
echo "<form method=\"post\" enctype=\"multipart/form-data\">";
echo "<label for=\"file\">Select a file:</label>";
echo "<input type=\"file\" name=\"userfile\" id=\"file\">";
echo "<br /><br />";
echo "<button>Upload File</button>";
echo "<form>";
}
}
I appreciate any input.
Try something like this
<form action="<?=admin_url( 'admin-post.php' ) ?>" method="POST">
<input type="hidden" name="action" value="my_custom_plugin_action"/>
<input type="submit" value="SEND"/>
</form>
add_action( 'admin_post_nopriv_my_custom_plugin_action',array( "class_that_owns_that_function", 'show_upload_form' ) );
public function show_upload_form()
{
//Here write your code
}
Problem disappeared after deactivating and individually reactivating all the plugins for the second or third time. Guess this one will remain a mystery ...

WordPress POST action is null

I'm trying to make a simple login form for my WordPress theme. I thought I followed WP documentation correctly, but I'm seeing that my forms action is not being detected.
I can see in my error log 'got here 1' is printing. Looking at process_form.php below, this condition should indicate that my user is not logged in and that action is empty.
I believed that this line from my form processing code:
add_action( 'admin_post_nopriv_streamLogForm', 'showroom_login_user' );
and this line from my actual form
<input type="hidden" name="action" value="streamLogForm">
would interact to bind the form action to this admin_post hook.
The showroom_login_user() function works and my GET variables actually seem to be working (at first I thought they were not), but still not sure why I'm reaching this condition.
login.php
<head>
<script type="text/javascript">
function validateLoginForm() {
var email = document.forms["streamLogForm"]["user_email"].value;
var password = document.forms["streamLogForm"]["user_password"].value;
if ( email == null || email == "" ) {
alert("User must be entered");
return false;
} else if ( password == null || password == "" ) {
alert("Password must be entered");
return false;
}
return true;
}
</script>
</head>
<div class="">
<form name="streamLogForm" id="streamLoginForm" onsubmit="return validateLoginForm()" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="get" >
<input type="hidden" name="action" value="streamLogForm">
<input type="hidden" name="location" value="<?php echo $URI ?>" />
<input type="hidden" name="action_type" value="<?php echo 'login'?>" />
<div class="field">
<label for="streamUserEmail">Email:</label>
<input type="text" id="streamUserEmail" name="user_email">
</div>
<div class="field">
<label for="streamUserPassword">Password: </label>
<input type="password" id="streamUserEmail" name="user_password">
</div>
<button> Login </button>
</form>
</div>
process_form.php
<?php
if ( ! wp_validate_auth_cookie() ) {
if ( empty( $action ) ) {
error_log('got here 1', 0);
do_action( 'admin_post_nopriv' );
} else {
error_log('got here 2', 0);
do_action( "admin_post_nopriv_{$action}" );
}
} else {
if ( empty( $action ) ){
error_log('got here 3', 0);
do_action( 'admin_post' );
} else {
error_log('got here 4', 0);
do_action( "admin_post_{$action}" );
}
}
function showroom_login_user()
{
error_log("GOT HERE 6!", 0);
$location = $_GET["action_type"];
$action_type = $_GET["action_type"];
$user_email = $_GET["user_email"];
$user_password = $_GET["user_password"];
echo 'testing......' . $user_email;
}
add_action( 'admin_post_nopriv_streamLogForm', 'showroom_login_user' );
add_action( 'admin_post_streamLogForm', 'showroom_login_user' );
?>
Update your form tag like this
<form name="streamLogForm" id="streamLoginForm" onsubmit="return validateLoginForm()" action="<?php echo admin_url('admin-ajax.php'); ?>" method="get" >
and place this snippet on your functions.php
function showroom_login_user() {
$creds = array();
$creds['user_login'] = $_GET["user_email"];
$creds['user_password'] = $_GET["user_password"];
$creds['remember'] = true;
$autologin_user = wp_signon( $creds, false );
if ( !is_wp_error($autologin_user) ) {
// "Logged In.!";
} else {
// "Log In Failed.!";
}
// do your redirect here
wp_safe_redirect( "URL of the page to be redirected" );
}
add_action ( 'wp_ajax_quick_streamLogForm', 'showroom_login_user' );
add_action ( 'wp_ajax_nopriv_streamLogForm', 'showroom_login_user' );

Create defaults to use in return in shortcode - Wordpress plugin

I'm making my first plugin to Wordpress which adds a shortcode that I can use in my header.
The plugin integrates with Wordpress option page. All admin related works fine including writing top wp_options table and/or delete/update fields.
My problem is in the custom shortcode itself (at the bottom).
What I want to achieve is, when get_option('bfcsc_logout_link') is not set in admin, a default value should be returned.
And of course, I am looking for the 'nice way', so my code looks good as well :) When the plugin works as I want to in the end, I'm thinking about taking it a step further and separate the code into init files etc, making it more professional.
Below is the full code (excluding assets):
<?php
/*
Plugin Name: Brokenfruit Custom Login Shortcode
Plugin URI: https://www.brokenfruit.dk/
Description: Adds custom login shortcode for Brokenfruit
Version: 1.0
Author: Kenn Nielsen
Author URI: https://www.brokenfruit.dk/
License: GPL
*/
// Meaning of abbreviations:
// bfclsc = brokenfruit custom login shortcode
/* Register styles and scripts */
function bfcsc_enqueue_scripts() {
global $wpdb;
$screen = get_current_screen();
if ( $screen->id != 'settings_page_brokenfruit-custom-shortcodes' )
return; // exit if incorrect screen id
wp_enqueue_style( 'brokenfruit-shortcodes-styles', plugins_url( '/css/styles.css', __FILE__ ) );
wp_enqueue_style( 'bootstrap', plugins_url( '/css/bootstrap.css', __FILE__ ) );
wp_enqueue_script('admin_js_bootstrap_hack', plugins_url( '/scripts/bootstrap-hack.js', __FILE__ ), false, '1.0.0', false);
}
add_action('admin_enqueue_scripts', 'bfcsc_enqueue_scripts' );
/* Runs when plugin is activated */
register_activation_hook(__FILE__,'bfcsc_install');
/* Runs on plugin deactivation*/
register_deactivation_hook( __FILE__, 'bfcsc_remove' );
function bfcsc_install() {
/* Creates new database field */
add_option('bfcsc_logout_link', '', '', 'yes');
add_option('bfcsc_login_link', '', '', 'yes');
add_option('bfcsc_account_link', '', '', 'yes');
}
function bfcsc_remove() {
/* Deletes the database field */
delete_option('bfcsc_logout_link');
delete_option('bfcsc_login_link');
delete_option('bfcsc_account_link');
}
if (is_admin() ) {
function add_bfcsc_option_page() {
add_options_page(
'Brokenfruit Custom Shortcodes', // The text to be displayed in the title tag
'Brokenfruit Custom Shortcodes', // The text to be used for the menu
'administrator', // The capability required to display this menu
'brokenfruit-custom-shortcodes', // The unique slug name to refer to this menu
'bfcsc_html_page'); // The function tooutput the page content
}
/* Call the html code */
add_action('admin_menu', 'add_bfcsc_option_page');
}
function bfcsc_html_page(){
?>
<form method="post" action="options.php">
<?php wp_nonce_field('update-options'); ?>
<div class="bootstrap-wrapper">
<div class="row top-buffer">
<div class="col-md-8">
<div><h1>Brokenfruit Custom Login Shortcode</h1></div>
<p>Til brug for shortcode:<br/><span class="shortcode-preview">[custom_login]</span></p>
<div class="top-buffer"></div>
<h5>Link til log ud:</h5><input placeholder="Eksempel: wp-login.php?action=logout" class="form-control" name="bfcsc_logout_link" type="text" id="bfcsc_logout_link" value="<?php echo get_option('bfcsc_logout_link'); ?>" /></td>
<div class="top-buffer"></div>
<h5>Link til log ind:</h5><input placeholder="Eksempel: /log-ind/" class="form-control" name="bfcsc_login_link" type="text" id="bfcsc_login_link" value="<?php echo get_option('bfcsc_login_link'); ?>" /></td>
<div class="top-buffer"></div>
<h5>Link til min konto:</h5><input placeholder="Eksempel: /min-brokenfruit/" class="form-control" name="bfcsc_account_link" type="text" id="bfcsc_account_link" value="<?php echo get_option('bfcsc_account_link'); ?>" /></td>
<input type="hidden" name="action" value="update" />
<input type="hidden" name="page_options" value="bfcsc_logout_link,bfcsc_login_link,bfcsc_account_link" />
<input class="btn btn-primary top-buffer" type="submit" value="<?php _e('Save Changes') ?>" />
</div>
</div>
</div>
</form>
<?php
}
/*---------------------------------------------------*/
/* Custom login shortcode - start */
/*---------------------------------------------------*/
function mydefaults (){
if (!get_option('bfcsc_logout_link')){
$logout_link = '/log-ud/';
} else {
$logout_link = get_option('bfcsc_logout_link');
}
if (!get_option('bfcsc_login_link')){
$login_link = '/log-ind';
} else {
$login_link = get_option('bfcsc_login_link');
}
if (!get_option('bfcsc_account_link')){
$account_link = '/min-brokenfruit/';
} else {
$account_link = get_option('bfcsc_account_link');
}
}
function custom_login_shortcode ( $atts ){
if ( is_user_logged_in() ) {
return '<i class="fa icon-user"></i>Mit Brokenfruit | <i class="fa icon-logout"></i>Log ud';
} else {
return '<i class="fa icon-login"></i>Log ind';
}
}
add_shortcode( 'custom_login', 'custom_login_shortcode' );
/*---------------------------------------------------*/
/* Custom login shortcode - end */
/*---------------------------------------------------*/
?>
Thank you all in advance!
Cheers Kenn
Correct. Your variable was not available inside that method.
As to the parameters, the shortcode api is not meant to work like that. The lone parameter $atts is used to pass the variables you need from the shortcode (the part inside the bracket) as an array.
I'm not sure how you're planning to use the shortcode. But you could pass your parameters with
[custom_login login='different_login' ]
then pick them up in the shortcode in the $atts array:
function custom_login_shortcode ( $atts ){
$a = shortcode_atts( array(
'login' => '/log-ind/', // default value for login
'account' => '/min-brokenfruit/', // default value for account
), $atts );
return $a['login']; // returns 'different_login'
return $a['account'] // returns '/min-brokenfruit/'
You could also define your variables as constants (with a global scope) so they are available inside your shortcode and all your methods:
define('MY_LOGIN_LINK','/log-ind');
Then you can use if (!defined('MY_LOGIN_LINK')) to see if you have something to work with. See http://php.net/manual/en/function.define.php for more on that.
But if you only need these values in this one method, this would work in your re-written code to streamline it a little:
$login_link = get_option('bfclsc_login_link','/log-ind/');
get_option() has an optional parameter for a default value:
$no_exists_value = get_option( 'no_exists_value', 'default_value' );
var_dump( $no_exists_value ); /* outputs 'default_value' */
https://codex.wordpress.org/Function_Reference/get_option
I found a solution.
I needed to put the content of function mydefaults into the function custom_login_shortcode. I guess my variables was created in the global state and could not be used?
After all, I don't understand why I could not pass the variables into the shortcode like:
function custom_login_shortcode ( $atts, $logout_link, $login_link, $account_link ){
Below is the working shortcode function:
/*---------------------------------------------------*/
/* Custom login shortcode - start */
/*---------------------------------------------------*/
/*function mydefaults (){
if (!get_option('bfclsc_logout_link')){
$logout_link = '/log-ud/';
} else {
$logout_link = get_option('bfclsc_logout_link');
}
if (!get_option('bfclsc_login_link')){
$login_link = '/log-ind';
} else {
$login_link = get_option('bfclsc_login_link');
}
if (!get_option('bfclsc_account_link')){
$account_link = '/min-brokenfruit/';
} else {
$account_link = get_option('bfclsc_account_link');
}
}*/
function custom_login_shortcode ( $atts ){
if (!get_option('bfclsc_logout_link')){
$logout_link = wp_logout_url( home_url()); //call wordpress logout with home redirect: wp_logout_url( home_url())
} else {
$logout_link = get_option('bfclsc_logout_link');
}
if (!get_option('bfclsc_login_link')){
$login_link = '/log-ind/';
} else {
$login_link = get_option('bfclsc_login_link');
}
if (!get_option('bfclsc_account_link')){
$account_link = '/min-brokenfruit/';
} else {
$account_link = get_option('bfclsc_account_link');
}
if ( is_user_logged_in() ) {
return '<i class="fa icon-user"></i>Mit Brokenfruit | <i class="fa icon-logout"></i>Log ud';
} else {
return '<i class="fa icon-login"></i>Log ind';
}
}
add_shortcode( 'custom_login', 'custom_login_shortcode' );
/*---------------------------------------------------*/
/* Custom login shortcode - end */
/*---------------------------------------------------*/

How to get the "really simple captcha" to work in a simple contact form?

I tried to create a simple contact form according to this tutorial
To avoid spam attacks I tried to combine that contact form with the really simple captcha plugin.
With the following code I'm able to use the shortcode [contact] in any of my pages and the form is displaying BUT there is a problem when checking the captcha.
This is the plugin's code:
function wptuts_get_the_ip() {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
return $_SERVER["HTTP_X_FORWARDED_FOR"];
}
elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
return $_SERVER["HTTP_CLIENT_IP"];
}
else {
return $_SERVER["REMOTE_ADDR"];
}
}
// short code function
function wptuts_contact_form_sc( $atts ) {
add_shortcode( 'contact', 'contact_form_shortcode' );
extract(shortcode_atts(array(
"email" => get_bloginfo('admin_email'),
"subject" => '',
"label_name" => 'Your Name',
"label_email" => 'Your E-mail Address',
"label_subject" => 'Your Answer',
"label_captcha" => 'Captcha',
"label_submit" => 'Submit',
"error_empty" => 'Please fill in all the required fields.',
"error_noemail" => 'Please enter a valid e-mail address.',
"success" => 'Thanks for your e-mail! We\'ll get back to you as soon as we can.'
), $atts));
$captcha_instance = new ReallySimpleCaptcha(); //imports really simple captcha plugin
$word = $captcha_instance->generate_random_word();
$prefix = mt_rand();
$image= $captcha_instance->generate_image( $prefix, $word );
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$error = false;
$required_fields = array("your_name", "email", "captcha", "subject");
foreach ($_POST as $field => $value) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$form_data[$field] = strip_tags($value);
}
foreach ($required_fields as $required_field) {
$value = trim($form_data[$required_field]);
if(empty($value)) {
$error = true;
$result = $error_empty;
}
}
if(!is_email($form_data['email'])) {
$error = true;
$result = $error_noemail;
}
if ($error == false) {
$captcha_text=$form_data['captcha'];
$correct = $captcha_instance->check( $prefix, $captcha_text );
if($correct==TRUE){
$email_subject = "[" . get_bloginfo('name') . "] " . $form_data['subject'];
$email_message = $form_data['captcha'] . "\n\nIP: " . wptuts_get_the_ip();
$headers = "From: ".$form_data['your_name']." <".$form_data['email'].">\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\n";
$headers .= "Content-Transfer-Encoding: 8bit\n";
wp_mail($email, $email_subject, $email_message, $headers);
$result = $success;
$sent = true;
}
}
}
if($result != "") {
$info = '<div class="info">'.$result.'</div>';
}
$email_form = '<form class="contact-form" method="post" action="'.get_permalink().'">
<div>
<label for="cf_name">'.$label_name.':</label>
<input type="text" name="your_name" id="cf_name" size="50" maxlength="50" value="'.$form_data['your_name'].'" />
</div>
<div>
<label for="cf_email">'.$label_email.':</label>
<input type="text" name="email" id="cf_email" size="50" maxlength="50" value="'.$form_data['email'].'" />
</div>
<div>
<label for="cf_subject">'.$label_subject.':</label>
<input type="text" name="subject" id="cf_subject" size="50" maxlength="50" value="'.$subject.$form_data['subject'].'" />
</div>
<div>
<label for="cf_message">'.$label_captcha.':</label>
<input type="text" name="captcha" id="cf_message" size="50" maxlength="50" value=""/>
</div>
<div id="captcha"><span id="captcha_text">Captcha:</span><img id="captcha_image" src="'.plugins_url("really-simple-captcha/tmp/" . $image) . '" alt="" /></div>
<div>
<input type="submit" value="'.$label_submit.'" name="send" id="cf_send" />
</div>
</form>';
if($sent == true) {
return $info;
} else {
return $info.$email_form;
}
}
add_shortcode('contact', 'wptuts_contact_form_sc');
// add plugins style to frontend
function prize_game_contact_form() {
wp_register_style('prize_game_contact_form', plugins_url('css/style.css',__FILE__));
wp_enqueue_style('prize_game_contact_form');
}
add_action('wp_enqueue_scripts', 'prize_game_contact_form');
I didn't add $captcha_instance->remove( $prefix ); so far because it works not as it should. It seems that every time I click on the submit button a new word is created and the function $captcha_instance->check() checks if the new word equals the captcha text in the input field but those words doesn't match of course because it's already a new word. I don't understand why a new word is created when clicking on the submit button. Where is the error?
I believe the problem is that you are generating a new $prefix each time the function runs. So there is no way to run the check() or the remove() because the $prefix used on the form is then a new value.
In your form, create a hidden input field with the value of the $prefix being used. So that value is posted with the form. When the function is run the 2nd time after the form post, use the posted $prefix value to do the check() and remove(). That should do it.
Here is a detailed article on how to integrate Really Simple Captcha plugin into your plugin or theme together with the hidden prefix field I just mentioned: http://www.lost-in-code.com/platforms/wordpress/wordpress-plugins/wordpress-using-really-simple-captcha/
Feel free to let me know if you need any assistance.
Are you using Wordpress? Do not try to reinvent the wheel.
Download a free plugin like Contact Form 7 which includes an Ajax powered (doesn't require page refresh) Askimet Spam Filter, plus CAPTCHA system.
CAPTCHA works only half as well as it did 3-5 years back.
My advise to you is this:
Do not look for simple, but look for what works.
if you're not using WordPress then you might check this simple form & captcha idea - if you can grab out the captcha part that is, captcha has become incredibly complex and over engineered when all it needs to do is differentiate simply between a human and non-human for most purposes.
You must create the variables $word, $prefix and $image only after you check the correctness of the user answer, and you must pass the $prefix value through a hidden input field. I haven't checked it, but this code should work now:
function wptuts_get_the_ip() {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
return $_SERVER["HTTP_X_FORWARDED_FOR"];
}
elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
return $_SERVER["HTTP_CLIENT_IP"];
}
else {
return $_SERVER["REMOTE_ADDR"];
}
}
// short code function
function wptuts_contact_form_sc( $atts ) {
add_shortcode( 'contact', 'contact_form_shortcode' );
extract(shortcode_atts(array(
"email" => get_bloginfo('admin_email'),
"subject" => '',
"label_name" => 'Your Name',
"label_email" => 'Your E-mail Address',
"label_subject" => 'Your Answer',
"label_captcha" => 'Captcha',
"label_submit" => 'Submit',
"error_empty" => 'Please fill in all the required fields.',
"error_noemail" => 'Please enter a valid e-mail address.',
"success" => 'Thanks for your e-mail! We\'ll get back to you as soon as we can.'
), $atts));
$captcha_instance = new ReallySimpleCaptcha(); //imports really simple captcha plugin
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$error = false;
$required_fields = array("your_name", "email", "captcha", "subject");
foreach ($_POST as $field => $value) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$form_data[$field] = strip_tags($value);
}
foreach ($required_fields as $required_field) {
$value = trim($form_data[$required_field]);
if(empty($value)) {
$error = true;
$result = $error_empty;
}
}
if(!is_email($form_data['email'])) {
$error = true;
$result = $error_noemail;
}
if ($error == false) {
$captcha_text=$form_data['captcha'];
$captcha_prefix=$form_data['prefix'];
$correct = $captcha_instance->check( $captcha_prefix, $captcha_text );
if($correct==TRUE){
$email_subject = "[" . get_bloginfo('name') . "] " . $form_data['subject'];
$email_message = $form_data['captcha'] . "\n\nIP: " . wptuts_get_the_ip();
$headers = "From: ".$form_data['your_name']." <".$form_data['email'].">\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\n";
$headers .= "Content-Transfer-Encoding: 8bit\n";
wp_mail($email, $email_subject, $email_message, $headers);
$result = $success;
$sent = true;
}
}
}
$word = $captcha_instance->generate_random_word();
$prefix = mt_rand();
$image= $captcha_instance->generate_image( $prefix, $word );
if($result != "") {
$info = '<div class="info">'.$result.'</div>';
}
$email_form = '<form class="contact-form" method="post" action="'.get_permalink().'">
<div>
<label for="cf_name">'.$label_name.':</label>
<input type="text" name="your_name" id="cf_name" size="50" maxlength="50" value="'.$form_data['your_name'].'" />
</div>
<div>
<label for="cf_email">'.$label_email.':</label>
<input type="text" name="email" id="cf_email" size="50" maxlength="50" value="'.$form_data['email'].'" />
</div>
<div>
<label for="cf_subject">'.$label_subject.':</label>
<input type="text" name="subject" id="cf_subject" size="50" maxlength="50" value="'.$subject.$form_data['subject'].'" />
</div>
<div>
<label for="cf_message">'.$label_captcha.':</label>
<input type="text" name="captcha" id="cf_message" size="50" maxlength="50" value=""/>
<input type="hidden" name="prefix" id="prefix" value="'.$prefix.'"/>
</div>
<div id="captcha"><span id="captcha_text">Captcha:</span><img id="captcha_image" src="'.plugins_url("really-simple-captcha/tmp/" . $image) . '" alt="" /></div>
<div>
<input type="submit" value="'.$label_submit.'" name="send" id="cf_send" />
</div>
</form>';
if($sent == true) {
return $info;
} else {
return $info.$email_form;
}
}
add_shortcode('contact', 'wptuts_contact_form_sc');
// add plugins style to frontend
function prize_game_contact_form() {
wp_register_style('prize_game_contact_form', plugins_url('css/style.css',__FILE__));
wp_enqueue_style('prize_game_contact_form');
}
add_action('wp_enqueue_scripts', 'prize_game_contact_form');

WordPress: Getting URL Variables with a Rewritten Page (Login Page)

As part of a larger project, I am attempting all login activity to occur at the following address:
www.url.com/login
So, a link that should lead to a form that would allow a user to reset their password would be found at the following:
www.url.com/login?action=lostpassword
However, the wp-login.php is not reading this correctly, and when I go to the above address, I get the normal log-in form.
This is how I have it set up:
add_action( 'init', 'add_virtual_page_template' );
function add_virtual_page_template()
{
global $wp, $wp_rewrite;
$wp->add_query_var( 'template' );
add_rewrite_endpoint( 'login', EP_PERMALINK | EP_PAGES );
add_rewrite_rule( 'login/?', 'index.php?template=login', 'top' );
add_rewrite_rule( 'login/?', 'index.php?template=login', 'top' );
$wp_rewrite->flush_rules();
}
add_action( 'template_redirect', 'add_virtual_page_redirect' );
function add_virtual_page_redirect()
{
global $wp;
$queryvar = get_query_var('template');
if ($queryvar && $queryvar == 'login')
{
include(site_url('wp-login.php'));
exit();
}
if ($queryvar == 'mylogin')
{
include( get_stylesheet_directory() . '/page-login.php' );
exit();
}
}
What am I missing?
Here's how I dealt with this when building out the WordPress for Web Apps toolkit (https://github.com/cferdinandi/web-app-starter-kit):
// LOGIN FORM SHORTCODE
function wpwebapp_login() {
// Get current page URL
$url_current = #( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] : 'https://'.$_SERVER["SERVER_NAME"];
$url_current .= ( $_SERVER["SERVER_PORT"] !== 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";
$url_current .= $_SERVER["REQUEST_URI"];
$url_clean = array_shift( explode('?', $url_current) );
$login_failed = $url_clean . '?login=failed';
$signup_success = $url_clean . '?signup=success';
$reset_success = $url_clean . '?password-reset=success';
// Variables
$login_status = '';
// If login failed
if ( $url_current == $login_failed ) {
$login_status = '<div class="alert alert-red">Invalid username or password. Please try again.</div>';
}
// If password reset
if ( $url_current == $signup_success ) {
$login_status = '<div class="alert alert-green"><strong>Success!</strong> We just sent you an email with your password.</div>';
}
// If password reset
if ( $url_current == $reset_success ) {
$login_status = '<div class="alert alert-green">Your password was successfully reset. We just emailed you a new one.</div>';
}
// The login form
$form =
$login_status .
'<form name="login" id="wp_login_form" action="' . get_option('home') . '/wp-login.php" method="post">
<div>
<label for="username">Username</label>
<input type="text" name="log" id="log" value="" tabindex="1" autofocus>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="pwd" id="pwd" value="" tabindex="2">
</div>
<div>
<label>
<input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90" checked>
Remember Me
</label>
</div>
<div>
<button type="submit" name="wp-submit" id="wp-submit" tabindex="100" class="btn btn-blue">Log In</button><br>
Forgot your password?
<input type="hidden" name="action" value="login">
<input type="hidden" name="redirect_to" value="' . get_option('home') . '">
<input type="hidden" name="testcookie" value="1">
</div>
</form>';
// Display the form
return $form;
}
add_shortcode( 'loginform', 'wpwebapp_login' );
// FAILED LOGIN REDIRECT
add_action('login_redirect', 'redirect_login', 10, 3);
function redirect_login($redirect_to, $url, $user) {
// URL Variables
$referrer = $_SERVER['HTTP_REFERER'];
$url_clean = array_shift( explode('?', $referrer) );
$login_failed = $url_clean . '?login=failed';
// If the post submission is a valid page that's not the backend login screen
if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')) {
// If the password is empty...
if($user->errors['empty_password']){
wp_redirect($login_failed);
}
// If the username is empty...
else if($user->errors['empty_username']){
wp_redirect($login_failed);
}
// If the username is invalid...
else if($user->errors['invalid_username']){
wp_redirect($login_failed);
}
// If the password is incorrect...
else if($user->errors['incorrect_password']){
wp_redirect($login_failed);
}
// Catch all for all other issues
else {
wp_redirect(get_option('home'));
}
exit;
}
// Prevents page from hanging when redirected from backend
if ( !empty($referrer) && ( strstr($referrer,'wp-login') || strstr($referrer,'wp-admin')) ) {
wp_redirect(get_option('home'));
exit;
}
}
// BLOCK BACKEND ACCESS FOR NON-ADMINS
add_action( 'init', 'blockusers_init' );
function blockusers_init() {
// If accessing the admin panel and not an admin
if ( is_admin() && !current_user_can('level_10') ) {
// Redirect to the homepage
wp_redirect( home_url() );
exit;
}
}
With this setup, you block users from ever getting redirected to the backend (the unfortunate side effect: if you're not logged in, you need to login from the front-end first). You can add custom error messages based on the situation, etc. And you can add this to a page just by using the [loginform] shortcode.
The WordPress for Web Apps toolkit has functions like this for password resets, signup forms, and more, so you might want to check it out. I went through this same learning process last year on a project I was working on.

Resources