Index: audio.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/audio/audio.module,v
retrieving revision 1.44
diff -u -r1.44 audio.module
--- audio.module	5 Apr 2006 08:38:38 -0000	1.44
+++ audio.module	5 Apr 2006 08:38:49 -0000
@@ -480,6 +480,13 @@
     $node->audio_fileinfo = $_POST['edit']['audio_fileinfo'] = $info['fileinfo'];
     $node->audio_tags = $_POST['edit']['audio_tags'] = $info['tags'];
 
+   /* NOTE: In Drupal 4.7, there are many cases in which the value of $node->audio_file->filemime -- which is returned by file_save_upload() --
+     *       is different from the value of $node->audio_fileinfo[mimetype] -- which is returned by mime_content_type(). 
+     *       In Drupal 4.6, file_save_upload also used mime_content_type().  Unfortunately, the way Drupal 4.7 currently retrieves filemime 
+     *       tends to return a lot of mime types unknown/unknown.  That's why I decided to use the old approach in the code below.
+     */
+    $node->audio_file->filemime = $node->audio_fileinfo['mimetype'];
+
     $_SESSION['audio_file'] = $node->audio_file;
   }
   else if (!empty($_SESSION['audio_file'])) {
@@ -1201,6 +1208,318 @@
   return $node;
 }
 
+/** 
+ * This is a single function that can be called from other modules
+ * to create an audio node. This doesnt 'attach' an audio node to 
+ * anything (yet), but is just a convenient way to have an external 
+ * piece of code create an audio node.
+ *
+ * Just pass in two associative arrays containing the following
+ * fields.
+ *
+ * node_params = array('title_format' => a t()formatting string for generating the node's title. you can use any
+ *                                       value in the node's audio_tags array as variable. if nothing is provided
+ *                                       the default title format will be used.
+ *                     'body' => 'The body goes here',
+ *                     'publish' => 1 // use 1 to publish the node, 0 to not publish,
+ *                     'promote' => 1, // use 1 to promote new node to front page
+ *                     'sticky' => 1, // use 1 to make new node stick in front of the list.  Use 0 otherwise.
+ *                     'revision' => 1 // use 1 to create a new version of the node.  Use 0 otherwise.
+ *                     'uid' => uid // uid of the author.  Optional parameter
+ *                     'name' => user name // user name of the author. Optional parameter
+ *                     'og_public' => whether the node is to be accessible for all. Optional.
+ *                     'og_groups' => og groups this entry is to be accessible to
+ *                     'tags' => an optional array of metadata to be added to the node.  These will be available 
+ *                               to the $title_format
+ *                )
+ *                 
+ * file_params = array('filepath' => 'the/temp/filepath/',
+ *                     'filename' => 'a filename',
+ *                     'filemime' => 'mime/type', // TODO: remove this parameter
+ *                     'downloadable' => '1' //this is either 0 or 1
+ *                )
+ *
+ * return object with the following values:
+ *   In case of success: ->nid points to the id of the new node created
+ *   In case of failure: ->nid is 0 and ->error_msg contains a description of the error.
+*/
+function audio_api_create_item($file_params, $node_params) {
+
+  global $user;
+  
+  $user_author = NULL;
+
+  $rc = new stdClass();
+  $rc->error_msg = '';
+
+  // some quick error checks...
+  if (!is_array($file_params) || !is_array($node_params)) {
+    $rc->nid = 0;
+    $rc->error_msg = t('Invalid parameter.');
+    return $rc;
+  }
+  
+  // check if the specified user is allowed to create audio nodes
+  if ($node_params['uid']) {
+  	
+  	// check if the specified user is valid
+    $user_author = user_load(array('uid' => $node_params['uid'], 'status' => 1));
+  
+    if (!$user_author) {
+      $rc->nid = 0;
+      $rc->error_msg = t('Invalid user id parameter: %uid', array('%uid' => theme('placeholder', $node_params['uid'])));
+      return $rc;
+    }
+  	
+  	// return an error if the specified user does not have permissions to create an audio node
+  	// and the global user is not the superuser
+  	$user_tmp = $user;
+  	$user = $user_author;
+  	if (!audio_access('create') && $user_tmp->uid != 1) {
+      $user = $user_tmp;
+      $rc->nid = 0;
+      $rc->error_msg = t('Specified user (%uid) not allowed to create audio node.', array('%uid' => theme('placeholder', $node_params['uid'])));
+  	  return $rc;
+  	}
+  	$user = $user_tmp;
+  }
+  // in case no user passed as parameter, make sure the global user has permissions to create the audio node
+  else if (!audio_access('create')) {
+    $rc->nid = 0;
+    $rc->error_msg = t('Current user (%uid) not allowed to create audio node.', array('%uid' => theme('placeholder', $user->uid)));
+  	return $rc;
+  }    
+
+  // start building an audio node
+  $node = new stdClass();
+  $node->type = 'audio';
+  $node->uid = isset($node_params['uid']) ? $node_params['uid'] : $user->uid;
+  $node->name = isset($node_params['name'])? $node_params['name'] : $user->name;
+
+  // set the appropriate node options
+  $node_options = variable_get('node_options_'. $node->type, array('publish' => 1, 'status' => 1, 'promote', 'sticky', 'revision'));
+  $node->publish = isset($node_params['publish']) ? $node_params['publish'] : in_array('publish', $node_options);
+  $node->status = isset($node_params['status']) ? $node_params['status'] : in_array('status', $node_options);
+  $node->promote = isset($node_params['promote']) ? $node_params['promote'] : in_array('promote', $node_options);
+  $node->sticky = isset($node_params['sticky']) ? $node_params['sticky'] : in_array('sticky', $node_options);
+  $node->revision = isset($node_params['revision']) ? $node_params['revision'] : in_array('revision', $node_options);
+  $node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
+  
+  // associate node with the specified groups
+  $node->og_public = isset($node_params['og_public'])? $node_params['og_public'] : TRUE;  // nodes are public by default
+  $node->og_groups = isset($node_params['og_groups'])? $node_params['og_groups'] : array();
+  
+  // make the proper path
+  $file_params['filepath'] = realpath($file_params['filepath']);
+  
+  // load in the id3 tags...
+  $info = audio_read_id3tags($file_params['filepath']);
+  if ($info) {
+    $node->audio_fileinfo = $info['fileinfo'];
+    $node->audio_tags = array_merge($info['tags'], $node_params['tags']);
+  } else {
+    watchdog('content', t('Error reading ID3 tags when adding audio file %filepath.', array('%filepath' => theme('placeholder', $file_params['filepath']))), WATCHDOG_ERROR);
+    $rc->nid = 0;
+    $rc->error_msg = t('Error reading ID3 tags when adding audio file %filepath.', array('%filepath' => $file_params['filepath']));
+    return $rc;
+  }
+
+  // make sure the node has a title and title_format.
+  $node->title_format = isset($node_params['title_format'])?$node_params['title_format']:'Audio entry';
+  $node = audio_set_title($node);
+  
+  // assign the body 
+  $node->body  = $node_params['body']; //TODO: replace by $body_format (similar to the above)
+ 
+  // build the file object
+  $node->audio_file = new stdClass();
+  $node->audio_file->filename = basename($file_params['filename']);
+  $node->audio_file->filepath = $file_params['filepath'];
+  if (function_exists('mime_content_type')) {
+    $node->audio_file->filemime = mime_content_type($file_params['filepath']);
+  } else {
+    // TODO: this may be a bad guess...
+    $node->audio_file->filemime = 'audio/mpeg';
+  }
+  $node->audio_file->filesize = filesize($file_params['filepath']);
+
+  // make sure the node to be created is valid and that the user is subscribed to the intended node og audiences
+  node_validate($node);
+  if ($errors = form_get_errors()) {
+    $rc->nid = 0;
+    $rc->error_msg = implode("\n", $errors);
+ 
+    return $rc;
+  }
+
+  // save the node (and call the audio_insert(&node) hook)
+  @node_save($node);
+
+  if ($node->nid) {
+    // return the id of the new node
+    $rc->nid = $node->nid;
+    return $rc;
+  } 
+
+  // error saving new node
+  $rc->nid = 0;
+  $rc->error_msg = t('Error saving audio node');
+  return $rc;
+}
+
+/*
+ * single function to delete a specified audio node
+ * 
+ * @param $nid
+ *   The node id of the audio entry to be deleted
+ *
+ * @return
+ *   object with 'result' equals 1 in case of success.  In case of failure, 'result' will be set to -1 and 'error_msg' will contain a description of the error.
+ */
+function audio_api_delete($nid = false){
+  global $user;
+  
+  $rc = new stdClass();
+  $rc->result = 1;
+  
+  if (!$nid) 
+    return $rc;
+    
+  $node = node_load(array('nid' => $nid));
+
+  // check if the user has permission to delete the specified node
+  if ($node) {
+    if (!node_access('delete', $node)) {
+      $rc->result = -1;   // user does not have permission to delete entry
+      $rc->error_msg = 'User does not have permission to delete specified audio entry.';
+    }
+    else {
+      node_delete($nid);
+    }
+  }
+  
+  return $rc;
+    
+}
+
+/*
+ * returns list with audio nodes that match specified criteria
+ *
+ * @param $query_info
+ *   array with the query criteria for the audio entries:
+ *     ['status'] :: 1 = published, 0 = unpublished, NULL = any
+ *     ['uid'] :: user id of the desired entries author, or NULL for any
+ *     ['name'] :: username of the desired entries author, or NULL for any. Note that this option
+ *       cannot not be used in conjunction with the 'uid' one.
+ *     ['categories_or'] :: array with category ids to be ORed; or NULL for all
+ *     ['categories_and'] :: array with category ids to be ANDed; or NULL for all
+ *     ['unread_entries_only'] :: TRUE, return only the entries that haven't been read by the user
+ *     ['read_entries_only'] :: TRUE, return only the entries that have already been read by the user.
+ *       Note that this option cannot be used in conjunction with 'unread_entries_only'
+ *     ['date_from'] :: time stamp of the oldest entry desired.  If NULL, return entries up to 30 days old.
+ *     ['date_to'] :: time stamp of the newest entry desired.  If NULL, assume no time limit.
+ *
+ * @return
+ *   array with the audio nodes that obey the specified criteria. Note that audio nodes
+ *   that haven't been read by the user will have an extra element ['unread'] set to TRUE.
+ */
+function audio_api_get_node_list($query_info) {
+
+  global $user;
+
+  //
+  // Prepare the arguments for the query
+  //
+
+  $query_status = (!$query_info['status']) ? '' : 'AND n.status=' . $query_info['status'];
+
+  $query_user = (!$query_info['uid']) ? '': 'AND n.uid=' . $query_info['uid'];
+
+  if (empty($query_user)) {
+    $join_name = (!$query_info['name']) ? '': ' INNER JOIN {users} u ON n.uid=u.uid ';
+    $query_name = (!$query_info['name']) ? '': "AND u.name='" . $query_info['name'] . "'";
+  }
+  else {
+    $join_name = '';
+    $query_name = '';
+  }
+
+  $tids_or_tmp = $query_info['categories_or'];
+  $query_tids_or = '';
+  if (!empty($tids_or_tmp) && !in_array(NULL, $tids_or_tmp)) { // make sure none of the array elements is NULL
+    $query_tids_or = 'AND ( t.tid=' . implode(' OR t.tid=', $tids_or_tmp);
+    $query_tids_or .= ')';
+  }
+
+  $tids_and_tmp = $query_info['categories_and'];
+  $query_tids_and = '';
+  if (!empty($tids_and_tmp) && !in_array(NULL, $tids_and_tmp)) { // make sure none of the array elements is NULL
+    $query_tids_and = 'AND ( t.tid=' . implode(' AND t.tid=', $tids_and_tmp);
+    $query_tids_and .= ')';
+  }
+
+  $join_categories = '';
+  if (!empty($query_tids_or) || !empty($query_tids_and)) { // if at least a category is being queried...
+    $join_categories = ' INNER JOIN {term_node} t ON n.nid=t.nid ';
+  }
+
+  $date_from = (!$query_info['date_from']) ? (time()-30*24*3600) : $query_info['date_from'];
+  $query_date_from = "AND n.changed >= $date_from";
+
+  $date_to = (!$query_info['date_to']) ? '' : $query_info['date_to'];
+  $query_date_to = ($date_to) ? "AND n.changed <= $date_to" : '';
+
+  //
+  // Do the query
+  //
+
+  $query = "SELECT DISTINCT n.nid FROM {node} n $join_name $join_categories "
+            . " WHERE n.type='audio' "
+            . " $query_status $query_user $query_name $query_tids_or $query_tids_and $query_date_from $query_date_to"
+            . " ORDER BY n.sticky DESC, n.changed DESC";
+  $query = db_rewrite_sql($query);
+
+  $result = db_query($query);
+
+  $unread_entries_only = (isset($query_info['unread_entries_only'])) ? $query_info['unread_entries_only'] : FALSE;
+
+  $read_entries_only = FALSE;
+  if (!$unread_entries_only) {
+    $read_entries_only = (isset($query_info['read_entries_only'])) ? $query_info['read_entries_only'] : FALSE;
+  }
+
+
+  while ($node = db_fetch_object($result)) {
+    $node_tmp = node_load(array('nid' => $node->nid));
+
+    // if user has permission to view the entry...
+    if (node_access('view', $node_tmp)) {
+
+      // check if the user has already read the entry
+      $mark = node_mark($node_tmp->nid, $node_tmp->changed);
+
+      // if node not already read...
+      if ($mark != MARK_READ) {
+        if ($read_entries_only == FALSE) {
+          $node_tmp->unread = TRUE;
+          $audio_nodes[] = $node_tmp;
+        }
+      }
+      // if node already read...
+      else {
+        if ($unread_entries_only == FALSE) {
+          $node_tmp->unread = FALSE;
+          $audio_nodes[] = $node_tmp;
+        }
+      }
+    }
+    else {
+    }
+  }
+
+  return $audio_nodes;
+}
+
 /**
  * Build a getID3 object.
  * @param $path directory with the getid3.php file, includes trailing slash.

