If a user is logged in as admin, it works fine but if user is logged in, it is sending them their profile page. Why?. What files can I check?
$items['go/to/school'] = array(
'title' => 'Some page Title',
'page callback' => 'my_function',
'access callback' => 'my_access',
'type' => MENU_CALLBACK
);
function my_function() {
echo "WHATS UP"; //NEVER SHOWS UP
}
Your callback function myaccess() must return TRUE for that user, else that user has no access. This callback function can get arguments trough access arguments. When you do not provide the access callback it defaults to function user_access($access_string), in which case you still need to provide access arguments, e.g. "access content".
Also note, that after each change in the hook_menu-code you must refresh the menu-cache, since this is cached quit heavily.
If you would like this page to be visible to all users (logged-in or anonymous), the simplest way is to just return TRUE in your access callback. For example:
'access callback' => TRUE,
Otherwise, like berkes said, your access callback must return TRUE for that user to see the page. For example:
function my_access() {
global $user;
return in_array('authenticated user', $user->roles);
}
This will return TRUE if the user has a role of "authenticated user" and FALSE if they do not.
Related
I have several things I want to check before a user may create a node. So, if the user visits node/add/proposal I want to check if he may do so, so I wrote a module:
function proposals_menu() {
$items['node/add/proposal'] = array(
'title' => t('Proposal'),
'access callback' => 'proposals_access',
);
return $items;
}
function proposals_access() {
$cond1;
$cond2;
...
return cond1 && cond2 && ....;
}
When I click on add content -> proposal I get a blank page. What am I missing?
To override existing menu items you need to use hook_menu_alter() instead of hook_menu(). e.g.
function proposals_menu_alter(&$items) {
$items['node/add/proposal']['access callback'] = 'some_function';
}
But there's also hook_node_access() which would be preferable to use for (as the name suggests) checking node access. e.g.
function proposals_node_access($node, $op, $account) {
$type = is_string($node) ? $node : $node->type;
if ($type == 'proposal' && $op == 'create') {
if ($allow_access) {
return NODE_ACCESS_ALLOW;
}
else {
return NODE_ACCESS_DENY;
}
}
return NODE_ACCESS_IGNORE;
}
Assuming you populate $allow_access with your access check. Be sure to use the $account object that's passed to the hook to verify the operation against that user object. Don't depend on the currently logged in user, which will not always be the same.
You get a blank page because you are not telling drupal how to render the path you are creating. For that you need to add a page callback to the item. As specified in the hook_menu documentation, this function will be called to display the page when the user visits the path.
...
$items['node/add/proposal'] = array(
...
'page callback' => 'proposals_display_function'
);
...
In the context of organic groups, I am writing a module which will stop users who are not members of a group from adding group posts into that group.
My module currently sets the permissions necessary and detects whether a user has the permission.
So when a user(s) are looking at a group page, I want to disable/remove the standard link to create group posts.
Try this method.
function mymodule_menu_alter(&$items) {
global $user;
// Perform code for finding out users permissions.
// lets suppose we set true or false to $restricted after all
if ($restricted && isset($items['node/add/yourtype'])) {
$items['node/add/yourtype']['access arguments'] = FALSE;
// or unset($items['node/add/yourtype']) to remove item for user
}
}
If I understood right you don't want certain users to create a content type.
So the steps are:
1) Create a menu hook.
// Here we make sure if the user goes to for creating this node type
// we can use the appropriate call back function to stop it.
function yourmodoule_menu() {
$items = array();
$items['node/add/page'] = array(
'page arguments' => array('yourmodule_additional_actions'),
'access arguments' => array('administer create content')
);
}
2) Then make a permission hook to make sure only certain users have this permission.
// drupal will only allow access to to path 'node/add/page' with people
// who have access given by you.
function yourmodule_permission() {
return array(
'add content' => array(
'title' => t('Administer create conent'),
'description' => t('Perform administration tasks and create content')
)
)
}
3) Write your code for those users who have the permission.
// Only affter they have this permisson drupal will allow them access
// to the below function.
function yourmodule_additional_actions() {
// this code will only execute if the user has the permission
// "Administer create conent"
}
Does anyone know what the best way would be solve this:
I've got a custom content type that you can view i.e via
http://site.com/node/8
The custom content type has a field with a url (Example www.google.com)
What I'm trying to do is to create a mechanism that will automatically redirect the browser to www.google.com (the field property) when I enter a url like
http://site.com/node/8/go
I tried using the Path and AutoPath modules, but couldn't get a redirect working
The shortest implementation:
<?php
function YOURMODULE_menu() {
$items = array();
$items['node/%node/go'] = array(
'page callback' => 'YOURMODULE_redirect',
'page arguments' => array(1),
'access arguments' => array('access content'),
);
return $items;
}
function YOURMODULE_redirect($node) {
if ($node->type == 'YOUR_TYPE' && isset($node->field_YOURFIELD[0]['value']) && $node->field_YOURFIELD[0]['value']) {
drupal_goto($node->field_YOURFIELD[0]['value']);
}
}
Edit: It would be advised to add some validation and probablty other stuff, but I believe this is quite obvious. And also, depends on details of your implementation.
You can use field_redirection module .
You can use Rabbit hole and Token modules. With Rabbit hole you will be able to set a Page Redirect for the content type, and with Token you can choose a field where users will be redirected when they try to access to a node.
We're building a small sub-site that, on the front page, has a one input box form that users can submit. From there, they're taken to a page with a few more associated form fields (add more details, tag it, etc.) with the first main form field already filled in. This works splendidly, thus far.
The problem comes for users that are not logged in. When they submit that first form, they're taken to a (LoginToboggan based) login page that allows them to login. After they login, they redirect to the second form page, but the first main form field isn't filled in -- in other words, the form data didn't persist.
How can we store that data and have it persist across the access denied page?
You could save the data in a cookie that would be passed to the page after the login page.
Assuming that you are using the Form API to create the form, and that you have a field called "fieldname" in the function to generate the form:
function my_form() {
$form['fieldname'] = array (
'#type' => 'textfield',
'#title' => 'Some fieldname'
);
// Second field if you need to save another
$form['fieldname2'] = array (
'#type' => 'textfield',
'#title' => 'Some other fieldname'
);
}
Set the cookie(s) in the submit handler for your form:
function my_form_submit($form, &$form_state) {
// Set the cookie with their data before they are redirected to login
// Use the array syntax if you have one than one related cookie to save,
// otherwise just use setcookie("fieldname",...
setcookie("saved_data[fieldname]", $form_state['values']['fieldname']);
// Your other code
}
After they login and are redirected to page two of your form, you can read the value of the cookie(s) and if they exist, insert them into the default values of the fields:
function my_form() {
if (isset($_COOKIE['saved_data[fieldname]'])) {
$default_fieldname = $_COOKIE['saved_data[fieldname]'];
}
else {
$default_fieldname = '';
}
// Same check for the second field
if (isset($_COOKIE['saved_data[fieldname2]']))...
$form['fieldname'] = array (
'#type' => 'textfield',
'#title' => 'Some fieldname',
'#default_value' => $default_fieldname
);
// Second field if used
$form['fieldname2'] = array (
'#type' => 'textfield',
'#title' => 'Some other fieldname',
'#default_value' => $default_fieldname2
);
}
The cookies(s) will be presented on each page load after they are set, so it doesn't matter if there are several failed login attempts or other page views in between. You should probably delete the cookies after they're used or set a short expiration time so that they are cleaned up automatically.
I don't know if there is a good way to transfer form data from two entirely different forms in Drupal, especially in the context of access denied. The best choices I can find would be to:
Use the url to send the data for the field.
You could also save the data in the db, but it might be a bit tricky to extract the data again.
I wanted to add a tab to the user edit page ie user/%/edit/foo, and was using the twitter module as a model. After much spelunking and stepping through with a debugger, I realised that I needed to add a hook_user function in my module so that the %user_category part of the menu router path would work.
It's now functioning as expected, but I don't really have a solid idea of what I just did, and haven't found a good explanation anywhere.
Can anyone explain to me what it's about?
user_category_loads fails if given a category that does not exist, which happens at user/uid/edit/not_a_category, and it passes that category for access checks to user/uid/edit/is_a_category and thus access to those is set to false, so bam, wonky menu :'(.
When you use %user_category it means that user_category_load function is called with that argument (the uid).
The function is defined in the user module. These functions serve as a validation, if False it return FALSE, it will result in a 404, but if it return something else, like a user object, that will be passed to whatever callback function / form is run for that url.
In your case, you could probably have used %user instead which would have called user_load which is more simple, and you wouldn't have needed to do all the extra stuff to make user_category_load pass.
Summary
So user_category_load does two things.
Check that the category exist so you just can't do user/%/edit/foo.
Caches the user object.
After much trial and error, I was able to get a page working as a child of the user/%/edit path using code like this:
<?php
/**
* Implementation of hook_menu().
*/
function noc_profile_privacy_menu() {
return array(
'user/%user_category/edit/privacy' => array(
'title' => 'Portfolio privacy',
'page callback' => 'drupal_get_form',
'page arguments' => array('noc_profile_privacy_form', 1),
'access callback' => 'content_profile_page_access',
'access arguments' => array('profile', 1),
'type' => MENU_LOCAL_TASK,
'load arguments' => array('%map', '%index'),
),
);
}
/**
* Implementation of hook_user().
*/
function noc_profile_privacy_user($op, &$edit, &$account, $category = NULL) {
if ($op === 'categories') {
return array(array(
'name' => 'privacy',
'title' => t('Profile privacy'),
'weight' => 0,
));
}
}
Note that the 'name' key of what I'm returning in hook_user() is the same as what comes after user/%user/category/edit in my hook_menu() definition. I believe that is key. You will also get an error if you omit the 'load arguments' item, with exactly that value.
So I believe what the user category is is the 'privacy' in my case - the bit after edit in the path of the menu item definition.
Is this an unnecessary complication? Yes, so it seems.
Edit: I see my co-worker hefox beat me to replying to this question. I wouldn't have been able to figure all of this out without Fox's help, so mad props to the Fox.