Smarter Grids With Sass And Susy


  

If you’re a designer, you’ll know that grids are your friends. More often than not, they’re the vital architecture that holds a beautiful design together; they create rhythm, structure your page, lead the eye, and prevent the whole thing collapsing in a sloppy mess.

Smarter Grids With Sass And Susy

I’m a firm advocate for designing with the browser: prototyping with HTML and CSS has many clear advantages over static Photoshop comps, which have less value for the responsive web. Unfortunately, HTML, CSS and grids aren’t natural bedfellows: the progression of web standards over the years has been lacking in this area, meaning we have to grapple with floats (which were never designed to be used this way) and clearfixes — not ideal when you want to spend less time debugging layout and more time crafting experiences.

The post Smarter Grids With Sass And Susy appeared first on Smashing Magazine.

Remix CodePen Challenge: Winners Announced!

One month ago we set you a challenge: to remix an HTML and CSS profile card on CodePen as creatively as possible. A massive 154 of you took part–and today we’re very happy to announce the three prizewinners!

How we Selected the Winners

The judges panel comprised an Editor (me), a Designer, a Project Manager, a UX Specialist, an SEO Pro and a Front-end Developer from the team at Envato. Together we whittled down the collection by examining each pen’s creativity, execution, personality, originality and UX. It was a difficult process, but the three which received the most votes are listed below! 

Drumroll please..

Third Place: Yegor Borisenco

Great bit of Sass and animation, with plenty of personality!

Yegor wins:

  • $50 PayPal Prize
  • 1-year CodePen Pro Account
  • 3-month subscription to Tuts+
  • Envato Studio 20% discount voucher

Second Place: David Jones

Hit Rerun (bottom right of the pen) to fully appreciate what David’s done..

David wins:

  • $100 PayPal prize
  • 1-year CodePen Pro Account
  • 3-month subscription to Tuts+
  • $50 Envato Studio voucher

First Place: Dion Pramadhan

Our judges couldn’t help but be charmed by this one, well done Dion!

Dion wins:

  • $200 PayPal Prize
  • CodePen Tee Shirt and Swag Bag
  • 1-year CodePen Pro Account
  • 1-year subscription to Tuts+
  • $150 Envato Studio voucher
  • A “Won a Contest“ badge on Envato Market

Great Job Everyone!

A well-deserved congratulations to our winners! We’ll be in touch shortly with details on how to get hold of the goodies.

Thank you to everyone who took part–selecting the best from these entries (don’t forget the check out the collection to see what you were all up against) was no easy task. Thanks to the judges team for lending us their expertise. Lastly, thanks must go to PayPal and the guys at CodePen for stumping up superb prizes. If you didn’t win, better luck next time, we hope to see you in another challenge!

Getting Started With the Instagram API: Media Endpoints

Final product image
What You’ll Be Creating

This is part two of a series on the Instagram API. In this tutorial, I’ll guide you through using Instagram’s Media Endpoints, which allow you to search for popular images from a specific time and place. 

You can download code for each episode by using the GitHub repository link in the sidebar. You may also be interested in my two-part Tuts+ series, Locating Potential Crime Scene Witnesses With Social Media APIs

The code for these tutorials is written in PHP using the Yii Framework. You can learn more about Yii in Introduction to the Yii Framework (Tuts+) and in the Programming With Yii2 Series (Tuts+). You can also easily adapt the code segments for your own PHP application.

I do participate in the discussions. If you have a question or topic suggestion, please post a comment below. You can also reach me on Twitter @reifman or email me directly.

Let’s begin by registering as a developer with Instagram.

Getting Started

To get started, visit the Instagram API page for developers and click Register Your Application:

Instagram Hello Developers

You’ll need to sign up for a developer account:

Instagram Developer Signup

Then you can register a new application to receive your Client ID:

Instagram New Client Registration

On the Manage Clients dashboard, you’ll see your Client ID and Client Secret, so make note of these:

Instagram Manage Clients

Using the Media Endpoints

As web service APIs go, the Instagram API is robust, and in my experience works very well. Instagram offers a handful of API endpoints:

Instagram API Documentation Overview and Endpoints

For this tutorial, we’ll focus on the Media endpoints:

Instagram API Media Endpoints

With Media endpoints, you can retrieve information about an Instagram photo or video by referencing its ID or the shortcode from its URL, e.g. 0EyZ53Ja9X from https://instagram.com/p/0EyZ53Ja9X. It also provides geosearch capabilities to find media posted from a specific time and place as we did in Locating Potential Crime Scene Witnesses With Social Media APIs. And finally, it allows you to retrieve popular, trending Instagram posts.

The API Console

To help you get started and debug, Instagram has an API console powered by Apigee:

Instagram API Console powered by Apigee

You can try out queries against the Media endpoints using the API console. Here’s an example result for media/popular:

Obviously, you can see how useful this is for working with media from the popular mobile photography service.

Let’s move on to installing our sample codebase and configuring it to work with your Instagram client application.

Installing the Codebase

For this series, I’m going to continue to build on the Eyewitness codebase from Locating Potential Crime Scene Witnesses With Social Media APIs. You can clone the GitHub repository located in the sidebar to run our sample code.

cd ~/Sites/eyew
https://github.com/link-in-sidebar/eyew.git

You’ll need to configure your local Apache configuration. I use MAMP, so it looks something like this:

cd /Applications/MAMP/htdocs
ln -s ~/Sites/eyew/web /Applications/MAMP/htdocs/eyew

You need to create a database locally. I use PHPMyAdmin to create one graphically:

Create your Eyewitness database

Then I create an initialization file in /var/secure/eyew.ini with my database credentials and Instagram IDs and keys. I described this process recently in another Tuts+ tutorial: Protecting Your Keys From GitHub.

My ini file looks like this:

mysql_host="localhost"
mysql_db="eyew"
mysql_un="xxxxxxxxx"
mysql_pwd="xxxxxxxxxxxx"
instagram_client_id = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7"
instagram_client_secret = "1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4"

Update your Composer and its vendor libraries:

sudo composer self-update
sudo composer update

Then initialize our database. The first migration installs user tables for our Yii2-User by developer Dmeroff extension, and the second creates our app-specific tables:

 ./yii migrate/up --migrationPath=@vendor/dektrium/yii2-user/migrations
 ./yii migrate/up

Again, you can learn more about setting up a Yii Framework application in my Programming With Yii2 series for Tuts+.

Here’s the MySQL schema for our Instagram image table—we call it the Gram table. We’ll use it to store geosearch results.

class m150308_184606_create_gram_table extends Migration
{
    public function up()
    {
          $tableOptions = null;
          if ($this->db->driverName === 'mysql') {
              $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
          }

          $this->createTable('{{%gram}}', [
              'id' => Schema::TYPE_PK,
              'moment_id' => Schema::TYPE_INTEGER . ' NOT NULL',
              'username' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0',
              'link' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0',
              'image_url' => Schema::TYPE_STRING . ' NOT NULL DEFAULT 0',
              'text' => Schema::TYPE_TEXT . ' NOT NULL ',
              'created_time' => Schema::TYPE_INTEGER . ' NOT NULL',
              'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',
              'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',
          ], $tableOptions);          
      $this->addForeignKey('fk_gram_moment', '{{%gram}}', 'moment_id', '{{%moment}}', 'id', 'CASCADE', 'CASCADE');     
    }

The Home Page

I’ve renamed the sample application “Instapi”, short for Instagram API.

Here’s a look at what you should see when you visit the site in your browser:

Instagram API Sample Code Home Page

Performing Media Searches

To implement media searches in our Instapi application, I’m using Galen Grover’s Instagram PHP package.

Search Popular Images

First, let’s implement a search for media/popular. We’ll query the API and display the results in a table.

I’ve created an action called popular in GramController.php:

    public function actionPopular()
    {
      $gram = new Gram();
      $media = $gram->searchPopular();
      return $this->render('popular', [
          'media' => $media,
      ]);
    }

It calls searchPopular() in the Gram.php model:

<?php

namespace appmodels;

use Yii;
use yiidbActiveRecord;
use Instagram;
...
public function searchPopular() {      
       $instagram = new InstagramInstagram;
       $instagram->setClientID( Yii::$app->params['instagram']['client_id'] );
       $media = $instagram->getPopularMedia(); 
       return $media;
     }

In /views/gram/popular.php, we set up an HTML table structure:

<?php

use yiihelpersHtml;

/* @var $this yiiwebView */
/* @var $searchModel appmodelsInstagramSearch */
/* @var $dataProvider yiidataActiveDataProvider */

$this->title = 'Instagrams';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="instagram-index">
  <table class="table">
      <thead>
      <tr class="small-header">
        <td>Image ID</td>
        <td>User</td>
         <td >Thumbnail</td>
         <td >Caption</td>
         <td >Created at</td>
    </tr>
     </thead>
<?php
  foreach ($media as $m) {    
    echo $this->render('_item', [
        'm' => $m,
    ]);
  }
?>
</table>

</div>

and include the _item.php partial view to display individual media results:

<tr>
  <td><a href="/eyew/gram/lookup/?id=<?= $m->id ?>"><?= $m->id ?></a></td>
  <td><a href="https://instagram.com/<?= $m->user->username ?>"><?= $m->user->username ?></a></td>
  <td><a href="<?= $m->link ?>"><img src="<?= $m->images->thumbnail->url ?>"></a></td>
  <td>
    <?php
    echo (isset($m->caption->text)?$m->caption->text:'');
    ?>
  </td>
  <td><?= $m->created_time ?></td>
</tr>

Here are the results of Instagram media popular queries. Go ahead and refresh the page in your app. It’s fun to see what comes up next.

Instagram Media Popular Results Table

Look Up Information About an Image or Video

I’ve linked the Instagram media ID in the first column to a controller action that calls the media endpoint which gets us more information:

    public function actionLookup($id)
    {
      $gram = new Gram();
      $media = $gram->lookup($id);
      print_r($media);
    }

Here’s the lookup function in the Instagram model:

     public function lookup($id) {      
        $instagram = new InstagramInstagram;
        $instagram->setClientID( Yii::$app->params['instagram']['client_id'] );
        $media = $instagram->getMedia( $id ); 
        return $media;
      }

Here’s a screenshot of the data dumped to the screen:

Instagram API Media Information Dumped to Screen

Obviously, you could use and store this information however you would like.

Search for Media From a Time and Place

Now, let’s search for images from a specific time and place. For this example, I’ll review our Eyewitness example.

Our codebase allows you to define a moment as a place and time. It consists of a friendly descriptor, a location (latitude and longitude), a start time and a duration (in minutes). For my first example, I’m looking for Instagram users who were present at Macklemore’s video shooting on the evening of Wednesday, July 24, 2013 at Seattle’s landmark Dick’s Drive In.

Using Google Maps, I can get the GPS latitude and longitude for Dick’s. It’s 47.6195 -122.321. 

Dicks Drive In Broadway Seattle GPS in Google Maps

From the article, I learned that the production shut down at 1 am. I’m going to choose a start time of 10 pm and a duration of 3 hours.

Create a Moment

Instagram accepts start times in GMT so I’ve hardcoded an eight-hour time change adjustment from my timezone (PST). You may need to change this in the code.

public function actionCreate()
    {
        $model = new Moment();
         if ($model->load(Yii::$app->request->post())) {
            // convert date time to timestamp
            $model->start_at = strtotime($model->start_at);
            // adjust for GMT
            $model->start_at+=(3600*8);
            // validate the form against model rules
            if ($model->validate()) {
                // all inputs are valid
                $model->save();              
                return $this->redirect(['view', 'id' => $model->id]);
            } else {
              return $this->render('create', [
                  'model' => $model,
              ]);
            }
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }

To search Instagram, just click on the camera icon below:

The Moments Index Grid

The actual search is fairly straightforward: $instagram->searchMedia( $this->latitude, $this->longitude,$params ); 

<?php

namespace appmodels;

use Yii;
use yiidbActiveRecord;
use appmodelsGram;
use Instagram;

...

public function searchInstagram() {      
       $instagram = new InstagramInstagram;
       $instagram->setClientID( Yii::$app->params['instagram']['client_id'] );
       $end_at = $this->start_at + ($this->duration*60);
       $params = array('min_timestamp'=>$this->start_at,'max_timestamp'=>$end_at,'distance'=>$this->distance,'count'=>50);
       $media = $instagram->searchMedia( $this->latitude, $this->longitude,$params ); 

       foreach ($media as $m) {
         if (isset($m->caption->text)) {
          $caption = $m->caption->text;
         } else {
           $caption ='';                    
         }
        $i = new Gram();           $i->add($this->id,$m->user->username,$m->link,$m->created_time,$m->images->thumbnail->url,$caption);
       }
     }

The results are stored in the Gram table, which we can then browse:

public function add($moment_id,$username,$link,$created_time,$image_url,$text) {
      if (!Gram::find()->where(['moment_id' => $moment_id])->andWhere(['link'=>$link])->andWhere(['created_time'=>$created_time])->exists()) {
        $i = new Gram();
        $i->moment_id = $moment_id;
        $i->username = $username;
        $i->link = $link;
        $i->created_time = $created_time;
        $i->image_url = $image_url;
        $i->text = $text;        
        $i->save();        
      }
    }

Here’s the first page of results from my search. You can see the crowds and Macklemore’s Cadillac limo driving up.

Macklemore Search Results

Then on page three, an Instagram user named Joshua Lewis has a shot of Macklemore exiting the Cadillac: 

More Macklemore Search Results

Here’s Macklemore:

Macklemore Arrives on Instagram

This example clearly shows the power that the Instagram search API provides. In just a few moments, we found a variety of eyewitnesses to an event from the summer of 2013.

What’s Next?

I hope you’ve enjoyed learning about the Instagram API thus far. In the next episode, we’ll explore OAuth authentication so that we can query areas of the Instagram service that require user authorization.

In the meantime, please feel free to post your questions and comments below. You can also reach me on Twitter @reifman or email me directly. You can also browse my Tuts+ instructor page to see other tutorials I’ve written. 

Related Links

The preview image is modified from a result that came up in our API search. 

The Beginners Guide to WooCommerce: Shipping Settings Part 2

In our previous article we discussed how a store owner can configure the settings in the Shipping Options section. WooCommerce offers multiple shipping methods which you can implement to deliver items/products to your customers. Today I will be taking up every method separately in detail, explaining how you can configure the settings for these shipping methods.

WooCommerce Shipping Options menu

As a reminder, WooCommerce offers five different types of shipping methods. Each is listed on a separate sub-page in the Shipping Settings tab. They are:

  1. Flat Rate
  2. Free Shipping
  3. International Delivery
  4. Local Delivery
  5. Local Pickup

Flat Rate

We will start this article with the settings of shipping through the flat rate shipping option.

Enable/Disable

Enable or Disable shipping method

By now I am sure you know what the option for Enable/Disable means. You may enable this option if you want to offer shipping at a flat rate to your customers. 

Method Title

Method title

The field for Method Title will decide what text will be displayed to your customers if you are offering flat rate shipping. Once again WooCommerce has set a default value of Flat Rate at the time of plugin installation, but a store owner can set it to any custom value.

Cart showing Flat Rate Shipping Method text

The figure above shows that if we change this field to Flat Rate Shipping Method and save the changes then the same title will appear on the front-end.

Availability 

Availability All allowed countries

You can limit the destinations where you will offer shipping at a flat rate. The option of Availability is a dropdown menu from which you can allow flat rate shipping to All allowed countries or to some Specific Countries. If you select some Specific Countries then you’ll have to choose the specific countries from another dropdown which appears next to this option.

Tax Status

Tax Status dropdown menu

An online store owner has the choice of applying taxes to the various shipping methods or not. You can add the cost of taxes like Value Added Tax (VAT) or the Sales Tax if you set the Tax Status option as Taxable. Otherwise you may select None and the shipping cost will not include any such tax.

Additional Rates

Additional Rates

In WooCommerce, if you are willing to implement some additional taxes other than the standard flat rates then you can use the function of Additional Rates. WooCommerce guides its users about how to fill the details in this setting. You will notice in the above figure that some attributes are displayed which are filled according to a particular format, i.e.

Option Name | Additional Cost [+-Percents%] | Per Cost Type (order, class or item)

Let’s see what these attributes denote:

  • Option Name: Here you will enter the names of shipping methods other than the flat rate, e.g. Express Shipping, Airmail Shipping, etc.
  • Additional Cost: This is the additional amount which will be applied on every product other than the base flat rate.
  • Per Cost Type: The attribute of Per Cost Type may apply to every class, order or item and will decide how this cost will be applied. 

Now I will explain how these Additional Rates can be set at the front-end with the help of an example.

Additional Rates

In the above figure I have added an additional price of 10.0 and 5.0 for the newly defined shipping rates of Express Shipping and Airmail Shipping, which will be applicable on every order. So, considering the fact that I have fixed £7.00 for shipping with flat rate, now the total charge for Express Shipping becomes £17.00 (10.0+7.0=17.00) and the Airmail Shipping becomes £12.00 (7.0+5.0=12.00). 

Shopping cart showing different shipping totals depending on shipping method

A customer who chooses shipping with flat rate will be charged £42.00 (35.0+7.0=42.00) whereas a person opting for the additional rate of Express Shipping will be charged £52.00 (35.0+17.0=52.00) for the same order. The difference in total cost was observed due to the selection of different shipping methods. (See above fig.)   

Additional Costs

Towards the end of this section we see some configurations that will control and manage various additional costs that will apply apart from the fixed flat rate. These settings include:

  • Costs Added…
  • Costs
  • Minimum Handling Fee

Costs Added

Costs Added dropdown menu

The settings in this field will decide how and on what basis the additional costs other than flat rate will apply. Here we see three different options. These costs may be applied:

  • per order: applicable on the entire order
  • per item: applicable on every single item
  • per class: applicable on the entire shipping class for a particular order

Costs

Costs options

The section for Costs is displayed in the form of a table where you can actually enter the cost of additional rates which will be applied per order, item or class. In this table you can see different columns. You can click the Add Cost button to add new fields in this table and click Delete selected costs to remove any field. You can find the following attributes in the table:

  • Shipping Class: This field defines various shipping classes of items that are added to the cart.
  • Cost: Here you will enter the applied cost, which will not include the tax rate.
  • Handling Fee: This is another kind of additional amount that will be added to your final product price. Here you will enter the data either in the form of numbers (e.g. 5.5) or in percentages (e.g. 4%).
  • Any class: If a user is defining the cost for a product’s shipping class then this field will apply.
Costs section showing additional amounts for cost and handling fee

For example, let’s fill the fields with the data shown in the above figure, where I have fixed Shipping Class=Any class; Cost=5; Handling Fee=2.5.

When I save these changes, the cart page will display new prices. So, when a customer selects flat rate shipping, the total price for the product is £49.50.

How £49.50?

Attributes Price (£)
Price of the product 35.00
Flat shipping rate 7.00
Additional cost 5.00
Handling fee  2.50
Total 49.50
Front end view showing the new rates as above

In the same manner you can calculate the total cost if a customer selects the option of Express Shipping Method or any other.

Minimum Handling Fee

Minimum Handling Fee

The last field for setting which you will see in this section is for the Minimum Handling Fee, which is the minimum amount which will always be charged to customers. If you do not want to apply this fee, then you may leave this field empty.

In the end, click the Save Changes button.

This setting completes the configuration of flat rate shipping. In the next article I will explain the rest of the settings for the remaining shipping methods. 

Build a Custom WordPress User Flow — Part 3: Password Reset

In the first two tutorials in this series, we have built custom pages for logging in and registering a new user. Now, there is only one part in the login flow left to explore and replace: what happens if a user forgets his or her password and wants to reset it.

In this tutorial, we will tackle that last step and complete the Personalize Login plugin we’ve been building throughout the series. 

The password reset functionality in WordPress follows what has become more or less the standard approach on today’s web sites: 

  1. A user initiates the reset by entering his or her user name or email address and requesting a password reset.
  2. A temporary password reset token is created and stored in the user data. A link containing this token is sent to the user’s email address.
  3. The user clicks on the link.
  4. On the password reset page, the token is verified and if it matches the user’s data, she gets to pick a new password.

Just like login and new user registration, this functionality is handled through wp-login.php — and so, the overall idea of how we’ll customize this flow will by now be mostly familiar from previous tutorials. 

If you haven’t read the first two tutorials yet, it’s best to start from Part 1 and go through the series in order. You can follow the tutorial while writing the code yourself or download the full source code from the linked Github repository.

Now, let’s get started by replacing the first screen in the flow.

Initiate the Password Reset

A password reset begins when a user arrives at your login page but doesn’t remember which password he or she used for this site. 

For this, we placed a Forgot your password? link at the bottom of the Sign In form in the first part of the series. By default, on WordPress powered sites, this link points to wp-login.php?action=lostpassword, a page that looks like this:

WordPress Forgot Your Password screen

To replace this page with a custom one, we will create a function to redirect the user to our custom page and hook that function to a WordPress action.

In this case, we have two options to choose from: we can use the action lost_password, which is called right before the page is rendered, or the action we have been using in previous tutorials: login_form_{action}, this time, login_form_lostpassword.

We could go both ways, but to limit the amount of unnecessary code being executed, let’s choose the latter option.

But first, let’s create the new page.

Step 1: Create a Page for Initiating Password Reset

As you remember, in Part 1, we created a function for creating WordPress pages at plugin activation, using the plugin_activated callback function.

In this function, add the new page’s definition at the end of the $page_definitions array. In the password reset flow, we’ll also need a second page for choosing the new password. So, to save time, let’s also add this second page now.

Here’s the entire array for clarity (with the two last page definitions added):

// Information needed for creating the plugin's pages
$page_definitions = array(
    'member-login' => array(
        'title' => __( 'Sign In', 'personalize-login' ),
        'content' => '[custom-login-form]'
    ),
    'member-account' => array(
        'title' => __( 'Your Account', 'personalize-login' ),
        'content' => '[account-info]'
    ),
    'member-register' => array(
        'title' => __( 'Register', 'personalize-login' ),
        'content' => '[custom-register-form]'
    ),
    'member-password-lost' => array(
        'title' => __( 'Forgot Your Password?', 'personalize-login' ),
        'content' => '[custom-password-lost-form]'
    ),
    'member-password-reset' => array(
        'title' => __( 'Pick a New Password', 'personalize-login' ),
        'content' => '[custom-password-reset-form]'
    )
);

The plugin activation callback is only called when the plugin is explicitly activated, so to create these new pages, you’ll have to deactivate the plugin and then activate it again.

Now, with the pages created, we can redirect the user to member-password-lost instead of wp-login?action=lostpassword

Step 2: Redirect the User to the Custom Page

As I mentioned above, we’ll use the action login_form_{action}, or login_form_lostpassword to cut in before wp-login.php gets a chance to render the default version of the “Lost your password?” screen.

In the plugin’s constructor, add the following line:

add_action( 'login_form_lostpassword', array( $this, 'redirect_to_custom_lostpassword' ) );

Then, create the function redirect_to_custom_lostpassword

This function will check for the request method: for now, we’ll only act on requests sent using the GET method as those are the ones meant for displaying the screen. We’ll take a look at what happens at POST in a little while.

/**
 * Redirects the user to the custom "Forgot your password?" page instead of
 * wp-login.php?action=lostpassword.
 */
public function redirect_to_custom_lostpassword() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        if ( is_user_logged_in() ) {
            $this->redirect_logged_in_user();
            exit;
        }

        wp_redirect( home_url( 'member-password-lost' ) );
        exit;
    }
}

The function is actually the same as the one we used for redirecting the user to our custom registration page in the previous tutorial, with just the redirect replaced with the page slug of the new page we created above (a good place for some refactoring in the future, maybe?).

Now, if you click on Forgot your password? on the login page, you’ll be redirected to a custom Forgot Your Password page. Now, let’s create a shortcode to add the form for initiating the password reset.

Step 3: Create a Shortcode for Password Reset Form

When creating the page for initiating the password reset, we added the shortcode, [custom-lost-password-form] to its body. Now, to replace the shortcode with a form, let’s create a shortcode handler.

In the plugin’s constructor, add the following line:

add_shortcode( 'custom-password-lost-form', array( $this, 'render_password_lost_form' ) );

Then, create the function for rendering the form:

/**
 * A shortcode for rendering the form used to initiate the password reset.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_lost_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );

    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        return $this->get_template_html( 'password_lost_form', $attributes );
    }
}

By now, most of this function is already familiar to you: First we parse the shortcode parameters (show_title is used to decide whether a title should be rendered before the form for initiating the password reset). Then, if the user isn’t logged in, the function renders a template containing the form for initiating the password reset.

Let’s add that template now. In the templates directory, create a new file, naming it password_lost_form.php. Then, add the following code to that template:

<div id="password-lost-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Forgot Your Password?', 'personalize-login' ); ?></h3>
    <?php endif; ?>

    <p>
        <?php
            _e(
                "Enter your email address and we'll send you a link you can use to pick a new password.",
                'personalize_login'
            );
        ?>
    </p>

    <form id="lostpasswordform" action="<?php echo wp_lostpassword_url(); ?>" method="post">
        <p class="form-row">
            <label for="user_login"><?php _e( 'Email', 'personalize-login' ); ?>
            <input type="text" name="user_login" id="user_login">
        </p>

        <p class="lostpassword-submit">
            <input type="submit" name="submit" class="lostpassword-button"
                   value="<?php _e( 'Reset Password', 'personalize-login' ); ?>"/>
        </p>
    </form>
</div>

The template begins by showing a title if the show_title attribute is set to true (lines 2-4).

This is followed by some instructions on lines 6-13 and the the actual form. As you’ll see on line 15, the form will be posted to the URL returned by the WordPress function  wp_lostpassword_url, the same URL that we saw above when we redirected the user to our custom page.

This form contains just one text field, user_login (line 18). In this field, the default password reset functionality in WordPress accepts either the user’s user name or email. As we are using email as the user name, they are both the same, and so we’ll ask for just the email in the field’s label (line 17).

With this template added, when you go click on the Lost your password? link on the login page, you’ll see a page that looks like this (If using the current WordPress default theme, Twenty Fifteen)

Custom Forgot Your Password screen

Step 4: Handle the Form Submit

Now that we have created the form, it’s time to look at what happens when the user submits it.

In order for us to do proper error handling without resorting to hacks, we’ll need to code some of the functionality ourselves — using helper functions from wp-login.php as much as possible, naturally. 

To do this, we’ll add a new function to handle the POST requests in thelogin_form_lostpassword action. 

This function will use the retrieve_password function defined in wp-login.php to look up the user and initiate the password update procedure. Then, depending on whether there were errors or not, the function redirects the user to the correct page: in case of errors, back to the Lost Your Password page and when successful, to the login page.

In the constructor, add the following line: 

add_action( 'login_form_lostpassword', array( $this, 'do_password_lost' ) );

Then, create the function:

/**
 * Initiates password reset.
 */
public function do_password_lost() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $errors = retrieve_password();
        if ( is_wp_error( $errors ) ) {
            // Errors found
            $redirect_url = home_url( 'member-password-lost' );
            $redirect_url = add_query_arg( 'errors', join( ',', $errors->get_error_codes() ), $redirect_url );
        } else {
            // Email sent
            $redirect_url = home_url( 'member-login' );
            $redirect_url = add_query_arg( 'checkemail', 'confirm', $redirect_url );
        }

        wp_redirect( $redirect_url );
        exit;
    }
}

The function begins by checking the request method (on line 5). As we’re interested in the case when the password lost form is submitted, this function only jumps in when it finds a POST request. The GET requests are already handled by the function redirect_to_custom_lostpassword we created earlier.

Then, on line 6, we call the WordPress function retrieve_password. The function’s name is a bit misleading: the function doesn’t really retrieve the password but instead checks the data from the form and then prepares the user’s account for password reset by creating the password reset token and emailing it to the user.

If there are errors (line 7), we redirect the user back to the page member-password-lost, with the error codes passed as a request parameter (lines 8-10, with the actual redirect done on line 17). 

If all goes well, the user is redirected to the login page with the request parameter checkemail set (lines 12-14) so that we can show a message to the user.

Now, if you submit the form, everything should work alright. But to make the user experience complete, we’ll need to go back to the shortcodes rendering the password lost and login forms and show the errors and success notifications.

Let’s start from the positive, and add the success message. 

In the shortcode function, render_login_form, add the following lines somewhere before the get_template_html call:

// Check if the user just requested a new password 
$attributes['lost_password_sent'] = isset( $_REQUEST['checkemail'] ) && $_REQUEST['checkemail'] == 'confirm';

In the form template, add a message, using the attribute from above:

<?php if ( $attributes['lost_password_sent'] ) : ?>
    <p class="login-info">
        <?php _e( 'Check your email for a link to reset your password.', 'personalize-login' ); ?>
    </p>
<?php endif; ?>

Now, after successfully initiating a password reset the Sign In form should look like this:

Password reset instructions shown on Sign In page

To display errors, we’ll go back to the lost password form. 

First, in the shortcode handler, render_password_lost_form, right before rendering the template, add the following lines to go through the error codes and collect matching error messages in the array $attributes['errors']:

// Retrieve possible errors from request parameters
$attributes['errors'] = array();
if ( isset( $_REQUEST['errors'] ) ) {
    $error_codes = explode( ',', $_REQUEST['errors'] );

    foreach ( $error_codes as $error_code ) {
        $attributes['errors'] []= $this->get_error_message( $error_code );
    }
}

Then, in the template, we’ll render the errors:

<?php if ( count( $attributes['errors'] ) > 0 ) : ?>
    <?php foreach ( $attributes['errors'] as $error ) : ?>
        <p>
            <?php echo $error; ?>
        </p>
    <?php endforeach; ?>
<?php endif; ?>

Finally, add the error messages to our function get_error_messages:

// Lost password

case 'empty_username':
    return __( 'You need to enter your email address to continue.', 'personalize-login' );

case 'invalid_email':
case 'invalidcombo':
    return __( 'There are no users registered with this email address.', 'personalize-login' );

Next, to complete the first step in the password reset flow, let’s take a look at how we can customize the email that is sent to the user.

Step 5: Customize the Password Reset Email

As we saw earlier, when the request for resetting a password is sent, in the function retrieve_password, WordPress sends an email message containing quick instructions on what to do and a link that can be used to finish the password reset.

The message is short and to the point. It does what it’s supposed to do, but you might want to customize it to give it a personal touch and maybe make it a little more descriptive.

The default text is hard coded in wp-login.php, but before sending the message, WordPress gives plugin developers a chance to replace it using two filters.

First, to replace the message body, you can use the filter retrieve_password_message. Let’s do that now.

In the plugin’s constructor, add the following line:

add_filter( 'retrieve_password_message', array( $this, 'replace_retrieve_password_message' ), 10, 4 );

Then, create the function, replace_retrieve_password_message:

/**
 * Returns the message body for the password reset mail.
 * Called through the retrieve_password_message filter.
 *
 * @param string  $message    Default mail message.
 * @param string  $key        The activation key.
 * @param string  $user_login The username for the user.
 * @param WP_User $user_data  WP_User object.
 *
 * @return string   The mail message to send.
 */
public function replace_retrieve_password_message( $message, $key, $user_login, $user_data ) {
    // Create new message
    $msg  = __( 'Hello!', 'personalize-login' ) . "rnrn";
    $msg .= sprintf( __( 'You asked us to reset your password for your account using the email address %s.', 'personalize-login' ), $user_login ) . "rnrn";
    $msg .= __( "If this was a mistake, or you didn't ask for a password reset, just ignore this email and nothing will happen.", 'personalize-login' ) . "rnrn";
    $msg .= __( 'To reset your password, visit the following address:', 'personalize-login' ) . "rnrn";
    $msg .= site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "rnrn";
    $msg .= __( 'Thanks!', 'personalize-login' ) . "rn";

    return $msg;
}

The function receives four parameters: 

  • $message is the default version of the message to be sent to the user. We’ll ignore this parameter and create our own text from scratch.
  • $key is the token used to verify the user’s password reset request. It needs to be included in the password reset link.
  • $user_login is the user’s user name (in our case, email address), also needed in the password reset link.
  • $user_data contains some data about the user. We’ll ignore this for now, but you can explore it further in your own customization if you like.

Most of the function is just creating a message as a series of strings concatenations. The  URL for completing the password reset is created on line 18.

For a more complete customization, one idea would be to add a settings field for editing the content of the password retrieval message and use that instead of coding the message inside the function this way.

If you like, you can use the filter retrieve_password_title to replace the email message title the same way. The filter function takes one parameter, the default title to be sent to the user, and should return the new title. 

Still one other way to further customize the is to replace the entire message and send an HTML message instead, for example using the method I explained in an earlier tutorial about using Mandrill to send email messages from WordPress. In this case, I would use the Mandrill API to send the message in the filter function above and return false so that WordPress wouldn’t try sending the email again.

You have now completed the first step in the password reset procedure: the user can ask to reset the password and the process is initiated by WordPress. 

Next, we’ll look at what happens when the user clicks on the link in the password reset email.

Do the Password Reset

As we saw above, after initiating a password reset, the user is redirected back to the login page, with instructions to check his or her email. 

In that email, there is a link back to wp-login.php with the parameters login and key for identifying the user and verifying the password reset request. When the user clicks on the link, WordPress verifies the user and the key for validity, and then if all is good, lets the user set a new password.

The functionality works well, and we’ll use parts of it, calling existing helper functions in wp-login.php, but again, because of how the actions and filters are organized in the password reset code, we’ll have to rewrite some of the code to be able to complete the customization.

Step 1: Redirect the User to a Custom Page

First, we’ll start by redirecting the user to our own reset password page (which we created at the beginning of this tutorial). 

By now, this is probably familiar to you: In the same way we did in the login and register actions as well as the first page in the password reset flow, we’ll use the action login_form_{action} to divert the password reset action to our own custom functions before WordPress gets to do anything. 

There are two wp-login.php actions that are used for the same functionality, rp and resetpass, so we’ll need to redirect them both to the same function, redirect_to_custom_password_reset.

In the plugin’s constructor, add the following lines:

add_action( 'login_form_rp', array( $this, 'redirect_to_custom_password_reset' ) );
add_action( 'login_form_resetpass', array( $this, 'redirect_to_custom_password_reset' ) );

Then, create the function:

/**
 * Redirects to the custom password reset page, or the login page
 * if there are errors.
 */
public function redirect_to_custom_password_reset() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        // Verify key / login combo
        $user = check_password_reset_key( $_REQUEST['key'], $_REQUEST['login'] );
        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }

        $redirect_url = home_url( 'member-password-reset' );
        $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url );
        $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url );

        wp_redirect( $redirect_url );
        exit;
    }
}

The function starts by checking that this is a GET request. POST requests sent to this same URL will be handled below. 

Then, on line 8, we call the WordPress function check_password_reset_key to verify that the parameters passed with the password reset link are valid. If there was an error, we redirect the user back to the login page, with the error code as a request parameter (lines 9-16). We’ll add the code for displaying the error soon.

If the parameters were successfully validated and the user is allowed to update his or her password, the function continues by redirecting the user to our custom (still empty) password reset page, member-password-reset

On lines 19-20, we add the parameters key and login to the redirect URL so that they’ll be available for another check when the user tries to set a new password on the next screen. The default version of the WordPress password reset uses a cookie for this, but for the tutorial’s sake, I decided to go with request parameters to keep the code easier to follow.

Next, let’s create a custom version of the password reset form.

Step 2: Show the Password Reset Form

The password reset form shown to the user after clicking on the link received in the email, by default looks like this:

WordPress Reset Password screen

It’s a simple form with two fields, pass1 and pass2, one for entering the password and the other to retype it to check that there were no typos.

To create our custom version of this form, we’ll use a shortcode. 

First, add the following line in the plugin’s constructor:

add_shortcode( 'custom-password-reset-form', array( $this, 'render_password_reset_form' ) );

Then, create the function for rendering the form:

/**
 * A shortcode for rendering the form used to reset a user's password.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_reset_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );

    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        if ( isset( $_REQUEST['login'] ) && isset( $_REQUEST['key'] ) ) {
            $attributes['login'] = $_REQUEST['login'];
            $attributes['key'] = $_REQUEST['key'];

            // Error messages
            $errors = array();
            if ( isset( $_REQUEST['error'] ) ) {
                $error_codes = explode( ',', $_REQUEST['error'] );

                foreach ( $error_codes as $code ) {
                    $errors []= $this->get_error_message( $code );
                }
            }
            $attributes['errors'] = $errors;

            return $this->get_template_html( 'password_reset_form', $attributes );
        } else {
            return __( 'Invalid password reset link.', 'personalize-login' );
        }
    }
}

The core of this function starts on line 17, where we check that the user identification parameters login and key are present. If not, the password reset link isn’t valid, and we just render an error message (line 34).

If the check is OK, the two variables are added to the $attributes array to make them available to the form template (lines 18-19). 

Then, on lines 21-30, we already prepare for errors that can occur when the form is submitted, using the same error passing method from earlier forms in the tutorial.

Finally, on line 32, the function reads the template and returns it to WordPress for rendering. 

Let’s create the template next. In the templates directory, create a new file and name it password_reset_form.php. Add the following content:

<div id="password-reset-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Pick a New Password', 'personalize-login' ); ?></h3>
    <?php endif; ?>

    <form name="resetpassform" id="resetpassform" action="<?php echo site_url( 'wp-login.php?action=resetpass' ); ?>" method="post" autocomplete="off">
        <input type="hidden" id="user_login" name="rp_login" value="<?php echo esc_attr( $attributes['login'] ); ?>" autocomplete="off" />
        <input type="hidden" name="rp_key" value="<?php echo esc_attr( $attributes['key'] ); ?>" />
        
        <?php if ( count( $attributes['errors'] ) > 0 ) : ?>
            <?php foreach ( $attributes['errors'] as $error ) : ?>
                <p>
                    <?php echo $error; ?>
                </p>
            <?php endforeach; ?>
        <?php endif; ?>

        <p>
            <label for="pass1"><?php _e( 'New password', 'personalize-login' ) ?></label>
            <input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" />
        </p>
        <p>
            <label for="pass2"><?php _e( 'Repeat new password', 'personalize-login' ) ?></label>
            <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
        </p>
        
        <p class="description"><?php echo wp_get_password_hint(); ?></p>
        
        <p class="resetpass-submit">
            <input type="submit" name="submit" id="resetpass-button"
                   class="button" value="<?php _e( 'Reset Password', 'personalize-login' ); ?>" />
        </p>
    </form>
</div>

The form begins with an optional title, displayed if the shortcode attribute show_title is set to true (lines 2-4). 

The actual form follows right after the title. Notice that the form will be posted to wp-login.php?action=resetpass (line 6), the same URL used in the link in the password reset email, except that the email link used a short version, rp, instead of resetpass.

At the beginning of the form (lines 7-8), we set up two hidden fields rp_key and rp_login to pass the key and login parameters to the form handler that will use them to validate the password change request.

On lines 10-16, the template will print out errors if there are any. This code is exactly the same as in the previous shortcode template earlier in this tutorial.

The two fields are printed out on lines 18-25, followed by some instructions for choosing a good password and the button for submitting the form.

Here’s what the form should look like now:

Custom Reset Password screen

Step 3: Handle the Reset Password Action

When the user submits the form by clicking on the Reset Password button, its contents are sent to wp-login.php?action=resetpass, the same URL we used above to redirect the user to our custom password reset page. 

Naturally, as we created the form ourselves, we could just as well use a different URL. However, by keeping this default URL and using the login_form_resetpass (and login_form_rp, just to be sure) action to replace the default functionality, we can make sure no one ends up accidentally calling the default version of the password reset.

To do this, once again, add two lines to the constructor:

add_action( 'login_form_rp', array( $this, 'do_password_reset' ) );
add_action( 'login_form_resetpass', array( $this, 'do_password_reset' ) );

Then, create the function:

/**
 * Resets the user's password if the password reset form was submitted.
 */
public function do_password_reset() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $rp_key = $_REQUEST['rp_key'];
        $rp_login = $_REQUEST['rp_login'];

        $user = check_password_reset_key( $rp_key, $rp_login );

        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }

        if ( isset( $_POST['pass1'] ) ) {
            if ( $_POST['pass1'] != $_POST['pass2'] ) {
                // Passwords don't match
                $redirect_url = home_url( 'member-password-reset' );

                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url )
                $redirect_url = add_query_arg( 'error', 'password_reset_mismatch', $redirect_url );

                wp_redirect( $redirect_url );
                exit;
            }

            if ( empty( $_POST['pass1'] ) ) {
                // Password is empty
                $redirect_url = home_url( 'member-password-reset' );

                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
                $redirect_url = add_query_arg( 'error', 'password_reset_empty', $redirect_url );

                wp_redirect( $redirect_url );
                exit;
            }

            // Parameter checks OK, reset password
            reset_password( $user, $_POST['pass1'] );
            wp_redirect( home_url( 'member-login?password=changed' ) );
        } else {
            echo "Invalid request.";
        }

        exit;
    }
}

The function begins by checking the request method, which should be POSTGET requests have already been handled by the redirect function above. 

Then, it collects the key and login parameters from the form data and uses them to verify the password reset link on line 9, using the WordPress function check_password_reset_key (the same function we used already in the redirect function).

On lines 10-18, we again check for possible errors in the password reset key check, redirecting the user to the page for Lost Your Password? page for rendering the errors. 

Then, if the reset key is valid, we can focus on the form. 

First, the function checks that the two passwords match (lines 21-31), and then that they are not empty (lines 33-43). In both cases, the user is redirected back to our password reset page, with the key and login parameters included in the URL to let the user retry the password update.

Finally, if all checks are successful (feel free to add more checks if you like), the function resets the password using the function reset_password (on line 46) and redirects the user to the login page with a parameter password=changed appended to the URL to show a notification. 

The password is now updated successfully, and all that’s left is to show the success notification and to add error messages.

First, let’s add the notification. In the shortcode function render_login_form, add the following check:

// Check if user just updated password
$attributes['password_updated'] = isset( $_REQUEST['password'] ) && $_REQUEST['password'] == 'changed';

Then, add the actual message to the template, login_form.php, right before rendering the form:

<?php if ( $attributes['password_updated'] ) : ?>
    <p class="login-info">
        <?php _e( 'Your password has been changed. You can sign in now.', 'personalize-login' ); ?>
    </p>
<?php endif; ?>

As we already added support for rendering the error messages above, all that’s left is adding the descriptive error messages to our function get_error_message

Add the following lines right before the default branch in the switch...case construct:

// Reset password

case 'expiredkey':
case 'invalidkey':
    return __( 'The password reset link you used is not valid anymore.', 'personalize-login' );

case 'password_reset_mismatch':
    return __( "The two passwords you entered don't match.", 'personalize-login' );
    
case 'password_reset_empty':
    return __( "Sorry, we don't accept empty passwords.", 'personalize-login' );

Conclusion

That’s it! The password reset functionality is ready, and so, we have finished customizing the WordPress login experience from registering a new user to logging in and resetting a lost password.

I hope the series has given you enough tools so that you feel well equipped for further customizations — for example by adding a new step to the password reset flow — and a better understanding on what happens inside wp-login.php.

Now, go and customize some more!

Apple Tightens Security With App Transport Security

The importance of and attention for security on the web has increased substantially over the past few years. During this year’s WWDC, Apple has made it clear that it plans to lead by example by improving security of its operating systems through a new feature, App Transport Security.

Of course, the security of a platform is only as strong as the security of its components and that includes third party applications. In other words, Apple expects developers to adopt App Transport Security in their applications.

In this article, I will explain what App Transport Security entails, how it will affect your applications, and how you can update your applications to stick to Apple’s guidelines and recommendations.

What Is App Transport Security?

App Transport Security, or ATS for short, is a new feature of iOS 9 and OS X El Capitan. While Apple didn’t mention watchOS, we can assume App Transport Security also applies to watchOS 2. App Transport Security aims to improve the security of Apple’s operating systems and any applications running on these operating systems.

Network requests that are made over HTTP transmit data as cleartext. It goes without saying that this poses a significant security risk. Apple stresses that every developer should strive to keep the data of their customers safe and secure, even if that data doesn’t seem important or sensitive.

App Transport Security actively encourages security by imposing a number of security best practices, the most important being the requirement that network requests need to be sent over a secure connection. With App Transport Security enabled, network requests are automatically made over HTTPS instead of HTTP.

There are a number of other requirements to further improve security. For example, App Transport Security requires TLS (Transport Layer Security) 1.2 or higher. While you may be unfamiliar with TLS, I’m sure you’ve heard of SSL (Secure Sockets Layer). TLS is the successor of SSL and is a collection of cryptographic protocols to enforce security over network connections.

Apple recently published a public, prerelease technote about App Transport Security to give developers the opportunity to plan for App Transport Security. The document outlines what App Transport Security expects from your applications and the web services it interacts with.

Exceptions

Wait a second. My application uses a CDN (Content Delivery Network) that I don’t have control over and it doesn’t support HTTPS. Don’t worry. Apple has your back covered. With regards to App Transport Security, an application falls into one of four categories. Let’s go over each category to see how it impacts an application.

HTTPS Only

If your application only interfaces with servers that support HTTPS, then you’re in luck. You’re application won’t have to make any changes. However, note that App Transport Security requires TLS 1.2 and it expects the domain to use ciphers that support forward secrecy. The certificate also needs to meet the requirements imposed by ATS. It’s therefore important to double-check that the servers your application communicates with comply with the requirements of ATS.

Mix & Match

It is possible that your application talks to servers that don’t meet the ATS requirements. In that case, you need to tell the operating system which domains are involved and specify in your application’s Info.plist what requirements aren’t met.

This means that App Transport Security is enforced for every endpoint your application talks to with the exception of the ones specified in your application’s Info.plist. You can configure the exceptions using a number of predefined keys. In the following Info.plist, we define three exceptions.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>api.insecuredomain.com</key>
			<dict>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<false/>
			</dict>
			<key>cdn.somedomain.com</key>
			<dict>
				<key>NSThirdPartyExceptionMinimumTLSVersion</key>
				<string>1.1<string/>
			</dict>
			<key>thatotherdomain.com</key>
			<dict>
				<key>NSIncludesSubdomains</key>
				<true/>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
			</dict>
		</dict>
	</dict>
	...
</dict>
</plist>

api.insecuredomain.com

The first exception we define tells ATS that communication with this subdomain overrides the requirement to use HTTPS. Note that this exception only applies to the subdomain specified in the exception. It’s important to understand that the NSExceptionAllowsInsecureHTTPLoads key doesn’t only relate to the use of HTTPS. The exception specifies that, for that domain, every requirement of App Transport Security is overridden.

cdn.domain.com

It’s possible that your application talks to a server that serves its data over HTTPS, but isn’t using TLS 1.2 or higher. In that case, you define an exception that specifies the minimum TLS version that should be used. This is a better and safer option than completely overriding App Transport Security for that particular domain.

thatotherdomain.com

The NSIncludesSubdomains key tells App Transport Security that the exception applies to every subdomain of the specified domain. The exception further defines that the domain can use ciphers that don’t support forward secrecy (NSExceptionRequiresForwardSecrecy) by expanding the list of accepted ciphers. For more information about forward secrecy, I recommend reading Apple’s technote on the topic.

Opt Out

If you’re building a web browser, then you have a slightly bigger problem. Because you don’t know which web pages your users are going to visit, you cannot possibly tell whether those web pages are served over HTTPS and meet the ATS requirements. In that case, there is no other option but to opt out of App Transport Security altogether.

It’s important that you explicitly opt out of App Transport Security. Remember that App Transport Security is enforced by default. In your application’s Info.plist, you add a dictionary for the key NSAppTransportSecurity. The dictionary should include one key, NSAllowsArbitraryLoads, and its value should be set to YES. This is what your application’s Info.plist file should look like if you opt out of App Transport Security.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	...
</dict>
</plist>

Opt Out With Exceptions

There is a fourth option in which your application opts out of App Transport Security, but defines a number of exceptions. This is useful if your application fetches data from a range of servers you don’t control, but also talks to an API you maintain. In that case, you specify in your application’s Info.plist that arbitrary loads are allowed, but you also define one or more exceptions for which App Transport Security is enabled. This is what the Info.plist could look like.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
		<key>NSExceptionDomains</key>
		<dict>
			<key>api.tutsplus.com</key>
			<dict>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<false/>
			</dict>
		</dict>
	</dict>
	...
</dict>
</plist>

Timing

Apple has emphasized that applications automatically opt in to App Transport Security if they are built against iOS 9 or OS X El Capitan. This means that you won’t have to make any changes to your applications as long as you build them against iOS 8 or OS X Yosemite.

Based on previous releases of iOS and OS X, however, we have learned that Apple requires developers to build their applications against the latest SDK fairly soon after their official release. In other words, even though you won’t have to comply with App Transport Security when iOS 9 and OS X El Capitan are released later this year, it is very likely that Apple will require developers to build against the latest SDK in the first or second quarter of 2016. I therefore recommend that you investigate how App Transport Security will impact your applications sooner rather than later.

Conclusion

I hope this article has made it clear that App Transport Security is not something your applications can adopt some day. It’s similar to Apple’s requirement for 64-bit support not too long ago. Unless your applications only talk to servers over HTTPS that comply with the ATS requirements, you need to invest some time to investigate how App Transport Security will impact your applications. Apple’s technote about App Transport Security can help you with this.

Easy Digital Downloads: Email Settings, Part 2

In my previous article, I discussed the configuration of the first few options which you find inside the tab of Emails Settings. Let’s look at the remaining options of this tab in today’s article. Emails SettingsAs I have discussed earlier, emails…

Understand Overriding in Magento: Models

In this series, we’re exploring overriding features available in the Magento eCommerce system. In the previous article, we discussed how to override core block files using a custom module. Today, I’ll extend it and demonstrate how you can override core model files using an XML-based configuration file.

Why Overriding Models?

In Magento, models play an important role as they implement most of the business logic of the core features. There are times when you need to change the flow or business logic in models to implement your custom features. 

It’s tempting to go ahead and change the core files directly, which seems an easy and straightforward solution. Having said that, it’s a bad practice, as it makes upgrading Magento really difficult. The more core files you modify directly, the more difficult it becomes for you to keep track of your changes and apply them during every version upgrade!

In this tutorial, we’ll make a custom module to understand how model overriding works in Magento. In this custom module, we’ll see how to override a category model class of the core “Catalog” module. Overriding works by setting up certain XML tags as per the conventions of Magento.

I assume that you’re familiar with the basic module creation process in Magento. If not, here’s a good article explaining the basics of custom module creation. Let’s jump right in to the course of this tutorial!

A Glance at the Setup

Here’s the list of files required for the desired setup:

  • app/etc/modules/Envato_All.xml: It’s a file used to enable our custom module.
  • app/code/local/Envato/Catalog/etc/config.xml: It’s a module configuration file in which we’ll set up model class overriding using certain tags as per the Magento conventions.
  • app/code/local/Envato/Catalog/Model/Category.php: It’s a model class of our custom module which will override the base model class.

Creating Files and Folders: Custom Module

First, we need to create a module enabler file. Create a file “app/etc/modules/Envato_All.xml” and paste the following contents in that file. We’ve used Envato as our module namespace and Catalog as our module name. It’ll enable our “Catalog” module by default.

<?xml version="1.0"?>
<config>
  <modules>
    <Envato_Catalog>
      <active>true</active>
      <codePool>local</codePool>
    </Envato_Catalog>
  </modules>
</config>

Next, we need to create a module configuration file. Create “app/code/local/Envato/Catalog/etc/config.xml” and paste the following contents in that file.

<?xml version="1.0"?>
<config>
  <modules>
    <Envato_Catalog>
      <version>1.0</version>
    </Envato_Catalog>
  </modules>
  
  <global>
    <models>
      <catalog>
        <rewrite>
          <category>Envato_Catalog_Model_Category</category>
        </rewrite>
      </catalog>
    </models>
  </global>
</config>

First, we’ve defined a module version number using the <version> tag. After that, the <catalog> and <rewrite> tags are used to inform the Magento overriding system that we’re going to override a “model” of the “Catalog” core module.

Next, the <category> tag is used to define a model identity which will be overridden by the Envato_Catalog_Model_Category class. It’s mapped to a model file “Category.php” under the “Model” directory of the Catalog module. An important thing to notice here is that we’re following a directory structure similar to the core module. Although that’s not strictly necessary, it’s better than using a different directory structure, because it helps to maintain readability.

Finally, the only remaining thing is to define a model class Envato_Catalog_Model_Category. Let’s create a model file “app/code/local/Envato/Catalog/Model/Category.php” and paste the following contents in that file.

<?php
/**
 * Catalog category model
 *
 * @category   Envato
 * @package    Envato_Catalog
 */
class Envato_Catalog_Model_Category extends Mage_Catalog_Model_Category
{
  public function getProductCollection()
  {
    // Include your custom code here!

    $collection = Mage::getResourceModel('catalog/product_collection')
      ->setStoreId($this->getStoreId())
      ->addCategoryFilter($this);

    return $collection;
  }
}

We’ve defined an Envato_Catalog_Model_Category class which extends the core Mage_Catalog_Model_Category model class of the “Catalog” module. Thus, you can override every method of the base class and create new methods if necessary.

In the above example, the getProductCollection method is overridden so it’ll be called instead of the method defined in the core model class! You can modify the model code as per your requirements. 

When you override any methods in models, you should make sure that the data type of the return value of that method matches with the data type of the base class method. Since model methods are called from several core modules, we should make sure that it doesn’t break other features!

Although this is a very basic example, it serves the purpose of overriding the core model, and you can extend it as per your custom requirements.

Conclusion

In this tutorial, we learned how to override core model files in Magento using a custom module. In the next and last part of this overriding series, we’ll see how to override core controller files. Don’t hesitate to leave your comments below!

Product Design Unification Case Study, Part 2: “Burger-Driven” Framework


  

In the first part of the case study about Mail.Ru Group product design unification, I described our first approach — a mobile web framework. Aside from creating a unified visual style and interaction principles for a dozen services, we’ve also transformed our design process from the classic “prototype → design mock-up → HTML → implementation” approach for every screen, to a modern and more efficient framework-based approach.

Product Design Unification Case Study, Part 2:

In this second part I’ll show how we have improved the same technology to embody larger versions of these products and made our “Bootstrap on steroids” more powerful. In the spring of 2012, our business unit acquired 11 content-based projects: Auto, Events Guide, Health, Horoscopes, Kids, Lady, Moto, News, Sports, TV, and Weather. Many of them are very successful in their market niche in Russia; however, they each have their own history, often with outsourced designs that led to inconsistencies.

The post Product Design Unification Case Study, Part 2: “Burger-Driven” Framework appeared first on Smashing Magazine.

How to Debug JavaScript Remotely With Vorlon.js

Recently at //BUILD/ 2015 we announced Vorlon.js—an open source,
extensible, platform-agnostic tool for remotely debugging and testing your
JavaScript. I had the opportunity to create Vorlon.js with the help of some
talented engineers and tech evangelists at Microsoft (the same guys that
brought you Babylon.js).

Vorlon.js is powered by Node.js,
Socket.IO, and late-night coffee. I would like to share with you why we made
it and how to incorporate it into your own testing workflow, as well as sharing some
more details on the art of building a JavaScript library like it.

Vorlonjs logo

Why Vorlon.js?

Vorlon.js helps you
remotely load, inspect, test and debug JavaScript code running on any device
with a web browser. Whether it is a game console, mobile device, or even an IoT-
connected refrigerator, you can remotely connect up to 50 devices and execute
JavaScript in each or all of them. 

The idea here is that dev teams can also
debug together—each person can write code, and the results are visible to all.
We had a simple motto in this project: No native code, no dependency
to a specific browser, only JavaScript, HTML and CSS running on the
devices of your choice.

Vorlon.js itself is a
small web server you can run from your local machine, or install on a server
for your team to access, that serves the Vorlon.js dashboard (your command
center) and communicates with the remote devices. 

Installing the Vorlon.js
client in your web site or app is as easy as adding a single script tag. It’s
also extensible, so devs can write plug-ins that add features to both the
client and the dashboard, such as feature detection, logging, and
exception tracking.

So why the name? There
are actually two reasons. The first one is because I am just crazy about Babylon 5 (the TV show). Based on
this, the second reason is because the Vorlons are one of the wisest
and most ancient races in the universe and thus, they are helpful as diplomats
between younger races. Their helpfulness is what inspired us: for web devs,
it’s still just too hard to write JavaScript that works reliably in the various
devices and browsers. Vorlon.js seeks to make it just a little easier.

You Mentioned
Vorlon.js Has Plug-ins?

Vorlon.js has been
designed so that you can extend the dashboard and client application easily by
writing or installing additional plugins. You can resize or add extra panes to
the dashboard which can communicate bidirectionally with the client
application. There are three plug-ins to begin with:

Console

Logging: The console tab will stream console messages from the client to the
dashboard that you can use for debugging. Anything logged with console.log(), console.warn()
or console.error() will appear in the dashboard. Like the F12 Dev Tool
DOM explorer, you can see the DOM tree, select a node (which will be
highlighted on the device, and update or add new CSS properties).

Interactivity:
You can also interact with the remote webpage by typing code into the input.
Code entered will be evaluated in the context of the page.

Console page

DOM Explorer

The
DOM inspector shows you the DOM of the remote webpage. You can inspect the DOM,
clicking on nodes to highlight them in the host webpage, and if you select
one you can also view and modify its CSS properties.

DOM Explorer page

Modernizr

The
Modernizr tab will show you the supported browser features as reported by Modernizr. You can use this to
determine what features are actually available. This might be particularly
useful on unusual mobile devices, or things like games consoles.

Modernizr tab showing CSS features detection

How Do I Use It?

From your node command
line, just execute this:

$ npm i -g vorlon 
$ vorlon

Now you have a server
running on your localhost on port 1337. To get access to the dashboard, just navigate to https://localhost:1337/dashboard/SESSIONID, where SESSIONID is the
id for the current dashboard session. This can be any string you want.

You have then to add a
single reference in your client project:

<script src="https://localhost:1337/vorlon.js/SESSIONID"></script>

Please note that SESSIONID can be omitted and in this case, it will be
automatically replaced by “default”. 

And that’s it! Now your client will send debug information to your dashboard
seamlessly. Let’s now have a look at an example using a real site. 

Debugging
Babylonjs.com Using Vorlon.js

Let’s use https://www.babylonjs.com/ for our example. First,
I have to launch my server (using node start.js inside the /server folder).
Then, I just have to add this line to my client site:

<script src="https://localhost:1337/vorlon.js"></script> 

Because I am not defining
a SESSIONID, I can just go to https://localhost:1337/dashboard. The
dashboard looks like this:

Vorlonjs dashboard

Sidenote: The browser shown above
is Microsoft Edge (formerly known as Project Spartan), Microsoft’s new
browser for Windows 10. You can also test your web apps for it remotely on your
Mac, iOS, Android, or Windows device @ https://dev.modern.ie/. Or try Vorlon.js too.

Back to it: I can see console messages for instance, which is useful when I
debug Babylon.js on mobile devices (like iOS, Android or Windows Phone). I can click on any node on the DOM Explorer to get info about CSS properties:

DOM Explorer info about CSS properties

 On the client side, the
selected node is highlighted with a red border:

client side showing the selected node highlighted with a red border

Moreover, I can switch to the Modernizr tab to see the capabilities of my specific device:

Modernizr tab showing the capabilities of my specific device

On the left side, you can
see the list of currently connected clients and you can use the Identify a
client
button to display a number on every connected device.

A Little More on
How We Built Vorlon.js

From the very beginning,
we wanted to be sure that Vorlon.js remains as mobile-first and platform-agnostic
as possible. So we decided to use open source tech that worked across the
broader number of environments.

Our dev environment was
Visual Studio Community which you can get for free now. We used the Node.js tools for Visual Studio and
Azure

for the back-end. Our front-end was JavaScript and TypeScript. If you’re not
familiar with TypeScript, you can learn why we’ve built Babylon.js with it in this blog post. Recently Angular 2 has been built with
TypeScript
. But you don’t have to know it to use Vorlon.js.

Here’s a global schema of
how it works:

Vorlonjs architecture diagram

 Here are the parts we built it with:

  • A Node.js server is
    hosting a dashboard page (served using Express) and a service.
  • The
    service is using Socket.IO to
    establish a direct connection with both the dashboard and the various
    devices.
  • Devices
    have to reference a simple Vorlon.js page served by the server. It
    contains all the plugins’ client code which interacts with the client device
    and communicates with the dashboard through the server.
  • Every
    plug-in is split in two parts:
    • the
      client side, used to capture information and to interact with the device
    • the
      dashboard side, used to generate a command panel for the plugin inside
      the dashboard

For instance, the console
plugin works this way:

  • The client
    side generates a hook on top of console.log(), console.warn() or console.error(). This hook is used to send the parameters of these
    functions to the dashboard. It can also receive orders from the dashboard
    side that it will evaluate.
  • The
    dashboard side gathers these parameters and displays them on the dashboard.

The result is simply a
remote console:

Remote console

You can get an even
better understanding of Vorlon.js extensibility, including how to build your own
plug-ins, at the Vorlon.js website.

What’s Next?

Vorlon.js is built on the
idea of extensibility. We encourage you to contribute! And we’re already thinking about how we might integrate Vorlon.js into browser dev tools as well as Web
Audio debugging.

If you want to try it,
you are just one click away: vorlonjs.com. And
the more technical docs are on our GitHub.

More Hands-On With
JavaScript

It might surprise you a bit, but Microsoft
has a bunch of free learning on many open source JavaScript topics, and we’re on
a mission to create a lot more with Microsoft Edge. Check out my own:

Or our team’s learning series:

And some free tools: Visual Studio Community, Azure Trial, and cross-browser testing tools for Mac, Linux, or
Windows.

This article is part of the web dev tech
series from Microsoft. We’re excited to share
Microsoft
Edge
and the new EdgeHTML
rendering engine
with you. Get free virtual machines or test remotely on
your Mac, iOS, Android, or Windows device @
https://dev.modern.ie/.