Wednesday, December 11, 2013

Extend old sessions in Drupal

View updated version of the blog here.

In this article I will explain how you can change session cookie lifetime for "old sessions" in Drupal. This kind of requirement may seem too localized, but I had such requirement once in a client project, hence I would like to share this with you.

I will explain you a use case:
You have built a site say cool-website.com for a client. The site is live for more than a year. The session cookie expiry for the site is the default (which is about 23 days). Client now decides to prolong the session expiry time to 1 year, and also wants to extend session expiry for already logged in users to 1 year.

For the first requirement, i.e. "prolong session expiry time to 1 year", there are many ways to do that in Drupal. There are modules like, session_cookie_lifetime or change session.cookie_lifetime value in settings.php.
The main problem you will have with the second requirement. "Old sessions" i.e. the sessions which were created before changing value in settings.php (or using module) will not have session cookie lieftime of 10 years. To extend their lifetime you need to write a custom module.

Suppose, module name is early_session_extend (Early session extend)

early_session_extend.info
name = Early session extend
description = Extend sessions for already logged in users
core = 7.x


early_session_extend.module
<?php

/**
 * @file
 * Extend session for logged in users.
 */

// Constants.
define('EARLY_SESSION_EXTEND_COMPARE_DATE', '12-10-2013'); // mm-dd-yyyy

/**
 * Implements hook_init().
 */
function early_session_extend_init() {
  global $user;
  $sessions_to_be_extended = early_session_extend_get_old_sessions();
  $temp = strptime(EARLY_SESSION_EXTEND_COMPARE_DATE, '%m-%d-%Y');
  $compare_timestamp = mktime(0, 0, 0, $temp['tm_mon'] + 1, $temp['tm_mday'], $temp['tm_year'] + 1900);

  // Do not extend sessions for anonymous users.
  if ($user->uid != 0) {
    $current_session = session_id();

    // If current session falls under old (not extended) sessions.
    if (in_array($current_session, $sessions_to_be_extended)) {
      // Get last accessed time of current session.
      // Since the site is HTTPS, we use ssid.
      $query = db_select('sessions', 's')
                ->fields('s')
                ->condition('ssid', $current_session, '=')
                ->execute();
      $result = $query->fetchAssoc();

      // If device not accessed within compare time then set session cookie
      // lifetime to 10 years.
      if ($result['timestamp'] < $compare_timestamp) {
        setcookie(session_name(), $current_session, $compare_timestamp + 315569520, '/', '.' . $_SERVER['SERVER_NAME']);
      }
    }
  }
}

/**
 * Get old sessions ealier than COMPARE_DATE.
 *
 * @return $output array
 *   Old session ids.
 */
function early_session_extend_get_old_sessions() {
  $temp = strptime(EARLY_SESSION_EXTEND_COMPARE_DATE, '%m-%d-%Y');
  $compare_timestamp = mktime(0, 0, 0, $temp['tm_mon'] + 1, $temp['tm_mday'], $temp['tm_year'] + 1900);
  $output = array();

  // Get all old (not extended) sessions.
  // Since the site is HTTPS, we use ssid.
  $query = db_select('sessions', 's')
            ->fields('s')
            ->condition('timestamp', $compare_timestamp, '<')
            ->execute();

  while ($result = $query->fetchAssoc()) {
    $output[] = $result['ssid'];
  }

  return $output;
}

EARLY_SESSION_EXTEND_COMPARE_DATE is the date which you want to consider as the compare date. All sessions which were last accessed before this date will be extended. You need to decide what date you put. I recommend provide next day's date when you will enable this module (this makes sure that you do not miss any old sessions). And later you will need this date to check whether all old sessions have been extended (you will need this, I will explain you later).
Here, I have extended session to 10 years, you can change it as desired.

You see that I have used hook_init() here, that means for every Drupal request this hook will be executed. Also, you will need this module for a certain time, I mean once when you see all old sessions have been extended you would like to disable this module. Simply using hook_init() will cause extra overhead to your site.

So I have written another code snippet that returns all sessions that are not extended yet.
<?php

/**
 * @file
 * Code snippet to check whether all old (not extended) sessions have been
 * extended.
 */

/**
 * Get all old (not extended) sessions.
 *
 * @return $output array
 *   Array of old session. Empty if no old sessions found.
 */
function early_session_extend_sessions_not_extended() {
  $output = array();
  $sessions_to_be_checked = early_session_extend_get_old_sessions();
  $temp = strptime(EARLY_SESSION_EXTEND_COMPARE_DATE, '%m-%d-%Y');
  $compare_timestamp = mktime(0, 0, 0, $temp['tm_mon'] + 1, $temp['tm_mday'], $temp['tm_year'] + 1900);

  // Get all old (not extended) sessions.
  // Since the site is HTTPS, we use ssid.
  $query = db_select('sessions', 's')
            ->fields('s')
            ->condition('ssid', $sessions_to_be_checked, 'IN')
            ->condition('timestamp', $compare_timestamp, '<')
            ->execute();

  while ($result = $query->fetchAssoc()) {
    $output[] = $result['ssid'];
  }

  return $output;
}

You can write this code snippet anywhere in the module. I prefer to write it in an include file, early_session_extend.admin.inc file. Call this function, if it returns some session ids, that means those sessions are not extended yet (let's disable this module later.. sigh!!!). If it returns no session then it means all old sessions have been extended (Yiiippeee!! all old sessions are extended, let's disable this module!! Mission Accomplished!!)

Friday, August 2, 2013

How to make magnesium sulphate paste

View updated version of this blog here.

Magnesium sulphate(or epsom salt) paste is good for skin. It prevents skin inflammation, and prevents wrinkles. It is easy to make magnesium sulphate paste.

Suppose you want to make 1 table spoon of paste. Take about 1/2 table spoon of water and add to it 1 table spoon of magnesium sulphate(epsom salt). Epsom salt is hydrous, therefore it itself has water in its crystals. Stir well, and make a paste of it. If the crystals are not forming a paste then heat the water for a while and stir at the same time. Stop heating as soon as the crystals gets dissolved in water.

Do not apply the hot paste, allow it to cool and then apply the paste on the affected area. The paste may get too thickened on cooling, you can add some water to it, but be careful do not add too much water, just a little amount of water about 1/2 table spoon would be enough.

Wednesday, July 10, 2013

Create Read Update Delete data table in Drupal

View updated version of this blog here.

This blog post is about how you can create, read, update and delete entries from data table in Drupal. Data table can be used to create custom database tables. This module allows you to create custom database tables and an API for create, read, update and delete(CRUD).

Why you need a data table?

I will explain you my use case. I was working on a project where I had to store college information. This "college information" was huge. I was thinking of creating content types and storing those information as nodes. But a node invokes many hooks. My requirement was to just store these information, which will hardly be changed once in five years. Also I did not needed any node properties like author uid, created time, changed time, etc. So it was mostly static. Therefore, I decided to use data table.

Now you may ask why not create a database table directly in the database instead of using an "extra" module?
The thing is, data table also provides views integration. I mean you can create a view for a data table, instead of writing queries. This module also has a good API. Great module I should say :)

So in brief, you can use data table to store static information for a web site and view the information without writing queries.

CRUD for data table

Create a new data table from admin >> structure >> data tables >> create new table. Add fields to it. You have to create a primary key in that data table, otherwise you will not be able to create a view for that data table.

I have created a data table called college_application as an example. Here is the structure of the data table. Views was not required for this data table, so there is no primary key. Otherwise you have to create a primary key.

Create new entry

$table = data_get_table('college_application');
$save_data = array(

  'student_id' => SOME_DATA,

  'college_id' => SOME_DATA,

  'application' => SOME_DATA,

  'assigner' => SOME_DATA,
);
$table->handler()->save($save_data);

This will create new entry with given data.

Read entry

$table = data_get_table('college_application');
$output = $table->handler()->load(array(
  'student_id' => SOME_DATA,
  'college_id' => SOME_DATA,
));
This will fetch all entries where student_id and college_id is equal to the given data.
Suppose you want to add an OR condition for values in college_id:
$table = data_get_table('college_application');
$output = $table->handler()->load(array(
  'student_id' => SOME_DATA,
  'college_id' => array(SOME_DATA1, SOME_DATA2),
));
This will fetch all rows where college_id is either SOME_DATA1 or SOME_DATA2 and student_id is SOME_DATA

Update entry

$table = data_get_table('college_application');
$update_data = array(
  'student_id' => SOME_DATA,
  'college_id' => SOME_DATA,
  'application' => SOME_DATA,
  'assigner' => SOME_DATA,
);
$table->handler()->update($update_data, array('student_id', 'college_id'));

This will update all entries where student_id and college_id equals to the given data.

Delete entry

$table = data_get_table('college_application');
$delete_data = array(
  'student_id' => SOME_DATA,
  'college_id' => SOME_DATA,
);
$table->handler()->delete($delete_data);

This will delete all entries where student_id and college_id equals to the the given data.

That's all.. I hope everything is clear to you.

Tuesday, April 23, 2013

Import images using Drupal feeds module

View updated version of this blog here.

Importing text content using Drupal feeds module is easy. Importing images using feeds is easy too but it requires a bit work and it is not as straightforward as importing text content.

At first you have to copy image files on your server, you can copy them anywhere inside your website directory, but I prefer copying it to public files directory(sites/default/files).

After you have copied the images, you need to create a CSV importer. Inside that CSV importer we will specify the path of the image. Look at the feed importer:
Feeds importer


Product images is the important thing in this feed importer. Product images is an image field.

Here is the CSV importer:

"SKU";"Title";"Description";"Brief Description";"Taxonomy Terms";"Product Selection";"Product Images"

"IMPORTED-PRODUCT-1";"Imported product display one";"This is an imported product one. This is an imported product one.";"This is an imported product one";"Clothing";"IMPORTED-PRODUCT-1";"http://mysite.local/sites/default/files/_MG_4933-s.jpg"


If you have already uploaded the image to the server then you can import data using the CSV.

This was about importing images using feeds. Suppose, the field accepts multiple images and you want to import multiple images using the importer, then you can use feeds tamper module for this. Look at the feeds tamper configuration for the images field:
Feeds tamper setting

Feeds tamper configuration for images field

You can change the exploding character to anything else, but make sure the character is unique and is not present in the URL of image.

Here is the CSV importer for importing multiple images:

"SKU";"Title";"Description";"Brief Description";"Taxonomy Terms";"Product Selection";"Product Images"

"IMPORTED-PRODUCT-1";"Imported product display one";"This is an imported product one. This is an imported product one.";"This is an imported product one";"Clothing~Jackets";"IMPORTED-PRODUCT-1";"http://mysite.local/sites/default/files/compressed/_MG_4933-s.jpg~http://mysite.local/sites/default/files/compressed/_MG_4934-s.jpg"


I hope everything is clear. Good luck :)

Sunday, March 31, 2013

Display current Git branch in bash prompt

View updated version of this blog here.

While working on a project I maintain multiple branches for development. I keep at least two branches, master (the default one) and develop. I work on develop branch and when I complete certain task I merge the work with master branch and push code to the repository. That's how I work :)

At times I forget on which branch I am working, I have to run:

git branch

to know the current branch. I am a bit lazy and I find running the same command again and again annoying. So I thought why not display the current branch in the command prompt. I did google search and found several results. This post is the result of those multiple search results.

Edit .bashrc file. Run the following command to edit .bashrc file

vim ~/.bashrc

You can replace vim with your favourite editor.

At the end of file enter the following piece of code:

# Append current git branch in prompt

parse_git_branch() {

  if ! git rev-parse --git-dir > /dev/null 2>&1; then

    return 0

  fi



  git_branch=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')



  echo "[$git_branch]"

}

PS1="${debian_chroot:+($debian_chroot)}\[\033[01;36m\]\u@\h\[\033[00m\]:\[\033[01;32m\]\w\[\033[00m\]\[\033[01;31m\]\$(parse_git_branch)\[\033[00m\]$ "

My bash prompt
My bash prompt
Cool.. eh? :)

PS1 is used to change the bash command prompt.

Inside the PS1 variable you can see I have given certain codes like 01;32, 01;31, etc. These are color codes for bash prompt. A list of colors are available here.

References:

Friday, March 15, 2013

How to use vim for Drupal development

View updated version of this blog here.

I am a Linux user, and a drupal developer too. Its been months I am using vim for writing custom drupal modules. Before it was eclipse, eclipse was good but I was having issues because of two reasons. First, I was working on a big project with lots of custom modules and huge database. Loading a module in eclipse editor took several minutes and secondly, my computer is a bit old Intel Core 2 Duo processor and 2GB RAM and . I have always heard being vim as one of the most powerful editors, but I realized it that time when I switched to vim for writing or just reading the code of custom modules.

Like everyone I googled for the vim support for drupal. The web pages that helped me most are these:
Non Linux users can also download and use vim, especially Windows users.

One of the recommended way to install required vim plugins for drupal development is to install them using drush. I had also installed vim plugins in this way. After installing drush, check drush version. Command to check drush version:

drush --version

If drush version is 5.8 then it is okay. Otherwise you need to upgrade drush.

After updating drush, install required vim plugins using the following commands:

drush @none dl vimrc
drush help vimrc-install
drush -v vimrc-install <options>

The first command will dowload the vimrc project. The second commad will show you the options for installing vim plugins.

But I installed it without using any options. I just did this:

drush -v vimrc-install

This will install certain vim plugins that will turn your simple vim to cooool vim. Absolutely ready for writing custom module. But you also need to configure certain vim settings so as to make it more developer friendly. I am providing my vim settings. Beginners can copy the settings, advanced users who knows tweaks and tricks of vim settings can make changes as they desire.


These are default vim settings that are loaded when you open vim. Vim global settings can be done from /usr/share/vim/vimrc while vim local settings can be done from ~/.vimrc. Vim global settings means that the vim settings will be available to all users of your system, while vim local settings are available for the particular logged in user. The file path I have given above are for Ubuntu, so Ubuntu users no worries. Sorry, for non Ubuntu Linux users you have to find it yourself.

Also it is recommended that you set color for your terminal. This will make the code more color distinguishable and easy to understand. Just edit ~/.bashrc and add the following line at the end:

export TERM="xterm-256color"

And do not forget to restart terminal after you have done this.

Now I am going to show you some amazing vim commands (available from plugins you installed earlier of course) that will seriously change your experience of custom module work in Drupal.

NERDTree
NERDTree

TagbarOpen
TagbarOpen

NERDCommeter
Command: NUMBER-OF-LINES/ci

NERDCommenter
Command: NUMBER-OF-LINES/ci

Frequently used shotcuts:
daw - Delete word under cursor
caw - Delete word under cursor and go to insert mode
d$ - Delete from under the cursor till end of line
c$ - Delete from under the cursor till end of line and go to insert mode
START-LINE-NUMBER,END-LINE-NUMBER"+y - Copy lines to system clipboard
gg"+yG - Copy all file content to system clipboard
CtrlXO - Autocomplete

Frequently used commands:
%s/TEXT-TO-SEARCH/TEXT-TO-REPLACE/gc - Interactive find and replace

View documentation of a Drupal function:
Bring the cursor at the start or under the function whose documentation you want to see. Then do:
<Leader>da - To view the documenation in drupal.org OR
<Leader>dc - To view the documentattion in drupalcontrib.org
The most wonderful thing I like about this is, it will automatically identify the core version from the module's info file. Suppose you are working on a 6.x core version module then it will show the documenation of the 6.x version. Cooollll, Right?

More information:
Drupal vimrc installs the following plugins:
pathogen - This plugin helps to manage your other vim plugins
nerdcommenter - This plugins helps you to comment out line of codes
nerdtree - This plugin acts like file explorer in eclipse where you can easily navigate through files in current directory
snipmate - This plugin provides code snippets. Drupal vimrc later adds its own module snippets in it
syntastic - This plugin provides syntax checking. Before writing to any file it will check syntax. Do not write and quit at the same time otherwise it will not be able to show errors, if any
tagbar - This plugin displays a list of functions and variables declared in the file
fugitive - Git wrapper

Other than this I installed another plugin:
SearchParty - This plugin provides color highlighting during text search
colorschemes -  A set of vim colorscheme

Update:
See a collection of vim plugins and settings for Drupal development in Use Vim as IDE for Drupal development, also see them in action.

Saturday, March 9, 2013

Dynamic loading of select list using AJAX

View updated version of this blog here.

Dynamic loading of select lists in drupal can be easily done using Drupal form API. I had to implement  dynamic select lists in several of my projects, I googled for some direct answer but did not find any. The answer was rather split among several sites or blogs. Hence, I am writing this blog so that you can find all the required code in one single place.

I will create a form using form API where there will be two select lists. The value of the second(lets say it as child list) will be dependent on the selected value of first list(lets say it as parent list). The changing of the value of child list will be dynamic and done using AJAX.

/**
 * @file
 * dynamic_select_list.module.
 */

/**
 * Implements hook_menu().
 */
function blogs_dynamic_list_menu() {
  $items = array();

  // Put your menu items here.
  $items['blogs/dynamic-list'] = array(
    'title' => 'Dynamic lists',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('blogs_dynamic_list_render_select_list'),
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

function blogs_dynamic_list_render_select_list($form, &$form_state) {
  $animal_category = array(
    'none' => t('-- None --'),
    'mammal' => t('Mammal'),
    'reptile' => t('Reptile'),
    'aves' => t('Aves'),
    'amphibia' => t('Amphibia'),
  );

  $mammal = array(
    'tiger' => t('Tiger'),
    'cat' => t('Cat'),
    'zebra' => t('Zebra'),
    'panda' => t('Panda'),
    'squirrel' => t('Squirrel'),
  );

  $reptile = array(
    'snake' => t('Snake'),
    'crocodile' => t('Crocodile'),
    'turtle' => t('Turtle'),
    'lizard' => t('Lizard'),
  );

  $aves = array(
    'parrot' => t('Parrot'),
    'eagle' => t('Eagle'),
    'owl' => t('Owl'),
    'peacock' => t('Peacock'),
  );

  $amphibia = array(
    'frog' => t('Frog'),
    'salamander' => t('Salamander'),
  );

  // Check the value of parent select list and populate the value of child
  // select list according to that.
  $default = !empty($form_state['values']['parent_select_list']) ? $form_state['values']['parent_select_list'] : 'none';

  switch ($default) {
    case 'mammal':
      $child_select_options = $mammal;
      break;

    case 'reptile':
      $child_select_options = $reptile;
      break;

    case 'aves':
      $child_select_options = $aves;
      break;

    case 'amphibia':
      $child_select_options = $amphibia;
      break;

    case 'none':
      $child_select_options = array('none' => '-- None --');
      break;
  }

  // Parent select list.
  $form['parent_select_list'] = array(
    '#type' => 'select',
    '#title' => t('Select animal category'),
    '#options' => $animal_category,
    '#default_value' => $animal_category['none'],
    '#description' => t('Select animal class'),
    '#ajax' => array(
      'callback' => 'blog_dynamic_list_select_list_ajax_callback',
      'wrapper' => 'child-select-list-wrapper',
      'event' => 'change',
    ),
  );

  // Child select list.
  $form['child_select_list'] = array(
    '#prefix' => '<div id="child-select-list-wrapper">',
    '#type' => 'select',
    '#title' => t('Select animal'),
    '#options' => $child_select_options,
    '#description' => t('Select animal'),
    '#suffix' => '</div>',
  );

  return $form;
}

/**
 * AJAX callback.
 */
function blog_dynamic_list_select_list_ajax_callback($form, &$form_state) {
  return $form['child_select_list'];
}

The above code will register a menu item where you can view the form. The form has two select lists, the parent list allows to select a class of animals, and the child list will dynamically show the animals that falls under that class.

I am going to give another example, the following example is more manageable than the previous one. Instead of loading the values of select lists from array, we will load the values from taxonomy.

Create a vocabulary called animals and specify the terms like this:



Now we will load the parent taxonomy terms in the parent select list and their respective child terms in the child select list.
/**
 * @file
 * blogs_dynamic_list_terms.module.
 */

/**
 * Implements hook_menu().
 */
function blogs_dynamic_list_terms_menu() {
  $items = array();

  // Put your menu items here.
  $items['blogs/dynamic-list-terms'] = array(
    'title' => 'Dynamic lists terms',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('blogs_dynamic_list_terms_render_select_list'),
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

function blogs_dynamic_list_terms_render_select_list($form, &$form_state) {
  // Load the vocabulary. Instead of 'taxonomy_animals' you have to give the
  // machine name of your vocabulary.
  $vocabulary = taxonomy_vocabulary_machine_name_load('taxonomy_animals');

  // Load all the parent terms of the vocabulary.
  // The second parameter 0 means that we wish to generate the whole tree.
  // The third parameter 1 means that we wish to see only the parent terms.
  // Default is 0.
  $parent_terms = taxonomy_get_tree($vocabulary->vid, 0, 1);

  $animal_category = array('none' => '-- None --');
  // Build the parent select list values.
  foreach ($parent_terms as $parent) {
    $animal_category[$parent->tid] = $parent->name;
  }

  // Check the value of parent select list and populate the value of child
  // select list according to that.
  $default = !empty($form_state['values']['parent_select_list']) ? $form_state['values']['parent_select_list'] : 'none';

  if ($default != 'none') {
    // Load all the child terms of the selected parent item.
    // The second parameter tells to load the tree based on the parent term ID.
    // We are ignoring the third parameter since we know that the vocabulary has
    // only two levels.
    $child_terms = taxonomy_get_tree($vocabulary->vid, $default);
    // Build the child select list values.
    foreach ($child_terms as $child) {
      $child_select_options[$child->tid] = $child->name;
    }
  }
  else {
    // No value selected in parent selct list.
    $child_select_options = array('none' => '-- None --');
  }

  // Parent select list.
  $form['parent_select_list'] = array(
    '#type' => 'select',
    '#title' => t('Select animal category'),
    '#options' => $animal_category,
    '#default_value' => $animal_category['none'],
    '#description' => t('Select animal class'),
    '#ajax' => array(
      'callback' => 'blogs_dynamic_list_terms_select_list_ajax_callback',
      'wrapper' => 'child-select-list-wrapper',
      'event' => 'change',
    ),
  );

  // Child select list.
  $form['child_select_list'] = array(
    '#prefix' => '<div id="child-select-list-wrapper">',
    '#type' => 'select',
    '#title' => t('Select animal'),
    '#options' => $child_select_options,
    '#description' => t('Select animal'),
    '#suffix' => '</div>',
  );

  return $form;
}

/**
 * AJAX callback.
 */
function blogs_dynamic_list_terms_select_list_ajax_callback($form, &$form_state) {
  return $form['child_select_list'];
}

See how much the code has shortened. And also it is more manageable, you can easily add or remove parent and child terms in future.
Also you may like to see AJAX Forms in Drupal 7 for more information

Monday, March 4, 2013

Drupal Features

View updated version of this blog here.

In Drupal you will sometimes need to export your database settings to another Drupal installation. For example, you have created a content type and you want to create that same content type in another Drupal installation with few clicks. Without going over the process of creating the content type and adding fields again, you can use features module.

How a feature works?
Features lets you to add components in it, a feature component can be anything, it can be a content type, CCK fields, views, etc. After adding components features module will create a custom module on the fly. On enabling that module on another Drupal installation it will create the components that you had added in the feature. In brief, a feature contains the database settings within code i.e. a custom module.

How to manage a feature?
You have created a feature and it has a component say, a view. Now you have made some changes in that view and you want that the changes should also be reflected in the feature. In this case, you have to update that feature. On updating a feature, any later database changes of the component gets into the feature code.

Suppose you have made some wrong changes in the view and messed up everything. Now you want that view's earlier settings, in this case you have to revert the feature component(in this case a view). On reverting a feature you mean that you want that the component should follow the settings as described in the feature code, this overrides any new database settings for the component.

Suppose you are adding a new component to the feature, say another view. In this case reverting or updating a feature will not do, since the component is not yet a part of the feature. You have to re-create the feature and add the new component manually.

Possible status of a feature
A feature status can be seen beside the name of the feature in the feature's admin page. So far I have seen five status that a feature can have:

  • Disabled - the feature is disabled
  • Default - it means that the settings described in the feature code and the feature component's database settings are same
  • Overridden - it means that the settings described in the feature code and the feature component's database settings are not same
  • Needs review - it means that you have added some new components in a feature that are not yet reviewed
  • Conflict - it means that duplicate components are added in more than one feature
Possible scenarios of feature status
You have created a content type and added that content type as a component in feature. You have not enabled that feature. In this case the feature status will be disabled.
Now you have enabled that feature, the feature status will be default.
Suppose you have changed the widget of a field that was in the content type. The feature status will be overridden, because the settings described in code does not match the database settings. In this case you either have to update your feature i.e. bring the database settings in the feature code, or revert your feature i.e. change the field widget as it was before.

You have added a new field to the content type, and have re-created the feature. You have copied the feature module to another Drupal instance which has that feature already enabled(content type created using feature but without that new field), in that Drupal instance the feature status will be needs review. On marking the components as mark as reviewed you mean that you are allowing the new components.

Suppose you have created another feature and has added a component say a field that is already added in some another feature. The status of both feature will be conflict with the feature name with which the feature conflicts. In this case you have to remove the component from either one of the feature.

Some things you cannot do using feature
Remember that you can only export your Drupal database settings using a feature, you cannot export a node or taxonomy terms using feature. There are other modules in Drupal that serves this purpose. Node export can be used for node export/import, taxonomy CSV import/export for taxonomy terms import/export.

You cannot delete a database setting using feature. Suppose you have created a feature with content type as a component, the feature has four fields. You copied the feature module in another Drupal instance and enabled it there. Now you do not want one of the fields and you delete it from the content type. Although the code for creating the field in the feature will be deleted(after updating the feature ofcourse), but since you have already the feature enabled in another Drupal instance, the unwanted field will not be deleted there. You have to manually delete it.

Integration with drush
One of the most exciting that I like about feature is that it is integrated with drush. That means you can easily create or manage a feature from command line. Some drush command that I frequently use for managing features are:

drush fu FEATURE_NAME
update feature

drush fr FEATURE_NAME
revert feature