I am using the following code to include a custom tab for my node types:
function mymodule_menu(){
$items['node/%node/register'] = array(
'page arguments' => array(1),
'access arguments' => array('access content'),
'type' => MENU_LOCAL_TASK,
'title' => 'Register',
);
return $items;
}
This has the effect of including a register tab for every node type. However, I need to include that tab for only page types and exclude it on all other type like article types etc.
What other directions can I consider?
The easiest way would be to provide your own access callback that checks the node type, e.g.
function mymodule_menu(){
$items['node/%node/register'] = array(
'page arguments' => array(1),
'access callback' => 'mymodule_node_register_tab_access',
'access arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'title' => 'Register',
);
return $items;
}
function mymodule_node_register_tab_access($node) {
$valid_types = array('page');
return in_array($node->type, $valid_types);
}
Related
I wonder what I've made wrong, I want to save in db some values whats not come form POST or GET:
public function saveAction()
{
$wikiTable = $this->getServiceLocator()->get('WikiTable');
$data = array('source' => $someVal);
$form = new WikiForm();
$inputFilter = new \MyApp\Form\WikiFilter();
$form->setInputFilter($inputFilter);
$form->setData($data);
$this->saveWiki($form->getData());
//$this->saveWiki($data);
}
WikiFilter:
$this->add(
array(
'name' => 'source',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
)
)
);
And Form:
$this->add(array(
'name' => 'source',
'type' => 'Zend\Form\Element\Hidden',
'options' => array(
'label' => 'source',
)
));
In response I recive error:
Zend\Form\Form::getData cannot return data as validation has not yet
occurred
After this line:
$form->setData($data);
You need to put the rest of your code into something like this:
if($form->isValid()){
$this->saveWiki($form->getData());
}
Otherwise your form isn't validated and you won't get any data back from it by calling $form->getData()
So whenever you work with a form (not matter if the data come from a POST request or not) make sure to call the function isValid() on the form variable because otherwise you won't get the data back and you will get the error you wrote before
$this->form_validation->set_rules('newusername', 'newfullname', 'newcity','newemail');
// is the set_rules correct. I want that if any one input field with above names are set. It should pass the validation . Please help me if there are any corrections.
May be you should read the manual again. If you want at least one of them filled, you'll need to write your own validation.
Using the following rules:
public $rules = array(
'newusername' => array(
'field' => 'newusername',
'label' => 'New User Name',
'rules' => 'trim|xss_clean|callback_needone'
),
'newfullname' => array(
'field' => 'newusername',
'label' => 'New Full Name',
'rules' => 'trim|xss_clean|callback_needone'
),
'newcity' => array(
'field' => 'newcity',
'label' => 'New City',
'rules' => 'trim|xss_clean|callback_needone'
),
'newemail' => array(
'field' => 'newemail',
'label' => 'New Email',
'rules' => 'trim|xss_clean|callback_needone'
)
)
in your controller you have to write
public function needone(){
if ( empty($this->input->post('newusername')) && empty($this->input->post('newfullname')) && empty($this->input->post('newcity')) && empty($this->input->post('newmail')) ) {
$this->form_validation->set_message('needone', 'At least one field must be entered');
return FALSE;
}
return TRUE;
}
Put the rule on any of the form's fields, or all of them to hilite those who are in the required group, it's up to you.
Each input field in your form, requires it's own validation rules. Which should look like this;
$this->form_validation->set_rules('field name', 'human name', 'rules');
https://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#validationrules
So, you would have 4 set_rules functions, like this;
$this->form_validation->set_rules('newusername', 'New username', 'trim|xss_clean|required');
$this->form_validation->set_rules('newfullname', 'New full name', 'trim|xss_clean|required');
$this->form_validation->set_rules('newcity', 'New City', 'trim|xss_clean|required');
$this->form_validation->set_rules('newemail', 'New Email', 'trim|xss_clean|required');
https://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#cascadingrules
Here's a rule reference, all the available rules;
https://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#rulereference
Now, to check if ANY of the items are set, I would do this;
if ($this->input->post('newusername') OR $this->input->post('newusername') OR $this->input->post('newusername') OR $this->input->post('newusername'))
{
// One of them is set
}
else
{
// Nothing is set
}
I have a module with a list of pages that it accesses via AJAX for different tasks
/spower
/spower-geometry
...
. I'm trying to create a single permission that will allow the anonymous user to access everything. If I'm logged in as administrator, everything works the way it's supposed to. However, the anonymous user gets a 403 error. Do I need a different permission hook for each path? This is what I have so far:
function spower_permission() {
return array(
'access intro page' => array(
'title' => t('Access Intro page'),
'description' => t('Allow anonymous users to access spower intro page'),
),
'access SparkerPower app' => array(
'title' => t('Access full page'),
'description' => t('Allow users to access full spower app'),
),
);
}
function spower_menu() {
$items = array();
$items['spower'] = array(
'title' => t('SparkerPOWER'),
'page callback' => 'spower_form',
'access arguments' => array('access SparkerPower app'),
'description' => t('form for SparkerPOWER. Enter your house information, and learn how solar panels can help you.'),
'type' => MENU_CALLBACK,
);
$items['spower_geometry/%'] = array( //send data from Jquery (map areas)
'title' => 'Ajax callback',
'description' => 'Callback for jQuery area AJAX request.',
'page callback' => 'spower_geometry_callback',
'page arguments' => array(1),
'access arguments' => array('access spower geometry'),
'access callback' => 'user_access',
'type' => MENU_CALLBACK,
);
Thanks for the help!
No, you don't need a different hook for each path defined in your HOOK_MENU. Your code is correct by using the access arguments. You don't need to specify the access callback in your second menu item.
Did you also updated the permissions in backend so the anonymous users can access your defined menu paths ? It is under admin/people/permissions.
I tried changing access arguments to TRUE, which didn't work. I then changed access arguments to array('access SparkerPower app'), the one I had defined earlier. That worked, and I was able to access all the url paths I needed to with the anonymous user.
When I run the code with an admin user, the module returns what it should. However, when I run it with a normal user, I get a 403 error. The module returns data from an AJAX call. I've already tried adding a 'access callback' => 'user_access'); line to the exoticlang_chat_logger_menu() function. I'd appreciate any pointers you might have.
Thanks for the help
The AJAX call:
jQuery.ajax({
type: 'POST',
url: '/chatlog',
success: exoticlangAjaxCompleted,
data:'messageLog=' + privateMessageLogJson,
dataType: 'json'
});
The module code:
function exoticlang_chat_logger_init(){
drupal_add_js('misc/jquery.form.js');
drupal_add_library('system', 'drupal.ajax');
}
function exoticlang_chat_logger_permission() {
return array(
'Save chat data' => array(
'title' => t('Save ExoticLang Chat Data'),
'description' => t('Send private message on chat close')
),
);
}
/**
* Implementation of hook_menu().
*/
function exoticlang_chat_logger_menu() {
$items = array();
$items['chatlog'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'exoticlang_chat_log_ajax',
'access arguments' => 'Save chat data');
//'access callback' => 'user_access');
return $items;
}
function exoticlang_chat_logger_ajax(){
$messageLog=stripslashes($_POST['messageLog']);
$chatLog= 'Drupal has processed this. Message log is: '.$messageLog;
$chatLog=str_replace('":"{[{','":[{',$chatLog);
$chatLog=str_replace(',,',',',$chatLog);
$chatLog=str_replace('"}"','"}',$chatLog);
$chatLog=str_replace('"}]}"','"}]',$chatLog);
echo json_encode(array('messageLog' => $chatLog));
// echo $chatLog;
echo print_r(privatemsg_new_thread(array(user_load(1)), 'The subject', 'The body text'));
drupal_exit();
}
access arguments needs to be an array:
$items['chatlog'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'exoticlang_chat_log_ajax',
'access arguments' => array('Save chat data')
);
When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.
The JavaScript:
jQuery(document).ready(function($) {
$('#toggle #graph').click(function() {
$.ajax({
url: "http://www.mysite.com/?q=publications/callback",
type: 'POST',
data: {
'format' : 'graph'
},
success: function(response) {
$('div#content div.content').html(response);
}
});
});
});
The PHP:
$items['publications/callback'] = array(
'type' => MENU_CALLBACK,
'title' => 'All Publications Callback',
'page callback' => '_process_publications',
'page arguments' => array(t('journal')),
'access callback' => TRUE,
);
which leads to the page callback: (I'm concerned with the if code block)
function _process_publications($venue) {
if( isset($_POST['format']) && $_POST['format'] == "graph" ){
_make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
_make_list($venue);
}
else{
return("<p>blah</p>");
}
}
and finally the function called within the callback function:
function _make_bar_chart($venue) {
// get active database connection
$mysql = Database::getConnection();
// if connection is successful, proceed
if($mysql){
// do stuff
$graphael = array(
'method' => 'bar',
'values' => $ycoordinates,
'params' => array(
'colors' => $colors,
'font' => '10px Arial, sans-serif',
'opts' => array(
'gutter' => '20%',
'type' => 'square',
),
'label' => array(
'values' => $xcoordinates,
'isBottom' => true,
),
),
'extend' => array(
'label' => array(
'values' => $ycoordinates,
'params' => array('attrText' => array(
'fill' => '#aaa',
'font' => '10px Arial, sans-serif',
)),
),
),
);
return theme('graphael', $graphael);
}
// else, connection was unsuccessful
else{
print("<p>bad connection</p>");
}
}
THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?
Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944
If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:
<?php
// drupal_add_library is invoked automatically when a form element has the
// '#ajax' property, but since we are not rendering a form here, we have to
// do it ourselves.
drupal_add_library('system', 'drupal.ajax');
// The use-ajax class is special, so that the link will call without causing
// a page reload. Note the /nojs portion of the path - if javascript is
// enabled, this part will be stripped from the path before it is called.
$link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
print $output;
?>
When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):
// A menu callback is required when using ajax outside of the Form API.
$items['ajax_link_callback/graph'] = array(
'page callback' => 'ajax_link_response_graph',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
.. and the callback to which it refers:
function ajax_link_response_graph($type = 'ajax') {
if ($type == 'ajax') {
$output = _make_bar_chart('journal');
$commands = array();
// See ajax_example_advanced.inc for more details on the available commands
// and how to use them.
$commands[] = ajax_command_html('div#content div.content', $output);
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
else {
$output = t("This is some content delivered via a page load.");
return $output;
}
}
This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.