4elements, Amsterdam, Holland

  1. Design Patterns: The Command Pattern

    After covering a few creational and structural design patterns, we have started behavioral patterns now. You can see the first article in this category of the strategy pattern. With creational patterns, we learned how we should create our objects, and from structural patterns we learned how we should structure our classes and objects to help build a better application.

    In this article, we will be going through the command design pattern. As the name says, in this pattern we will be dealing with executing various commands. Let me take a word about this pattern from Wikipedia:

    The command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

    Basically a pattern has numerous elements involved, which are as below. In the next section, we will be exploring each element with a code example. I will be taking the example of radio actions‚ÄĒvery basic actions would be turning the radio on or off. So let's dive into each element.

    Receiver

    This element contains the actual implementation (knows how to carry out requested command) of any commands. This also maintains the history of executed commands, but it is not part of the actual command pattern. We will see that part in the Memento Design Pattern.

    Command

    This element contains information about the necessary action to be taken. It calls the required method from receiver.

    Client

    This element really behaves like a client (deciding what to do). Its job is to determine which command to execute, without knowing who will execute it and how it will be executed. In this example I have taken command as a hard-coded value, but it can be grabbed from anywhere like a value from a URL and/or post variable as well.

    Invoker

    This element initiates the whole process. It takes arguments from the client and invokes the process to call the required command.

    Once we execute this command it will show "Turning Off Radio" as an output, because the client has invoked that command. Additional commands can be executed in the same way. If our action was set as turnOffRadio, then it should show "Turning On Radio". Simple enough, isn't it?

    Putting It All Together

    Let's wrap up all the elements here to see how it works.

    Adding New Commands

    Earlier we had only one frequency to play on the radio, so we had only two methods, which are to turn On or Off radio. But imagine that as time goes we have multiple frequencies to play, forcing us to add two new methods: tuneUp and tuneDown. Let's see how we can add those.

    When we use design patterns, it enables us to make changes or extend functionality without making any changes in the client code. This applies here as well. We are going to add two more commands, but our client and invoker code will remain as they are.

    Adding new commands requires changes in two places. The first is to create new commands which implement our radioCommand interface, and next is to define the actual implementation of those commands in the receiver.

    New Commands

    Updated Receiver Code

    We will be adding two new methods in our receiver class.

    Conclusion

    So we should go with the Command design pattern when we have multiple commands to execute, and it does not matter if those commands are related to each other or not. I have tried my best to elaborate on this design pattern, and you can post your feedback in the comment section.

     

    0 Comments

    Leave a comment › Posted in: Daily

    1. A Definitive Guide to Magento Security

      Although the security of all websites is important, the security of an eCommerce website is particularly important because these sites keep records of users’ data and order-related financial information. Any attempt to hack such data can cause a huge loss to your store. Although Magento is considered the safest and most secure eCommerce CMS, there are still some additional security steps advised to make its security foolproof. In this article I’ve explored some easy to implement steps to make your Magento store even more secure and robust.

      1. Making the Admin Name & Password Secure

      One of the first steps towards securing your Magento site is using a secure username and password. The rule of thumb for creating a secure password is to always use a password which is not easily guessable, for instance strings like ‚Äė123‚Äô or ‚Äėabc‚Äô, or your phone number, date of birth, etc. It is always a best practice to keep a password longer than eight characters, and that should be a combination of letters¬†(a, b, c, etc.), numbers (1, 2, 3, etc.) and special characters (@, &, #, etc.).

      Besides having a secure password, it is also very important to create a username which is not easily predictable. Most hacking attempts succeed because hackers only have to guess the password, as usernames are mostly set to easy-to-guess¬†names like ‚Äėadmin‚Äô, ‚Äėadministrator‚Äô, etc.¬

      Therefore I strongly advise you to create non-generic usernames like your nickname, last name, company name, etc. There is an option to create a username at the time of installing Magento, but even after installation, you can change your Magento username and password by going to System > My Account.

      Magento Changing username  Password

      2. Creating a Custom Path for the Admin Panel

      By default the admin panel path for Magento looks like this: http://myexamplestore.com/admin. As it is a¬†fairly well-known path for everyone, it is prone to many security risks. If we change the admin path to a unique and unpredictable¬†path like http://myexamplestore.com/secureadmin, we can nip most hacking attempts in the bud. This small step can heavily contribute to making your Magento installation much more secure, and can be the best defense against Broken Authentication and Session Management Attacks.¬

      To change the admin path in Magento, go to the app/etc/local.xml file, find the line with this code:¬ <![CDATA[admin]]>, and change the string admin to the required admin string. For instance, if you want to change the admin panel URL to¬ http://myexamplestore.com/securedadmin, change the CDATA code to¬ <![CDATA[securedadmin]]>¬

      3. Adding Two-Factor Authentication for Admin

      A common technique for increasing any system's¬†security is to add another security layer to it¬†using two-factor authentication, where the system demands two separate authentications to give access.¬

      A simple example of this is ATM card authentication. You¬†not only have to enter your card, as one factor of the authentication, but also your PIN code, which is another factor of authentication, hence two-factor authentication.¬

      There are some excellent extensions available which enable two-factor authentication in Magento, and make it much more secure.

      One such Magento extension is Rubon. It allows you to add trusted smartphone devices, through which you can access the Magento admin panel. Another is Extendware, which adds two-factor authentication to your system through Google Authenticator. Both of them are very good extensions, and worth a try.

      4. Using an Encrypted (SSL/HTTPS) Connection

      Another quite easy-to-implement Magento security step is to enable HTTPS/SSL secure URLs.¬

      Whenever data is communicated between you and your server, there is a risk of that data being intercepted by third¬†parties. As that data can contain vital information like login details, database information, etc., that data falling into the wrong¬†hands can cause significant trouble.¬

      It is therefore always a good idea¬†to use secure encrypted connection for transmission of data. Making your site HTTPS/SSL encrypted will also make it PCI-compliant, and more trustworthy in the eyes of your customers.¬

      You can do that in Magento by simply going to System > Configuration > General > Web. In Base URL, change 'http' to 'https', and enable Use secure URLs in Frontend and Use secure URLs in Admin.

      Magento Enabling Secure URL

      5. Using Secure FTP for File Upload

      While it is important to encrypt and secure the data transfer between your browser and your server, it is also pertinent to secure the data communication to your server via FTP. One of the common ways of hacking internet sites is through FTP password interceptions. This security problem can be effectively checked by using SFTP (SSH File Protocols). This protocol provides additional encryption of user credentials by using a private key file for authentication. You should also ensure that your file permissions are not set to 777, as this will make them writable by anyone, and cause a security risk.

      6. Restricting Admin Access to Only Pre-Approved IP Addresses

      There is an option in Magento by which we can pre-define IP addresses which can access the Magento admin panel.¬†This step can add a great security layer to your Magento store. You can create a list of IP addresses of your and your coworkers‚Äô computers and add them in the list of IP addresses which can access your Magento site‚Äôs admin panel. All other IP address users will not be able to access your Magento admin panel.¬

      To enable this IP address restriction, first of all you need to edit your .htaccess file to enter the IP addresses you want to allow. For that, enter the following code in the .htaccess file:

      Here the IP address ‚Äė192.168.112.11‚Äô will be allowed, and secondly, all the IP addresses starting with ‚Äė168.121‚Äô will be allowed. You can allow as many IP addresses as you want, following this format.¬†All other IP addresses not mentioned there¬†will be denied access.¬

      The next step is to create a new folder ‚Äėadmin‚Äô in your Magento root directory. Copy your Magento's index.php file into that folder, and change the relative paths to config.php and Mage.php file by changing these two lines:

      Notice, we have only added ../ in these file paths.

      Now we have to direct the users coming to our admin paths to this directory. To do that, enter these lines into your .htaccess file:

      Here {admin_path} indicates the new admin path we manually changed in step 2. For instance it can be securedadmin, as we defined in the step 2 example.

      Please note that you should only implement this security step if your ISP provides you a static IP address. Some ISPs assign dynamic IP addresses to users each time they connect to the internet. In such cases, as your IP address keeps on changing, you shouldn't implement this security step.

      7. Disabling of Malicious PHP Functions

      Some PHP functions are more prone for virus injections and are security risks. It is best to disable these malicious PHP functions in the first place. If your code relies on any such functions, the best way is to use some alternative, more secure function with similar functionality. To disable such malicious functions, open your php.ini file and add the following code in it:

      If you already have some code disable functions in your php.ini file, then simply append the functions given in the above code. If any of the above-mentioned functions are really important to your theme/module files, and you are unable to find an alternative, you can omit them from this list.

      8. Disabling Directory Indexing

      Directory listing is another loophole in many servers. Through directory listing, anyone can enter your website’s URL and see the directory structure and files location of all your website (like the screenshot below). This can make your website very vulnerable to security attacks.

      Magento Directory Indexing
      Image Credit:¬ Red Leopard

      This loophole can be effectively plugged by disabling directory indexing. For this, add the following line of code in your .htaccess file:

      9. Lowering the Risk of MySQL Injections

      Like any other eCommerce system, Magento websites have many form fields where users can enter data, like order fields, profile fields, customer review fields, etc. Sometimes hackers use these fields to inject a MySQL statement, which can resultantly disclose back-end technology information, or can enable access to restricted areas of the website. Although Magento does a good job of outmaneuvering any such attacks, it is still advisable to use web application firewalls to ensure that your website remains safe from any such attacks.

      There are many more ways to make your Magento installation even more secure, but I‚Äôm sure that if you implement all the above steps, you‚Äôll have a very robust and secure Magento site, which will be able to sustain most hacking attempts.¬

      Besides the above-mentioned steps, one obvious way to make your Magento site more secure is by always keeping your Magento installation updated. The Magento team does an excellent job of fixing possible security vulnerabilities, so the latest Magento version is usually better and more secure. You should also keep your Magento associated email address secure, because anyone who can access that email address can access your Magento store.

      Do mention in the comments your thoughts and feedback about this article, and don’t forget to share it with your friends if you like it.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. HTTP Mock Testing in NodeJS

      Final product image
      What You'll Be Creating

      HTTP mock tests let you implement and test a feature even if dependent services are not implemented yet. Also, you can test¬†services that have¬†already been¬†implemented without actually¬†calling those services‚ÄĒin other words you can test them offline. You need to analyze your business needs for that application first, and write them as scenarios in your design documents.

      Let's say that you are developing a NodeJS client API for a media client that is a service (there is no such service in real life, just for testing) for music, video, pictures, etc. There will be lots of features in this API, and there might be a need for some changes from¬†time to time.¬

      If you have no tests for this API, you will not know what problems it will cause. However, if you have tests for this API, you can detect issues by running all the tests you have written before. If you are developing a new feature, you need to add specified test cases for that. You can find an API that's already been implemented in this GitHub repository. You can download the project and run npm test in order to run all the tests. Let’s continue the test part.

      For an HTTP mock test, we will use nock, which is an HTTP mocking and expectations library for NodeJS. In HTTP mock testing, you can apply the following flow:

      1. Define a Request/Response mock rule.
      2. Create a test and use your function in the test.
      3. Compare the expected results with the actual results in the test callback.

      Simple Testing

      Let's think about a media client API. Let's say you call the function musicsList by using an instance of the Media library as below:

      In this case,¬†you will get a music list in the¬ response variable by making a request to https://ap.example.com/musics inside this function. If you want to write for this, you need to mock requests in order to make your tests run offline.¬†Let's simulate this request in nock.¬

      describe('Musics Tests', function() ..... is for grouping your tests. In the above example, we are grouping music related tests under the same group.¬ it('should list music', function(done).... is for testing specific actions in music-related functions. In each test, the¬ done callback is provided in order to check the test result inside the callback function of the real function. In the mock request, we assume that it will respond¬ OK if we call the¬ musicList function. The expected and actual result is compared inside the callback function.

      Matching From a File

      You can define your request and response data inside a file. You can see the below example for matching response data from a file.

      When you create a piece of music, the response should match the response from the file.

      Chaining Mock Requests

      You can also chain a mock request in one scope as below:

      As you can see, you can mock music creation and response first, and then music deletion, and finally the response to¬†other data.¬

      Matching Request Headers

      In the media client,¬ Content-Type: application/json is provided in request headers. You can test a specific header like this:

      When you make a request to https://api.example.com/musics with a header Content-Type: application/json, it will be intercepted by the nock HTTP mock above, and you will be able to test the expected and actual result. You can also test response headers in the same way just by stating the response header in the reply section:

      Reply With Default Headers

      You can specify default reply headers for the requests in one scope by using defaultReplyHeaders as follows:

      When you call the API, you will find default reply headers in the response, even if it is not specified.

      HTTP Operations

      HTTP operations are the fundamentals of client requests. You can intercept any HTTP operation by using¬ intercept:

      When you try to delete music with id 1, it will respond 404. You can compare your actual result with 404 to check the test status. Also you can use GET, POST, DELETE, PATCH, PUT, and HEAD in the same way.

      Response Repetition

      Normally, mock requests made by using nock are available for the first time. You can make it available as much as you want like this:

      You are limited to doing two requests as mock HTTP requests. When you make three or more requests, you will automatically make a real request to the API.

      Custom Port

      You can also provide a custom port in your API URL:

      Scope Filtering

      Scope filtering becomes important when you want to filter the domain, protocol, and port for your tests. For example, the below test will let you mock requests that have sub-domains like API0, API1, API2, etc.

      You are not limited to one URL here; you can test sub-domains specified in the regexp.

      Path Filtering

      Sometimes your URL parameters may vary. For example, pagination parameters are not static. In that case, you can use the following test:

      Request Body Filtering

      If you have varying fields in your request body, you can use¬ filteringRequestBody to eliminate varying fields like this:

      Here¬ author may vary, but you can intercept the request body with title=test.

      Request Header Match

      In this client, a token is used to authenticate the client user. You need to check the header to see a valid token in the¬ Authorization header:

      Turn Mocking On or Off

      In test cases, you can enable real HTTP requests by setting allowUnmocked as true. Let's look at the following case:

      In a nock scenario, you can see a scenario for the¬ /musics URI, but also if you make any URL different from /musics, it will be a real request to the specified URL instead of a failing test.

      Other Utilities

      We have covered how to write scenarios by providing a sample request, response, header, etc., and checking the actual and expected result. You can also use some expectation utilities like isDone(), clear the scope scenario with cleanAll(), use a nock scenario forever by using persist(), and list pending mocks inside your test case by using pendingMocks().

      isDone()

      Let's say that you have written a nock scenario and execute a real function to a test scenario. Inside your test case, you can check whether the written scenario is executed or not as follows:

      Inside the request callback, we are expecting that URL in the nock scenario (http://api.example.com/musics) to be¬†called.¬

      cleanAll()

      If you use a nock scenario with persist(), it will be available forever during the execution of your test. You can clear the scenario whenever you want by using this command as shown in the following example:

      In this test, our request and response match with the scenario. However, after¬ nock.cleanAll() we reset the scenario, and we are not expecting a result with 'OK with music list'.

      persist()

      Every nock scenario is available only the first time. If you want to make it live forever, you can use a test like this one:

      pendingMocks()

      You can list the pending nock scenarios that are not done yet inside your test as follows:

      You may also want to see the actions performed during test execution. You can manage to do that by using the following example:

      This test will generate an output as shown below:

      Quick Tips

      Sometimes, you need to disable mocking for specific URLs. For example, you may want to call the real¬ http://tutsplus.com, instead of the mocked one. You can use:

      This will make a real request inside your tests. Also, you can globally enable/disable by using:

      Note that, if you disable net connect, and try to access an unmocked URL, you will get a¬ NetConnectNotAllowedError exception in your test.¬

      Conclusion

      It is best practice to write your tests before real implementation, even if your dependent service is not implemented yet. Beyond this, you need to be able to run your tests successfully when you are offline. Nock lets you simulate your request and response in order to test your application.¬

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Get Started Building Your Blog With Parse.js: Add a New Blog

      Final product image
      What You'll Be Creating

      Have you ever got excited by your idea for a website, but found yourself becoming miserable when trying to make it dynamic and actually run it on a server?¬

      With Parse.js, everyone who understand the basics of HTML, CSS, and JavaScript can create dynamic websites and working web apps. This tutorial is going to take you through the process of creating a blog system step by step with Parse.js. And by the end of this series, you should be able to create your own CMS site with ease.

      In the past three sessions, you've built the groundwork of the blog system. You created a Blog class and a User class on Parse.com, you are rendering blogs in the front end, and you enabled user login. From this session on, we are going to build out different functions of that admin panel, starting with "Add a New Blog."

      1. Create and Render AddBlogView

      Step 1: Prepare an HTML Template

      First things first, let's prepare an HTML template for that page so that we have something to play with. Again, you can use existing elements of Bootstrap to speed up the process:

      Add that to admin.html.

      Notice that we are making it a template, although there is no dynamic value at this point. I am doing that because:

      1. I'd like to keep my HTML very structured and everything is its own template block.
      2. In future sessions we are going to build the category dropdown, so potentially there could be dynamic content on this page.
      3. The same page template would be reusable when we build the "Edit" function, and we definitely need to pull the existing content in EditBlogView.

      Step 2: Create AddBlogView

      Moving on, go to admin.js and create a new View: AddBlogView. We can keep it very minimal for now, since we are just rendering the template:

      Step 3: Link to AddBlogView

      Now that we have AddBlogView, we want to link to it from the admin panel. Go ahead and add a button to the WelcomeView:

      And then, you need to bind an event on that button click. Usually you might do something like this in your admin.js:

      However, that's not necessary when you are using Parse.js. You can just add an event to a View object and bind a function like this:

      You can give it a try before we move on:

      Test View Function

      And now we can change the function to render a new instance of AddBlogView.

      Rendered addBlogView

      Feels awesome.

      2. Write to the Database

      Now all you need is to bind a function to the submit button on this page and write the blog into your database on Parse.com.

      Step 1: Add a Submit Event

      Add a submit event to your AddBlogView‚ÄĒit's not very different from the click event we just added.

      Step 2: Include the¬ Blog Class

      Then, because we are trying to write to the Blog table on Parse.com, we need to include the Blog class:

      Step 3: Add a¬ create() Function to the¬ Blog Class

      After that, let's add a create() function to the Blog class, so we can call it from any view object. It should take two parameters,¬ title and content, and save it into the database.

      Parse.js made it very simple. Once a new instance of the Blog class is created, we can just set the values we want it to have and call the save() function to save it to the database.

      Or you can also just write the data in the save() function:

      Both would work.

      Notice that I also include author in the database with Parse.User.current(). That's the method you should use to get the current user logged in.

      Step 4: Call blog.create() from AddBlogView

      Now, as the final step to make it work, you need to call blog.create() from the AddBlogView we just created.

      Let's add it to the submit() function:

      Give it a test run. Looks like it's working!

      Submit Success Alert

      And if you check it on Parse.com, you will see it's stored in the Blog table.

      Submit Success Database

      Congrats! You are writing to the database.

      3. Store Author Name and Time of Post

      Now let's take a look at the blog list again:

      Problem in the Blog List

      You will notice that instead of the user name, we are showing the user ID. And we are not showing the time when the blog is created. We do have createdAt and updatedAt values in the back end, but they are not very readable for the user.

      If we want to fix that, there are two general approaches:

      • When we read from the database, we get the username by the ID, and we change the format of the time of post.
      • When we write to the database, we add two more fields to store the username and the time.

      If we take the first approach, we are doing the same thing over and over again, and that's using the visitor's time and resources. Therefore, we want to do it while writing to the database. Don't worry about things like "what if the user changed his/her name?" yet‚ÄĒwe can always do a group update when that happens.

      Step 1: Add Two More Columns in the Blog Table

      You should be really familiar with this process now. Let's set the name and the type of those two fields as following:

      • authorName (String)
      • time (String)

      Step 2: Add Data Fields to the¬ create() function

      Then you need to modify the create() function to record those values:

      Notice that I just use the .toDateString() function here; you can use other date functions to get the time format you want.

      Step 3: Update the Blogs Template to Use Those Values

      Lastly, let's update #blogs-tpl in index.html to pull the new values:

      Now you can delete those existing posts, and add some more from the new "Adding a New Blog" page.

      Delete Existing Posts

      Now all the fields should be working.

      Blog List Updated

      4. Bonus: WYSIWYG Editor

      Because we use {{{content}}} in the template, you will find you can already put HTML tags in your content <textarea> and it will render correctly in the front end. However, most people, myself included, don't feel it's the most natural way to write a blog.

      I will show you how to add a simple WYSIWYG editor very quickly, so you know it's readily doable.

      Step 1: Download Plugin

      First, download the plugin.

      It has been updated already, but for the demo and tutorial purpose, let's just use the old one.

      Step 2: Link CSS and JS Files

      Unzip the files, copy /dist/bootstrap-wysihtml5-0.0.2.css and put it in your CSS folder. Similarly, copy /dist/bootstrap-wysihtml5-0.0.2.min.js and /lib/js/wysihtml5-0.3.0.min.js into your JS folder.

      Then, link those files in admin.html:

      Step 3: Enable Wysihtml5 in JavaScript

      To enable wysihtml5, all you need is to call wysihtml5() on the <textarea> element. Let's just add that to the render() function in AddBlogView:

      Then, instead of getting the plain text from the serializeArray() function, we can get the HTML from val(). Let's change the create() call to use that:

      The code here is really simple; feel free to modify it to be more efficient if you want. (Use a class name as the selector, store $('textarea') as a variable, etc.)

      Now if you refresh and test, it should be working already!

      wysihtml5 in Action

      As it's not the focus of this tutorial, I will stop here. wysihtml5 offers many options beyond this, so take a look at these two repos if you are interested:

      Conclusion

      In this session, you enabled users to add a new blog. You prepared a user interface, and linked it to the back-end database. You also added more fields to the Blog class, so it's more readable in the list. Lastly, you also implemented a simple WYSIWYG plugin. I think that's a lot, and hopefully you feel it this way, too!

      In the next session, we will lay the groundwork for a more functional admin panel. You will learn the concept of a router, and you will merge index.html and admin.html into one. Moreover, we will output the blog list in the admin panel, so the user can edit and delete them. Stay tuned.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Create a Simple CRM in WordPress: Creating Custom Fields

      In this series, we've been looking at how to create a simple CRM system in WordPress.  In the first part of this series, we created a WordPress Plugin that registered a 'Contacts' Custom Post Type, but we've yet to cover how to store additional information for a Contact.

      Creating Custom Fields

      WordPress has the add_meta_box() function, which allows plugin and theme developers to register custom meta boxes against various WordPress Administration screens.

      WordPress registers some of its own meta boxes for display when you create a Post or a Page. For example, on Pages, you have the Page Attributes meta box:

      Let’s add a meta box to our Contacts custom post type. Open the plugin file you created in the first tutorial of this series. Then, in the plugin’s constructor, update the code to match the below. This registers our register_meta_boxes() function against the add_meta_boxes action:

      Next, in our register_meta_boxes() function, we add a call to add_meta_box(). This tells WordPress we want a meta box called Contact Details, which is rendered by our output_meta_box() function. Add the below code after the constructor function:

      Finally, we need an output_meta_box() function, which is called by add_meta_box above. Add the below code after the register_meta_boxes() function:

      Let’s check we have a meta box appearing on our Contacts custom post type. Create a new Contact in the WordPress dashboard by going to Contacts > Add New.

      If everything has been written correctly, you should see something similar to the follow screenshot:

      Populating the Meta Box With a Field

      Let’s go ahead and add an email address field to this meta box. Change your output_meta_box function to the below code:

      Save your plugin code, and reload the Add Contact screen. You should see our new Email Address field appear in the Contact Details meta box:

      Saving Custom Field Data

      We’re not quite done yet. We need to tell WordPress to save the content that a user inputs into this field. In WordPress, we do this by registering a function against the save_post action.

      As with most actions, we’ll register our action in the plugin’s constructor:

      Next, let’s create our save_meta_boxes() function:

      This function performs several actions, because the save_post action can be called quite frequently by WordPress and other plugins (for example, when periodically autosaving a draft, or a different Post Type is saved). We need to be sure that we only save our custom field data if the user saved or updated a Contact.

      If we are saving a Contact, we sanitize the email address. From the WordPress Codex:

      Checks for invalid UTF-8, Convert single < characters to entity, strip all tags, remove line breaks, tabs and extra white space, strip octets.

      In short, we make sure there’s no funky formatting on our text string.

      Finally, we store the email address in the post meta data, using update_post_meta. Think of post meta as a series of key/value pairs that are attached to a post. You can have as few or as many as you like. In our example, we’re storing the value of our custom field against the key _contact_email.

      Reading Custom Field Data

      Create a new Contact and enter an email address. Save the new Contact, and you’ll notice that the email address doesn’t appear in the field:

      We need to edit our output_meta_box() function to read the Post meta, and display it in the input field. Change the output_meta_box() function to the below code:

      We use get_post_meta() to get the value for the given Post ID and meta key combination. We know the meta key is _contact_email, as that’s what we used when we saved the custom field value in update_post_meta()

      Security

      Security is extremely important when submitting and handling form data. We need to know that the source of our data is trustworthy when saving it. If we cannot trust the source of our data, we must not store it ‚Äď the data may be compromised or corrupted in a way to try and exploit a bug or security flaw.

      WordPress provides us with nonces (a ‚Äúnumber used once‚ÄĚ), that can be sent along with the form data. This nonce can be checked when our save routine runs, to ensure it matches the value we‚Äôd expect.

      This helps prevent cross-site request forgery (CSRF) attacks i.e. someone trying to submit form data to our save routine from a different web site.

      We need to add in security to the above code in two places:

      1. output_meta_box(): add a nonce value to the form
      2. save_meta_boxes(): verify a submitted nonce value

      Let’s edit the output_meta_box() function, replacing it with the below code:

      This uses wp_nonce_field(), to generate a hidden field called contacts_nonce, with an action called save_contact. Its value is generated by WordPress.

      Next, let’s edit the save routine in save_meta_boxes():

      This adds two checks to our save routine:

      1. Check that a nonce field has been set in our form. If not, don’t save anything.
      2. Check that the nonce field’s value is what we expect. If not, don’t save anything.

      Create or edit your Contact, and make sure that the email address is now being saved.

      Up Next…

      In the next article, we’re going to use Advanced Custom Fields to add custom fields to our Contact custom post type, allowing us to create a rich user interface with a wider range of input types.

       

      0 Comments

      Leave a comment › Posted in: Daily

  • Page 3 of 55 pages  < 1 2 3 4 5 >  Last ›
  • Browse the Blog

    Syndicate

    Most recent entries

    governing-bruise