4elements, Amsterdam, Holland

  1. Data Visualization App Using GAE Python, D3.js and Google BigQuery

    Imagine that you have a large set of data with millions of rows and you're faced with the task of extracting information from the data. How do you make sense of a large set of data? The simple answer to this question is that we do so via data visualization, but what is that, exactly?

    Data visualization is the pictorial representation of data to figure out what is hidden inside the information. In this three-part series, we'll create a visualization app to extract information and make sense of a large set of data.

    Querying large chunks of data without proper hardware can result in performance issues. Google provides a solution to this problem in the form of BigQuery. Backed by Google's infrastructure, it enables you to query large chunks of data. We'll be using a dataset from Google BigQuery for our visualization application.

    In this tutorial, I'll take you through the process of creating a visualization application using Python, Google BigQuery, and the D3.js JavaScript library. We'll be using Google App Engine (or GAE) to host our application.This tutorial assumes that you have a basic knowledge of Python and JavaScript. For creating graphs, we'll be using D3.js.

    Note also that the code from the above tutorial is available on GitHub, and a demo is hosted on AppSpot.

    Getting Started With Google App Engine 

    Step 1: Downloading and Using The GAE Python SDK 

    Let's get started by setting up our development environment. Download the Google App Engine Python SDK and extract it. We'll be using the webapp2 framework for Python. 

    From Google's documentation:

    A webapp2 application has two parts: 
    1) one or more RequestHandler classes that process requests and build responses 
    2) a WSGIApplication instance that routes incoming requests to handlers based on the URL.

    The aforementioned points will become more clear when we create our request handler class. Create a directory called PythonD3jsMashup which will be our project directory. Navigate to the project directory and create a file called app.py. This will be our application module. Let's create a request handler class to process the request and build a response, and a WSGIApplication instance to route requests. 

     Here is how app.py should look:

    import webapp2
    
    class ShowHome(webapp2.RequestHandler):
        def get(self):
            ## Code to render home page
    
    ## Here is the WSGI application instance that routes requests
    
    application = webapp2.WSGIApplication([
        ('/', ShowHome),
    ], debug=True)

    When a / request occurs, it's routed to the ShowHome class which renders the home page. Let's write the Python code to display our homepage. First, create a new folder called Templates in the PythonD3jsMashup folder. Inside it, create an HTML page called index.html

    It should contain the following code:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <link rel="icon" href="http://getbootstrap.com/favicon.ico">
        <title></title>
        <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="http://getbootstrap.com/examples/justified-nav/justified-nav.css" rel="stylesheet">
    
    
    </head>
    
    <body>
    
        <div class="container">
    
            <div class="masthead">
                <h3 class="text-muted">Data Visualization App</h3>
                <ul class="nav nav-justified">
                    <li class="active"><a href="#">Home</a>
                    </li>
    
                    <li><a href="#">Source Code</a>
                    </li>
                    <li><a href="#">About</a>
                    </li>
                </ul>
            </div>
    
            <!-- Jumbotron -->
            <div class="jumbotron">
                <h1>Data Visualization App</h1>
                <p class="lead">Python & D3.js Mashup app</p>
                <p><a class="btn btn-lg btn-success" href="#" role="button">Click here</a>
                </p>
            </div>
    
    
    
            <!-- Site footer -->
            <div class="footer">
                <p>© Company 2014</p>
            </div>
    
        </div>
        <!-- /container -->
    
    
    </body>
    
    </html>

    In order to render templates, we'll need to import the template library. After doing so, we'll use it to render the index.html page as shown below:

    import webapp2
    from google.appengine.ext.webapp import template
    
    class ShowHome(webapp2.RequestHandler):
        def get(self):
            temp_data = {}
            temp_path = 'Templates/index.html'
            self.response.out.write(template.render(temp_path,temp_data))
    
    application = webapp2.WSGIApplication([
        ('/', ShowHome),
    ], debug=True)

    Next, navigate to the project directory PythonD3jsMashup and create a file called app.yaml. This file will act as a configuration file for our application. It should look like this:

    application: appid
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: app.application

    As you can see, we have defined a number of things in the app.yaml. Most of the parameters are self-explanatory. The handlers directive dictates that every URL request that matches /.* be handled by the application object in the app module.

    To run the application locally, navigate to the GAE SDK and run the following command:

    ./dev_appserver.py <path-to-PythonD3jsMashup-folder>

    Point your browser to http://localhost:8080 and you should see this page:

    Deploying an App to AppSpot 

    Next, we'll be deploying our app onto the Google App Engine. In order to deploy the app, first log in to the GAE console:

    From the dashboard click on the Create Application button.

    Next, you'll see a screen similar to the one shown below. Type an Application Identifier and Application Title for the app and click Create Application.

    Once the application is registered successfully you'll be greeted with a success message:

    Make a note of the red circled text which will be used as application identifier later.

    Click on the dashboard link. From the left menu in the Dashboard, under the Administration tab, click on the Application Settings. You'll see the following screen:

    Make a note of the Service Account Name. We'll need this in the Google developer console.

    Next, modify the application name to pythond3jsmashup in app.yaml.

    application: pythond3jsmashup
    version: 1
    runtime: python27
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: app.application

    Now to deploy the app to GAE, navigate to GAE Python SDK and type the following command:

    ./appcfg.py update PythonD3jsMashup/

    Once deployed, try browsing the AppSpot URL.

    Getting Started With Google BigQuery

    To get started with Google BigQuery, log in to the Google API console. You should see a dashboard listing all the available projects in your Google account. Click on the project name PythonD3jsMashup.

     

    Make a note of the Project Number, which we'll use while connecting with Google BigQuery.

    From the left side menu, click on the APIs & auth tab. From the listed items click on APIs. Now you should see a list of available APIs:

    BigQuery API is turned OFF. Click on the OFF status to turn it ON.

    Click on the project name pythond3jsmashup on the left side menu and click Permissions. Click Add Member and add the Service Account Name (which we noted down earlier) with "Can edit" permissions as shown below:

    Collecting Data From Google BigQuery

    Until now, we created our simple app and deployed it on GAE with BigQuery API enabled. Next, we'll be connecting to one of the freely available datasets on BigQuery. 

    Let's start by creating a new page called  Templates/chart.html where we'll show the visualization. Create a method to route the Click Here link on our home page to chart.html

    Here is what it looks like:

    class ShowChartPage(webapp2.RequestHandler):
        def get(self):
            temp_data = {}
    	    temp_path = 'Templates/chart.html'
    	    self.response.out.write(template.render(temp_path,temp_data))

    Also modify the request handler to route the request /chart to ShowChartPage as shown below:

    application = webapp2.WSGIApplication([
        ('/chart',ShowChartPage),
        ('/', ShowHome),
    ], debug=True)

    Next, modify the href attribute of the Click here link as shown:

    <a class="btn btn-lg btn-success" href="http://pythond3jsmashup.appspot.com/chart" role="button">Click here</a>

    Now try running the app and on clicking Click here, and you should be redirected to chart.html.

    Next, we'll try to authenticate our app with Google BigQuery and fetch some data. For authentication, we'll require Google API Python client. Download google-api-python-client-gae-1.2.zip and extract it into the project folder.

    Include the following libraries in app.py.

    import httplib2
    from apiclient.discovery import build
    from oauth2client.appengine import AppAssertionCredentials

    First, to query a dataset from BigQuery we need to build a BigQuery service as shown: 

    url = 'https://www.googleapis.com/auth/bigquery'
    credentials = AppAssertionCredentials(scope=url)
    httpss = credentials.authorize(httplib2.Http())
    bigquery_service = build('bigquery','v2',http=httpss)

    Second, we need to create a query that we'll be executing against the BigQuery dataset. We'll be using the Shakespeare dataset. Here is the query that we'll be executing against the dataset:

    queryData = {'query':'SELECT word FROM [publicdata:samples.shakespeare] LIMIT 1000'}

    To query the data we'll create a job from the bigquery_service:

    tableData = bigquery_service.jobs()

    And then query from the created job:

    response = tableData.query(projectId=PROJECT_NUMBER,body=queryData).execute()

    Replace PROJECT_NUMBER with the project number we had noted down earlier. So, here is the modified app.py:

    import httplib2
    import webapp2
    from google.appengine.ext.webapp import template
    from apiclient.discovery import build
    from oauth2client.appengine import AppAssertionCredentials
    
    url = 'https://www.googleapis.com/auth/bigquery'
    PROJECT_NUMBER = 'xxxxxxxxxxxxx'
    
    credentials = AppAssertionCredentials(scope=url)
    httpss = credentials.authorize(httplib2.Http())
    bigquery_service = build('bigquery','v2',http=httpss)
    
    class ShowChartPage(webapp2.RequestHandler):
        def get(self):
            temp_data = {}
    	    temp_path = 'Templates/chart.html'
    	    queryData = {'query':'SELECT word FROM [publicdata:samples.shakespeare] LIMIT 1000'}
    	    tableData = bigquery_service.jobs()
    	    response = tableData.query(projectId=PROJECT_NUMBER,body=queryData).execute()
    	    self.response.out.write(response)
    	    #self.response.out.write(template.render(temp_path,temp_data))
    	
    class ShowHome(webapp2.RequestHandler):
        def get(self):
            template_data = {}
            template_path = 'Templates/index.html'
            self.response.out.write(template.render(template_path,template_data))
     	
    	
    
    application = webapp2.WSGIApplication([
        ('/chart',ShowChartPage),
        ('/', ShowHome),
    ], debug=True)

    The response from the query would be printed out on chart.html. Save all your code and upload the modified code to GAE using appcfg.py update PythonD3jsMashup/.

    Now if you point your browser to http://pythond3jsmashup.appspot.com/chart you'll see the json response returned from querying the dataset.

    Conclusion

    In this tutorial, we created a Python application and deployed it on Google App Engine. We connected our application with Google BigQuery and fetched data from the freely available dataset. 

    Next, we'll try to parse the data fetched from Google BigQuery and visualize it using JavaScript library D3.js. In the meantime, please don't hesitate to leave any questions or comments in the feed below.

     

    0 Comments

    Leave a comment › Posted in: Daily

    1. Custom Events in Magento With the Observer Pattern

      Considering the number of eCommerce frameworks available in the market, Magento is one of the most popular choices for medium-to-large-scale web shops. Both its feature set and its architecture help set it apart from many of the other options that are available today.

      Although there are a lot of third-party extensions for Magento available, it's also easy to develop your own. The purpose of this tutorial is not to walk through how to create a custom extension; however, it does assume that you're familiar with the process as we'll be using a design pattern to implement our own custom module.

      Specifically, we'll be looking at the Event-Observer pattern. For those who are unfamiliar, observers register themselves to wait for an event so that they can execute code whenever an event is fired. 

      As mentioned, this tutorial assumes that you're familiar with how to develop custom modules within Magento, because we're going to create a custom module that employs that design pattern.

      Setting Up the Observer

      First, we need to declare the observer for our custom event. To do this, enter the following code into your module's config.xml file just inside the global element.

      We'll explain the code momentarily.

      <global>
        ..
        ..
        <events>
          <my_custom_event>
            <observers>
              <namespace_modulename_my_custom_event_observer>
                <type>singleton</type>
                <class>modulename/observer</class>
                <method>my_custom_method</method>
              </namespace_modulename_my_custom_event_observer>
            </observers>
          </my_custom_event>
        </events>
        ..
        ..
      </global>

      In the code above, we've just declared the observer for the event named my_custom_event. This simply means that whenever my_custom_event is fired, it will see that the observer for this event is registered in your module and then execute the code associated with event. 

      In our case, it'll call the method my_custom_method defined in the class Namespace_Modulename_Model_Observer.

      Now, let's take this a step further. Notice that in the <events> tag, you can define the events for which you would like to register the observers. In our case, we've registered the observer for the event <my_custom_event>. You can also define multiple observers for the same event. In that case, declare all your observers inside the <observers> tag.

      Next, each observer is wrapped with a unique identifier. In our example, it's <namespace_modulename_my_custom_event_observer>. Furthermore, you need to specify the class name and the method name which will be executed. The <class> tag specifies the location of the class as per the Magento convention. 

      In our example, it will be Observer.php under the model directory of modulename module. The method name is declared by the <method> tag. The value of the <type> tag is "singleton" which means that it will use the same instance of the observer object for each event call.

      Now, after declaring our observer, let's create the observer class and related method code. Create a file Observer.php under the Model directory of your module. Copy and paste the following code in that file.

      <?php
      class Namespace_Modulename_Model_Observer
      {
        public function my_custom_method($observer) {
          $event = $observer->getEvent();
      
          // getter method to fetch cid value passed from the dispatcher
          $cid = $event->getCid();
          echo $cid;
          exit;
        }
      }
      ?>

      Here, we've just created the observer class. In the my_custom_method method, you'll have access to the observer object and the data passed along with it from the dispatcher so that you can use it to do something meaningful. 

      In this example, we have just fetched the value of the cid variable passed from the dispatcher code which we'll see in a moment.

      Of course, you need to modify the modulename and namespace according to your custom module in the class file and XML declaration.

      Dispatch Our Custom Event

      As we've declared the observer in the custom module, the only thing remaining is to dispatch our custom event. 

      Let's see how you can use Magento's event dispatcher from your custom module. Write the following code in your controller's method from where you would like to dispatch the event. Having said that, you can also fire the event from other places apart from the controller.

      <?php
      ..
      $event_data_array  =  array('cid' => '123');
      Mage::dispatchEvent('my_custom_event', $event_data_array);
      ..
      ?>
      
      

      As you can see it's fairly straightforward to dispatch the event from almost anywhere in Magento. The first argument of the dispatchEvent method is the name of the event and the second argument is used to pass the data to observers.

      As you may have noticed earlier in the observer class, we have used the getter method to access the value of variable cid.

      In most cases the event data passed to the observers is in read only mode. More specifically, observers can't change the value of the variables passed by the event dispatcher method.

      Granting the Write Access

      Assume that you have dispatched a custom event in your module, and you want the observers to be able to modify the original event data passed. Let's revisit the dispatcher code to accomplish this.

      <?php
      ..
      $event_data_array  =  array('cid' => '123');
      $varien_object = new Varien_Object($event_data_array);
      Mage::dispatchEvent('my_custom_event', array('varien_obj'=>$varien_object));
      
      // should output '456' as we'll change the value in observer
      echo $varien_object->getCid();
      ..
      ..
      ?>

      We've just used the special object from Magento Varien_Object and passed our data using that to make sure any modification to the data is preserved.

      You'll also need to change the observer class code accordingly. Here's the modified observer class.

      <?php
      class Namespace_Modulename_Model_Observer
      {
        public function my_custom_method($observer) {
          $event = $observer->getEvent();
      
          // getter method to fetch varien object passed from the dispatcher
          $varien_object = $event->getVarienObj();
          $varien_object->setCid('456');
        }
      }
      ?>

      The only major change in the code is fetching the varien object and using that to change the value of the array variable cid.

      Summary

      Though this is a relatively simple tutorial, it shows how we can easily implement the Event-Observer Pattern in the context of a Magento custom module. At this point, you should be familiar with creating your own custom modules using the Event-Observer pattern.

      Please don't hesitate to leave questions and/or comments in the form below!

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. The Beginner’s Guide to WordPress Taxonomies: A Custom Plugin

      Throughout this series, we've been taking a look at WordPress taxonomies: what they are, how they work, how to differentiate them between the different types that exist, and how they're stored in the underlying database.

      The only thing we've yet to do is actually put together a plugin that demonstrates how to use the API to implement our own custom taxonomies. So in this post, we're going to do exactly that. 

      Recall from the first post in this series:

      Taxonomy is one of those words that most people never hear or use. Basically, a taxonomy is a way to group things together.

      And throughout this series, we've been using photography and videography as our examples of classifications. So for the plugin that we're going to build, we'll include both hierarchical and non-hierarchical taxonomies relevant to both of these classifications.

      1. The hierarchical taxonomies will include base taxonomies of Photographs and Videos.
      2. The non-hierarchical taxonomy will be for specifying the type of film that was used. This may be Black and White, Color, Sepia, or whatever color you would like to specify.

      Finally, the plugin is going to work with the existing standard post type that ships with WordPress. This should give the most flexibility as it relates to building a plugin, demonstrating the concepts, and using it in your own installation.

      My Custom Taxonomies

      For the purposes of the example plugin, we're going to be calling it My Custom Taxonomies and we'll be building it in the following stages:

      1. We'll prepare the core plugin file that has the proper header text necessary to display the plugin in the WordPress dashboard.
      2. We'll setup the code necessary for executing the core plugin.
      3. We'll write code that will introduce both the Photographs and Videos taxonomy.
      4. We'll write code that will introduce the Film Type taxonomy.
      5. We'll then test the full plugin.

      1. The Plugin Header

      Before doing anything else, go ahead and create a directory in wp-content/plugins called my-custom-taxonomies and introduce a file called my-custom-taxonomies.php.

      My Custom Taxonomies Directory

      Within the file, add the following code comment block:

      <?php
      /**
       * My Custom Taxonomies
       *
       * Demonstrates how to create custom taxonomies using the WordPress API.
       * Showcases both hierarchical and non-hierarchical taxonomies.
       *
       * @link              http://code.tutsplus.com/series/the-beginners-guide-to-wordpress-taxonomies--cms-706
       * @since             1.0.0
       * @package           Custom_Taxonomies
       *
       * @wordpress-plugin
       * Plugin Name:       My Custom Taxonomies
       * Plugin URI:        http://example.com/plugin-name-uri/
       * Description:       Demonstrates how to create custom taxonomies using the WordPress API.
       * Version:           1.0.0
       * Author:            Tom McFarlin
       * Author URI:        http://tommcfarlin.com/
       * License:           GPL-2.0+
       * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
       */

      At this point, you should be able to login to the WordPress dashboard, see the name of the plugin, and activate it. Of course, nothing will actually happen since we haven't done anything with the source code yet.

      Next, we need to create another file that will be used to actually power the plugin. This will be based on object-oriented programming principles so we'll create a file called class-my-custom-taxonomies.php.

      Don't worry about populating it with any source code just yet. Let's return back to my-custom-taxonomies.php and add a conditional to make sure that the core plugin file can't be run outside of the WordPress environment.

      <?php
      
      // If this file is called directly, abort.
      if ( ! defined( 'WPINC' ) ) {
          die;
      }

      Place this directly under the code comment that we provided above.

      2. Executing The Core Plugin

      At this point, we're ready to write code that will actually drive the plugin. So let's define the class and a basic function for initialization:

      <?php
      
      /**
       * The core plugin class file
       *
       * Defines the functions necessary to register our custom taxonomies with
       * WordPress.
       *
       * @link       http://code.tutsplus.com/series/the-beginners-guide-to-wordpress-taxonomies--cms-706
       * @since      1.0.0
       *
       * @package    Custom_Taxonomies
       * @author     Tom McFarlin <tom@tommcfarlin.com>
       */
      class My_Custom_Taxonomies {
      
          /**
      	 * Initializes the plugin by registering the hooks necessary
      	 * for creating our custom taxonomies within WordPress.
      	 *
      	 * @since    1.0.0
      	 */
      	public function init() {
      
      	}
      
      }

      After that, let's return to my-custom-taxonomies.php and add a code to include the file as well as a method that will create an instance of the class and execute it:

      <?php
      
      /** Loads the custom taxonomy class file. */
      require_once( dirname( __FILE__ ) . '/class-my-custom-taxonomies.php' );
      
      /**
       * Creates an instance of the My_Custom_Taxonomies class
       * and calls its initialization method.
       *
       * @since    1.0.0
       */
      function custom_taxonomies_run() {
      
          $custom_tax = new My_Custom_Taxonomies();
      	$custom_tax->init();
      
      }
      custom_taxonomies_run();

      Now we have everything we need to begin actually setting up our hooks and callbacks to create our custom taxonomies.

      3. Introduce Photographs and Videos

      At this point, we're ready to begin introducing our taxonomies. We'll first focus on our two hierarchical taxonomies - Photographs and Videos.

      In the body of the class of class-my-custom-taxonomies.php file, add the following function:

      <?php
      
      /**
       * Creates the Photographs taxonomy that appears on all Post dashboard
       * pages.
       *
       * @since    1.0.0
       */
      public function init_photographs() {
      
          $labels = array(
      		'name'          => 'Photographs',
      		'singular_name' => 'Photograph',
      		'edit_item'     => 'Edit Photograph',
      		'update_item'   => 'Update Photograph',
      		'add_new_item'  => 'Add New Photograph',
      		'menu_name'     => 'Photographs'
      	);
      
      	$args = array(
      		'hierarchical'      => true,
      		'labels'            => $labels,
      		'show_ui'           => true,
      		'show_admin_column' => true,
      		'rewrite'           => array( 'slug' => 'photograph' )
      	);
      
      	register_taxonomy( 'photograph', 'post', $args );
      
      }

      This function is responsible for creating the Photographs taxonomy and will be called from within the init function when the time is right.

      Now, let's do the same thing for Videos:

      <?php
      
      /**
       * Creates the Videos taxonomy that appears on all Post dashboard
       * pages.
       *
       * @since    1.0.0
       */
      public function init_videos() {
      
          $labels = array(
      		'name'          => 'Videos',
      		'singular_name' => 'Video',
      		'edit_item'     => 'Edit Video',
      		'update_item'   => 'Update Video',
      		'add_new_item'  => 'Add New Video',
      		'menu_name'     => 'Videos'
      	);
      
      	$args = array(
      		'hierarchical'      => false,
      		'labels'            => $labels,
      		'show_ui'           => true,
      		'show_admin_column' => true,
      		'rewrite'           => array( 'slug' => 'video' )
      	);
      
      	register_taxonomy( 'video', 'post', $args );
      
      }

      Let's call these two from within the init function. We do this by registering these functions with the init hook as provided by WordPress:

      <?php
      
      public function init() {
      
          add_action( 'init', array( $this, 'init_photographs' ) );
          add_action( 'init', array( $this, 'init_videos' ) );
      
      }

      Here, we should be able to head over to Add New Post and see our new taxonomy options visible in the dashboard. If not, double-check your code against that which is shared above.

      Photograph and Video Categories

      Now that we've introduced our hierarchical taxonomies, let's move on to introducing our Film Type - or our non-hierarchical - taxonomy.

      4. Introduce Film Type

      This really isn't that much different from the code we've written up to this point. Really, the main difference is that instead of specifying hierarchical as true, we'll set it as false.

      <?php
      
      /**
       * Creates the Film Type taxonomy that appears on all Post dashboard
       * pages.
       *
       * @since    1.0.0
       */
      public function init_film_type() {
      
          $labels = array(
      		'name'          => 'Film Type',
      		'singular_name' => 'Film Type',
      		'edit_item'     => 'Edit Film Type',
      		'update_item'   => 'Update Film Type',
      		'add_new_item'  => 'Add New Film Type',
      		'menu_name'     => 'Film Type'
      	);
      
      	$args = array(
      		'hierarchical'      => false,
      		'labels'            => $labels,
      		'show_ui'           => true,
      		'show_admin_column' => true,
      		'rewrite'           => array( 'slug' => 'film-type' )
      	);
      
      	register_taxonomy( 'film-type', 'post', $args );
      
      }

      This will result in a different type of user interface element that looks more like tags rather than the category options that you see above.

      Finally, add the following line to the init method along with the rest of the hooks:

      <?php
      add_action( 'init', array( $this, 'init_film_type' ) );

      Notice that is functions more like tags that categories. Again, to reiterate, that's one of the main differences in hierarchical and non-hierarchical taxonomies.

      5. Testing The Full Plugin

      Now we're ready to give the plugin a spin. Assuming you've followed everything correctly throughout this tutorial, then you should be able to create a new post, stamp it with a type of Photograph or a type of Video as well as a type of Film and have it persist the changes after saving or updating your post.

      If not, double-check your code with what's referenced here and with what's referenced in the associated GitHub repository.

      Conclusion

      That wraps up The Beginner's Guide to WordPress Taxonomies. Throughout the series, we've taken a broad look at a definition of what taxonomies are, the role they play in WordPress, and we've even implemented a few of our own.

      At this point, you should have a solid understanding of the concept and how to proceed with including them in your next project.

      If not, don't hesitate to leave questions, comments, or general feedback in the field below.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Integrate Bitcoin Payment Gateway Into OpenCart: Part 1

      In this series, we are going to look at building a Bitcoin payment system into our installation of OpenCart. Before we get started, I recommend that you practice the basic OpenCart module development if you are not familiar with how to build your own modules.

      Once done, you should have enough knowledge to continue with developing more advanced modules. In this series, that's exactly what we aim to do.

      Getting Started

      Before we begin building the extension, set up OpenCart on your local machine. Next, download the BitPay API Library from the article attachment and place it in your store root as shown in the following screenshot:

      BitPay API Library

      To configure and set up up our Bitcoin Payment Module, we need an admin interface. To do this, we'll follow the MVC pattern for implementing our admin panel.

      1. Create the Admin Controller

      1. Navigate to admin/controller/payment
      2. Create a PHP file and name it bitpay.php
      3. Open the file in your favorite IDE and create a class following the OpenCart class naming convention, for example: class ControllerPaymentBitpay extends Controller {}
      4. Inside the controller class, define the default index function. 
      5. Then, inside this function, start writing the code as featured below.

      1.1 Loading Language & Models

      $this->language->load('payment/bitpay');
      $this->load->model('localisation/order_status'); // loading the model to get system Order Statuses

      1.2 Setting Up Page Title

      To set the Page Title of the document we use the following code:

      $this->document->setTitle($this->language->get('text_title')); // Setting the document heading title

      1.3. Parsing Controllers Elements to View

      /* Assigning and parsing the from values  */
      
      $this->data['heading_title']           = $this->language->get('text_title');
      $this->data['text_enabled']            = $this->language->get('text_enabled'); // gets default language text
      $this->data['text_disabled']           = $this->language->get('text_disabled'); // gets default language text
      $this->data['text_high']               = $this->language->get('text_high');
      $this->data['text_medium']             = $this->language->get('text_medium');
      $this->data['text_low']                = $this->language->get('text_low');
      $this->data['api_key']           = $this->language->get('text_api_key');
      $this->data['confirmed_status']  = $this->language->get('text_confirmed_status');
      $this->data['invalid_status']    = $this->language->get('text_invalid_status');
      $this->data['transaction_speed'] = $this->language->get('text_transaction_speed');
      $this->data['test_mode']         = $this->language->get('text_test_mode');
      $this->data['status']            = $this->language->get('text_status');
      $this->data['sort_order']        = $this->language->get('text_sort_order');
      $this->data['button_save']             = $this->language->get('button_save'); // gets default language text
      $this->data['button_cancel']           = $this->language->get('button_cancel'); // gets default language text
      $this->data['tab_general']             = $this->language->get('tab_general'); // gets default language text
      
      /* End Text Assignation */
      

      1.4. Routing Save & Cancel Buttons

      The following code is used to assign Action / Save & Cancel URLs triggers:

      $this->data['action'] = HTTPS_SERVER . 'index.php?route=payment/'.$this->payment_module_name.'&token=' . $this->session->data['token'];
      $this->data['cancel'] = HTTPS_SERVER . 'index.php?route=extension/payment&token=' . $this->session->data['token']; 

      1.5. Getting Available Order Statuses

      The following code gets all the order statuses from the Localisation-Model (which is pre-coded into OpenCart) and parses it for the view:

      $this->data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses(); 

      1.6. Fetching Data From the Database

      Our saving process will come in the model section. However the following code is responsible for fetching this module data (if any) and parsing it for view.

      /* Fetching the Field Values saved in Database*/ 
      $this->data['bitpay_api_key'] = $this->config->get('bitpay_api_key');
      
      $this->data['bitpay_confirmed_status_id'] = $this->config->get('bitpay_confirmed_status_id'); 
      
      $this->data['bitpay_invalid_status_id'] = $this->config->get('bitpay_invalid_status_id'); 
      
      $this->data['bitpay_transaction_speed'] = $this->config->get('bitpay_transaction_speed'); 
      
      $this->data['bitpay_test_mode'] = $this->config->get('bitpay_test_mode'); 
      
      $this->data['bitpay_status'] = $this->config->get('bitpay_status');
      
      $this->data['bitpay_sort_order'] = $this->config->get('bitpay_sort_order');
      /* Database fields fetching ends */
      

      1.6 Rendering the View Template

      The following code adds children to our view template and renders it for the user view.

      $this->template = 'payment/bitpay.tpl'; // Template Assigning
      $this->children = array(
      'common/header',    
      'common/footer'    
      ); // Provide the list of template childeren
      
      $this->response->setOutput($this->render(TRUE), $this->config->get('config_compression')); // Rendering the Template Output

      2. Creating Admin View

      1. Navigate to admin/view/template/payment
      2. Create a file and name it bitpay.tpl
      3. You can place your own HTML. In my case, I've done that using the following steps.

      2.1. Adding Header Child

      To load the header that we passed as a child at 1.6:

      <?php echo $header; ?> 

      2.2 Warning Block

      Warning Block is a div section which will display user warnings if any:

      <?php if ($error_warning) {  ?> <div class="warning"><?php echo $error_warning; ?></div><?php } ?>

      2.3 The Complete Template

      The complete HTML will look something like below:

      <div id="content">
        
      <?php 
      /* Warning Block*/
      if ($error_warning) {  ?>
      <div class="warning"><?php echo $error_warning; ?></div>
      <?php }
      /* Warning Block Ends */
       ?>
      <div class="box">
        <div class="left"></div>
        <div class="right"></div>
          <div class="heading">
            <h1><?php echo $heading_title; ?></h1>
            <div class="buttons"><a onclick="$('#form').submit();" class="button"><span><?php echo $button_save; ?></span></a><a onclick="location = '<?php echo $cancel; ?>';" class="button"><span><?php echo $button_cancel; ?></span></a></div>
          </div>
        <div class="content">
          <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form">
            <table class="form">
              <tr>
                <td><span class="required">*</span> <?php echo $api_key; ?></td>
                <td><input type="text" name="bitpay_api_key" value="<?php echo $bitpay_api_key; ?>" style="width:300px;" />
                  <?php 
                  // API Key Error case block
                  if ($error_api_key) { ?>
                  <span class="error"><?php echo $error_api_key; ?></span>
                  <?php }
                  // Error Case Block Ends
                   ?></td>
              </tr>
               <tr>
                  <td><?php echo $confirmed_status; ?></td>
                  <td><select name="bitpay_confirmed_status_id">
                      <?php foreach ($order_statuses as $order_status) { ?>
                      <?php if ($order_status['order_status_id'] == $bitpay_confirmed_status_id) { ?>
                      <option value="<?php echo $order_status['order_status_id']; ?>" selected="selected"><?php echo $order_status['name']; ?></option>
                      <?php } else { ?>
                      <option value="<?php echo $order_status['order_status_id']; ?>"><?php echo $order_status['name']; ?></option>
                      <?php } ?>
                      <?php } ?>
                    </select></td>
                </tr>
                <tr>
                  <td><?php echo $invalid_status; ?></td>
                  <td><select name="bitpay_invalid_status_id">
                      <?php foreach ($order_statuses as $order_status) { ?>
                      <?php if ($order_status['order_status_id'] == $bitpay_invalid_status_id) { ?>
                      <option value="<?php echo $order_status['order_status_id']; ?>" selected="selected"><?php echo $order_status['name']; ?></option>
                      <?php } else { ?>
                      <option value="<?php echo $order_status['order_status_id']; ?>"><?php echo $order_status['name']; ?></option>
                      <?php } ?>
                      <?php } ?>
                    </select></td>
                </tr>
                <tr>
                  <td><?php echo $transaction_speed; ?></td>
                  <td><select name="bitpay_transaction_speed">
                      <?php if ($bitpay_transaction_speed == 'high') { ?>
                      <option value="high" selected="selected"><?php echo $text_high; ?></option>
                      <?php } else { ?>
                      <option value="high"><?php echo $text_high; ?></option>
                      <?php } ?>
                      <?php if ($bitpay_transaction_speed == 'medium') { ?>
                      <option value="medium" selected="selected"><?php echo $text_medium; ?></option>
                      <?php } else { ?>
                      <option value="medium"><?php echo $text_medium; ?></option>
                      <?php } ?>
                      <?php if ($bitpay_transaction_speed == 'low') { ?>
                      <option value="low" selected="selected"><?php echo $text_low; ?></option>
                      <?php } else { ?>
                      <option value="low"><?php echo $text_low; ?></option>
                      <?php } ?>
                    </select></td>
                </tr>
                <tr>
                  <td><?php echo $test_mode; ?></td>
                  <td><select name="bitpay_test_mode"> 
                      <?php if ($bitpay_test_mode) { ?>
                      <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
                      <option value="0"><?php echo $text_disabled; ?></option>
                      <?php } else { ?>
                      <option value="1"><?php echo $text_enabled; ?></option>
                      <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
                      <?php } ?>
                    </select></td>
                </tr>
              <tr>
                <td><?php echo $status; ?></td>
                <td><select name="bitpay_status"> 
                    <?php if ($bitpay_status) { ?>
                    <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
                    <option value="0"><?php echo $text_disabled; ?></option>
                    <?php } else { ?>
                    <option value="1"><?php echo $text_enabled; ?></option>
                    <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
                    <?php } ?>
                  </select></td>
              </tr>
              <tr>
                <td><?php echo $sort_order; ?></td>
                <td><input type="text" name="bitpay_sort_order" value="<?php echo $bitpay_sort_order; ?>" size="1" /></td>
              </tr>
            </table>
          </form>
        </div>
      </div>
      </div>
      <?php echo $footer; //loading the footer ?>

      At this point, we are done with the layout of the module. Now its time to save the Module Data into the database. So we will be putting a little code inside the controller for this purpose.

      Saving the Data

      Inside your controller's default function, place some serialization code as shown below:

      if (($this->request->server['REQUEST_METHOD'] == 'POST') && ($this->validate())) // Checking if the data is coming through post and validate it
              {
                  $this->model_setting_setting->editSetting($this->payment_module_name, $this->request->post); // saving all the data into  the database
                  $this->session->data['success'] = $this->language->get('text_success'); // Success Identifier
                  $this->redirect(HTTPS_SERVER . 'index.php?route=extension/payment&token=' . $this->session->data['token']); // Redirecting to the payment modules list
              }

      Introduction Validation

      The following is the validation function that validates the required data:

      private $error = array(); // All errors will be saved into this array
          private function validate()
          {
          // User Module Permission Check 
              if (!$this->user->hasPermission('modify', 'payment/'.$this->payment_module_name)) 
              {
                  $this->error['warning'] = $this->language->get('error_permission'); 
              }
          // User Module Permission Check Ends
          
          // Check if the API Key is not empty
              if (!$this->request->post['bitpay_api_key']) 
              {
                  $this->error['api_key'] = $this->language->get('error_api_key');
              }
          // Api Check ends here
      
          // If there is no error, the function returns True else False
              if (!$this->error)
              {
                  return TRUE;
              }
              else
              {
                  return FALSE;
              }    
              // Boolean Check Ends here
          }

      We are done creating the payment module layout for the dashboard, and you should be able to test-drive the admin panel. Remember to grant permission to the administration user before testing.

      Conclusion

      In this article, we introduced the administrative portion of the payment module. Note that it's a good idea to give the site administrator more control via an interface than, say, to require that they write in code.

      In the next article, we'll implement the payment module with respect to the front-end. In the meantime, feel free to shoot any questions or comments via the form below.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Create a Multi-Store Setup Using OpenCart

      Most of the popular eCommerce frameworks available in the market provide the ability to offer multiple stores from within a single installation, and OpenCart is no different. In this tutorial, you're going to learn how to create a multi-store setup using a single installation of OpenCart. 

      Throughout the tutorial, we'll walk through the back-end section to explore what exactly a multi-store setup is and how it can benefit us in the use case of setting up multiple websites.

      What Is Multi-Store?

      First, let's understand what multi-store is all about. Suppose you've set up a nice-looking online store selling products using OpenCart. And you're happy with it as it's rolling on and you're making sales.

      Now, however, you're planning to set up a variety of products, but you realize that it would be too much to include everything in the same store.

      So you've come up with a solution to set up different subdomains for each major category. For example, "electronics.mysite.com" sells all the products related to electronics in the same way that "books.mysite.com" represents your online book store. This kind of setup is certainly beneficial in that you can have a different look and feel for each subdomain according to the type of product it represents.

      For the moment, assume that you're not familiar with the multi-store setup of OpenCart. Generally speaking, you would copy and duplicate the OpenCart installation for every subdomain and do the same for the database as well. So as you can see, every time you want to set up a new subdomain store, you need to duplicate the code and database.

      Although it may sound easy at first, you'll soon realize that it's really difficult to manage all the subdomain sites. Also during the OpenCart version upgrade process, you need to do the same for every subdomain. On top of that, if you're using a lot of third-party extensions, you need to manage that for each and every store.

      The multi-store feature comes to the rescue. This feature allows you to set up multiple stores using a single installation of OpenCart. Yes: You can set up as many stores you would like, using just a single installation.

      Set Up the New Subdomain

      Before we move ahead to set up the new store in the OpenCart back-end, you'll need to make sure you've already set up the new subdomain or domain pointing to the same default OpenCart installation. You can do that using the control panel of your hosting provider. We won't go into the details of creating a new subdomain, as this is something outside the scope of this tutorial.

      For the rest of the tutorial, we'll consider "www.myexamplestore.com" as our main default OpenCart installation and "store1.myexamplestore.com" as our new store. So I assume that "store1.myexamplestore.com" is also pointing to the same document root as that of the "http://www.myexamplestore.com".

      Create a New Store From the Back-End

      Head over to the back-end of OpenCart. Go to System > Settings and it will list all the stores available in OpenCart. In most cases, it'll be a just a single entry for your default and the only store. Click on the Insert button to create a new store.

      Create a New Store

      In the new store creation interface, there are different tabs available. Lets check each tab in detail.

      General

      The most important setting in this tab is Store URL. This should be set to the new subdomain/domain of your store. In our case, it would be "http://store1.myexamplestore.com/". The other setting, SSL URL, is useful if you want to provide secure checkout in the front-end and also want to secure your back-end dashboard.

      The rest of the settings like Store Name, Store Owner, etc., are self-explanatory.

      Store

      Other important settings in this tab are Template and Default Layout. You can specify a different theme for your new store using the Template setting. And you can set up the default layout of the cart using the Default Layout setting.

      Local

      Under this tab, you can find settings related to localization. You can set the country, state and language for your store. Another important setting is Currency, which is used to set the specific currency a user would be prompted with during checkout in this store.

      Option

      This tab allows you to set front-end-related parameters.

      Image

      Under this tab, you can upload a Store Logo and Icon. Also you can set the dimensions for the different versions of the images used in the front-end.

      Server

      The toggle setting for the SSL is available under this tab if you want to enable this for the checkout and admin dashboards.

      So once you've filled in all the necessary details, click on the Save button to create the new store.

      Management of the Multi-Store

      So we've just created a new store in the OpenCart back-end. Let's see what you can do with your new store. In most cases, the reason for creating a new store is to set up a different set of categories and products. The settings OpenCart allows you to set up for your store are:

      • Products
      • Categories
      • Manufacturers
      • Page Layouts
      • Front-end Theme
      • Information (Static Pages)

      For example, let's see how you can set up store-specific categories and products.

      Go to the back-end and access Catalog > Categories to bring the list of categories. Click on Insert to create a new category.

      Create a New Category - Store Selection Tab

      Under the Data tab, there is a field Stores showing all the available stores in your OpenCart installation. So the category will only be displayed under the stores which are checked here. In the screenshot, you can see that only Store1 is selected, which means that this category won't be displayed in the Default store.

      Now let's see the corresponding setting in the case of products. Go to Catalog > Products to bring up the list of products. Click on Insert to create a new product.

      Create a New Product - Store Selection

      Under the Links tab, there is a field labeled Stores that shows all of the available stores in your OpenCart installation. So as explained earlier, in the case of category, you can select the stores here under which you would like the product to be listed.

      So in this way, you can set up a whole bunch of categories and products for your store. The same procedure applies to the other entities like "Information", "Manufacturers", etc.

      Apart from this, you can manage all the stores using a single admin interface. In our case, we can log in to the back-end through either "www.myexamplestore.com/admin" or "store1.myexamplestore.com/admin". So if you've set up a couple of stores, it's really easy to manage all the stores through the central admin interface.

      Front-End Aspects

      As I mentioned earlier, you could assign a different theme for your store. So it'll help you to design the look and feel of each store completely differently from each other, as they are totally different sites.

      The orders and customer accounts created from the front-end are associated with the corresponding store from which they were created. It'll help you to analyze the sales reporting for each store.

      So overall, that's almost every feature OpenCart provides to help you migrate your different web shops to a single multi-store-based OpenCart site.

      Summary

      Hopefully, you've enjoyed the post and learned something new as far as OpenCart is concerned. I encourage you to go ahead and give it a try, which is the best way to understand how it works.

      Don't forget to share your experiences, comments, or queries using the feed below!

       

      0 Comments

      Leave a comment › Posted in: Daily

  • Page 1 of 40 pages  1 2 3 >  Last ›
  • Browse the Blog

    Syndicate

    governing-bruise