Show a Drupal node exactly one time

I had the requirement of showing a Drupal node only one time to an anonymous user. Anonymous users are given the right to create a cck node. After creation they get the chance to print it or email it to someone. Afterwards the node must be kept private. Only privileged users are given the right to view/change it.


In order to accomplish this task I used the modules cck and simple_access. This post isn't about cck. I just used it to create a new node type. simple_access is used to restrict the access to the nodes. I created two roles and put them into two simple_access groups.


Now I had to do some coding.
First I created a small table which holds the view counter per node:

CREATE TABLE IF NOT EXISTS `node_view_count` (
  `nid` int(10) NOT NULL,
  `view_count` int(11) NOT NULL,
  `rights_set` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`nid`)
);

 

Then I started counting the number of times the node is vied in hook_nodeapi():

<?
function zuweisung_nodeapi(&$node, $op, $a3 = NULL, $a4  = NULL) {
  if ($op=='view&& $node->type=='zuweisung') {
    $result = db_result(db_query("SELECT view_count FROM {node_view_count} WHERE nid=%d", $node->nid));
    if ($result==1) {
      db_query("UPDATE {node_view_count} SET view_count=%d WHERE nid=%d", $result+1, $node->nid);
    }
    elseif ($result===FALSE) {
      db_query("INSERT INTO {node_view_count} (nid, view_count) VALUES (%d, 1)", $node->nid);
    }
  }
}

No I had to make sure, the access control checks are done in the right way, by implementing hook_menu_alter() and redirecting the access control checks to zuweisung_menu_alter():

<?
  function zuweisung_menu_alter(&$items) {
    $items['node/%node']['access callback'] = 'zuweisung_node_access';
  }
  
  function zuweisung_node_access($op, $node, $account = NULL) {
    if ($op=='view') {
      $result = db_result(db_query("SELECT view_count FROM {node_view_count} WHERE nid=%d AND rights_set=%d", $node->nid, 0));
      if ($result==1) {
        // restrict access, the book keeping in node_view_count is done in zuweisung_nodeapi()
          $conf = array('sa_owner_permissions=>
            array(
              'sa_view=> 'sa_view',
              'sa_update=> 'sa_update',
              'sa_delete=> 'sa_delete',
            ),
          );
          simple_access_owner_revoke($node, $conf);
          // gid 4 = gad group
          // gid 5 = intake group
          $conf = array('sa_group_permissions=>
            array(
              4 => array(
                'sa_view=> '1',
                'sa_update=> '0',
                'sa_delete=> '0',
              ),
              5 => array(
                'sa_view=> '1',
                'sa_update=> '1',
                'sa_delete=> '1',
              ),
            ),
          );
          simple_access_group_grant($node, $conf);
          db_query("UPDATE {node_view_count} SET rights_set=%d WHERE nid=%d", 1, $node->nid);
          node_save($node);
          drupal_set_message(t('Restricted access to gad and intake users.'));
          watchdog('zuweisung', t('Restricted access to gad and intake users.'), array($node->nid, $node->title));
      }
    }
    return node_access($op, $node, $account);
  }

That's it.
It took quite some time figure everything out. Hopefully it helps some people to do similar things in less time!