Code News

Dynamic Page Templates in WordPress, Part 1

  • WordPress page templates are a great way to completely alter how particular web pages are displayed. You can use them to add a vast range of functionality to your site.

    They do, however, have one limitation in that they are 'static' templates. You cannot customize them or affect their behavior in any way. You can only choose whether to enable a page template or not. By default, a page template will simply carry out a fixed function, e.g. display a sitemap, or remove the sidebar to display a full-width page.

    In this tutorial series, I'll be looking at how you can extend page templates to be more flexible, improving their functionality greatly. I'll start by introducing how to create a standard page template via a child theme, before moving on to a more flexible approach where I'll create a general-purpose dynamic page template.

    Finally, I'll show you three real-world examples of fully working dynamic page templates. I'll also cover advanced topics such as how to assign page templates to custom post types.

    Want to Follow Along?

    To follow along with this tutorial series, you'll need a WordPress site with admin access. By far the easiest way to do this is to use a local development environment. A dedicated text editor is also useful but not essential.

    If you happen to be developing with WordPress via a remote server then you'll need to be able to edit theme files via the WordPress admin, or edit files locally and use FTP software to transfer them back to the server. For the sake of simplicity, I'll assume that you're working with WordPress locally throughout the rest of this tutorial.

    To implement our page templates, I'll be using a child theme based on the Twenty Seventeen parent theme, which (at the time of writing) is the latest default WordPress theme. So if you are following along then it's a good idea to have this installed before moving on.

    You can use a child theme based on another parent theme if you prefer, but you'll need to modify some of the code to make it work seamlessly with your particular theme. The basic method, though, is pretty much the same for any child theme.

    WordPress Page Templates

    Before learning how to make page templates more flexible, let's go over some basic details.

    WordPress uses a template hierarchy to decide which template renders the current page. The template used in most scenarios for pages is page.php but can be different if you're viewing a page with a particular ID or slug. However, if you select a page template for a particular page, this will always be used in preference, which makes it very easy to customize any page using a page template.

    Here are some typical examples of commonly used WordPress page templates:

    • Contact Form
    • Portfolios
    • Frequently Asked Questions
    • Custom 404 Page
    • Custom Login Page
    • Sitemap
    • Full Width Page
    • Blog Posts Page
    • Widgetized Page
    • And many more…

    I could go on, but you get the idea. Page templates are cool! You can use them for almost anything.

    If you've used WordPress for any length of time then it's highly likely you've already come across one or more of the examples above. Most themes include page templates to complement theme functionality, and you can easily add your own via a child theme. I'll be covering how to do this shortly.

    Page templates are so useful because they give you complete control over the whole page. You can leave out the header, footer, and/or sidebars if you wish. This is one of the reasons why full-width page templates are so common because it's very easy to manipulate the sidebars via a page template.

    To see all currently available page templates, go to the WordPress page editor and access the Template drop down via the Page Templates meta box. Simply select the page template you want and, once the page has been updated, it will be visible the next time the page is viewed.

    Adding Page Templates via a Child Theme

    As mentioned above, we'll be using a custom WordPress child theme to implement all page templates throughout this tutorial. I'll start off with a basic child theme and page template, and then add more complexity to it as we go along.

    The whole process will be covered step by step, so don't worry if you're not familiar with child themes and/or page templates. You will be by the end of the tutorial!

    The basic idea behind child themes is that they allow you to customize the look and feel of your current theme (called a parent theme) in a way that won't be affected when the parent theme is updated.

    If code is added directly to the parent theme then all customizations will be overwritten and lost during a scheduled theme update. This is an important point as any well-maintained theme will be regularly updated. To find out more about child themes, I'd recommend taking a look at the official documentation

    It's interesting to note that it's technically possible to use a WordPress plugin to add page templates, but it's much simpler to use a child theme. I don't want to complicate things unnecessarily with extraneous code, so I'll be sticking with child themes for our page template implementation.

    Let's Get Started!

    Ok, so enough theory—let's create our initial page template! It will be located in a custom Twenty Seventeen child theme which will act as our page template container, so we need to create the child theme first.

    Open up your theme folder and create a new folder for your child theme. According to WordPress best practices, it's recommended that you name the child theme folder the same as the parent theme it's based on, amended with '-child'. As our parent theme folder is named twentyseventeen, name your child theme folder twentyseventeen-child. Inside this new folder, create a single file named style.css and add the following comment block at the top.

    /* Theme Name: Twenty Seventeen Child Description: Twenty Seventeen Child Theme Author: David Gwyer Template: twentyseventeen Version: 0.1 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: twenty-seventeen-child */

    We now need to reference all the styles from the Twenty Seventeen parent theme. If you've ever worked with child themes before, then you might be used to adding a CSS @import statement directly underneath the comment block. This is no longer considered a WordPress best practice due to speed concerns. Instead, we'll enqueue the parent theme styles, which will be more efficient.

    Inside the child theme root folder, create a functions.php file and add the following code to set up an empty class container. We'll use this class for all our setup code.

    <?php /** * Twenty Seventeen child theme class. * * DPT = D[ynamic] P[age] T[emplates]. */ class DPT_Twenty_Seventeen_Child { /** * Register hooks. */ public function init() { // ... } } $ts_child_theme = new DPT_Twenty_Seventeen_Child(); $ts_child_theme->init();

    Note: The closing PHP statement is not necessary, but you can add it if you prefer.

    Now add a hook and callback to enqueue the Twenty Seventeen parent theme styles, rather than importing them directly inside the style.css file. Do this by adding two new class methods.

    <?php /** * Register hooks. */ public function init() { add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_parent_theme_styles' ) ); } /* Enqueue parent theme styles. */ public function enqueue_parent_theme_styles() { wp_enqueue_style( 'twenty-seventeen-css', get_template_directory_uri() . '/style.css' ); }

    Save your changes and activate the child theme. You now have a fully functioning, albeit simple, Twenty Seventeen child theme. To test whether it's working properly, add a line of custom CSS to style.css.

    * { color: red !important; }

    If all is well then you should see all your site text now colored a nice garish red!

    Don't forget to delete the test CSS before moving on. Now that the child theme is active, we can begin to implement our first page template.

    Adding Our First Page Template

    One thing is worth mentioning about where you store page templates inside your child theme. You can store the page templates either directly inside the root child theme folder or in a top-level folder. It doesn't matter which one you choose; either location is fine.

    However, if you have multiple page templates, you may decide to store them in a folder for organizational purposes. The folder name is unimportant, but it must be located directly inside the root child theme folder, otherwise WordPress won't recognize your page templates. For this tutorial, I'll be using a folder called page-templates.

    Let's now add a new page template to the child theme. The standard way to do this is to make a copy of the parent theme page.php theme template file and add it to your child theme. You can name the file anything you like, but I'd recommend including something that makes it recognizable as a page template. I'll go with test-page-template.php.

    Once you've copied the page.php file (and renamed it) to the page-templates folder, your child theme structure should now look like this:

    Open up test-page-template.php and replace the comment block at the top of the file with the following.

    <?php /** * Template Name: Test Page Template * * @package WordPress * @subpackage Twenty_Seventeen * @since 1.0 */

    This step is very important as the comment block tells WordPress to recognize the file as a page template and will add it to the list of available page templates on the page editor screen.

    The full page template code should now look like this.

    <?php /** * Template Name: Test Page Template * * @package WordPress * @subpackage Twenty_Seventeen * @since 1.0 */ get_header(); ?> <div class="wrap"> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php while ( have_posts() ) : the_post(); get_template_part( 'template-parts/page/content', 'page' ); // If comments are open or we have at least one comment, load up the comment template. if ( comments_open() || get_comments_number() ) : comments_template(); endif; endwhile; // End of the loop. ?> </main><!-- #main --> </div><!-- #primary --> </div><!-- .wrap --> <?php get_footer();

    Let's test our page template. Go to the WordPress admin and edit any existing page, or create a new one. On the page editor screen, select the Template drop-down from the Page Attributes meta box to assign our page template to the current page.

    Because we simply copied the parent theme page.php template file, our custom page template is doing nothing more than outputting the current page, which is not very useful. Also, we won't be needing to output the editor content or comments, so remove these from the page template while loop, and add a custom message. Change the contents of the while loop to the following.

    <?php while ( have_posts() ) : the_post(); echo "<p>This is our custom page template!</p>"; endwhile; // End of the loop.

    Save this and view the page on the front end.

    Note: If you can't see the custom message then make sure you have selected the custom page template on the page editor and saved it to update settings.

    Let's now make our custom page template a little more useful. Replace the message we added above with the following code to output a sitemap of all published pages.

    <?php while ( have_posts() ) : the_post(); echo "<h2>Sitemap</h2>"; echo "<ul>" . wp_list_pages( array( 'title_li' => '' ) ) . "</ul>"; endwhile; // End of the loop.

    This will result in the following output.

    It's easy to see just how useful page templates can be. But we can do even better!

    Conclusion

    So far, we've created a child theme and used it to implement our standard page template. In the next tutorial, I'll show you step by step how to extend this, demonstrating how page templates can be made more flexible.

    Specifically, we'll create a general-purpose dynamic page template by adding custom controls to the page editor screen. Control logic will then be added to the page template to allow us to directly customize how the page template is rendered.

    WordPress has an incredibly active economy. There are themes, plugins, libraries, and many other products that help you build out your site and project. The open source nature of the platform also makes it a great option from which you can better your programming skills. Whatever the case, you can see what we have available in the Envato Marketplace.

    This is my first tutorial (be gentle!) so please feel free to leave any feedback you may have in the comments feed below. I'll do my best to answer every question.

    1 day 12 hours ago

How to Install the Elixir Runtime

  • Elixir is a meta-programming language based on Erlang and is available on all major operating systems. In this guide we will cover how to get Elixir installed, use the interactive console, and expand on the libraries available.

    By the end of this guide you will be able to have a working development environment for creating Elixir apps. If you are interested in a framework for creating web apps, please look at using Phoenix.

    Getting Elixir

    The easiest and preferred way to install Elixir is via a distribution, or by using an installer. 

    Erlang 18.0 or later is used by Elixir and will be installed by default by the distribution installer.

    Precompiled Packages

    If you wish to install from source or a precompiled package, Erlang will need to be installed separately; for that, please check this guide.

    MacOS
    • Homebrew
      • Update your homebrew to latest: brew update
      • Run: brew install elixir
    • Macports
      • Run: sudo port install elixir
    Unix (and Unix-like)
    • Arch Linux (Community repo)
      • Run: pacman -S elixir
    • openSUSE (and SLES 11 SP3+)
      • Add Erlang devel repo: zypper ar -f http://download.opensuse.org/repositories/devel:/languages:/erlang/openSUSE_Factory/ erlang
      • Run: zypper in elixir
    • Gentoo
      • Run: emerge --ask dev-lang/elixir
    • GNU Guix
      • Run: guix package -i elixir
    • Fedora 21 (and older)
      • Run: yum install elixir
    • Fedora 22 (and newer)
      • Run dnf install elixir
    • FreeBSD
      • From ports: cd /usr/ports/lang/elixir && make install clean
      • From pkg: pkg install elixir
    • Ubuntu 12.04/14.04/16.04 or Debian 7
      • Add Erlang Solutions repo: wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
      • Run: sudo apt-get update
      • Install the Erlang/OTP platform and all of its applications: sudo apt-get install esl-erlang
      • Install Elixir: sudo apt-get install elixir
    Windows Docker

    For ease of portability, you can also use the official elixir docker image. This is easy to work with just by running one of the following commands:

    • Enter interactive mode
      • Run: docker run -it --rm elixir
    • Enter bash within container with installed elixir
      • Run: docker run -it --rm elixir bash
    Installing From Git

    Ensure you have Erlang installed first by visiting the Erlang download page and getting a distribution for your Operating System.

    Once Erlang is installed on your machine, please use the following commands:

    $ git clone https://github.com/elixir-lang/elixir.git $ cd elixir $ make clean testTesting Your Installation

    Once you have installed Elixir, please run the following at your terminal prompt:

    $ elixir --version

    If you are getting an error, please ensure the binary is in your PATH environmental variable.

    export PATH="$PATH:/path/to/elixir/bin"

    Windows users can read this guide.

    Interactive Development

    Akin to other languages such as Node, Ruby, and Java, Elixir has an interactive mode, which we can access via the command-line prompt as so:

    $ iex Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help) iex> c "my_file.ex" # Compiles a file iex> t Enum # Prints types defined in the module Enum iex> h IEx.pry # Prints the documentation for IEx pry functionality iex> i "Hello, World" # Prints information about the given data type

    Windows users will need to run iex.bat to access the interactive console. 

    When we enter this mode, we can type any Elixir code and get the return instantly, so it's good for starting to learn the language.

    Let's do some basic expressions:

    ie> 2 + 2 4 ie> round(3.58) 4 iex> "hello" <> " world" "hello world"

    When we are running a script, we do that from the shell terminal as so:

    $ elixir scriptName.exsSetting Up Your IDE

    If you are using JetBrains' IntelliJ, Sublime or Atom then you will be happy to know there are several integration plugins available which will make code completion, syntax highlighting, linting your code and displaying errors and warnings easy.

    Vim Users

    If you are using Vim or Emacs, then you can configure support for Elixir such as automatic filetype detection, syntax highlighting and automatic indentation. 

    Installation can be done with a Vim plugin manager such as pathogen.vim inside ~/.vim/bundle:

    git clone https://github.com/elixir-lang/vim-elixir.git ~/.vim/bundle/vim-elixirAdding Packages With Hex

    Take full advantage of the thousands of packages available for the Elixir ecosystem via Hex.pm.

    Search for packages and install them via the mix dependency manager—usage on how to setup mix is in the documentation. Once you have a mix.exs set up, adding this line would install the popular JSON library poison:

    {:poison, "~> 3.1"}

    There are many packages ready for your use on Hex which can provide a plethora of solutions such as JSON and XML support, SSL cryptography functions, database abstraction and caching, to name a few.

    If you are looking for powerful packages, as mentioned before, check out Poison, a very fast pure Elixir JSON library!

    Also worth checking is hackney, a simple HTTP client, and plug, a specification for composable web modules which can easily port between your applications and save you a lot of time.

    Conclusion

    Elixir is easily available via all of the distribution channels accessible and some rather exotic ones also, such as Raspberry Pi. Installing from source is easy, as is using a package manager such as the popular brew on macOS.

    Going forward, you may wish to review the Erlang libraries available for Elixir, and also, as mentioned earlier, get further into taking advantage of using Hex packages.

    If you are looking for some excellent packages that expand Elixir then you will enjoy this curated list on GitHub.

    1 day 13 hours ago

Sponsored Post: Etleap, Pier 1, Aerospike, Loupe, Clubhouse, Stream, Scalyr, VividCortex, MemSQL, InMemory.Net, Zohocorp

  • Who's Hiring? 
    • Pier 1 Imports is looking for an amazing Sr. Website Engineer to join our growing team!  Our customer continues to evolve the way she prefers to shop, speak to, and engage with us at Pier 1 Imports.  Driving us to innovate more ways to surprise and delight her expectations as a Premier Home and Decor retailer.  We are looking for a candidate to be another key member of a driven agile team. This person will inform and apply modern technical expertise to website site performance, development and design techniques for Pier.com. To apply please email cmwelsh@pier1.com. More details are available here.

    • Etleap is looking for Senior Data Engineers to build the next-generation ETL solution. Data analytics teams need solid infrastructure and great ETL tools to be successful. It shouldn't take a CS degree to use big data effectively, and abstracting away the difficult parts is our mission. We use Java extensively, and distributed systems experience is a big plus! See full job description and apply here.

    • Advertise your job here! 
    Fun and Informative Events
    • DBTA Roundtable OnDemand Webinar: Leveraging Big Data with Hadoop, NoSQL and RDBMS. Watch this recent roundtable discussion hosted by DBTA to learn about key differences between Hadoop, NoSQL and RDBMS. Topics include primary use cases, selection criteria, when a hybrid approach will best fit your needs and best practices for managing, securing and integrating data across platforms. Brian Bulkowski, CTO and Co-founder of Aerospike, presented along with speakers from Cask Data and Splice Machine. View now.

    • Advertise your event here!
    Cool Products and Services
    • A note for .NET developers: You know the pain of troubleshooting errors with limited time, limited information, and limited tools. Log management, exception tracking, and monitoring solutions can help, but many of them treat the .NET platform as an afterthought. You should learn about Loupe...Loupe is a .NET logging and monitoring solution made for the .NET platform from day one. It helps you find and fix problems fast by tracking performance metrics, capturing errors in your .NET software, identifying which errors are causing the greatest impact, and pinpointing root causes. Learn more and try it free today.

    • Etleap provides a SaaS ETL tool that makes it easy to create and operate a Redshift data warehouse at a small fraction of the typical time and cost. It combines the ability to do deep transformations on large data sets with self-service usability, and no coding is required. Sign up for a 30-day free trial.

    • InMemory.Net provides a Dot Net native in memory database for analysing large amounts of data. It runs natively on .Net, and provides a native .Net, COM & ODBC apis for integration. It also has an easy to use language for importing data, and supports standard SQL for querying data. http://InMemory.Net

    • www.site24x7.com : Monitor End User Experience from a global monitoring network. 

    • Working on a software product? Clubhouse is a project management tool that helps software teams plan, build, and deploy their products with ease. Try it free today or learn why thousands of teams use Clubhouse as a Trello alternative or JIRA alternative.

    • Build, scale and personalize your news feeds and activity streams with getstream.io. Try the API now in this 5 minute interactive tutorial. Stream is free up to 3 million feed updates so it's easy to get started. Client libraries are available for Node, Ruby, Python, PHP, Go, Java and .NET. Stream is currently also hiring Devops and Python/Go developers in Amsterdam. More than 400 companies rely on Stream for their production feed infrastructure, this includes apps with 30 million users. With your help we'd like to ad a few zeros to that number. Check out the job opening on AngelList.

    • Scalyr is a lightning-fast log management and operational data platform.  It's a tool (actually, multiple tools) that your entire team will love.  Get visibility into your production issues without juggling multiple tabs and different services -- all of your logs, server metrics and alerts are in your browser and at your fingertips. .  Loved and used by teams at Codecademy, ReturnPath, Grab, and InsideSales. Learn more today or see why Scalyr is a great alternative to Splunk.

    • VividCortex is a SaaS database monitoring product that provides the best way for organizations to improve their database performance, efficiency, and uptime. Currently supporting MySQL, PostgreSQL, Redis, MongoDB, and Amazon Aurora database types, it's a secure, cloud-hosted platform that eliminates businesses' most critical visibility gap. VividCortex uses patented algorithms to analyze and surface relevant insights, so users can proactively fix future performance problems before they impact customers.

    • MemSQL provides a distributed in-memory database for high value data. It's designed to handle extreme data ingest and store the data for real-time, streaming and historical analysis using SQL. MemSQL also cost effectively supports both application and ad-hoc queries concurrently across all data. Start a free 30 day trial here: http://www.memsql.com/

    • Advertise your product or service here!

    If you are interested in a sponsored post for an event, job, or product, please contact us for more information.

    2 days 9 hours ago

Working With MeSH Files in Python: Linking Terms and Numbers

  • This tutorial shows how we can use different aspects of Python (i.e. dictionaries, lists, and regular expressions) together to solve different issues. It also shows how we can use Python to link the relationships in the MeSH file, making it easier to understand its hierarchy and structure.

    Before moving ahead with this tutorial, you might be wondering what we mean by MeSH. So let's start by defining this term first, and then go into a bit more detail on its structure.

    What Is MeSH?

    MeSH is an acronym for Medical Subject Headings. It is considered the U.S. National Library of Medicine's controlled vocabulary (thesaurus), which gives uniformity and consistency to the indexing and cataloging of biomedical literature. MeSH, a distinctive feature of MEDLINE, is arranged in a hierarchical manner called the MesH Tree Structure, and is updated annually.

    MeSH is thus a nomenclature of medical terms available from the U.S. National Library of Medicine, that aims to create new knowledge by exploiting the relationships among terms that annotate the biomedical literature.  

    People searching MEDLINE/PubMed and other databases make use of MeSH to assist with subject searching. The National Library of Medicine (NLM) indexers use MeSH to describe the subject content of journal articles for MEDLINE. Catalogers use MeSH to describe books and audiovisuals in the NLM and other library collections. So MeSH can be used for numerous tasks involving indexing, tagging, searching, retrieving, analyzing, coding, merging, and sharing biomedical text.

    MeSH File Structure

    MeSH descriptors are organized into 16 categories:

    • A: anatomy
    • B: organisms 
    • C: diseases
    • D: drugs and chemicals
    • E: analytical, diagnostic and therapeutic techniques and equipment
    • F: psychiatry and psychology
    • G: phenomena and processes 
    • H: disciplines and occupations
    • I: anthropology, education, sociology, and social phenomena
    • J: technology, industry, agriculture
    • K: humanities
    • L: information science
    • M: named groups
    • N: health care
    • V: publication characteristics
    • Z: geographicals

    You can find more information about the categories from the U.S. National Library of Medicine. As we can see, each category is further divided into subcategories. This structure is, however, not considered an authoritative subject classification system, but rather as an arrangement of descriptors for the guidance and convenience of people who are assigning subject headings to documents or are searching for literature. It is thus not an exhaustive classification of the subject and contains only the terms that have been selected for inclusion in this thesaurus.

    Here's some more information on the MeSH Tree Structures:

    Because of the branching structure of the hierarchies, these lists are sometimes referred to as "trees". Each MeSH descriptor appears in at least one place in the trees, and may appear in as many additional places as may be appropriate. Those who index articles or catalog books are instructed to find and use the most specific MeSH descriptor that is available to represent each indexable concept. Downloading a MeSH File

    For the purpose of this tutorial, we need a MeSH file to work with in Python. You can find MeSH file on the NLM download site.

    Let's go ahead and download the latest ASCII MeSH file. We can first go to the MeSH FTP Archive: ftp://nlmpubs.nlm.nih.gov/online/mesh/, and then choose the 2017 directory. In the asciimesh/ directory, you will find three .bin files: c2017.bin, d2017.bin, and q2017.bin. Let's download d2017.bin. You can download the file from: ftp://nlmpubs.nlm.nih.gov/online/mesh/2017/asciimesh/d2017.bin (27.5 MB).

    Linking Terms to Numbers

    Let's jump into the core of this article. What we are trying to do is read a MeSH file (i.e. the .bin file you just downloaded), browse through the entries, find all the MeSH numbers for each entry, and list the terms along with their relevant numbers. 

    The first thing we would normally do is read the .bin file, as follows:

    meshFile = 'd2017.bin' with open(meshFile, mode='rb') as file: mesh = file.readlines()

    Notice that we have used the rb mode, meaning that we are reading binary with no line-break translation.

    We also need to define an output file where we would store the results (output):

    outputFile = open('mesh.txt', 'w')

    At this point, we want to check the lines that start with MH = (MeSH term) and MN = (MeSH number). I shouldn't do this now, but will show you a snapshot of the MeSH file to have some idea of the structure and to remove any confusions (MH and MN are surrounded by red rectangles, respectively).


    To check lines that start with MH = and MN =, we need to use regular expressions. So, if we want to check the lines that start with MH = followed by any characters, we would do as shown in the code below (I'll get to what line is in a moment). Notice that I have used b instead of r for the regular expression, since we are applying the pattern on a byte object and not a string object, so we should use a byte pattern.

    import re meshTerm = re.search(b'MH = (.+)$', line)

    The same thing would apply for the MeSH number, but this time for lines starting with MN =.

    Coming back to line, this refers to the lines in the MeSH file. So we would be walking through the file line by line, looking for the MeSH terms and numbers. As you can see from the above MeSH file snapshot, the MeSH term comes before the MeSH number. So, in our code, the MeSH number will always be the number corresponding to the previously captured MeSH term. We will thus do the following:

    for line in mesh: meshTerm = re.search(b'MH = (.+)$', line) if meshTerm: term = meshTerm.group(1) meshNumber = re.search(b'MN = (.+)$', line) if meshNumber: number = meshNumber.group(1) numbers[number.decode('utf-8')] = term.decode('utf-8') if term in terms: terms[term] = terms[term] + ' ' + number.decode('utf-8') else: terms[term] = number.decode('utf-8')

    Let's go through the above code step by step. If we look at the regular expression MH = (.+)$, this is basically telling us to find the literal MH = followed by at least one character. (.) means any character, and + means that it has to be one or more characters, and return everything to the end of the line ($). 

    The parenthesis around .+, that is (.+), is a capture group so we can retrieve the result. So, for the MeSH term surrounded by a red rectangle in the above snapshot, the retrieved term will be Calcomycin. The reason we are using if-statements is that some lines will neither start with MH = nor MN =.

    For the captured MeSH term and MeSH number, we create a new key-value pair for a dictionary object, as shown in this line of code: numbers[str(number)] = term.

    It is important to note that a single MeSH term might have more than one MeSH number. So we concatenate every new MeSH number with the relevant term into a string, as shown in this portion of the code:

    if term in terms: terms[term] = terms[term] + ' ' + number.decode('utf-8') else: terms[term] = number.decode('utf-8')

    Thus in this case we will be having a dictionary object with key-value pairs that consist of a MeSH term as the key, and the concatenation collection of all corresponding MeSH numbers as the value.

    What we want to do now is list the different keys (terms), and have the relevant values (numbers) listed under the relevant term. To list the different terms, we do the following:

    meshNumberList = [] meshTermList = terms.keys() for term in meshTermList: item_list = terms[term].split(' ') for phrase in item_list: meshNumberList.append(phrase)

    Finally, we will list the term and its relevant numbers as follows:

    used_items = set() for item in meshNumberList: if numbers[item] not in used_items: print(numbers[item], '\n', item, file=outputFile) used_items.add(numbers[item]) else: print(item, file=outputFile)

    Before showing the output of the program, let's put it all together.

    Putting It All Together

    In this section, I will show you what our full Python program that links the MeSH term to its numbers looks like:

    import re terms = {} numbers = {} meshFile = 'd2017.bin' with open(meshFile, mode='rb') as file: mesh = file.readlines() outputFile = open('mesh.txt', 'w') for line in mesh: meshTerm = re.search(b'MH = (.+)$', line) if meshTerm: term = meshTerm.group(1) meshNumber = re.search(b'MN = (.+)$', line) if meshNumber: number = meshNumber.group(1) numbers[number.decode('utf-8')] = term.decode('utf-8') if term in terms: terms[term] = terms[term] + ' ' + number.decode('utf-8') else: terms[term] = number.decode('utf-8') meshNumberList = [] meshTermList = terms.keys() for term in meshTermList: item_list = terms[term].split(' ') for phrase in item_list: meshNumberList.append(phrase) meshNumberList.sort() used_items = set() for item in meshNumberList: if numbers[item] not in used_items: print(numbers[item], '\n', item, file=outputFile) used_items.add(numbers[item]) else: print(item, file=outputFile)Output

    You can download the output from Dropbox (1.77 MB). Taking a sample of the output as shown below, we can see how a MeSH term (Pterygopalatine Fossa) is listed with its MeSH numbers that are grouped immediately underneath.

    Pterygopalatine Fossa A02.835.232.781.670 A02.835.232.781.750 A02.835.232.781.750.150 A02.835.232.781.750.165 A02.835.232.781.750.400Conclusion

    The tutorial showed how we can use different aspects of Python (i.e. dictionaries, lists, and regular expressions) together to solve different issues. It also shows how we can use Python to work with MeSH files for linking some parts of this complex file in a way that makes it easier to understand its hierarchy and structure, as we did here by linking the MeSH term to its relevant MeSH numbers.

    2 days 13 hours ago

SpriteKit Basics: Sprites

  • In this series, we're learning how to use SpriteKit to build 2D games for iOS. In this post, we'll continue our exploration of SpriteKit nodes, and learn about a special kind of node called a "sprite"—an SKSpriteNode.

    To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

    Sprite Nodes

    An SKSpriteNode is drawn either as a rectangle with a texture mapped onto it, or as a colored untextured rectangle. Creating a SKSpriteNode with a texture mapped onto it is the most common, as this is how you bring your game's artwork to life.

    Add the following to the didMove(to:) method within GameScene.swift.

    override func didMove(to view: SKView) { let startGameLabel = SKLabelNode(text: "Start Game") startGameLabel.name = "startgame" startGameLabel.position = CGPoint(x: size.width/2, y: size.height/2) addChild(startGameLabel) let redSprite = SKSpriteNode(color: .red, size: CGSize(width: 200, height: 200)) addChild(redSprite) }

    Here we are using the convenience intiailizer init(color:size:) which will draw a rectangular sprite with the color and size you pass in as parameters. If you test the project now, you will see half of the red square showing.

    You might be wondering why only half of the sprite is showing since we already determined that SKNode's origins are at (0,0). This because the SKSpriteNode's frame and therefore its texture is centered on its position. To change this behaviour, you can change the sprite's anchorPoint property, which determines the point at which the frame is positioned. The diagram below shows how the anchorPoint works.

    The anchorPoint is specified in the unit coordinate system, which places (0,0) at the bottom left and (1,1) at the top right corner of the frame. The default for SKSpriteNodes is (0.5,0.5).

    Go ahead and change the anchorPoint property to (0,0) and notice the difference it makes.

    override func didMove(to view: SKView) { let startGameLabel = SKLabelNode(text: "Start Game") startGameLabel.name = "startgame" startGameLabel.position = CGPoint(x: size.width/2, y: size.height/2) addChild(startGameLabel) let redSprite = SKSpriteNode(color: .red, size: CGSize(width: 200, height: 200)) redSprite.anchorPoint = CGPoint(x: 0, y:0) addChild(redSprite) }

    Now, if you test, you will see that the sprite is lined up perfectly with the bottom left of the scene.

    Now let's move it to the top center of the scene by changing its position property. Replace your didMove(to:) function with the following:

    override func didMove(to view: SKView) { let startGameLabel = SKLabelNode(text: "Start Game") startGameLabel.name = "startgame" startGameLabel.position = CGPoint(x: size.width/2, y: size.height/2) addChild(startGameLabel) let redSprite = SKSpriteNode(color: .red, size: CGSize(width: 200, height: 200)) redSprite.anchorPoint = CGPoint(x: 0, y:0) redSprite.position = CGPoint(x: size.width/2 - 100, y: size.height - 210) addChild(redSprite) }

    Notice how we had to subtract from both the x and y values to center the sprite. If we had left the anchorPoint at its default then it would already have been centered on the x axis. It is important to remember that when you change the anchor point, you may have to make some adjustments in your positioning.

    Textured Sprites

    That red box is good for practice with positioning, but you'll usually want to texture your sprite with artwork for your game. 

    Let's create a textured SKSpriteNode. Add the following code at the bottom of the didMove(to:) method.

    override func didMove(to view: SKView) { ... let player = SKSpriteNode(imageNamed: "player") player.position = CGPoint(x: size.width/2 , y: 300) addChild(player) }

    Here we use the convenience initializer init(imageNamed:), which takes as a parameter the name of an image without the extension. This is the easiest way to create a textured sprite as it creates the texture for you from the image you pass in. 

    The other way to create a textured SKSpriteNode is to create an SKTexture beforehand, and use one of the intializers that take a texture as a parameter.

    Let's create a couple more SKSpriteNodes and change some of their properties. Again, add these to the bottom of your didMove(to:) function.

    override func didMove(to view: SKView) { ... let enemy1 = SKSpriteNode(imageNamed: "enemy1") enemy1.position = CGPoint(x: 100 , y: 300) enemy1.xScale = 2 addChild(enemy1) let enemy2 = SKSpriteNode(imageNamed: "enemy2") enemy2.position = CGPoint(x: size.width - 100 , y: 300) enemy2.zRotation = 3.14 * 90 / 180 addChild(enemy2) }

    Here we create two SKSpriteNodes, enemy1 and enemy2. We set the xScale on enemy1 to 2 and change the zRotation on enemy2 to rotate it by 90 degrees. (The zRotation property takes it values in radians, and a positive value indicates a counterclockwise rotation.) 

    We've experimented with changing a few properties on a sprite. Take a look at the documentation for SKNodes and SKSpriteNodes and try changing a few of the other properties to see the effects they have.

    Sprite nodes are good for basic rectangles and textures, but sometimes a more complex shape will be needed. The SKShapeNode has you covered in those cases. We'll take a look at shape nodes next.

    Shape Nodes

    Another useful node is the SKShapeNode. This node renders a shape defined by a Core Graphics path. SKShapeNodes are useful for content that cannot be easily realized with an SKSpriteNode. This class is more memory intensive and has lower performance than using an SKSpriteNode, so you should try to use it sparingly.

    To assign a shape to SKShapeNode, you can set a CGPath to the node's path property. However, there are a few initializers that offer predefined shapes such as rectangles, circles, and ellipses. Let's create a circle using the convenience initializer init(circleOfRadius:).

    Then, add the following to the bottom of the didMove(to:) method.

    override func didMove(to view: SKView) { ... let circle = SKShapeNode(circleOfRadius: 50) circle.strokeColor = SKColor.green circle.fillColor = SKColor.blue circle.lineWidth = 8 circle.position = CGPoint(x: size.width/2, y: 400) addChild(circle) }

    We change a few properties on the shape node, position it, and add it to the scene. It is very easy to use the predefined shape initializers. However, creating a complex CGPath manually takes a considerable amount of time and is not for the faint of heart as it usually involves some complex math. 

    Thankfully, there is a tool that lets you draw shapes visually and export their CGPath as Swift code. Check out PaintCode if you want to learn more.

    Sprite Nodes and Shape Nodes will cover most cases, but sometimes you may wish to display video in your apps. The SKVideoNode, which we'll take a look at next, has you covered.

    Video Nodes

    The last node we will be taking a look at is the SKVideoNode. As the name implies, this node allows you to play video within your games.

    There are a few different ways to create an SKVideoNode. One uses an instance of an AVPlayer, another just uses the name of a video file that is stored in the app bundle, and the third way is to use a URL.

    One thing to keep in mind is that the video's size property will initially be the same as the size of the target video. You can change this size property, though, and the video will be stretched to the new size.

    Another thing to be aware of is that the SKVideoNode offers play() and pause() methods only. If you wanted more control over your videos, you would initialize an SKVideoNode with an existing AVPlayer and use that to control your videos.

    Let's use the simplest method to create an SKVideoNode. Add the following to the bottom of the didMove(to:) method.

    override func didMove(to view: SKView) { ... let video = SKVideoNode(fileNamed: "video.mov") video.position = CGPoint(x: size.width/2,y: 600) addChild(video) video.play() }

    Here we used the intiailizer init(fileNamed:) to create a video. You pass in the video's name along with the extension. I have not included a video along with the project's source code, but if you want to see this work, you can add a video named "video.mov" to your project.

    Conclusion

    This completes our study on nodes. After reading this post and the previous one, you should have a good understanding of SKNodes and their subclasses. In the next part of this series, we will take a look at SKActions and using physics within our games. Thanks for reading, and I will see you there!

    In the meantime, check out some of our other great courses and tutorials on creating iOS apps with Swift and SpriteKit.

    Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

     

    2 days 13 hours ago

Get Started With Ionic Services: Auth

  • One of Ionic's strengths is in the services that it offers on top of the framework. This includes services for authenticating users of your app, push notifications, and analytics. In this series, we'll be learning about those three services by creating an app which uses each of them.

    The first service we're going to look at is the Auth service. This allows us to implement authentication in an Ionic app without writing a single line of back-end code. Or if you already have an existing authentication system, you can also use that. The service supports the following authentication methods:

    • Email/Password: user is registered by supplying their email and password.
    • Social Login: user is registered using their social media profile. This currently includes Facebook, Google, Twitter, Instagram, LinkedIn, and GitHub.
    • Custom: user is registered by making use of an existing authentication system. 

    In this tutorial, we're only going to cover email/password and social login with Facebook. 

    What You'll Be Creating

    Before we proceed, it's always good to have a general idea of what we're going to create, and what the flow of the app will be like. The app will have the following pages:

    • home page
    • signup page
    • user page
    Home Page

    The home page is the default page of the app where the user can log in with their email/password or their Facebook account. 

    When the user clicks on the Login with Facebook button, a screen similar to the following is displayed, and once the user agrees, the user is logged in to the app:

    Signup Page

    The signup page is where the user can register by entering their email and password. Facebook login doesn't require any signup because the user info is supplied by the Facebook API. 

    User Page

    The final page is the user page, which can be seen only when the user has already logged in. 

    Bootstrap a New Ionic App

    Now that you know what we're making, let's get started building our app!

    First, we bootstrap a new Ionic app using the blank starter template:

    ionic start authApp blank

    Navigate inside the newly created authApp folder. This serves as the root directory of the project. 

    To quickly get set up with the UI of the app, I've created a GitHub repo where you can find the starter source files. Download the repo, navigate inside the starter folder, and copy the src folder over to the root of the Ionic project that you just created. This contains the template files for each of the pages of the app. I'll explain to you in more detail what each of those files does in a later section.

    Serve the project so you can immediately see your changes while developing the app:

    ionic serveCreate an Ionic Account

    Since we'll be using Ionic's back-end to handle user authentication, we need a way to manage the users of the app. This is where the Ionic account comes in. It allows you to manage your Ionic apps and the services that they use. This includes managing the Auth service. You can create an Ionic account by visiting the Ionic.io signup page.

    Connect the App to Ionic Services

    Next, navigate to the root directory of the project and install the Ionic Cloud plugin:

    npm install @ionic/cloud-angular --save

    This plugin will allow the app to easily interact with Ionic services.

    After that, you can initialize the app to use Ionic services:

    ionic io init

    This prompts you to log in with your Ionic account. Once you've entered the correct login details, the command-line tool will automatically create a new app record under your Ionic account. This record is connected to the app that you're developing. 

    You can verify that this step has worked by opening the .io-config.json file and the ionic.config.json file at the root of your project. The app_id should be the same as the app ID assigned to the newly created app in your Ionic dashboard.

    Home Page

    Navigate inside the src/pages/home directory to see the files for the home page. Open the home.html file and you'll see the following:

    <ion-header> <ion-navbar> <ion-title> Ionic2 Auth </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-item> <ion-label fixed>Email</ion-label> <ion-input type="email" [value]="email" [(ngModel)]="email"></ion-input> </ion-item> <ion-item> <ion-label fixed>Password</ion-label> <ion-input type="password" [value]="password" [(ngModel)]="password"></ion-input> </ion-item> </ion-list> <button ion-button full outline (click)='login("email");'>Login</button> <button ion-button full icon-left (click)='login("fb");'> <ion-icon name="logo-facebook"></ion-icon>Login with Facebook </button> <button ion-button clear (click)='signup();'>Don't have an account?</button> </ion-content>

    This page will ask the user for their email and password or to log in with their Facebook account. If the user has no account yet, they can click on the signup button to access the signup page. We'll go back to the specifics of this page later on as we move on to the login part. I'm just showing it to you so you can see the code for navigating to the signup page.

    Next, open the home.ts file. For now, it only contains some boilerplate code for navigating to the signup and user page. Later on, we're going to go back to this page to add the code for logging the user in.

    User Sign Up

    The layout of the signup page is found in src/pages/signup-page/signup-page.html. Take a look at this file and you'll find a simple form with an email field and a password field.

    Next, let's take a look at the signup-page.ts file.

    Let's break this down. First, it imports the controllers for creating alerts and loaders:

    import { AlertController, LoadingController } from 'ionic-angular';

    Then, it imports the classes needed from the Cloud Client:

    import { Auth, UserDetails, IDetailedError } from '@ionic/cloud-angular';
    • The Auth service which deals with user registration, login, and sign-out. 
    • UserDetails is the type used for defining the user details when registering or logging in a user. 
    • IDetailedError is used for determining the exact reason for the error that occurred. This allows us to provide user-friendly error messages to the user whenever an error occurs. 

    Declare the variables to be used for storing the email and password input by the user. This should be the same as the name you've given to the value and ngModel attributes in the layout file. 

    export class SignupPage { email: string; password: string; constructor(public auth: Auth, public alertCtrl: AlertController, public loadingCtrl: LoadingController) { } register() { ... } }

    Next is the register method, which is called when the Register button is pressed. Let's code this method together. 

    First it fires up a loader, and then makes it automatically close after five seconds (so that in case something goes wrong, the user isn't left with a loading animation that is spinning forever).

    register() { let loader = this.loadingCtrl.create({ content: "Signing you up..." }); loader.present(); setTimeout(() => { loader.dismiss(); }, 5000);

    Next, let's create an object to store the user details:

    let details: UserDetails = { 'email': this.email, 'password': this.password };

    Finally, we'll call the signup() method from the Auth service and supply the user details as the argument. This returns a promise, which we unwrap with then(). Once a success response is received from the back-end, the first function that you pass to then() will get executed; otherwise, the second function will get executed.

    this.auth.signup(details).then((res) => { loader.dismiss(); //hide the loader let alert = this.alertCtrl.create({ title: "You're registered!", subTitle: 'You can now login.', buttons: ['OK'] }); alert.present(); //show alert box }, (err: IDetailedError<string[]>) => { ... });

    If an error response is received from Ionic Auth, we'll loop through the array of errors and construct an error message based on the type of error received. Here you can find the list of Auth signup errors that can occur.

    loader.dismiss(); var error_message = ''; for (let e of err.details) { if (e === 'conflict_email') { error_message += "Email already exists. <br />"; } else { error_message += "Invalid credentials. <br />"; } } let alert = this.alertCtrl.create({ title: error_message, subTitle: 'Please try again.', buttons: ['OK'] }); alert.present(); }

    Once that's done, you can try the app in your browser. The email/password login doesn't have any plugin or hardware dependencies, so you should be able to test it out in the browser. You can then find the newly registered user in the Auth tab of your Ionic app dashboard.

    Setting Up Facebook App

    The next step is to set up the app so that it can handle native Facebook logins. First, you need to create a Facebook app. You can do that by logging in to your Facebook account and then going to the Facebook Developer Site. From there, create a new app:

    Once the app is created, click on the Add Product link on the sidebar and select Facebook Login. This will open the Quickstart screen by default. We don't really need that, so go ahead and click on the Settings link right below the Facebook Login. That should show you the following screen:

    Here you need to enable the Embedded Browser OAuth Login setting and add https://api.ionic.io/auth/integrations/facebook as the value for the Valid OAuth redirect URIs. Save the changes once that's done.

    Next, you need to connect Ionic Auth to the Facebook app that you've just created. Go to your Ionic dashboard and select the app that was created earlier (see the "Connect the App to Ionic Services" section). Click on the Settings tab and then User Auth. Under the Social Providers, click on the Setup button next to Facebook:

    Enter the App ID and App Secret of the Facebook app that you created earlier and hit Enable

    Install the Facebook Plugin

    Next, install the Facebook plugin for Cordova. Unlike most plugins, this requires you to supply a bit of information: the Facebook App ID and App Name. You can just copy this information from the Facebook app dashboard.

    cordova plugin add cordova-plugin-facebook4 --save --variable APP_ID="YOUR FACEBOOK APP ID" --variable APP_NAME="YOUR FACEBOOK APP NAME"Configure Facebook Service

    Once that's done, the last thing that you need to do is to go back to your project, open the src/app/app.module.ts file, and add the CloudSettings and CloudModule services from the cloud-angular package:

    import { CloudSettings, CloudModule } from '@ionic/cloud-angular';

    Declare the cloudSettings object. This contains the app_id of your Ionic app and any additional permissions (scope) that you want to ask from the users of your app. By default, this already asks for the email and public_profile. 

    const cloudSettings: CloudSettings = { 'core': { 'app_id': 'YOUR IONIC APP ID' }, 'auth': { 'facebook': { 'scope': [] } } };

    If you want to ask for more data from your users, you can find a list of permissions on this page: Facebook Login Permissions.

    Next, let Ionic know of the cloudSettings you've just added:

    @NgModule({ declarations: [ MyApp, HomePage, SignupPage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp), CloudModule.forRoot(cloudSettings) // <--add this ], ...

    Later on, when you add other social providers to your app, a similar process is followed.

    Logging the User In

    Now it's time to go back to the home page and make some changes. The HTML template already has everything we need, so we only need to update the script. Go ahead and open the src/pages/home/home.ts file. At the top of the file, import the following in addition to what you already have earlier:

    import { NavController, AlertController, LoadingController } from 'ionic-angular'; import { Auth, FacebookAuth, User, IDetailedError } from '@ionic/cloud-angular'; import { UserPage } from '../user-page/user-page';

    Inside the constructor, determine if a user is currently logged in or not. If a user is already logged in, we automatically navigate to the User Page. 

    export class HomePage { //declare variables for storing the user and email inputted by the user email: string; password: string; constructor(public navCtrl: NavController, public auth: Auth, public facebookAuth: FacebookAuth, public user: User, public alertCtrl: AlertController, public loadingCtrl: LoadingController) { if (this.auth.isAuthenticated()) { this.navCtrl.push(UserPage); } } ... }

    Next, when the Login button is pressed, we start by displaying a loading animation.

    login(type) { let loader = this.loadingCtrl.create({ content: "Logging in..." }); loader.present(); setTimeout(() => { loader.dismiss(); }, 5000); ... }

    As you saw in the src/pages/home/home.html file earlier, a string that represents which login button has been pressed (either the email/password login button or the Facebook login button) is passed to the login() function. This allows us to determine which login code to execute. If the type is 'fb', it means that the Facebook login button was pressed, so we call the login() method of the FacebookAuth service.

    if(type == 'fb'){ this.facebookAuth.login().then((res) => { loader.dismiss(); this.navCtrl.push(UserPage); }, (err) => { //hide the loader and navigate to the user page loader.dismiss(); let alert = this.alertCtrl.create({ title: "Error while logging in to Facebook.", subTitle: 'Please try again.', buttons: ['OK'] }); alert.present(); }); }

    Otherwise, the email/password login button was pressed, and we should log the user in with the details entered in the login form.

    else{ let details: UserDetails = { 'email': this.email, 'password': this.password }; this.auth.login('basic', details).then((res) => { loader.dismiss(); this.email = ''; this.password = ''; this.navCtrl.push(UserPage); }, (err) => { loader.dismiss(); this.email = ''; this.password = ''; let alert = this.alertCtrl.create({ title: "Invalid Credentials.", subTitle: 'Please try again.', buttons: ['OK'] }); alert.present(); });

    Take a look at the final version of the home.ts file to see how it should all look.

    User Page

    The last page is the User page. 

    The layout, in src/pages/user-page/user-page.html, displays the profile photo of the user and their username. If the user signed up with their email/password, the username will be the email address of the user and the profile photo will be the default profile photo assigned by Ionic. On the other hand, if the user signed up with Facebook, their profile photo will be their Facebook profile photo and their username will be their full name.

    Next, look at the user-page.ts file. 

    Under the ionic-angular package, we're importing the Platform service aside from NavController. This is used to get information about the current device. It also has methods for listening to hardware events such as when the hardware back button in Android is pressed.

    import { NavController, Platform } from 'ionic-angular';

    And for the cloud-angular package, we need the Auth, FacebookAuth, and User services:

    import { Auth, FacebookAuth, User } from '@ionic/cloud-angular';

    Inside the class constructor, determine if the user logged in with their email/password user or their Facebook account. Fill in the username and photo based on that. Then, below that, assign a function to be executed when the hardware back button is pressed. The registerBackButtonAction() accepts two arguments: the function to be executed and the priority. If there are more than one of these in the app, only the highest priority will be executed. But since we only need this in this screen, we just put in 1. 

    export class UserPage { public username; public photo; constructor(public navCtrl: NavController, public auth: Auth, public facebookAuth: FacebookAuth, public user: User, public platform: Platform) { if(this.user.details.hasOwnProperty('email')){ this.username = this.user.details.email; this.photo = this.user.details.image; }else{ this.username = this.user.social.facebook.data.full_name; this.photo = this.user.social.facebook.data.profile_picture; } this.platform.registerBackButtonAction(() => { this.logoutUser.call(this); }, 1); } }

    The logoutUser() method contains the logic for logging the user out. The first thing it does is to determine if a user is actually logged in. If a user is logged in, we determine whether the user is a Facebook user or an email/password user. 

    This can be done by checking the email property under the user.details object. If this property exists, that means that the user is an email/password user. So if it's otherwise, we assume that it's a Facebook user. Calling the logout() method in Auth and FacebookAuth clears out the current user of the app. 

    logoutUser() { if (this.auth.isAuthenticated()) { if(this.user.details.hasOwnProperty('email')){ this.auth.logout(); }else{ this.facebookAuth.logout(); } } this.navCtrl.pop(); //go back to home page }Running the App on a Device

    Now we can try out our app! First, set up the platform and build the debug apk:

    ionic platform add android ionic build android

    For the Facebook login to work, you need to supply the hash of the apk file to the Facebook app. You can determine the hash by executing the following command:

    keytool -list -printcert -jarfile [path_to_your_apk] | grep -Po "(?<=SHA1:) .*" | xxd -r -p | openssl base64

    Next, go to your Facebook app basic settings page and click on the Add Platform button in the bottom part of the screen. Select Android as the platform. You'll then see the following form:

    Fill out the Google Play Package Name and Key Hashes. You can put anything you want as the value for the Google Play Package Name as long as it follows the same format as the apps in Google Play (e.g. com.ionicframework.authapp316678). For the Key Hashes, you need to put in the hash returned from earlier. Don't forget to hit Save Changes when you're done.

    Once that's done, you can now copy the android-debug.apk from the platforms/android/build/outputs/apk folder to your device, install it, and then run.

    Conclusion and Next Steps

    That's it! In this tutorial, you've learned how to make use of the Ionic Auth service to easily implement authentication in your Ionic app. We've used email/password authentication and Facebook login in this tutorial, but there are other options, and it should be easy for you to add those to your app as well. 

    Here are some next steps you could try on your own that would take your app to the next level. 

    • Store additional user information—aside from the email and password, you can also store additional information for your users.
    • Use other social login providers—as mentioned at the beginning of the article, you can also implement social login with the following services: Google, Twitter, Instagram, LinkedIn, and GitHub.
    • Add a password reset functionalitypassword resets can be implemented using Ionic's password reset forms, or you can create your own.
    • Custom authentication—if you already have an existing back-end which handles the user authentication for your service, you might need to implement custom authentication.

    That's all for now. Stay tuned for more articles on using Ionic services! And in the meantime, check out some of our other great posts on cross-platform mobile app development.

    3 days 10 hours ago

New Course: Add MailChimp Signup to Your WordPress Site

  • What You'll Be Creating

    MailChimp makes it easy to send email to users of your WordPress site. And our new Coffee Break Course, Add MailChimp Signup to Your WordPress Site, shows you how to get set up with MailChimp in just ten minutes.

    In this quick, ten-minute course, Rachel McCollin will show you how easy it is to get set up to send a newsletter to users of your WordPress site. You'll learn how to install a MailChimp plugin, how to link it to your MailChimp account and configure a widget, and how to let users sign up to your MailChimp mailing lists via your WordPress site.

    Watch the introduction below to find out more.

     

    You can take our new Coffee Break Course straight away with a free 10-day trial of our monthly subscription. If you decide to continue, it costs just $15 a month, and you’ll get access to hundreds of courses, with new ones added every week.

    If you need some custom functionality beyond what's offered by the standard installation, check out the wide range of MailChimp WordPress plugins on Envato Market. You can find all sorts of add-ons to give you special contact forms, to help you integrate with WooCommerce or Visual Composer, and much more.

    3 days 11 hours ago

Building Your Startup: Securing an API

  • What You'll Be Creating

    Welcome to the Building Your Startup With PHP series, which is guiding readers through the launch of an actual startup, Meeting Planner. Each episode details different coding and business challenges, with detailed examples you can use to learn.

    Introduction

    Recently, I introduced you to Yii's simple REST API generation and Meeting Planner's new "RESTful" service API. At that time, I mentioned that these APIs were only loosely secured. Sure, there was a shared secret between the client and the server, but there were a couple of problems.

    First, the secret key and user tokens were repeatedly transmitted in query parameters of SSL calls. And there was no other authenticity check for the data, allowing a middle-person attack.

    In today's episode, I'll guide you through how I secured the API against these weaknesses for a more robust API.

    If you've been reading our startup series, you've probably already tried Meeting Planner and Simple Planner, but if not, please do. Scheduling a meeting is easy:

    As usual, I'll be participating in the comments below, so please offer your thoughts. You can also reach me on Twitter @lookahead_io. I'm always especially intrigued if you want to suggest new features or topics for future tutorials.

    As a reminder, all of the code for Meeting Planner is written in the Yii2 Framework for PHP. If you'd like to learn more about Yii2, check out our parallel series Programming With Yii2.

    The Initial API Security

    Let's begin by taking a look at the early API security I coded. We'll presume there's a mobile app that I've shared an $app_id and $app_secret with. Only API callers with these keys are accepted.

    For example, the app tries to register its owner, likely a new Meeting Planner user:

    public function actionRegister($app_id='', $app_secret='', $source='',$firstname ='',$lastname='', $email = '',$oauth_token='') { Yii::$app->response->format = Response::FORMAT_JSON; // verify app_id and app_key if (!Service::verifyAccess($app_id,$app_secret)) { // to do - error msg return false; }

    The app calls the above actionRegister via https://api.meetingplanner.io/user-token/register/ with arguments as follows:

    • $app_id and $app_secret for authentication
    • $source = 'facebook' for the OAuth service we're using, and accompanying $oauth_token from that service
    • $email, $firstname, and $lastname provided via OAuth

    All of those are query arguments such as:

    https://api.meetingplanner.io/user-token/register/?app_id=777&app_secret=imwithher&source=facebook&oauth_token=zuckerburger&email=tom@macfarlins.com&firstname=thomas&lastname=macfarlins

    Service::verifyAccess($app_id,$app_secret) looks up the keys to authenticate the call as shown below:

    class Service extends Model { public static function verifyAccess($app_id,$app_secret) { if ($app_id == Yii::$app->params['app_id'] && $app_secret == Yii::$app->params['app_secret']) { Yii::$app->params['site']['id']=SiteHelper::SITE_SP; return true; } else { return false; } }

    Because the keys and the data were sent via SSL, they're pretty secure but not invincible. Neither is the secret key safe on users' iPhones for certain.

    How can we make this more secure? Here are a few ideas:

    1. Don't ever transmit the secret key over the Internet.
    2. Don't transmit any of the data as URL parameters which might show up in server logs.
    3. Sign all the data to verify its accuracy.

    These are actually standard practices used for securing APIs.

    Note: An example of the risk of transmitting data that could be exposed in server logs would be the email and the Facebook OAuth token. If found in logs, these could be used with the Facebook API to access someone's Facebook account.

    Implementing Better API SecurityUsing Hash Signatures

    First, I'm going to stop transmitting the $app_secret. Instead, we'll sign the outgoing data with it before making an API call. 

    So we'll alphabetize the variables and concatenate them into a string, like this:

    $data = $email.$firstname.$lastname.$oauth_token.$source;

    Resulting in:

    $data = 'tom@macfarlins.comthomasmacfarlinszuckerburgerzuckerburger'

    Then, we'll hash the data with PHP's hash_hmac and the sha256 algorithm using our secret key.

    $signature = hash_hmac('sha256', $data,Yii::$app->params['app_secret']);

    This creates a unique hash code based on the arguments of the API call and our shared secret key:

    $signature => 9f6d2f7dd7d674e85eff51f40f5f830787c37d84d4993ac9ccfea2800285bd02

    Now, we can make a call on the API without transmitting the secret key. Instead, we transmit the signature of the hashed data above.

    I've been using Postman to test the API, but you can also use cURL:

    Here's the receiving API code that responded to the call above:

    public function actionRegister($app_id='', $source='',$firstname ='',$lastname='',$email = '',$oauth_token='',$sig='') { Yii::$app->response->format = Response::FORMAT_JSON; $sig_target = hash_hmac('sha256',$email.$firstname.$lastname.$oauth_token.$source,Yii::$app->params['app_secret']); if ($app_id != Yii::$app->params['app_id'] && $sig==$sig_target) { return 'it worked!'; } else { return 'failed!'; }

    Furthermore, as I reviewed last time, each user receives their own token when they access Meeting Planner through the API, e.g. via their mobile phone. So, subsequent to registration, we can sign calls with their individual token and don't need to transmit either the application's secret key or the user's individual token.

    Sending Data in the HTTPS Headers

    Next, we'll migrate sending data in the headers. You can do this easily with Postman or cURL. Here's Postman:

    And here's cURL:

    public function actionCurl($sig) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,"http://localhost:8888/mp-api/user-token/register?sig=".$sig); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers = [ 'app_id: '.'imwithher', 'email: '.'tom@macfarlins.com', 'firstname: '.'thomas', 'lastname: '.'macfarlins', 'oauth_token: '.'zuckerburger', 'source: '.'facebook', ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $server_output = curl_exec ($ch); var_dump($server_output); curl_close ($ch); }

    Here's the receiving code which gets the API data from HTTPS Headers:

    public function actionRegister($sig='') { Yii::$app->response->format = Response::FORMAT_JSON; $headers = Yii::$app->request->headers; $email= $headers->get('email'); $firstname= $headers->get('firstname'); $lastname= $headers->get('lastname'); $oauth_token= $headers->get('oauth_token'); $source = $headers->get('source'); if ($headers->has('app_id')) { $app_id = $headers->get('app_id'); } $sig_target = hash_hmac('sha256',$email.$firstname.$lastname.$oauth_token.$source,Yii::$app->params['app_secret']); if ($app_id != Yii::$app->params['app_id'] && $sig==$sig_target) { return 'it worked!'; } else { return 'failed!'; }In Closing

    We began today with the following goals:

    1. Don't ever transmit the secret key over the Internet.
    2. Don't transmit any of the data as URL parameters which might show up in server logs.
    3. Sign all the data to verify its accuracy.

    And we accomplished all of these goals with only modest changes to our API code. It was fun making these changes and seeing how easily we can better secure an API. I hope you enjoyed following along with today's episode.

    I regularly monitor the comments, so please join in the discussion. You can also reach me on Twitter @lookahead_io directly. And, of course, watch for upcoming tutorials here in the Building Your Startup With PHP series.

    If you didn't earlier, try scheduling a meeting at Meeting Planner and let me know what you think. I especially appreciate feature requests.

    Related Links

    3 days 13 hours ago

While You Were Offline: Trump Says He’s Treated Unfairly. Abe Lincoln Like, ‘What?’

Pages