Categories
Intermediate

DO THIS!! Instead of using AJAX for WordPress Async requests

If you ever had to build asynchronous interfaces for WordPress, you may have opted to use AJAX requests. Today I’ll talk about the drawbacks of this approach and introduce you to a better solution. 

First of all, if you have a need for just one or two ajax requests, then this post might not be for you. But if you manage a lot of data with AJAX then read on.

So what are the disadvantages of AJAX? Well, if you manage data entities using AJAX, then you probably need to write a lot of different handlers – create, update, delete, and so forth… This becomes a lot of work pretty fast. Secondly, you would need to write the code for success and error handling yourself. Granted, you have methods like wp_send_json and wp_send_error_json that make life easier, but wouldn’t it be nice to just return an error from your function and be done with it?

So what else is there? Easy, REST. WordPress allows you to build your own RESTful APIs. Using REST allows you to easily manage different actions for your data entities (POST, GET, DELETE…). You can manage secure access with REST easily. REST also makes error handling easier – simply return a WP_Error instance and WordPress will do all of the work for you.

If the above still hasn’t convinced you to move to REST, consider this: many javascript packages will support REST requests out of the box. take Angular packages such as @NgRx/data – they manage your data entities for you, requiring a lot less work for you, and they assume the existence of some REST interface. It’s quite impossible to think about how a 3rd party package may have support ajax requests, as these are not predefined interfaces.

Finally – consider testing, npm packages like json-server mimic a RESTful API allowing you to simulate the production environment while testing.

To read about how to use REST interfaces with WordPress read here https://developer.wordpress.org/rest-api/.

So make your life easier and stop using AJAX today! 🙂 

Categories
Intermediate

Angular Typescript (async) Catch-Finally Decorator

Hey Guys! Today I want to talk about error handling for async and non-async Typescript methods. Let’s take a look at some error-prone typescript method:

someRegularMethod(){

// code
someDangerousMethod();
//more code
}

So what if some Dangerous Method threw an exception? Solution try-catch!

someRegularMethod(){
// code
try{
someDangerousMethod();

}catch(err)[

]
//more code

}

But this bloats the code a bit, right?

So what’s the alternative?  Catch Decorator. Click on the image below to access the code:

Using the catch decorator your code will look like this:

@Catch(Error, (err: Error, ctx) => ctx.handleError(err), (ctx) => ctx.finalizeRequest())
someRegularMethod(){

// code
someDangerousMethod();
//more code
}

This mimics the try-catch-finally block. The first parameter is the Error type, the second is the error handler, and the third is the finally block. This saves us the trouble to write it in the method itself.

You can even use it with async methods: 

@Catch(Error, (err: Error, ctx) =>  ctx.handleError(err), (ctx) => ctx.finalizeRequest())
async someRegularMethod(){
 
 // code
 await someDangerousMethod();
 //more code
}

So what do you think? Will you stop using regular try-catch blocks?

Categories
Intermediate

Amazon SES (How to Receive and Send Emails?)

Amazon  SES (Simple Email Service), can be configured to receive emails as well as sending them. We’ll describe the steps necessary to configure SES to receive emails and forward them to your personal mailbox. This tutorial assumes you have already verified your domain with Amazon SES:

We will do this through the SES Email Receiving menu on the bottom left.

Step 1 – Access the active rule set menu and store your emails

1) Click on Rule Sets

2) Click on View Active Rule Sets

We’ll set up some rules for an S3 bucket to hold our emails. S3 is a scalable cloud storage service.

3) Click on Create Rule

4) Choose recipient:

Enter the recipient email address. This is the address we will receive emails at (Not the final destination), For example, if your domain is example.com, you may enter admin@example.com. Note: the domain must be in the list of verified domains.

5) Choose S3:

6) Choose Create S3 Bucket:

7) Give your bucket some indicative name like “Store my emails”:

8) Go to the next step. Put the rule at the beginning:

9) You may need to create a default rule set:

10) Give the rule a nice name – “Email Store Rule”:

11) Go to the next step and approve.

Step 2 – Create Lambda (The code to forwards emails) 

1) Go to Amazon’s Lambda service and click “Create function”:

2) Choose node 12:

3) Create an environment variable:

4) Add an environment variable. Name the key to_address and enter your email (the one you want to forward to) in the value:

5) Head back to the configuration screen – Paste the following code to index.js:

Banjith De Silvabanjith

var AWS = require('aws-sdk');
//var forwardFrom = process.env.from_address;
var forwardTo = process.env.to_address;  
exports.handler = function(event, context) {
    var msgInfo = JSON.parse(event.Records[0].Sns.Message);
    // don't process spam messages
    if (msgInfo.receipt.spamVerdict.status === 'FAIL' ||         
        msgInfo.receipt.virusVerdict.status === 'FAIL') {
        console.log('Message is spam or contains virus, 
        ignoring.');
        context.succeed();
    }
 
    var email = msgInfo.content, headers = "From:    
    "+msgInfo.mail.destination[0]+"\r\n";
    headers += "Reply-To: 
    "+msgInfo.mail.commonHeaders.from[0]+"\r\n";
    headers += "X-Original-To: 
    "+msgInfo.mail.commonHeaders.to[0]+"\r\n";
    headers += "To: "+forwardTo+"\r\n";
    headers += "Subject: Fwd: 
    "+msgInfo.mail.commonHeaders.subject+"\r\n";
 
    if (email) {
        var res;
        res = email.match(/Content-Type:.+\s*boundary.*/);
        if (res) {
            headers += res[0]+"\r\n";
        }
        else {
            res = email.match(/^Content-Type:(.*)/m);
            if (res) {
                headers += res[0]+"\r\n";
            }
        }
 
        res = email.match(/^Content-Transfer-Encoding: 
        (.*)/m);
        if (res) {
            headers += res[0]+"\r\n";
        }
 
        res = email.match(/^MIME-Version:(.*)/m);
        if (res) {
            headers += res[0]+"\r\n";
        }
 
        var splitEmail = email.split("\r\n\r\n");
        splitEmail.shift();
 
        email =headers+"\r\n"+splitEmail.join("\r\n\r\n");
    }
    else {
        email = headers+"\r\n"+"Empty email";
    }
 
    new AWS.SES().sendRawEmail({
        RawMessage: { Data: email }
    }, function(err, data) {
        if (err) context.fail(err);
        else {
            console.log('Sent with MessageId: ' + 
            data.MessageId);
            context.succeed();
        }
    });
}

Step 3: Create SNS Topic

 1) Go to Amazon’s SNS service dashboard and create a new topic:

2) Give it some indicative name and click “Create topic”:

3) Go to the topic dashboard and click “Create subscription”:

4) For the protocol choose Lambda and use the Lambda we just created.

5) Click the “Create subscription button”:

Step 4 – Put it all together 

1) Back to the SES console, create another rule, call it ‘forward emails rule’.

2) This time for “Add Action” choose SNS, and choose the topic we created.

3) Implement the next rule, which is after the rule from Step 1

Test it! if it doesn’t work please let us know so we can fine-tune this tutorial.

Categories
Intermediate

Svelte App on a WordPress Admin Page??

Since I work a lot using WordPress, I was wondering if I could put a Svelte app on an admin WordPress page. As I found out, it’s not that complicated to achieve this – but you do need some tinkering. Initially, we must define the admin page as so:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
 
	});

Notice I’m using an anonymous function to render the page. In the function I will enqueue the script and style of the app as follows:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
             wp_enqueue_script( 'bundle_js',plugins_url( 'js/' . "bundle.js", __FILE__ )  ,array(), 1.1, true );
             wp_enqueue_style( "bundle_css",plugins_url( 'css/' . "bundle.css", __FILE__ ));
        });

This is almost adequate. But Svelte targets the body of the document, so some minor amendments will be needed to do the trick.

First, have Svelte target some unique tag in your main js file:

const app = new App({
	target: document.querySelector("my-special-tag")
});

Secondly, add one more piece of code to your add_menu_page call:

add_menu_page( "Menu Name, "Menu Name, "manage_options", "menu_slug", function(){
             echo "<my-special-tag/>"; // add this
             wp_enqueue_script( 'bundle_js',plugins_url( 'js/' . "bundle.js", __FILE__ )  ,array(), 1.1, true );
             wp_enqueue_style( "bundle_css",plugins_url( 'css/' . "bundle.css", __FILE__ ));
         });

That’s it! Providing that you copied the Svelte code to the relevant directories in your plugin- everything should work! I also recommend reading my post about Hash File Suffixing to prevent the browser from caching your scripts.

Categories
Intermediate

Making Life Easier with wp_localize_script

wp_localize_script is a great way to face recurring challenges.We often need to enqueue a script that relies on data from the server (i.e. the database).

For example, say we want our script to store a list of all site category Ids in a variable. One way to do this would be to include a script tag in our HTML and then echo the data as a return value for a function as shown below:

// some HTML
<script>
function getCats(){
return '<?php echo json_encode(get_cat_ids())?>';
}
</script>
// some more HTML

But this method has many drawbacks. Firstly, we may not have any HTML that we want included. Secondly, we would need to add these types of functions for all kinds of data (trust me, I’ve been through it). 

This is exactly what wp_localize_script solves. Look at this alternative solution:

/ First I'm enqueuing a script, notice the handle of the script is "my_cool_script"
wp_enqueue_script( 'my_cool_script',plugins_url( 'js/my_cool_script.js' , __FILE__ )  ,array(), 1.0, true );
// Now I'm using wp_localize_scipt
wp_localize_script( 'my_cool_script', 'coolScriptData',  
   [
		'cat_ids' => get_cat_ids(),
   ] 
);

WordPress will now create a coolScriptData object which I can use inside my script directly.

Any comments? Thoughts? let me know in the comments.