I'm trying to create a test module in drupal 6.x that loads php pages. I made a test.module and test.info file and also put inside the .php page. Below is the test.module code. But it doesnt work on my drupal_site/test I get page not found.
function test_perm() {
return array('access test content');
}
function test_contents() {
module_load_include('php', 'test', 'index');
}
function test_menu() {
$items = array();
$items['test'] = array(
'title' => t('Test'),
'description' => t('Test desc'),
'page callback' => 'test_page',
'access arguments' => array('access test content'),
'type' => MENU_NORMAL_ITEM
);
return $items;
}
function test_page() {
$page_array['test_arguments'] = array(
'#markup' => test_contents(),
);
return $page_array;
}
I'll take a guess that your test_contents() outputs HTML directly to the page buffer? This isn't the way Drupal works, it expects you to build up a string and return that in your $page_array variable.
Either change your test_contents() function to return the string not output it, or store the output in a temporary buffer and assign that to a string:
function test_page() {
// Start your buffer
ob_start();
// Output into the buffer
test_contents();
// Save the result to a string and close the buffer
$contents = ob_get_clean();
$page_array['test_arguments'] = array(
'#markup' => $contents,
);
return $page_array;
}
Related
I have a custom drupal module. I have a demo pages for different APIs I have. (Like, host.com/demo/abc or host.com/demo/bcd or host.com/demo/def ...)
hook_menu()
$items['demo/%'] = array(
'page callback' => 'xxx',
'page arguments' => array(1),
'access callback' => 'xxx',
....
);
I want to change the URL to host.com/abc/demo for all the demo pages. Since I cannot a wild card at the beginning of the hook (Like %/demo) I am considering URL alias. But how can I generate url alias dynamically for all the demo pages?
The best solution :
http://www.zyxware.com/articles/3636/drupal-how-to-create-url-alias-for-custom-menu-implementation-of-hook-pathauto
Otherwise :
Before you need to know that all dynamical solution available is not totally safe , take care before using it.
With url_alias you can try this, but you have to restrict by defined path to avoid flood insertion :
function mymodule_menu(){
$items= array();
$items['demo/%'] = array(
'page callback' => 'xxx',
'page arguments' => array(1),
'access callback' => 'xxx',
);
return $items;
}
function mymodule_init(){
global $language;
$path_allowed = array(
'abc',
'dbe'
); // restrict to avoid flood
if(arg(1) == 'demo' && in_array(arg(0), $path_allowed)) { // detect demo mode
$path = arg(1).'/'.arg(0);
$alias = arg(0).'/'.arg(1);
$a = db_query('SELECT alias FROM url_alias WHERE source = :source AND alias = :alias', array(':source' => $path, ':alias' => $alias))->fetchField();
if($a == null) ) {
db_insert('url_alias')->fields(array(
'source' => $path,
'alias' => $alias,
'language' => $language->language
))->execute();
}
}
}
Otherwise, I'm not sure but you can try this too , you can handle it from hook_init but it can cause some issue form all module loading init
function mymodule_init(){
if(arg(1) == 'demo') { // detect demo mode
$mycallbacks = array( // define your callback related
'abc' => 'mymodule_callback1',
'dbe' => 'mymodule_callback2',
);
if(isset($mycallbacks[arg(0)]) && function_exists($mycallbacks[arg(0)])) { // if callback is available
call_user_func($mycallbacks[arg(0)]); // call it
}
}
}
function mymodule_callback1(){ //do what you want }
function mymodule_callback2(){ //do what you want }
So , mysite.com/abc/demo will execute mymodule_callback1() and mysite.com/dbe/demo will execute mymodule_callback2()
Etc..
Clear all caches and see :)
I have two Drupal sites hosted on different servers. In the main they need to operate separately however site1 has one specific content type which I'd like to show in a list on site2.
I can't simply use feeds to import as the original has to remain and if edited, the changes be instantly reflected on both sites. Site2 has no requirement to edit the content - only show it.
The content is already being presented in a list on site1. The list was created using views.
My intention was to call the view on site2 using the following code in a custom module.
function site2_menu() {
$items = array();
$items['content-from-site1'] = array(
'title' => 'Content from Site1',
'page callback' => 'site_two_list',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function site2_list() {
db_set_active('site1');
$content = views_embed_view('articles', 'default');
db_set_active('default');
return $content;
}
site1 DB is defined in the settings.php file.
However this isn't returning any data. Using the same approach on Site1 (without switching DBs) works fine.
Was I being over-optimistic in hoping this approach would work or am I missing something obvious?
If this isn't likely to work, what would the alternative be? I can do my own SQL query, but I'd prefer to use views for built in arguments, pagination, templates, etc.
Thanks.
I've not been able to use views_embed_view, however I have been able to use views_get_view to retrieve everything I need and iterate over the results myself. It's a very close second.
function site2_menu() {
$items = array();
$items['content-from-site1'] = array(
'title' => 'Content from Site1',
'page callback' => 'theme_site2_list',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function site2_theme() {
return array (
'site2_list_page' => array(
'arguments' => array('content' => NULL),
'template' => 'templates/site2-list-page'
)
);
}
function theme_site2_list() {
db_set_active('site1');
$view = views_get_view('articles');
$view->base_database = "site1";
$view->init_display();
$view->pre_execute();
$view->execute();
db_set_active('default');
foreach ($view->result as $key => $data) {
$content[$key]['nid'] => $data->nid;
$content[$key]['title'] => $data->node_title;
$content[$key]['body'] => $data->field_body;
$content[$key]['image'] => $data->field_field_image;
}
return theme('site2_list_page', array('content' => $content));
}
Then in site2-list-page.tpl.php I can use the $content array to do what I need. It's not quite as clean as a simple views_embed_view, but it's a close second and allows the content from one site to be pulled to another fairly easily.
What I am trying to do is generate some raw output within a module.
I would like to pass an array of data through to a template file, and then use that data to populate the code from the template. The template is represented by a file in my theme folder.
I have a hook set up for a certain URL (/itunes):
$items['itunes'] = array(
'page callback' => 'itunespromo_buildpage',
'type' => MENU_SUGGESTED_ITEM,
'access arguments' => array('access content'),
);
..inside itunespromo_buildpage...
function itunespromo_buildpage() {
//grab some data to pass through to template file, put into $promo_data
$details = theme('itunes_page', array(
'promo_data' => $promo_data,
));
return $details;
}
Here is the hook_theme():
function itunespromo_theme() {
return array(
'itunes_page' => array(
'template' => 'itunes_page',
),
);
}
Inside my theme's template.php:
function geddystyle_itunes_page($vars) {
return print_r($vars['promo_data'], true);
}
Right now, $promo_data is being passed through fine, and it is print_r'd on to the result page. However, I'd like to then take this $promo_data variable and use it in my itunes_page.tpl.php template file.
I'm kind of certain I'm close here. Am I supposed to call some sort of render function and pass the $promo_data variable to it from function itunespromo_theme()?
I believe you just need to update your hook_theme() to provide the ability to send variables to your template file.
Something like this should do the trick:
function itunespromo_theme($existing, $type, $theme, $path) {
return array(
'itunes_page' => array(
'variables' => array(
'promo_data' => NULL,
),
'template' => 'itunes_page',
)
);
}
Also, instead of calling the theme() function directly what you want to be doing is actually constructing a renderable array and letting Drupal call the theme() function. What you should be doing is calling drupal_render which in turn calls theme() for you. Look at this piece of advice here for a little more clarity:
http://drupal.org/node/1351674#comment-5288046
In your case you would change your function itunespromo_buildpage to look something like this:
function itunespromo_buildpage() {
//grab some data to pass through to template file, put into $promo_data
$output = array(
'#theme' => 'itunes_page',
'#promo_data' => $promo_data //call $promo_data from the tpl.php page to access the variable
);
$details = drupal_render($output);
return $details;
}
the info file is right,the following is my module file code. when i access the http://localhost/drupal/mymenu why it can't work.
<?php
function mymenu(){
$item = array();
$item['mymenu'] = array(
'description'=>'test1',
'page callback'=>'mymenu_test',
'access arguments' => array('access mymenu'),
'type'=>MENU_CALLBACK,
);
return $item;
}
function mymenu_perm(){
return array('access mymenu');
}
function mymenu_test() {
$output = 'hello world';
return $output;
}
i have gave the 'access mymenu' permission to the anonymous.
It should be
function mymenu_menu() {
...
}
You don't need the $item = array(); there also.
whenever you see a api function with hook_something, you have to replace the 'hook' part with the name of your module
in this case it's indeed mymenu_menu
Try the following: use function name as modulename_menu and use 'access arguments' => array('access content').
<?php
function test_menu(){
$item = array();
$item['mymenu'] = array(
'description'=>'test1',
'page callback'=>'mymenu_test',
'access arguments' => array('access content'),
'type'=>MENU_CALLBACK,
);
return $item;
}
function mymenu_test() {
$output = 'hello world';
return $output;
}
you need to flush menu cache(at least two times in drupal 7) after adding menu item with hook_menu.
I have a drupal module with a function that returns an attachment text/plain,
function mymodule_menu() {
$items = array();
$items[MY_PATH] = array(
'title' => 'some page',
'page callback' => 'myfunction',
'type' => MENU_CALLBACK,
);
}
function myfunction()
{
drupal_set_header('Content-Type: text/plain');
return "some text";
}
But it returns the page in the page.tpl.php template, however I want it untemplated, how do I over-ride the theme to make it return plain text?
Thanks,
Tom
This will return plain text
function myfunction() {
drupal_set_header('Content-Type: text/plain');
print "some text";
exit(0);
}
Alternatively you can use the 'delivery callback' setting in your menu callback definition. Now your page callback function will be run through a custom function that just prints and exits, rather than calling drupal_deliver_html_page(), which is what outputs all the typical theme markup, etc.
function mymodule_menu() {
$items = array();
$items['MY_PATH'] = array(
'title' => 'some page',
'page callback' => 'myfunction',
'type' => MENU_CALLBACK,
'delivery callback' => 'mymodule_deliver_page',
);
return $items;
}
function mymodule_deliver_page($page_callback_result) {
print $page_callback_result;
exit(0);
}
The best and simplest solution is to just have your callback print your html and return nothing.
For example,
// Hooks menu to insert new url for drupal
function MYMODULE_menu() {
$items = array();
$items['member-stats.php'] = array(
'page callback' => '_MYMODULE_menu_callback',
'access callback' => TRUE,
);
return $items;
}
// Callback prints and doesn't return anything
function _MYMODULE_menu_callback() {
print "Hello, world";
}
if you'd create a template like html--barebones.tpl.php, containing just
<?php
drupal_set_header('Content-Type: text/plain');
print $barebones;
?>
you could hook that template to YOURTHEME_preprocess_html(), like so:
function YOURTHEME_preprocess_html(&$variables) {
if (array_key_exists('barebones',$_REQUEST)) {
$variables['barebones'] = $variables['page']['foo']['bar'];
$variables['theme_hook_suggestions'][] = 'html__barebones';
}
}
now, if you call your page with the additional query ?barebones, like drupal/foo/bar?barebones, it will return the barebones version.
theres a tricky bit in getting your result back. var_dump($variables['page']) to see where drupal left your text. Its been tucked inside the render array surrounded by all kind of info used to render the text, which you are not using. Making me wonder if it wouldnt be more efficient to just print it and exit() inside myfunction :-)
Your module can define template files (reference):
<?php
function mymodul_preprocess_page(&$variables) {
foreach ($variables['template_files'] as $file) {
$template_files[] = $file;
if ($file == 'page-node') {
$template_files[] = 'page-'. $variables['node']->type;
}
}
$variables['template_files'] = $template_files;
}
?>
By creating a new .tpl.php file for the page in question. E.g.
page-module.tpl.php
page-module.tpl.php would only need to be a simple page, e.g.
<?php
print $content;
?>