Samuel Elh Blog

WordPress, bbPress, BuddyPress, JavaScript tutorials and snippets

Page 2 of 5

Add Link to WordPress Comment Avatar

In this quick snippet of coding tutorial, we learn about adding an anchor link to WordPress comment avatar.

Link WordPress Comment Avatar

By default, if a user has left a comment on your WordPress blog through a post comment form, they can specify a link to their website, which will be assigned as anchor to the name they specified and displayed within the comments loop, and WordPress does not make this link added to the avatars.

Filtering get_avatar:

Simple work-around for achieving this is by filtering entire get_avatar output, which we will concentrate to apply this only when the queried avatar (gravatar) is used for comments, and this can be achieved by checking the second parameter provided while hooking into get_avatar, if it is a comment identifier, while it can be a user ID, email address or something else.

The coding:

Add the following code to your child theme’s functions file or with a custom plugin:

/**
  * PHP < 5.3 ? use a custom function instead of the anonymous callback
  */

add_filter('get_avatar', function( $avatar, $indent ) {

	/**
	  * check if the current queried avatar is for comments
	  */

	if ( !empty( $indent->comment_ID ) ) { // now that's a comment avatar

		/**
		  * Check if the comment poster has left a link
		  * You can link somewhere else regardless of link availability
		  * by commenting out the if statement lines and specifying a $url
		  * in the sprintf 2nd param, e.g link to bbPress, BuddyPress, author
		  * archives, etc..
		  */

		if ( "" < ( $url = get_comment_author_url( $indent->comment_ID ) ) ) {
			$avatar = sprintf(
	   			'<a href="%s" rel="external nofollow" class="url">%s</a>',
	   			$url,
	   			$avatar
			);
		}

	}

	return $avatar;

}, 10, 2);

That should make the avatar clickable in the comments section and ONLY if the comment author has left and specified a URL in the website comment form field while submitting.

Filter avatar link:

You can link to something else, such as bbPress profile

bbp_get_user_profile_url( $ident->user_id )

or BuddyPress profile

bp_core_get_user_domain( $ident->user_id )

or even to the author archives of this user ( and to know if the comment author is a verified registered user, just check if $ident->user_id is not empty ):

get_author_posts_url( $ident->user_id )

This should always work as long as you’re pulling the comment avatar by the comment ID in your comments output callback function, that if you are overriding the default WordPress’s comments callback.

An effective way of preventing spam registration with JavaScript – WordPress

As I am writing this blog post about preventing spam registration on wordPress, many weblogs out there are getting tons of new accounts registered which belong to robots and are totally untolerated spam.

Preventing Spam Registration on WordPress

There are so many ways out there, free and paid, which would help you knock off spam registration on your WordPress blog or website. One of them is CleanTalk, I love this one as it has a great database of malware checks (blacklist) and many online ready tools to verify a user before it successfully signs up.

But for me, I always prefer not to add another plugin to the load, so if it was to coding a little snippet of script that would help then that would be super. So hopefully this could help out preventing spam registration somehow.

Preventing Spam Registration – JavaScript

As many of you know, or as if you don’t know, spam bots (robots) actually run microsystems that do not have JavaScript running. This means that no DOM JavaScript is available for bots, so we will use this point to add a required (but hidden) field into the user registration form that will work with WordPress nonces too (cool, right?) which will be verified with wp_verify_nonce() function..

Every time the registration screen is requested, the form field for spam check will be added on window load, and it will be required to process the registration.

Important notice – if you are on an environment where your users prefer not to enable JavaScript, then do not use this process OR, notify your users to enable JavaScript in order to register and then switch back to disabled JS mode.

Once the field was not added, the request will be killed with a simple error message:

WordPress are you spamming go back - preventing spam registration

Are you spamming?

Or possibly if you don’t want to kill the request but show a warning message notice instead, comment out wp_die function and remove the comments for $errors->add method usage in the script code; inside se_nospam_register_validate callback function, and this would appear:

bad guy spotted spam registration wordpress - preventing spam registration

Cool! now where can I get the plugin? (no plugin, just some small snippet of non commented code) ; read on.

Preventing Spam Registration on WordPress: The code

You can use the following code to be added to your child theme’s functions file, or download the plugin from Github gist:

<?php
/**
  * Plugin Name: No Spam Registration with JavaScript
  * Plugin URI:  http://blog.samelh.com
  * Description: Prevents spam registration on your WordPress blog/website by adding a necessary form field with JavaScript on document load
  * Author:      Samuel Elh
  * Author URI:  http://samelh.com
  * Version:     0.1
  */
add_action('register_form', 'se_nospam_register_append_input');
add_action('register_post', 'se_nospam_register_validate', 10, 3);
if ( !function_exists('se_nospam_register_append_input') ) :;
function se_nospam_register_append_input()
{
?>
	<script type="text/javascript" id="se_nospam_inline_js">
		window.onload = function() { // it's all about this JS, once JS is loaded, the spamcheck field will be available..
			var e = document.getElementById('se_nospam_inline_js');
			if ( null !== e ) {
				e.outerHTML = '<input id="process-register" type="hidden" name="process-register" value="<?php echo wp_create_nonce( 'se-nospam-register' ); ?>" />';
			} return;
		}
	</script>
<?php
}
endif;
if ( !function_exists('se_nospam_register_validate') ) :;
function se_nospam_register_validate( $login, $email, $errors )
{
	$die_message = apply_filters( "se_nospam_register_error", "Are you spamming?<br/><br/> <a href=\"javascript: window.history.go(-1);\">&laquo; Go back</a>" );
    if( !isset($_POST['process-register']) ) {
    	wp_die( $die_message );
        // or just: $errors->add( 'empty_realname', "<strong>ERROR</strong>: Are you spamming?" );
    }
    else if( empty($_POST['process-register']) )
    {
    	wp_die( $die_message );
        // or just: $errors->add( 'empty_realname', "<strong>ERROR</strong>: Are you spamming?" );
    }
    else if(!wp_verify_nonce($_POST['process-register'], 'se-nospam-register'))
    {
    	wp_die( $die_message );
        // or just: $errors->add( 'empty_realname', "<strong>ERROR</strong>: Are you spamming?" );
    }
    return $errors;
}
endif;

Cool! if preventing spam registration on WordPress with this custom trick has worked for you, then that’s what matters! Yay!! Personally it helped me a lot on my product support forums website where I have bbPress installed for the forums functionality.

Preventing Spam Registration on WordPress: After

Saying that it was helpful to preventing spam registration, there should be more to do after this, right? I mean like, capturing the prevented spam registration attempts and saving some count to the database so you can see a log of how many spam bots were blocked; something like adding this code:

update_option( $name = "se_how_many_spam", ( (int) get_option( $name ) ) + 1 );

That to be added right before each wp_die in the code, And then calling

get_option( "se_how_many_spam" );

to tell how much spam was denied. Also you might want to capture the user IP to block them or something, as long as possible, saying that spam can never be tolerated. (beware, bots will call you agressive then)

Note that this can also be effective on embedded forms like registration forms added with widgets or shortcodes, as the form field for spam check will be added with JavaScript there too.

That is it for this tutorial and I am hoping this helps you as it helped me and if there is any improvements or suggestions and ideas to implement, please feel free to discuss in below comments.

Thank you!

Simple and secure php password hashing and verification system

As I am writing this post, there happens to be dozens of online tutorials that are still basing their password hashing process on weaker technologies and tools. The widely known one is md5, a reportedly no-longer secure password hashing system available in almost every programming language.

Plain text passwords (no password hashing done)

Some people are lazy and dumb enough to save their inputted passwords as is, into their database as plain text! This is totally bad and horrible! I mean, let’s assume some hacker has gained access to your database (that only means this person can read the data or delete it), as this person lists the users table, they can access raw and plain text passwords and use them to login easily and quickly so as to access more tools and actions limited to admins (saying that as assuming they can’t do nothing hacking into our database except reading raw data). Or even save again a new password and use it later.

Just thinking about it sucks. But if you were to hash your passwords with a strong password hashing system then, they can not revert these passwords, or even if they replace them with plain text, then your password verification will also be negative and keep the bad guys locked out.

md5 is insecure

Yes, if you were hashing your user input passwords with this tool and store into the database users table, that is dangerous and and a bad practice. For its salting and cryptography that is probably static, it is being reverted and reportedly many people have succeeded to do that.

Even though it is insecure, it can be used for hashing strings for minor uses, example when dealing with a quick project that does not require much security. MD5 is used to hash email addresses to get a Gravatar image URL based on the user email, you can test that out.

Using a PHP built-in password hashing system

As if you haven’t heard yet, PHP password_* functions are introduced as of PHP 5 (>= 5.5.0), and available also on PHP’s latest; 7.

The hashing function introduced uses a strong algorithm therefore it’s making it impossible to revert the hash into the plain text password. This is a great security practice to base your project on, especially when creating a social network with PHP where uses are able to register new accounts, reset passwords and so forth.

For earlier PHP versions ( < 5.5 ):

Thanks to ircmaxell’s hard work, you can use password_* functions while you can’t get to PHP 5.5 at least (I know, sometimes to do an upgrade you need to set tight and fix a lot); simple download this package from Github:

https://github.com/ircmaxell/password_compat

And so load the package:

require_once 'password_compat/lib/password.php';

And now you can use those functions and even access useful documentation in the project’s Github page.

Assuming you have the functions in use, let’s carry on with the simple process.

password_hash() function

It is always easy and flexible coding with PHP, from the documentaion you can use:

password_hash( password_from_input_as_plain_text, PASSWORD_DEFAULT )

And here’s an example:

password_hash( 'samuel', PASSWORD_DEFAULT )

Assuming your password field in the form is tagged with the name password:

$password = password_hash( $_POST['password'], PASSWORD_DEFAULT )

Now it is perfect to save into your database users table (wait, saving? let’s not bring that SQL injection talk, be a nice and use PDO’s prepared statements. )

I am just dumping the return of the hash, but it is changing each time even though the plain text password is the same and that is because of the randomly-generated salt used for cryptography.

$2y$10$.HRdBcQBdCSJ0fW60x.MR.v4s6TePvv35p/YxGLlBo0c67n8KcX0.

So let’s say you now feel a little secure, and that you have one more step ahead which is verifying the user inputted password to detect if it matches the one on the database which is hashed, or if not. That’s what you will be using in your login forms, assuming you are at first place searching for a user by its username, email or ID and then move on to verify the password inputted to process and log in this user and then set the PHP session and so..

We’re now taking advantage of PHP’s password_verify() function, which takes 2 parameters one for the plain text and the other for the hash.

Verifying input password with hashed password from the database:

As mentioned earlier, we’re after the boolean returned by password_verify() function. And for it we need to pass the plain text password (as inputted in the form by the user) with the hashed password from the database:

$log_in_verify = password_verify( 'samuel', '$2y$10$.HRdBcQBdCSJ0fW60x.MR.v4s6TePvv35p/YxGLlBo0c67n8KcX0.' )

And $log_in_verify will either return true or false (boolean).

if ( $log_in_verify ) { 
  // Welcome, user!
  // do things in terms of cookie setting and session etc to login this user
} else {
  // You're not welcome, anonymous!
  // alert them that somehow they're not the right guy!
}

Once true, then, don’t worry much and proceed with logging in your user, if it was false then warn the user that they submitted a wrong password, or give them extra more shots and lock them away if they are still insisting to consume your server ressources and bandwidth in order to try silly attempts. Oops, to much aggressive? sometimes you should, especially when you are on a shared hosting and your hosting provided yells at you all the time.

Making a social site that needs more traffic and server ressources? try deploying a VPS on the cloud with Digital Ocean, it’s the most recommended, and I am comfortable with it hosting my applications websites. (Note: referral link for extra bonus)

That’s it!

Yep, feeling like it is. Go out there and make the web a secure place by securing your projects, and sharing secure ways as if you were to help someone with their own project.

How to force SSL on WordPress

So you want to force SSL on WordPress for your  blog or website and you had trouble with some (if not all) requests still being served in HTTP? that’s a common issue, which can be fixed with no such trouble. Or something else?

How to force SSL on WordPress

How to force SSL on WordPress: Some free SSL certificates providers

There are so many free SSL certificates providers which you can use for your WordPress, on top of them finally Let’s Encrypt was introduced, and there’s also CloudFlare if you are already using it for DNS or want to further try it, then it offers free SSL on all plans, but it reportedly does not work on outdated operating systems like Windows XP, earlier Android versions..

How to force SSL on WordPress: the process

Anyways, the first thing to do is to change that HTTP to HTTPS in our URL settings (Dashboard>Settings>General):

force SSL on WordPress - change http to https WordPress

Doing so would probably be followed with a login redirect which after you should be able to browse the site on HTTPS.

Right after, we will always make requests from http:// redirect to https://, and there are 2 ways of doing this, I recommend using both:

Through htaccess:

Adding these 2 lines to your .htaccess file located in the root directory of your WordPress installation (You’ll need to login to ftp or using CPanel file manager):

RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=302,L]

Through functions.php file:

This will catch the http traffic and points right to a secure path of the current request URI. Simply we detect if

$_SERVER['REQUEST_SCHEME']

property is not ‘https’ string, and then we redirect:

add_action("init", function() { 
	if ( "https" !== $_SERVER['REQUEST_SCHEME'] ) {
		wp_redirect( "https://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] );
		exit;
	}
}, 0);

Great! that should be handy. Now let’s browse our site, try on http and it should redirect back to https. Now, let’s check how green the https lock in the address bar is.

force SSL on WordPress - https green sign

How to force SSL on WordPress: The green lock

Green? cool. Not so green, then you’re in trouble, no, just some minor fixes required.

When it is not green, that means that still, your current page is serving assets and scripts (1 at least) from http. And if you just open a static file in https (e.g an uploaded photo), the sign should be green because there’s nothing loaded in http.

Broken scripts, stylesheets, assets, and so? no worries, a lots of work to do is ahead.

There are some plugins and themes that are hard-coding the scripts enqueing process, so they always load their assets on http:// and you need to change that to https. Contact them for a fix.

Right after that, you are also required to look into your page source code, and see which scripts are loaded from http (by pressing ctrl+f in the developer tools, and search for http://yoursite..)

Media attachements:

While adding the media attachements to your posts while in http (earlier), those stick to http and they are a reason the site says something as “this page is not secure”. You’ll need to edit these posts or pages and update these included attachements, simple as clicking to edit each attachement in the TINYMCE editor, and then update and the new included file URL should be now secure. Now update your posts and visit, and the result should be in your favor.

I also suspect that you can edit these media from the media screen in the admin, and there should be a tweak (hook) also to update these URLs without this whole process as you force SSL on WordPress..

Until you finally succeed to make everything be called on HTTPS, that green lock would be there with you as you browse. While not, you should always look through the developer console and search for which file was loaded on http protocol and switch back to the secure protocol. Links on http do not matter, but assets do (e.g img src, script src, stylesheet href)..

Thanks for reading! and good luck securing every inch of that site!

Reference:

404 page related posts WordPress

In this tutorial we will be learning about how to add 404 page related posts and contents to our 404 (“Error 404”, “404 not found”, ..) page.

These 404 page related posts will be based on the permalink which resulted in a 404 error, so we will be looking into the WordPress query arguments to find out which contents and slugs resulted in a 404 page, and then, fetch our blog posts and contents to find and get some related ones..

Here is an example:

If I browse this nonexistent page of my blog: “http://blog.samelh.com/404-wordpress/” it will of course take you to the 404 screen and show a custom notice with a search form. Now our main target is getting the contents after the home URL http://blog.samelh.com/ and querying for posts with similar strings in them. So in the example we will be querying for posts with strings like “404-wordpress” and that is pretty much simple as of now.

Permalink structure:

This “404-wordpress” could be a page name, a category name, a tag name, and it all depends on your permalink structure. Say for example you have set the permalink settings to “Post name” then WordPress will consider the 404 string as a page name, which is the default, and you can find out while debugging the wp_query object (coming up). Supposing you have set the structure to a “Custom Structure” and have /%category%/ in the beginning of the structure, then, “404-wordpress” will come to the category_name argument. What’s the point of all this? just trying to tell how to exactly match the 404 page related posts, so rather than always search for strings match in all posts, search posts within the requested category, tag or custom taxonomy for better results and user experience.

Debugging $wp_query object:

This should be a lot helpful to see which query arguments are available and which to use to fetch content. Debug $wp_query object and then, try some 404 pages and see the debugging message, a temporary code to add until you are done with debugging would look like this:

add_action("wp", function() { 
	global $wp_query;
	echo var_dump( $wp_query ); // or better echo "<pre>"; print_r( $wp_query ); echo "</pre>";
	return;
});

Query posts:

For the blog that I have been working on while writing this article, I had a custom permalink structure which starts with the category name so I am giving priority for “category_name” (index.php?category_name=xx) argument over the default page name “name” argument (index.php?pagename=xx):

global $wp_query;
$name = $wp_query->query_vars['name'];
if ( $cat_name = $wp_query->query_vars['category_name'] && ! $name ) {
	$name = $cat_name;
}

And I am keeping things simple and search for posts with such name ($name) in the content or title using ‘s’ key while querying for posts:

$args = array(
	'post_type' => 'post',
	's' => $name,
	'posts_per_page' => 10
);
$posts = get_posts( $args );

That would give us few matching results if found, else returns an empty array.

Great! since we got a list of related posts meta data now we can parse this list into HTML content, and add them to our 404 pages.

The best way to do this is by copying your 404.php page from your active theme into a child theme, and there you can make the necessary edits.

Not going to mix up between HTML and PHP, just add

<?php do_action( "after_404_content" ) ?>

at the bottom of the 404 page (maybe below the search form if there’s any) and then go back to your child theme functions file to attach a callback function into the custom hook you just created:

404 page related posts: the code:

// add to your child theme functions (functions.php) file
add_action("after_404_content", function() { 
	global $wp_query;
	$name = $wp_query->query_vars['name'];
	if ( ! empty( $wp_query->query_vars['category_name'] ) ) {
		$name = $cat_name;
	}
	if ( $name ) {
		$args = array(
			'post_type' => 'post',
			's' => $name,
			'posts_per_page' => 10
		);

		if ( $posts = get_posts( $args ) ) : ?>
			<p>We think we found some related content:</p>
			<?php foreach ( $posts as $post ) : ?>
				<li>
					<a href="<?php echo get_the_permalink($post->ID); ?>" rel="bookmark"><?php echo get_the_title( $post->ID ); ?></a>
					<?php if ( ! empty( get_the_category($post->ID)[0] ) ) : $cat = get_the_category($post->ID)[0]; ?>
						- found in <a href="<?php echo get_category_link( $cat->term_id ); ?>"><?php echo $cat->cat_name; ?></a>
					<?php endif; ?>
				</li>
			<?php endforeach; ?>
		<?php endif;

	}
});

Hopefully that would work, make few tests and play around with the code.

WordPress 404 page related posts

How to measure WordPress load time and execution time of scripts

In this tutorial, we will be measuring the WordPress load time and execution time of everything WordPress loads into our user end-point.

This can be handy when you are about optimizing your site speed and load time, for instance test out the WordPress installation load time before and after installing certain WordPress plugin or plugins or themes or so.

Before you proceed:

Please note that we are doing this process for the sake of testing WordPress and getting stats from it and it requires a small modifications to a main WordPress core file (index.php) which you should totally backup and restore back the backup once the tests are done. And, we are doing this in a local installation (e.g Using XAMPP, WAMP, MAMP etc..). Do not test this online unless you are pretty sure about everything you do.

WordPress load time: The syntax

PHP is blocking, that way processes our code line by line, and will not jump to the next callbacks until the first ones are done. I don’t know how to explain that (I just know that in Node.js it runs in a non-blocking IO and mutli-threaded event looping asynchronous mode)..  This way, we will record the current time with time() for seconds or even microtime() for milliseconds (You know which one you need for your testing criteria). And once WordPress is loaded, we record the current time again and calculate the difference between this time integer and the past one which we previously recorded before the WordPress installation is being initiated.


$starting_time = microtime(1);

/* Load WordPress now */

print_r( microtime(1) - $starting_time ); // the difference

 

So I was looking into the WordPress hooks BUT using those hooks means you also need to wait for WordPress to be initiated. Hence I went straight to the index.php file located in the root folder. and that is where I made the tests ( I was only testing out some messaging plugin performance before and after caching, that is why I thought it would be a good thing to share here )

Looking into the index file:
How to measure WordPress load time and execution time of scriptsGreat so everything makes sense now.

Counting WordPress load time:

Just follow along, add this code before the require function

$starting_time = microtime(1);

And this after the require function (at the end of the file)

print_r(
  sprintf( "WordPress took %s seconds to load (%s milliseconds)", date( "i:s", $diff = microtime(1) - $starting_time ), $diff )
);

 

Now save, and go ahead to your WordPress front-end, wait for it to load, and then scroll to the maximum bottom of the page view-port and there you will see some text..

Yep;

WordPress took 00:05 seconds to load (5.6693241596222 milliseconds)

That is for me. How about you?

I am done:

That is awesome. Please consider updating the index.php file straight away after you are done. Update it with your backup or from a fresh installation

I hope that helps a little optimizing your site and analyzing the page load time and finding out which plugin or theme was making affecting your site load speed. You could do the same thing in the admin endpoint, just think a little how to get that done, which is a pretty simple process indeed.

do stuff after a post is published wordpress

This is a quick tutorial, where we will be hooking into save_post to process and do certain things after a post is being published initially in our WordPress blog.

The syntax:

 

add_action( 'save_post', 'se_post_save_post' );
function se_post_save_post( $post_id ) {

   if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return; // bail while doing auto-save for revisions ..

   // now do things here. To get the post data, use get_post( $post_id )

}

Hooking into save_post to do the magic:

Cool. Considering that we want to do things when our post is being published, we will try to do this process only once, because save_post happens to be called every time you make changes to the post, and when you get started with writing a new post it is being saved with an auto-draft status..

There happens to be a special hook for this named publish_post but this according to the codex, this one is being triggered whenever a post is published, or if it is edited and the status is changed to publish. Kind of something that we don’t want to do.

So, here’s the coding:

add_action( 'save_post', 'se_post_save_post' );
function se_post_save_post( $post_id ) {
    if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return;

    if ( "publish" == get_post_status( $post_id ) && ! get_post_meta( $post_id, "se_publish_post_stuff_done", 1 ) ) {
        do_action( "se_publish_post_stuff", $post_id );
        update_post_meta( $post_id, "se_publish_post_stuff_done", time() );
    }

}

 

That code will get us a custom action hook with the tag se_publish_post_stuff  which we can use to do custom things after the post is published. Things like, you know, emailing someone alerting them about the new post, doing some SEO tweaks, pinging some robot, or so Lol. P.S: the code should be added to your child theme’s functions file.

Done, so now you can hook your custom things and callbacks into se_publish_post_stuff which has the first parameter as post ID:

add_action( 'se_publish_post_stuff', 'se_publish_post_do_stuff' );
function se_publish_post_do_stuff( $post_id ) {
    
	/*
	You now have the post ID so you can use it to get the post data like get_post( $post_id )
	or get_the_permalink( $post_id ), get_the_title( $post_id ), get_the_date( $post_id )
	*/

}

Custom Post Type:

To limit this process to a custom post type only (because save_post is always called no matter what the post type is), then add an underscore followed by the post type name after save_post like: save_post_page, save_post_topic, save_post_CPT etc. and this will be limited to this custom post type we are saving.

I hope this simple process helps.

Restrict access to custom posts and pages and allow from referrers

In this tutorial, we will try to achieve:

Restrict access to posts, pages, or custom post types and allow access and traffic from certain referrers specifying their domain names

Let’s get things started.

First off, say which content to restrict:

Custom Posts/Pages:

You can restrict access to posts and/or pages while you specify their associated post IDs. An example:

$posts_to_restrict = array( 1, 2 ); // that's for hello world and sample page entities

The point is, insert the post IDs into the array separated by commas. Even custom post types are allowed here.

Entire post type:

Choosing this, you’ll end up restricting access to the entire post type that you specify its name. For example:

$restrict_entire_post_type = 'page';

That is going to restrict access to all your site pages.

Allow certain referrers:

Choosing this, you are going to allow access and incoming traffic from certain referrers as you set their associated domain names in the following variable:

$allow_referrer = array( 'google.com', 'stackoverflow.com' );

That’s me allowing traffic from Google and Stack Overflow!

Great, now say “You shall not pass!”

As per the specified criteria, our content should now be restricted and we can do certain actions on restrictions. For the sake of keeping things simple in this tutorial, I am just going to redirect my users to the home page where they will be given a notice that the content they requested can not be displayed for them with a custom JavaScript alert box.

To redirect to some custom page with a certain message or signup form or something else, just set the URL in the $on_restriction_redirect variable. Just make sure that page is not restricted either :~D

You can do things, simply hook into ‘se_restrict_access_not_passed‘ which runs when a user  could not access the restricted content or ‘se_restrict_access_passed‘ as they pass.

The restriction code

Assuming you know which content to restrict, which referrers to allow, and what to do on restrictions, you can add the following code with a custom plugin or to your child theme’s functions file after you replace the placeholder declarations with your own:


add_action('wp', function(){

	// list of posts to resctrict access to
	$posts_to_restrict = array( 1, 2 ); // posts|pages IDs to restrict
	// or simply a whole post type
	$restrict_entire_post_type = false; // 'post', 'page', 'myCPT' etc
	// referrers to allow access from
	$allow_referrer = array( 'google.com', 'stackoverflow.com' );
	// where to redirect on no access granted
	$on_restriction_redirect = home_url('?se_shall_not_pass=1'); // false to turn off

	if( is_feed() ) { return; }

	if( ! get_the_ID() || ! is_singular() ) {
		return;
	}

	if( ! $restrict_entire_post_type ) {
		$restrict = in_array( get_the_ID(), $posts_to_restrict );
	} else {
		$restrict = is_singular( $restrict_entire_post_type );
	}

	echo var_dump( $restrict );

	// getting the referrer domain name
	$referrer = parse_url(isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '', PHP_URL_HOST);
	// you can filter the restrict access to data
	$restrict = apply_filters( "se_restrict_access_to_post", $restrict, get_the_ID(), $referrer );

	if( $restrict && ! current_user_can( "manage_options" ) ) {

		$pass = false;
		
		if( ! empty( $allow_referrer ) ) {
			foreach( $allow_referrer as $domain ) {
				if( ! $pass ) {
					$pass = false !== mb_strpos( $referrer, $domain );
					// or $domain == $referrer for full match
				}
			}
		}

		if( $pass ) {
			// you can hook to this and do stuff
			do_action( "se_restrict_access_passed", $referrer, get_the_ID(), $allow_referrer );
			// do nothing because the user has passed from that referrer
		}

		else { // you shall not pass!
			// you can hook to this and do stuff, Gandalf!
			do_action( "se_restrict_access_not_passed", $referrer, get_the_ID(), $allow_referrer );
			// do things after user can not pass to restricted content without a referrer, like redirect

			if( $on_restriction_redirect ) {
				// You can get the referrer from $_GET['ref'] if set
				$on_restriction_redirect .= ( mb_strpos( $on_restriction_redirect, "?" ) ? "&" : "?" ) . 'ref=' . strval( $referrer );
				wp_redirect( $on_restriction_redirect );
				exit;
			}

		}

	}

	return;

});

// alerting the user with a custom restriction message
add_action('wp_footer', function(){

	if( ! isset( $_GET['se_shall_not_pass'] ) ) {
		return;
	}

	?>
	<script type="text/javascript">
		window.onload = function(){
			alert("You shall not pass!!!!");
		}
	</script>
	<?php

});

How to show a plugin update custom warning in admin WordPress

In this tutorial, we will focus on alerting and notifying the admin user in WordPress admin area about an available plugin update with a custom warning message.

Listing the update-available plugins

To find out which plugins have updates available, there’s a built-in WordPress function  get_plugin_updates() which lists all plugins that require updates along with their data, such as the plugin’s current version, new version, download package URL, and much more:

print_r( get_plugin_updates() );

plugins that need update wordpress

Finding our own plugin

Great. so from there the task is easier, we’ll just iterate through that list to find out if out plugin is listed, and then alert the admin with a custom warning message. Make sure to add your plugin name in the $requested_name variable:

add_action('admin_init', function() { 

	// Specify here the plugin name and that's all
	$requested_name = 'AJAX File Upload';
	
	function se_plugin_has_update( $name ) {

		if ( ! function_exists( 'get_plugin_updates' ) ) {
			require_once ABSPATH . 'wp-admin/includes/update.php';
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$list = get_plugin_updates();
		$data = array();

		foreach( $list as $i => $item ) {	
			if( strtolower( $name ) == strtolower( $item->Name ) ) {
				$data = $list[$i];
			}
		}

		if( ! empty( $data ) ) {

			$data = array(
				'name' => $data->Name,
				'version' => $data->Version,
				'new_version' => $data->update->new_version,
				'url' => $data->update->url,
				'package' => $data->update->package
			);

		} else {
			$data = array();
		}

		return $data;

	}

	$update_data = se_plugin_has_update( $requested_name );

	// var_dump( $update_data ) or print_r( $update_data ) for debugging

	if( ! empty( $update_data ) ) { // has update avail

		// You can avoid for specific versions (current: $update_data['version'] and latest: $update_data['new_version'])

		$GLOBALS['se_plugin_has_update_data'] = $update_data;
		
		add_action( 'admin_notices', function() {

			global $se_plugin_has_update_data;
			$update_data = $se_plugin_has_update_data;

			?>
			
				<div id="updated" class="error notice is-dismissible">
					<p><?php echo sprintf(
						"\"%s\" plugin has updates available. You are running v. %s while the latest version is %s",
						$update_data['name'],
						$update_data['version'],
						$update_data['new_version']
					); ?></p>
				</div>
			
			<?php
		});

	}

});

That’s all. You can add the above snippet of code to your child theme’s functions file. You can customize the warning message the way you want..

How to add a captcha to bbPress Messages plugin

Hello World,

So in this basic tutorial I am going to talk about how you can implement a spam quiz (know as Captcha) in your WordPress installation.

From the title, you’ll be required to use bbPress Messages v. 0.2.2 or greater, for the lite version I am going to make an update very shortly and you’ll be able to implement and complete this process on your lite plugin as well.

Using reCaptcha for bbPress Messages WordPress Plugin addon:

google reCaptcha bbPress messages

I have spent couple hours making a simple plugin to add and enable Google reCaptcha anti-spam in your bbPress Messages plugin. It is available for download on Github, make sure to check https://github.com/elhardoum/bbpm-recaptcha.

Working your own script:

First things first, let’s talk a little about captchas:

A Captcha can be used to ignore and kill some (if not all) robot requests to your scripts. Now here with WordPress, it’s a common issue that you can have spam users signup and sign in to your website, and from there make request calls which are limited to logged in users now that they are logged in.

Beating these malware bots can be a real trouble, especially when you are on shared hosting or run server with limited ressources. Spam can eat up your bandwidth, and get you in trouble with your host and make you pay more money for the ressources.

Implementing a Captcha in bbPress Messages:

bbPress Messages WordPress plugin is very easy to extend, you can just read the core files to find any hook you need then hook into it. That is what we are going to do to add a spam check tool for specific user roles.

bbPress Messages already uses WordPress nonces which can be handy most of the time.

You can use image Captchas, test written on image, but those could be beaten up easily nowadays since there are hundreds or anti-captcha scripts and APIs and OCR providers, that could not work most of the time..

In the following example we will be using a simple test, where we till our user to calculate something and do the maths.

“What’s 9+10?” – let’s try to use the word plus instead of symbol, perhaps bots will get workarounds to solve that one but when providing words and hints you are causing them more failure to solve the test.

User roles:

If you want to show the spam test to only one or specific roles, add or remove those roles in the following function in the 11th line:

Good. Now we know when to add the spam test and validate the answer provided by the user before sending a message.

Embed fields into form:

Now we will add the fields for the spam check into the conversation input form. Remember, you can go for any quiz you want, just name it and validate the client provided solution (we’ll talk about this later) as you go.

We will hook into ‘bbpm_conversation_form_additional_fields’ tag which puts fields within the form:

Now we can see that the field is added to the form:

bbpress messages spam check form preview

Awesome! now let’s talk about the validation.

Validating the solution:

This is the last part where we will be verifying the form data to get our spam test user input. We’ll then see if the answer is correct or not, then allow sending if everything’s good.

I am not going to explain the code line by line because it depends on the type of quiz you implement. For this tutorial the user input is stored in an input named

capCheck[value]

and the form has a POST method so the way of getting the value is through

$_POST['capCheck']['value']

and there we validate the answer.

We’ll hook into ‘bbpm_bail_sending_message’ this time to filter whether to bail sending the current message or not. When the captcha answer is wrong then we bail:

As we bail sending, an error will be added to the user interface in the front-end telling the user that something went wrong.. That means the spam quiz was not completed successfully..

To conclude, I have put the full code into a Github gist and you can add it to your child theme’s functions file in order for this process to work, after making your modifications:

I have fully tested it and it works great on my installations. If anything went wrong or you need help with your code, feel free to discuss below ( no wonder how much spam would this topic attract ;~) )

« Older posts Newer posts »

© 2017 Samuel Elh - Powered by WordPress, DigitalOcean & NameCheap

Theme by Anders NorenUp ↑

Subscribe to our mailing list

Sign up to receive updates about WordPress, free and premium plugins and themes in general and tips and tricks

* indicates required