Posted by mrweaver on February 9, 2010 at 9:07pm
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:
<?php
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:
<?php
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
Try something like this
<?php...
$items['node/%/files'] = ...
...
?>
and
<?php...
page arguments => array(1),
...
?>
There might be other changes needed, but those were the ones that leapt out at me.
--
Anton
I tried it but...
nothing happened.
Is this line correct:
<?php
$node = menu_get_object();
?>
or do I need to include a variable?
Finished products are for decadent minds. -- Isaac Asimov
Try this: <?phpfunction
Try this:
<?php
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)));
}
?>
Full-time freelancer, always looking for work.
jaypan.com (my portfolio)
I tried this...
but the tab still didn't appear.
Finished products are for decadent minds. -- Isaac Asimov
Cache Maybe?
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.
Mike Wacker
Assistant Web Editor Emeritus, The Cornell Daily Sun
mwacker@cornellsun.com
Exactly. Menu's are cached in
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.
Full-time freelancer, always looking for work.
jaypan.com (my portfolio)
Forgot to mention...
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.
<?php
// $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
You don't see the permissions
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:
<?phpreturn (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.
Full-time freelancer, always looking for work.
jaypan.com (my portfolio)
To test...
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
<?php"page callback => 'og_files',
?>
Finished products are for decadent minds. -- Isaac Asimov
If you want to test to see if
If you want to test to see if the tab is working at all, then change this code from my earlier post:
<?phpfunction 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:
<?phpfunction og_files_access_callback($node)
{
return TRUE;
}
?>
This means the access check will always return TRUE, so the tab will always appear.
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'.
Full-time freelancer, always looking for work.
jaypan.com (my portfolio)
Aha!
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?
<?php
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
I had tried changing access
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.
Full-time freelancer, always looking for work.
jaypan.com (my portfolio)