? .AppleDouble
? lock.png
Index: premium.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/premium/premium.install,v
retrieving revision 1.2
diff -u -p -r1.2 premium.install
--- premium.install	20 Aug 2007 20:58:23 -0000	1.2
+++ premium.install	20 Dec 2007 22:39:05 -0000
@@ -7,18 +7,68 @@ function premium_install() {
     case 'mysqli':
       db_query("CREATE TABLE {premium} (
         nid               INT NOT NULL,
+        plid              INT NOT NULL,
         start_ts          INT,
         end_ts            INT,
         PRIMARY KEY(nid)
       ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
+      db_query("CREATE TABLE premium_level (
+        plid                  INT NOT NULL,
+        name                  VARCHAR(255),
+        mode                  VARCHAR(10) NOT NULL DEFAULT '0',
+        time_count            INT,
+        time_unit             VARCHAR(1) DEFAULT 'W',
+        denied_message        LONGTEXT,
+        denied_message_format INT NOT NULL DEFAULT 1,
+        PRIMARY KEY(plid)
+      ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
       break;
     case 'pgsql':
-      db_query("CREATE TABLE {premium} (
-        nid               INT NOT NULL,
-        start_ts          INT,
-        end_ts            INT,
-        PRIMARY KEY(nid)
-      )");
       break;
   }
 }
+
+function premium_update_1() {
+  // Create the new table, insert a definition to mirror the existing settings,
+  // and update the existing premium records to point to the new premium level.
+  $ret = array();
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("CREATE TABLE premium_level (
+        plid                  INT NOT NULL,
+        name                  VARCHAR(255),
+        mode                  VARCHAR(10) NOT NULL DEFAULT '0',
+        time_count            INT,
+        time_unit             VARCHAR(1) DEFAULT 'W',
+        denied_message        LONGTEXT,
+        denied_message_format INT NOT NULL DEFAULT 1,
+        PRIMARY KEY(plid)
+      ) /*!40100 DEFAULT CHARACTER SET utf8 */;");
+
+      $plid = db_next_id('{premium_level}_plid');
+      $mode = variable_get('premium_mode', '0');
+      $count = variable_get('premium_time_count', '2');
+      $unit = variable_get('premium_time_unit', 'W');
+      $message = variable_get('premium_message', t('Full text available to members only'));
+
+      $ret[] = update_sql("INSERT INTO {premium_level} 
+          (plid, name, mode, time_count, time_unit, denied_message, denied_message_format)
+          VALUES ($plid, 'Members-only content', '$mode', $count, '$unit', '$message', '1')");
+
+      $ret[] = update_sql("ALTER TABLE {premium} ADD plid INT UNSIGNED NOT NULL");
+      $ret[] = update_sql("UPDATE {premium} SET plid = $plid");
+      
+      variable_del('premium_mode');
+      variable_del('premium_time_count');
+      variable_del('premium_time_unit');
+      variable_del('premium_message');
+      break;
+      
+    case 'pgsql':
+      break;
+
+  }
+  return $ret;
+  
+}
Index: premium.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/premium/premium.module,v
retrieving revision 1.7
diff -u -p -r1.7 premium.module
--- premium.module	21 Aug 2007 19:02:02 -0000	1.7
+++ premium.module	20 Dec 2007 22:39:05 -0000
@@ -5,13 +5,50 @@
 
 function premium_menu($may_cache) {
   $items = array();
+  $access = user_access('administer premium content levels');
+  
   if ($may_cache) {
-    $items[] = array('path' => 'admin/settings/premium',
+    $items[] = array(
+      'path' => 'admin/settings/premium',
       'title' => t('Premium'),
-      'description' => t('Settings for access control to premium content.'),
+      'description' => t('Create levels of premium content and settings for access.'),
+      'callback' => 'premium_overview',
+      'access' => $access,
+      'type' => MENU_NORMAL_ITEM,
+    );
+    $items[] = array(
+      'path' => 'admin/settings/premium/list',
+      'title' => t('List Levels'),
+      'callback' => 'premium_overview',
+      'access' => $access,
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+      'weight' => '-10',  
+    );
+      $items[] = array(
+        'path' => 'admin/settings/premium/edit',
+        'title' => t('Edit Level'),
+        'callback' => 'premium_edit_level',
+        'access' => $access,
+        'type' => MENU_CALLBACK, 
+      );
+    
+    $items[] = array(
+      'path' => 'admin/settings/premium/add',
+      'title' => t('Add Level'),
+      'callback' => 'premium_add_level',
+      'access' => $access,
+      'type' => MENU_LOCAL_TASK, 
+      'weight' => '-1',
+    );
+    $items[] = array(
+      'path' => 'admin/settings/premium/delete',
+      'title' => t('Delete Level'),
       'callback' => 'drupal_get_form',
-      'callback arguments' => 'premium_settings',
-      'access' => user_access('administer site configuration'));
+      'callback arguments' => array('premium_delete_confirm'),
+      'access' => $access,
+      'type' => MENU_CALLBACK,
+      'weight' => '1', 
+    );
   }
   return $items;
 }
@@ -20,7 +57,14 @@ function premium_menu($may_cache) {
  * Implementation of hook_perm()
  */
 function premium_perm() {
-  return array('access premium content');
+  $perms = array();
+  $perms[] = 'administer premium content levels';
+  $perms[] = 'administer node premium status';
+
+  foreach (_premium_level_list() as $l) {
+    $perms[] = _premium_access_perm($l);
+  }
+  return $perms;
 }
 
 /**
@@ -28,7 +72,7 @@ function premium_perm() {
  */
 function premium_cron() {
   $ts = time();
-  db_query("DELETE FROM {premium} WHERE start_ts < $ts AND end_ts != 0 AND end_ts < $ts");
+  db_query('DELETE FROM {premium} WHERE start_ts < %d AND end_ts != 0 AND end_ts < $%d', $ts, $ts);
 }
 
 /**
@@ -47,43 +91,63 @@ function premium_nodeapi(&$node, $op, $t
         if ($op == 'delete') return;
       }
       if ($node->premium) {
-       $start_ts = $end_ts = 0 ;
-        _premium_offset($node, $start_ts, $end_ts);
-        db_query('INSERT INTO {premium} (nid, start_ts, end_ts) 
-          VALUES ( %d, %d, %d )', $node->nid, $start_ts, $end_ts);
+        $start_ts = $end_ts = 0 ;
+        _premium_offset($node, $plid, $start_ts, $end_ts);
+        db_query('INSERT INTO {premium} (nid, plid, start_ts, end_ts) 
+          VALUES ( %d, %d, %d, %d )', $node->nid, $node->premium, $start_ts, $end_ts);
       }
       return;
       
     case 'load':
       $ts = time();
       return array('premium' => (int) db_result(db_query(
-          "SELECT 1 FROM {premium}  WHERE nid = %d 
-          AND ( start_ts = 0 OR start_ts > $ts) AND end_ts < $ts", $node->nid)));
+          'SELECT plid FROM {premium}  WHERE nid = %d 
+          AND ( start_ts = 0 OR start_ts > %d) AND end_ts < %d', $node->nid, $ts, $ts)));
       
     case 'view':
       $node->premium_access = true;
 
       global $user;
-      if (!$node->premium || user_access('access premium content')) {
-        return;                  // not premium content or user has privileges
+      if (!$node->premium) {
+        return;                  // not premium content
+      }
+      $levels = _premium_levels();
+      $level = $levels[$node->premium];
+      if (user_access(_premium_access_perm($level->name))) {
+        return;                 // user has privledges for this premium level
       }
+      
       if ($teaser) {
         return;                  // not viewing the body
       }
       foreach (module_implements('premium_access') as $name) {
-        $function = $name.'_premium_access';
-        if ($function($user, $node)) {
+        $function = $name .'_premium_access';
+        if ($function($user, $node, $level)) {
           return;                // access granted explicitly
         }
       }
   
       $node->premium_access = false;
-      $node->content['body']['#value'] = theme('premium_body', $node);
+      $node->content['body']['#value'] = theme('premium_body', $node, $level);
   }
   return;
 } 
 
 /**
+ * Implementation of hook_link() -- adds a premium icon to the links for a node
+ */
+function premium_link($type, $node = null, $teaser = false) {
+  $links = array();
+
+  if ($type == 'node' && $node->premium && $teaser == true) {
+    $links[] = array('title' => theme('premium_link', $node), 'html' => true, );
+  }
+
+  return $links;
+}
+
+
+/**
  * Implementation of hook_form_alter()
  * 
  * Add the Premium checkbox to the node editing options and default settings
@@ -91,23 +155,29 @@ function premium_nodeapi(&$node, $op, $t
  */
 function premium_form_alter($form_id, &$form) {
   $type = $form['type']['#value'];
-  $title = t('Access restricted for non-premium users');
+  $title = t('Access to full node content');
   switch ($form_id) {
     
     case 'node_type_form':
-      $form['workflow']['node_options']['#options']['premium'] = $title;
-      if (_premium_node($type)) {
-        $form['workflow']['node_options']['#default_value'][] = 'premium';
-      }
+      unset($type);
+      $type = $form['#node_type'];
+      $node_type = $type->type;
+      $form['workflow']["node_{$node_type}_premium"] = array(
+        '#type' => 'select',
+        '#title' => $title,
+        '#default_value' => variable_get("node_{$node_type}_premium_{$node_type}", 0),
+        '#options' => array(0 => t('No restrictions')) + _premium_level_list(), 
+      );
       return;
       
-    case $type.'_node_form':
-      if (user_access('administer nodes')) {
+    case $type .'_node_form':
+      if (user_access('administer node premium status')) {
         $node = $form['#node'];
         $form['options']['premium'] = array(
-          '#type' => 'checkbox', 
+          '#type' => 'select', 
           '#title' => $title, 
-          '#default_value' => _premium_node($node),
+          '#default_value' => settype(_premium_node($node), 'integer'),
+          '#options' => array(0 => t('No restrictions')) + _premium_level_list(),
         );
       }
       return;
@@ -117,14 +187,128 @@ function premium_form_alter($form_id, &$
 /**
  * Settings form
  */
-function premium_settings() {
+function premium_overview() {
+  drupal_set_title(t('Administer premium content settings'));
+  $levels = _premium_levels();
+  
+  $output = "Premium content is content that is restricted to certain users of a web site. To create premium content: ". l('add a level', 'admin/settings/premium/add') .", ". l('set permissions', 'admin/user/access') ." for your users, set a default level for each ". l('content type', 'admin/content/types') .", and create new content as usual.";
+
+  $header[] = array('data' => t('name'), 'colspan' => 1);
+  $header[] = array('data' => t('actions'), 'colspan' => 2);
+
+  foreach ($levels as $level) {
+    $row = array();
+    $row[] = $level->name;
+    $row[] = l(t('edit'), 'admin/settings/premium/edit/'. $level->plid);
+    $row[] = l(t('delete'), 'admin/settings/premium/delete/'. $level->plid);
+    $rows[] = $row;
+  }
+
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No premium content levels been defined.'), 'colspan' => '3'));
+  }
+
+  $output .= theme('table', $header, $rows);
+
+  return $output;
+}
+
+function premium_edit_level($plid = 0) {
+  $levels = _premium_levels();
+  $level = $levels[$plid];
+
+  drupal_set_title(t('Edit') .' "'. $level->name .'" '. t('level'));
+  
+  // Override the form field definition, as we don't want it edited
+  // once it's created.
+//  $form['name'] = array(
+//    '#type' => 'value',
+//    '#value' => $level->name,
+//  );
+  
+  return drupal_get_form('_premium_level_edit_form', $level);
+}
+
+function premium_add_level() {
+  drupal_set_title(t('Add premium content level'));
+  return drupal_get_form('_premium_level_edit_form');
+}
+
+
+function premium_edit_level_submit($form_id, $form_values) {
+// @todo add message updates to edit and add submissions
+  db_query("UPDATE {premium_level} SET name = '%s', mode = '%s', time_count = %d, time_unit = '%s', denied_message = '%s', denied_message_format = %d WHERE plid = %d",
+    $form_values['name'], $form_values['mode'], $form_values['time_count'], $form_values['time_unit'],
+    $form_values['denied_message'], $form_values['denied_message_format'],
+    $form_values['plid']);
+  return 'admin/settings/premium';
+}
+
+function premium_add_level_submit($form_id, $form_values) {
+  db_query("INSERT INTO {premium_level} (plid, name, mode, time_count, time_unit, denied_message, denied_message_format) VALUES(%d, '%s', '%s', %d, '%s', '%s', %d)",
+    db_next_id('{premium_level}_plid'), $form_values['name'], $form_values['mode'], $form_values['time_count'], $form_values['time_unit'],
+    $form_values['denied_message'], $form_values['denied_message_format']);
+  return 'admin/settings/premium';
+}
+
+function premium_delete_confirm($plid = 0) {
+  $levels = _premium_levels();
+  $level = $levels[$plid];
+  
+  $form['plid'] = array('#type' => 'value', '#value' => $plid);
+  return confirm_form($form,
+    t('Are you sure you want to delete %name? All content at this level will be unlocked.', array('%name' => $level->name)),
+    isset($_GET['destination']) ? $_GET['destination'] : 'admin/settings/premium',
+    t('This action cannot be undone.'),
+    t('Delete'), t('Cancel'));
+}
+
+function premium_delete_confirm_submit($form, $form_values) {
+  global $user;
+  if ($form_values['confirm']) {
+    if (user_access('administer premium content levels')) {
+      db_query('DELETE FROM {premium} WHERE plid = %d', $form_values['plid']);
+      db_query('DELETE FROM {premium_level} WHERE plid = %d', $form_values['plid']);
+      drupal_set_message(t('Premium content level deleted.'));
+    }
+    else {
+      drupal_access_denied();
+    }
+  }
+  return 'admin/settings/premium';
+}
+
+
+/**
+ * Builds an add or edit form for an individual premium level.
+ */
+function _premium_level_edit_form($level = null) {
   $form = array();
   
-  // timeframe for premium + update existing nodes
-  $form['premium_mode'] = array(
+  if ($level) {
+    $form['plid'] = array(
+      '#type' => 'value',
+      '#value' => $level->plid,
+    );
+    $form['#base'] = 'premium_edit_level';
+  } 
+  else {
+    $form['#base'] = 'premium_add_level';
+  }
+  
+  $form['name'] = array(
+    '#type'          => 'textfield', 
+    '#title'         => t('Name'), 
+    '#default_value' => $level->name, 
+    '#size'          => 60,
+    '#maxlength'     => 128,
+    '#required'      => true,
+  );
+
+  $form['mode'] = array(
     '#type'          => 'radios', 
     '#title'         => t('Mode'), 
-    '#default_value' => variable_get('premium_mode', '0'), 
+    '#default_value' => $level->mode ? $level->mode : '0', 
     '#options'       => array(
       '0' => t('Premium items are permanently restricted'), 
       'archive' => t('Protect archives only: Items switch to premium status after a specified period'), 
@@ -132,55 +316,98 @@ function premium_settings() {
     ),
   );
   
-  $form['premium_time_count'] = array(
+  $form['time_count'] = array(
     '#type'          => 'select', 
     '#title'         => t('Count'), 
-    '#default_value' => variable_get('premium_time_count', '2'), 
-    '#options'       => array(1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 
-      10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15), 
+    '#default_value' => $level->time_count ? $level->time_count : 2,
+    '#options'       => array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 
+      10 => 10, 11 => 11, 12 => 12, 13 => 13, 14 => 14, 15 => 15), 
   );
   
-  $form['premium_time_unit'] = array(
+  $form['time_unit'] = array(
     '#type'          => 'select', 
     '#title'         => t('Unit'), 
-    '#default_value' => variable_get('premium_time_unit', 'W'), 
+    '#default_value' => $level->time_unit ? $level->time_unit : 'W',
     '#options'       => array('D' => t('Days'), 
-        'W' => t('Weeks'), 
-        'M' => t('Months'), 
-        'Y' => t('Years')), 
+      'W' => t('Weeks'), 
+      'M' => t('Months'), 
+      'Y' => t('Years')), 
+  );
+
+  $form['denied_message_fieldset'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Access denied message'),
+  );
+  $form['denied_message_fieldset']['denied_message'] = array(
+    '#type' => 'textarea',
+    '#default_value' => $level->denied_message ? $level->denied_message : t('Full text available to premium subscribers only'),
+    '#cols' => 60,
+    '#rows' => 6,
+    '#description' => t('When a visitor doesn\'t have access to an item at this level they will see this message instead of its full text'),
   );
+
+  $form['denied_message_fieldset']['denied_message_format'] = filter_form($level->denied_message_format, 1, array('denied_message_format'));
   
-  $form['premium_message'] = array(
-    '#type'          => 'textarea', 
-    '#title'         => t('Premium body text'), 
-    '#default_value' => variable_get('premium_message', t('Full text available to premium subscribers only')), 
-    '#cols'          => 60, 
-    '#rows'          => 30, 
-    '#description'   => t('When a visitor doesn\'t have access to a premium item they will see this message instead of its full text')
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
   );
-  return system_settings_form($form);
+
+  return $form;
+}
+
+
+/**
+ * Get a list of premium levels as an id-keyed array (for selection menus, etc)
+ */
+
+function _premium_level_list() {
+  $levels = array();
+  foreach (_premium_levels() as $plid => $level) {
+    $levels[$plid] = $level->name;
+  }
+  return $levels;
+}
+
+
+/**
+ * Get a list of premium level names keyed by id
+ */
+
+function _premium_levels() {
+  static $levels;
+  if (!is_array($levels)) {
+    $levels = array();
+    $result = db_query('SELECT * FROM {premium_level}');
+    while ($lvl = db_fetch_object($result)) {
+      $levels[$lvl->plid] = $lvl;
+    }
+  }
+  return $levels;
+}
+
+function _premium_access_perm($level_name) {
+  return 'access '. strtolower($level_name);
 }
 
 
 /**
  * Calculate time offset for auto-aging / auto-archiving
  */
-function _premium_offset($node, &$start_ts, &$end_ts) {
-  $c = variable_get('premium_time_count',2);
-  $u = variable_get('premium_time_unit','W');
+function _premium_offset($node, $plid, &$start_ts, &$end_ts) {
+  $levels = _premium_levels();
+  $level = $levels[$plid];
+
+  $c = variable_get('premium_time_count', 2);
+  $u = variable_get('premium_time_unit', 'W');
   $s = $node->created;
   
-  switch ( variable_get('premium_mode', '0') ) {
-    
-    case 'archive' :             // public first, premium after awhile
-      $start_ts = mktime(date('H',$s)+($u=='H')*$c, 0, 0, date('m',$s)+($u=='M')*$c,
-        date('d',$s)+($u=='D')*$c+($u=='W')*$c*7, date('y',$s)+($u=='Y')*$c);
-      return;
-    
-    case 'latest' :             // premium first, ages to general availability
-      $end_ts   = mktime(date('H',$s)+($u=='H')*$c, 0, 0, date('m',$s)+($u=='M')*$c,
-        date('d',$s)+($u=='D')*$c+($u=='W')*$c*7, date('y',$s)+($u=='Y')*$c);
-      return;
+  if ($level) {
+    $c = $level->time_count;
+    $u = $level->time_unit;
+    $s = $node->created;
+
+ 
   }
   return;
 }
@@ -191,19 +418,33 @@ function _premium_offset($node, &$start_
 function _premium_node($node) {
   // This is a node type: use default settings
   if (is_string($node)) {
-    return in_array('premium', variable_get("node_options_{$node}",array()));
+    return in_array('premium', variable_get("node_options_{$node}", array()));
   }
 
   // Already has a value
   if (isset($node->premium)) return $node->premium;
 
-  // Use default settings for this node type
-  return in_array('premium', variable_get("node_options_{$node->type}",array()));
+  // Use default settings for this node type  
+  return variable_get("node_{$node->type}_premium_{$node->type}", 0);
 }
 
 /**
  * Reformat the message body with a premium content message
  */
-function theme_premium_body($node) {
-  return check_markup($node->teaser, $node->format, FALSE) . '<div class="premium-message">'.variable_get('premium_message', t('Full text available to premium subscribers only')).'</div>';
+function theme_premium_body($node, $level) {
+  $message = check_markup($level->denied_message, $level->denied_message_format, false);
+  
+  if ($message) {
+    return $node->teaser .'<br />'. $message;
+  }
+  else {
+    return $node->teaser;
+  }
+}
+
+
+function theme_premium_link($node) {
+  global $base_url;
+  $link = '<img src="'. $base_url .'/'. drupal_get_path('module', 'premium') .'/lock.png" alt="[P]" />';
+  return $link;
 }
