Hi,

I'm trying to create a gift registry for my commerce website. I managed to create a node type called 'Protected List' which contains a field with references to the products that are in the list. I need a page or block where people can log in to a protected list and view the list. So users have to fill in the name of the list and password (similar to a regular user login) to see the list. Anybody has any directions for me on this. Thanks in advance!

Comments

badjava’s picture

This is more of a "How do I do this.." type of question and should be moved to the Post Installation forum.

One way to do this would be to use Views and Protected Pages module. I have never used the latter module but it appears to do what you want.

Not the exact same flow, but set up a view that searches and displays protected list nodes. Then when you click on them, the URL is password protected with the Protected Pages module.

This should give you a starting point and allow you to figure out a workflow that does what you need.

~Chad

wardoost’s picture

Thanks for the reply Chad.

The problem with this flow is that the names of the protected list should be private. It's for a shop with mainly products for baby's so the protected lists are titled after the baby's name so it's delicate information. They can't be displayed in a public list/view.

I have already been testing and trying out the Protected Pages module which gives me a second problem that I need to be able to set the password manually..

badjava’s picture

It sounds like you will need to create a custom module to try and then use the help of a few contrib modules to do exactly what you want.

You can use:

https://drupal.org/project/password_field

This can be used to add a password field to protected list node.

You may also want to use:

https://drupal.org/project/unique_field

To force a unique title on the node as it sounds like you are using that as a psuedo username.

Then you would need a custom module, I have roughed something out for you but you will need to do some work to fill it in based on your requirements:

<?php
/**
 * Implements hook_menu().
 */
function my_module_menu() {
  $items = array();

  $items['view-list-whatever-path'] = array(
    'title' => 'Page Title',
    'description' => 'A description of what this does',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('my_module_custom_form'),
    'access arguments' => TRUE // insert permission here
  );

  return $items;
}

function my_module_init() {
    // check to see if its a node and what node type, if so check for session
    if ($node = my_module_current_node && $node->type == 'protected_node_type') {
        // now check for session that would have recieved (you could put the node id in there if you like)
        // if $node->nid doesn't match the session node id, redirect them to the path defined in hook_menu above.
    
    }
}

/**
 * Create your form
 */
function my_module_custom_form($form, &$form_state) {

    // create your form

    $form = array();

    $form['name'] = array(
        '#type' => 'textfield',
        '#title' => t('Name'),
        '#description' => t('Enter the name of the list you want to access.'),
        '#size' => 30,
        '#maxlength' => 125,
    );

    $form['pass'] = array(
      '#type' => 'password', 
      '#title' => t('Password'), 
      '#maxlength' => 64, 
      '#size' => 15,
    );
    
    $form['search'] = array(
        '#type' => 'submit',
        '#value' => t('Search'),
    );

    return $form;    
}

/**
 * Validate your form
 */
function my_module_custom_form_validate($form, &$form_state) {

    // lookup node title where node type = protected_list, password = form value, title = form value
    // using $form_state['values']['pass'], $form_state['values']['name'] as values from form
    // returning the node ID
    $nid = db_select....
    
    // if result, set a session variable of the nid and let the submit handler do its thing
    $form_state['redirect'] = 'node/' . $nid;

    // else form_set_error and flag the form fields
}

/**
 * Validate your form
 */
function my_module_custom_form_validate($form, &$form_state) {

    // if session, redirect with $form_state['redirect'] = 'node/' . $nid;

}

/**
 * Checks for the node page, and loads the node
 */
function my_module_current_node() {
  if (preg_match('#^node/([0-9]+)#i', $_GET['q'], $matches)) {
    return node_load($matches[1]);
  }
  return FALSE;
}

I hope that helps.

~Chad

wardoost’s picture

Thanks for your starting point Chad. I'm a total newbie to drupal module development so I'm starting to learn how to code Drupal modules.
Your starting point has already thought me alot so thanks again :) I'll post back when I figured this out.

wardoost’s picture

Hi,
I wrote my first custom module. Here is the code I used for my node_login.module file.

<?php

/**
 * Implements hook_permission
 */
function node_login_permission() {
  return array(
    'node_login user login page' => array(
      'title' => t('Login to protected nodes'),
      'description' => t('Access to the node login page'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function node_login_menu() {
  $items = array();
  $items['node-login'] = array(
    'title' => 'Node login',
    'description' => 'A login form for protected protected lists',
    'type' => MENU_CALLBACK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_login_login_form'),
    'access arguments' => array('node_login user login page'),
    );
  return $items;
}

/**
 * Create your form
 */
function node_login_login_form($form, &$form_state) {
  // create your form
  $form = array();
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#description' => t('Enter the name of the baby'),
    '#size' => 30,
    '#maxlength' => 125,
    '#required' => TRUE,
    );
  $form['date'] = array(
    '#type' => 'date_popup', // Provided by the date_popup module
    '#title' => t('Date of birth'),
    '#date_format' => 'j F Y', // Uses the PHP date() format
    '#date_year_range' => '-5:0', // Limits the year range to the the previous 5 years
    '#required' => TRUE,
    '#default_value' => date('Y-m-d', time()), // Default value of today in 'Y-m-d' format.
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Login'),
    );
  return $form;
}

/**
 * Implements hook_block_info().
 */
function node_login_block_info() {
  $blocks['node_login_form'] = array(
    // The name that will appear in the block list.
    'info' => t('The login form for the node login module'),
    // Default setting.
    'cache' => DRUPAL_CACHE_PER_ROLE,
    );
  return $blocks;
}

/**
 * Implements hook_block_view().
 *
 * Prepares the contents of the block.
 */
function node_login_block_view($delta = '') {
  switch ($delta) {
    case 'node_login_form':
    $block['subject'] = t('Node login');
    $block['content'] = drupal_get_form('node_login_login_form');
    return $block;
  }
}

/**
 * Validate your form
 */
function node_login_login_form_validate($form, &$form_state) {
  $form_name = $form_state['values']['name'];
  $form_date = $form_state['values']['date'];

  // Get logged in usser
  if (!isset($account)) {
    $account = $GLOBALS['user'];
  }

  // Lookup node where node type = protected_list, name = form value, date_birth = form value
  $query = new EntityFieldQuery;
  $result = $query->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'protected_list')
    ->fieldCondition('field_baby_name', 'value', $form_name)
    ->fieldCondition('field_baby_date_of_birth', 'value', $form_date)
    ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT') // bypass nodeaccess check
    ->execute();

  // If result, grant access and redirect to node
  if (!empty($result['node'])) {
    $node = reset($result['node']);
    $nid = $node->nid; // Protected list node ID
    $uid = $account->uid; // Current user ID

    // Add user to access reference list
    $node = node_load($nid);
    if(count($node->field_users_with_access) > 0){
      $field_lang = field_language('node', $node, 'field_users_with_access');
    }
    else{
      $field_lang = 'und';
      $node->field_users_with_access[$field_lang] = array();
    }
    if (!(in_array(array('target_id' => $uid), $node->field_users_with_access[$field_lang]))){
      array_push($node->field_users_with_access[$field_lang], array('target_id' => $uid));
      drupal_set_message(t('You were granted access to '.strtolower($node->title).'.'), 'status');
    }
    node_save($node); // Update changes to database, updates grant permissions

    // Redirect to node
    $form_state['redirect'] = 'giftlist/' . $nid;
  } else {
    form_set_error('Name or date not found', t("Sorry, unrecognized name or date of birth." ));
  }
}

I used the Node access user reference module to grant access to the gift list nodes by adding them to a user reference field. The advantage of this approach is that I can easily see who has accessed the list. I also used a date field instead of a password field. Thanks for the help again :)