I have run the og_files module through Coder to see if I can upgrade it to D6. I use the module on an intranet, and it also seems like the right size of module to use to learn about module development.

I got the database table to install, and the option to enable the module to appear in Organic Groups nodes, but the "Files" tab does not appear with those for the group.

Here is the D5 instance of hook_menu:

function og_files_menu($may_cache) {
  global $user;
  $items = array();
  if(!$may_cache) {
    if(arg(0) == 'node' && is_numeric(arg(1))) {
      $node = node_load(arg(1));
      if(isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups))) {
        $items[] = array(
          'path' => 'node/'.arg(1).'/files', 
          'title' => t('Files'), 
          'callback' => 'og_files',
          'callback arguments' => array(arg(1)),
          'type' => MENU_LOCAL_TASK,
        );
      }
    }
  }

  return $items;
}

And this is what I have come up with as the D6 code:

function og_files_menu() {
  global $user;
      $node = menu_get_object();
      if (isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups))) {
        $items['node/'. arg(1) .'/files'] = array(
          'title' => 'Files',
          'page callback' => 'og_files',
          'page arguments' => array(arg(1)),
          'type' => MENU_LOCAL_TASK,
          'access arguments' => array('OG Files'),
        );
      }
  return $items;
}

I ditched $may_cache, and switched node_load to menu_get_object. But maybe I didn't get the array for $items[] right, or...well, if I knew, I wouldn't be posting, would I? :)

Can anyone give me a little help?

thanks

mrweaver

Comments

styro’s picture

...
$items['node/%/files'] = ...
...

and

...
page arguments' => array(1),
...

There might be other changes needed, but those were the ones that leapt out at me.

mattrweaver’s picture

nothing happened.

Is this line correct:


$node = menu_get_object();

or do I need to include a variable?

Finished products are for decadent minds. -- Isaac Asimov

jaypan’s picture

Try this:

function og_files_menu() 
{
  $items['node/%node/files'] = array
  (
    'title' => 'Files',
    'page callback' => 'og_files',
    'page arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'access callback' => 'og_files_access_callback',
    'access arguments' => array(1),
  );
  return $items;
}

function og_files_access_callback($node)
{
  global $user;
  return (user_access('OG Files', $user) && isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups)));
}

Contact me to contract me for D7 -> D10/11 migrations.

mattrweaver’s picture

but the tab still didn't appear.

Finished products are for decadent minds. -- Isaac Asimov

Mike Wacker’s picture

If you make changes to the menu, you usually need to empty out the cache (or do some task that will empty the cache) before you can see the changes.

jaypan’s picture

Exactly. Menu's are cached in Drupal 6, so no changes will be visible until the cache is cleared. On top of this, you will need to make sure that the user has 'OG Files' permission. Without this permission, the tab won't appear for anyone except user 1.

Contact me to contract me for D7 -> D10/11 migrations.

mattrweaver’s picture

I hadn't mentioned that I had cleared the cache tables after every code change. I'm doing this on a test site, running as user 1 and I'm still not seeing the tab.

I even tried creating a new group, just to see if starting with a fresh node might help, but no dice.

Also, I checked admin/user/permissions and OG Files doesn't appear there. So I'm wondering if I have another problem elsewhere in the module file.

// $Id: og_files.module,2010/02/08 13:16:40 wundo Exp $
/**
 * @file
 * the OG_Files module.
 */

function og_files_menu()
{
  $items['node/%node/files'] = array
  (
    'title' => 'Files',
    'page callback' => 'og_files',
    'page arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'access callback' => 'og_files_access_callback',
    'access arguments' => array(1),
  );
  return $items;
}

function og_files_access_callback($node)
{
  global $user;
  return (user_access('OG Files', $user) && isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups)));
}


function og_files($gid) {
  $group = node_load($gid);
  $params = func_get_args();
  array_shift($params);

  $path = og_files_base_path($gid);
  if (is_array($params))
    $path .= implode('/', $params);

  if (db_result(db_query("SELECT fid FROM {files} WHERE nid = %d AND filepath = '%s' LIMIT 1", $gid, $path))) {
    //it's a file, download it.

    if (file_exists(file_create_path($path))) {
      $headers = module_invoke_all('file_download', $path);
      if (in_array(-1, $headers)) {
        return drupal_access_denied();
      }

      if (count($headers)) {
        file_transfer($path, $headers);
      }
    }
    return drupal_not_found();
  }
  else {
    if (is_array($params))
      $params .= '/';
    //listing files
    return drupal_get_form('og_file_list_form', $gid, $path);
  }
}

function og_files_file_download($file) {
  global $user;

  // Should only check files from 'og_files' dir. This is needed when drupal file system is
  // set to private - then accessing files from /files dir is not possible because this function
  // returns -1.
  if (strpos($file, '/og_files/') === FALSE)
    return;

  // Sql is not created correctly - f.filepath = '%d' should be f.filepath = '%s'
  if (($user->uid != 1) && !db_result(db_query("SELECT o.uid FROM {og_uid} o, {files} f WHERE f.filepath = '%s' AND f.nid = o.nid AND o.uid = '%d' LIMIT 1", $file, $user->uid))) {
    return -1;
  }
}

function og_file_list_form($gid, $path) {
  $form = array();
  $form['#attributes']['enctype'] = 'multipart/form-data';

  $form['gid'] = array(
    '#type' => 'value',
    '#value' => $gid,
  );
  $form['path'] = array(
    '#type' => 'value',
    '#value' => $path,
  );

  $form['upload'] = array(
    '#type' => 'fieldset',
    '#title' => t('Upload a new file'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE
  );
  $form['upload']['file'] = array(
    '#type' => 'file',
    '#title' => t('File'),
  );
  $form['upload']['upload'] = array(
    '#type' => 'submit',
    '#value' => t('Upload'),
  );

  $form['mkdir'] = array(
    '#type' => 'fieldset',
    '#title' => t('Create a new directory'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE
  );
  $form['mkdir']['dir'] = array(
    '#type' => 'textfield',
    '#title' => t('Directory'),
    '#description' => t('Type the directory name, multiple levels allowed. For example "foo/bar" creates the directories foo and foo/bar.'),
  );
  $form['mkdir']['createdir'] = array(
    '#type' => 'submit',
    '#value' => t('Create directory'),
  );

  $file_list = array();
  $file_count = 0;
  $dir_count = 0;
  $files = db_query("SELECT * FROM {files} WHERE nid = %d AND filepath LIKE '%s%%' ORDER BY filename ASC", $gid, $path);
  $virtualpath = og_files_relative_path($gid, $path);
  if ($virtualpath[strlen($path)-1] == '/')
    $virtualpath[strlen($path)-1] = 0;
  $aux = explode('/', $virtualpath);

  if ($aux[0] == '')
    array_shift($aux);

  $virtualpath_count = count($aux);

  if ($virtualpath_count && $aux[0] != '') {
    array_pop($aux);
    $dir_list['..'] = l('..', og_files_virtual_base_path($gid) . implode('/', $aux));
  }




  while ($file = db_fetch_object($files)) {
    $array = explode('/', og_files_relative_path($gid, $file->filepath));
    array_pop($array);
    if ((count($array) - $virtualpath_count) > 0) { //in a subdir


      // We just want to show first level of subfolders in current folder
      if (count($array) - $virtualpath_count < 2) {
        $dir_list[$array[count($array)-1]] = l($array[count($array)-1], og_files_virtual_base_path($gid) . implode('/', $array));
        $dir_count++;
      }

    }
    else {
      $file_list[$file->fid] = l($file->filename, og_files_virtual_base_path($gid) . og_files_relative_path($gid, $file->filepath));
      $file_count++;
    }
  }

  $form['filelist'] = array(
    '#type' => 'fieldset',
    '#title' => '/'. og_files_relative_path($gid, $path),
    '#collapsible' => TRUE,
    '#collapsed' => false
  );

  //if($dir_count) {
    $dir_html = theme_item_list($dir_list);
    $form['filelist']['folders'] = array(
      '#prefix' => $dir_html,
      '#type' => 'hidden'
    );
  //}

  if ($file_count) {
    $form['filelist']['files'] = array(
      '#type' => 'checkboxes',
     // '#title' => $path, //t('File list'),
      '#options' => $file_list,
    );
    $form['filelist']['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete selected files'),
    );
  }
  return $form;
}

function og_file_list_form_submit($form, &$form_state) {
  $gid = $form_state['values']['gid'];
  switch ($form_state['values']['op']) {
    case t('Upload'):
      //print('Upload a new file'); die;
      $path = $form_state['values']['path'];

      //$return = file_check_directory($path,FILE_CREATE_DIRECTORY);
      if (!is_dir($path) && mkdir($path, 0777, TRUE)) {
        @chmod($path, 0775);
        drupal_set_message(t('The directory %directory has been created.', array('%directory' => $directory)));
      }

      $file = file_save_upload('file', $path);
      $fid = db_last_insert_id('{files}_fid');
      db_query("INSERT into {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s','%s','%s',%d)", $fid, $gid, $file->filename, $file->filepath, $file->filemime, $file->filesize);
      drupal_set_message(t('The file %file has been sucessful uploaded.', array('%file' => $file->filename)));
      break;

    case t('Create directory'):
      $destination = 'node/'. $gid .'/files';
      if ($form_state['values']['dir'][0] != '/') {
        // The last '/' should be added only if og_files_relative_path return nonempty string
        // in other situation adding of '/' should be skiped.
        $destination .= '/';
        $relpath = og_files_relative_path($form_state['values']['gid'], $form_state['values']['path']);
        if ($relpath)
          $destination .= $relpath .'/';
      }
      $destination .= $form_state['values']['dir'];
      drupal_set_message(t('Directory will be created when you upload first file in it.'));
      drupal_goto($destination);
      break;

    case t('Delete selected files'):
      $string = implode(', ', $form_state['values']['files']);
      $files = db_query("SELECT * FROM {files} WHERE nid = %d AND fid IN ('%s') ", $gid, $string);
      while ($file = db_fetch_object($files)) {
        file_delete($file->filepath);
        drupal_set_message(t('The file %file has been sucessful deleted.', array('%file' => $file->filename)));
      }
      db_query("DELETE FROM {files} WHERE nid = %d AND fid IN ('%s')", $gid, $string);
  }

}

function og_files_base_path($gid) {
  return 'files/og_files/'. $gid .'/';
}

function og_files_virtual_base_path($gid) {
  return 'node/'. $gid .'/files/';
}

function og_files_relative_path($gid, $filepath) {
  return drupal_substr($filepath, drupal_strlen(og_files_base_path($gid)));
}
function og_files_format_path($gid, $filepath) {
  $patharray = explode('/', $filepath);
  array_shift($patharray);
  $patharray = array('node', $gid) + $patharray;
  $patharray[2] = 'files';

  return implode('/', $patharray);
}



function og_files_form_alter(&$form, $form_state, $form_id) {
  if (!isset($form['#node']) || ($form_id != $form['#node']->type .'_node_form') || (!og_is_group_type($form['#node']->type)))
    return;

  $node = $form['#node'];
  $enabled = isset($node->og_files_enabled);

  if (!isset($node->nid))
    $enabled = TRUE;

  $form['og_files_enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable OG Files to this group?'),
    //'#default_value' => ,
    '#value' => $enabled,
    '#weight' => 30
  );

}

function og_files_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if (!og_is_group_type($node->type))
    return;

  switch ($op) {
    case 'update':
      db_query('DELETE FROM {og_files} WHERE gid = %d', $node->nid);
    case 'insert':
      if (isset($node->og_files_enabled)) {
        db_query("INSERT INTO {og_files} VALUES (%d,'%s')", $node->nid, '');
      }
      break;
    case 'load':
      if (db_result(db_query('SELECT count(gid) FROM {og_files} WHERE gid = %d', $node->nid))) {
        $node->og_files_enabled = TRUE;
      }
      break;
    case 'delete':
      db_query('DELETE FROM {og_files} WHERE gid = %d', $node->nid);
      break;
  }
}

Finished products are for decadent minds. -- Isaac Asimov

jaypan’s picture

You don't see the permissions in the permissions table because you haven't got hook_perm() in your module. You will also need to check all the conditions in this statement:

return (user_access('OG Files', $user) && isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups)));

...to see what their values are. The basic outlay of hook_menu() with its callback function is ok in what you showed there, so something above is probably returning FALSE.

Contact me to contract me for D7 -> D10/11 migrations.

mattrweaver’s picture

I'm reading up on Access Control. But, how can I structure the access callback just to make the tab appear for testing, to see if the module is working at all?

Does the "page callback => 'og_files', refer to the function "og_files" in the module file?

Finished products are for decadent minds. -- Isaac Asimov

jaypan’s picture

If you want to test to see if the tab is working at all, then change this code from my earlier post:

function og_files_access_callback($node)
{
  global $user;
  return (user_access('OG Files', $user) && isset($node->type) && $node->og_files_enabled && in_array($node->nid, array_keys($user->og_groups)));
}

to this:

function og_files_access_callback($node)
{
  return TRUE;
}

This means the access check will always return TRUE, so the tab will always appear.

Does the

"page callback => 'og_files',

refer to the function "og_files" in the module file?

Yes. The page callback is the name of the function that is called when the menu path is accessed. In your case, that's 'og_files'.

Contact me to contract me for D7 -> D10/11 migrations.

mattrweaver’s picture

Then there must be a bigger problem, because the tab still didn't appear.

I had tried changing access callback to "access callback => TRUE," and had no positive response (does this do the same thing as your most recent code?)

Could there be a problem with og_files_form_alter?

function og_files_form_alter(&$form, $form_state, $form_id) {
  if (!isset($form['#node']) || ($form_id != $form['#node']->type .'_node_form') || (!og_is_group_type($form['#node']->type)))
    return;

  $node = $form['#node'];
  $enabled = isset($node->og_files_enabled);

  if (!isset($node->nid))
    $enabled = TRUE;

  $form['og_files_enabled'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable OG Files to this group?'),
    //'#default_value' => ,
    '#value' => $enabled,
    '#weight' => 30
  );

}

On the individual OG node page, the checkbox for enabling OG files appears checked as default when a node is created. Is it maybe not actually enabled?

Finished products are for decadent minds. -- Isaac Asimov

jaypan’s picture

I had tried changing access callback to "access callback => TRUE," and had no positive response (does this do the same thing as your most recent code?)

It's not the same thing. You aren't calling the acceess callback function in hook_menu(), you are just passing the name of the function that will be called. The actual calling of the function doesn't happen until later. So hook_menu() is expecting a string, which it will use later on by searching for a function with that name, and you are passing it a boolean. This isn't the same thing. That's why you need to return a value of TRUE from the function.

Contact me to contract me for D7 -> D10/11 migrations.