? file_upload.patch
Index: node_example/node_example.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/examples/node_example/node_example.install,v
retrieving revision 1.1.2.1
diff -u -5 -p -r1.1.2.1 node_example.install
--- node_example/node_example.install	14 Oct 2009 23:51:34 -0000	1.1.2.1
+++ node_example/node_example.install	25 Aug 2010 11:07:08 -0000
@@ -26,10 +26,11 @@ function node_example_uninstall() {
 function node_example_schema() {
   $schema['node_example'] = array(
     'fields' => array(
       'vid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
       'nid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+      'fid'      => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
       'color'    => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
       'quantity' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
     ),
     'primary key' => array('vid', 'nid'),
   );
Index: node_example/node_example.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/examples/node_example/node_example.module,v
retrieving revision 1.1.2.7
diff -u -5 -p -r1.1.2.7 node_example.module
--- node_example/node_example.module	19 Jul 2010 15:53:20 -0000	1.1.2.7
+++ node_example/node_example.module	25 Aug 2010 11:07:09 -0000
@@ -16,10 +16,11 @@
  * Database definition:
  * @code
  *   CREATE TABLE node_example (
  *     vid int(10) unsigned NOT NULL default '0',
  *     nid int(10) unsigned NOT NULL default '0',
+ *     fid int(10) unsigned NOT NULL default '0',
  *     color varchar(255) NOT NULL default '',
  *     quantity int(10) unsigned NOT NULL default '0',
  *     PRIMARY KEY (vid, nid),
  *     KEY `node_example_nid` (nid)
  *   )
@@ -48,14 +49,20 @@
  * - "has_body": boolean that indicates whether or not this node type has a
  *   body field.
  * - "body_label": the label for the body field of this content type.
  * - "min_word_count": the minimum number of words for the body field to be
  *   considered valid for this content type.
+ *
+ * The key in this example "node_type", needs to be unique for a Drupal site.
+ * This value is used as the node's type (it's machine name), and is stored
+ * in {node}.type. The node's type value cannot be changed through the admin
+ * section for nodes and can be useful to distinguish nodes apart. 
+ * 
  */
 function node_example_node_info() {
   return array(
-    'node_example' => array(
+    'node_type' => array(
       'name' => t('Example node'),
       'module' => 'node_example',
       'description' => t("This is an example node type with a few fields."),
       'has_title' => TRUE,
       'title_label' => t('Example Title'),
@@ -149,10 +156,33 @@ function node_example_form(&$node, $form
     '#default_value' => isset($node->quantity) ? $node->quantity : 0,
     '#size' => 10,
     '#maxlength' => 10
   );
 
+  // Allow file upload.
+  $form['#attributes'] = array('enctype' => "multipart/form-data");
+  // We create a fieldset for the file upload since we need more than one
+  // field.
+  $form['file'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('File'),
+  );
+  $form['file']['file_upload'] = array(
+  	'#type' => 'file',
+  	'#title' => t('File upload'),
+  	'#description' => t('Allowed extensions: txt, csv')
+  );
+  // We check to see if a value for file_upload is set, so users can only
+  // delete files that's actually there
+  if (isset($node->fid) && !empty($node->fid)) {
+    $form['file']['file_delete'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Delete file'),
+      '#description' => t('Check this, if you want to delete the current file'),
+    );
+  }
+
   return $form;
 }
 
 /**
  * Implementation of hook_validate().
@@ -161,41 +191,88 @@ function node_example_form(&$node, $form
  * us ensure that the user entered an appropriate value before we try
  * inserting anything into the database.
  *
  * Errors should be signaled with form_set_error().
  */
-function node_example_validate($node, &$form) {
+function node_example_validate(&$node, &$form) {
   if ($node->quantity) {
     if (!is_numeric($node->quantity)) {
       form_set_error('quantity', t('The quantity must be a number.'));
     }
   }
+
+  // Validation for the file:
+  // First we save the uploaded file to the temporary dir while doing some
+  // validation. The first param used is the form name, the second is the
+  // validation we want. Here we only allow txt and csv files. The last param
+  // we pass the dir to save the file, we use Drupal to get the for from the
+  // file-system settings.
+  $file = file_save_upload('file_upload', array(
+    'file_validate_extensions' => array('txt csv'),
+  ), file_directory_path());
+ 
+  if ($file || $node->file_delete) {
+    // Delete the old file, if it's set to be deleted, or a new one is uploaded.
+    // Load file object from database.
+    $old_file = db_fetch_object(db_query('SELECT * FROM {files} WHERE fid = %d', $node->file_upload));
+    // Remove the file.
+    if (file_exists($old_file->filepath)) {
+      file_delete($old_file->filepath);
+    }
+    // And remove it from the files table.
+    db_query('DELETE FROM {files} WHERE fid = %d', $fid);
+
+    if ($file) {
+      // Now get ready to do what's needed to save the file.
+      // Mark the file for permanent storage.
+      file_set_status($file, FILE_STATUS_PERMANENT);
+      // Update the files table.
+      drupal_write_record('files', $file, 'fid');
+      // Save the file id to save it later. In Drupal 6 there is a bug in the API
+      // that makes this impossible to do with the API see: http://drupal.org/node/241364
+      // Instead we save the file id in the user's session.
+    }
+  }
 }
 
 /**
  * Implementation of hook_insert().
  *
  * As a new node is being inserted into the database, we need to do our own
  * database inserts.
  */
 function node_example_insert($node) {
-  db_query("INSERT INTO {node_example} (vid, nid, color, quantity) VALUES (%d, %d, '%s', %d)", $node->vid, $node->nid, $node->color, $node->quantity);
+  $fid = isset($_SESSION['node_example_fid']) ? $_SESSION['node_example_fid'] : 0;
+  // Unset the variable so it doesn't give trouble later.
+  unset($_SESSION['node_example_fid']);
+  db_query("INSERT INTO {node_example} (vid, nid, color, quantity, fid) VALUES (%d, %d, '%s', %d, %d)", $node->vid, $node->nid, $node->color, $node->quantity, $fid);
 }
 
 /**
  * Implementation of hook_update().
  *
  * As an existing node is being updated in the database, we need to do our own
  * database updates.
  */
 function node_example_update($node) {
+  $fid = isset($_SESSION['node_example_fid']) ? $_SESSION['node_example_fid'] : 0;
+  unset($_SESSION['node_example_fid']);
+  // If delete is set, set fid to 0.
+  if ($node->file_delete) {
+    $node->fid = 0;
+  }
+  // If there is a new file uploaded, save this.
+  if (!empty($fid)) {
+    $node->fid = $fid;
+  }
+
   // if this is a new node or we're adding a new revision,
   if ($node->revision) {
     node_example_insert($node);
   }
   else {
-    db_query("UPDATE {node_example} SET color = '%s', quantity = %d WHERE vid = %d", $node->color, $node->quantity, $node->vid);
+    db_query("UPDATE {node_example} SET color = '%s', quantity = %d, fid = %d WHERE vid = %d", $node->color, $node->quantity, $node->fid, $node->vid);
   }
 }
 
 /**
  * Implementation of hook_nodeapi().
@@ -229,11 +306,11 @@ function node_example_delete($node) {
  * Now that we've defined how to manage the node data in the database, we
  * need to tell Drupal how to get the node back out. This hook is called
  * every time a node is loaded, and allows us to do some loading of our own.
  */
 function node_example_load($node) {
-  $additions = db_fetch_object(db_query('SELECT color, quantity FROM {node_example} WHERE vid = %d', $node->vid));
+  $additions = db_fetch_object(db_query('SELECT color, quantity, fid FROM {node_example} WHERE vid = %d', $node->vid));
   return $additions;
 }
 
 /**
  * Implementation of hook_view().
