Drupal 7 and using custom templates with theme() - drupal

I have a list of items in the default main-menu. I am trying to override the template so I may iterate over each item and custom template/theme the entire menu.
echo theme('links', array('links' => menu_navigation_links('main-menu', 0)));
main-menu is the default menu ID drupal provides. The first param to theme is telling it to use the default "links" template - this much I understand. How do I tell it to use MY mainmenu.tpl.php that resides in mytheme directory?
I have tried creating a file named mainmenu.tpl.php and calling it with
theme('links__mainmenu.tpl.php')
So as to provide a fallback to default links in case mainmenu.tpl.php should every disappear. I am naming the files wrong or something and I cannot for the life of me figure it out. Help :)
Cheers,
Alex

A module's default theme is defined in the hook_theme method. This function allows you to declare theme files (.tpl.php) and the variables passed to them. To declare the default theme file, use the template field.
function hook_theme($existing, $type, $theme, $path) {
return array(
'mymodule_display' => array( /* displayable name */
'template' => 'mymodule_display', /* template file, leave off .tpl.php */
'variable' => array(...), /* associative array of vars used */
)
);
}
This link contains a more in depth example.
To invoke the module's default theme, use the theme() method, as shown in your original post. Something like:
<?php echo theme('mymodule_display', array(/* vars */));
The double-underscore is used for defining fallback themes, with the last one being preferred. Therefore, theme('links__mymodule_display', ...) means that Drupal will use the Links module theme only if mymodule_display cannot be resovled.

Kind of basic but does your theme implement the base theme and is your theme set to the default?

Related

How I can print all variable of a hook in drupal 8?

I'm very new in Drupal 8 and I have issue now with hook. Mainly I though that I don't clearly understand structure and hook definition in Drupal 8.
So my main problem is that I have some hook to interact with main menu (add custom class name to ul, li and link, a tag). I can do it by changing template file and now try to do it with any hook.
Although I found that some hook relating to menu ex. hook_contextual_links_alter (link: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Menu%21menu.api.php/function/hook_contextual_links_alter/8.9.x).
At the end of this hook we have the code related:
function hook_contextual_links_alter(array &$links, $group, array $route_parameters) {
if ($group == 'menu') {
// Dynamically use the menu name for the title of the menu_edit contextual
// link.
$menu = \Drupal::entityTypeManager()
->getStorage('menu')
->load($route_parameters['menu']);
$links['menu_edit']['title'] = t('Edit menu: #label', [
'#label' => $menu
->label(),
]);
}
}
So I have installed devel module with kint function and in my .theme file and try:
function hook_contextual_links_alter(array &$links, $group, array $route_parameters) {
kint($links);
}
and then reload my Home page but nothing showed. But I can get some information about other like:
function eg_learn_theme_suggestions_page_alter(&$suggestions, $variables) {
kint($suggestions);
}
So what happens here? Can you help to explain if how I can print the variable of this hook (in .theme file) and the site page to see the printing variable?
In general when I found a hook, how I can print there array and check it in website?
There are some problems about your approach:
When implementing a hook, you must replace "hook" with the module name/theme name where you put the hook function inside. For example, if you want implement hook_contextual_links_alter in your_custom module, it becomes your_custom_contextual_links_alter().
Not all hook can be implemented in the theme. Some hook can only be implemented in modules (in .module file). You can read more here.
In your case, I think hook_preprocess_menu would be more suitable. You can implement it in your custom theme like this:
function <your_theme_name>_preprocess_menu(&$variables) {
if ($variables['menu_name'] == 'main') {
kint($variables);
}
}

How to reconfigure custom post type after it has been defined?

I'm using a WordPress theme that adds a custom post type.
This is somewhat useful, but would be even more useful if I could adjust some of the CTP's configuration.
In particular, I need to adjust the capabilities defined on the CTP. I already have an array of the capability values needed, e.g.,
$caps = array(
'publish_posts' => 'activate_plugins',
'read_post' => 'read',
... etc
);
Is there a generic way to reconfigure a CTP with these values after it has been defined, i.e, via functions.php?
Or would I need to overwrite whatever theme code is creating the CTP, perhaps using a child theme?
Yes you can reconfigure the already defined CPT's properties. By using following filter: register_post_type_args
Src: https://developer.wordpress.org/reference/hooks/register_post_type_args/
Filters the arguments for registering a post type.
For example you can change slug like this:
add_filter('register_post_type_args', 'movies_to_films', 10, 2);
function movies_to_films($args, $post_type){
if ($post_type == 'movies'){
$args['rewrite']['slug'] = 'films';
}
return $args;
}
You can edit capabilities similarly see already answered question which solved exact problem:
https://wordpress.stackexchange.com/a/215697/30852

Working with forms in drupal 8

I am facing problem with "#markup" in form API.
In Drupal 7 we can use "#markup" form element which look like this:
<?php
$form['test'] = array(
'#type' => 'markup',
'#markup' => '<div><script src="http://localhost/drupal7/sites/all/libraries/test.js"></script></div>',
);
?>
//Here is my custom test.js
(function($) {
Drupal.behaviors.test = {
attach: function(context, settings) {
console.log('testttt');
document.write('*Hello, there!*');
}
};
})(jQuery);
and above code will print "Hello, there!" when form will be render.
Now in Drupal 8 I am using below code but it prints nothing.
<?php
$form['test'] = array(
'#markup' => '<div><script src="http://localhost/project8/sites/all/libraries/test.js"></script></div>',
);
?>
So how can implement this functionality in Drupal 8, which is already working in Drupal 7 .
Under script tag it can be local script or external script..
Please help...
Thanks
In Drupal 8, using "#markup" is not the proposed method to attach javascript files.
You can define libraries in your custom module or theme and attach the library to your form. The library can contain multiple js and (or) css files.
To define a library in your module:
Suppose your module name is "my_module", create a file "my_module.libraries.yml" in your module folder and specify the js and css files like this
form-script:
version: 1.x
css:
theme:
css/form.css: {}
js:
js/form.js: {}
js/form-ajax.js: {}
dependencies:
- core/jquery
In order to attach this library to your form:
$form['#attached']['library'][] = 'my_module/form-script';
Then clear cache. The js and css files will be loaded in the same order as you mentioned in the libraries.yml file.
You can define multiple libraries in the same "my_module.libraries.yml" file.
#markup still works in Drupal 8, but now it is filtered before output. As it is stated in Render API overview:
#markup: Specifies that the array provides HTML markup directly. Unless the markup is very simple, such as an explanation in a paragraph tag, it is normally preferable to use #theme or #type instead, so that the theme can customize the markup. Note that the value is passed through \Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS vectors while allowing a permissive list of HTML tags that are not XSS vectors. (I.e, and are not allowed.) See \Drupal\Component\Utility\Xss::$adminTags for the list of tags that will be allowed. If your markup needs any of the tags that are not in this whitelist, then you can implement a theme hook and template file and/or an asset library. Aternatively, you can use the render array key #allowed_tags to alter which tags are filtered.
As an alternative you may use FormattableMarkup:
'#markup' => new FormattableMarkup('<div><script src="http://localhost/project8/sites/all/libraries/test.js"></script></div>', []),
though it is not recommended in this case.

How do i set a specific template for a specific module in drupal 6 using hook_theme

Is there any way by which i could assign a template to my custom module.I heard it may be possible.I tried out with the hook_theme function.My hook_theme looks something like this
function special_theme() {
return array(
'special' => array(
'template' => 'special',
'arguments' => array('link' => NULL),
),
);
}
I do have a special.tpl.php file in my module folder.But the tpl file is not called.Its my default template that is been shown as output.Could someone please help me in the right direction.would be very helpful.
What you define via hook_theme() is an available template, not one that is automatically used. In order to use that template you need to call theme('special', $link);.
It is also advised to avoid using simple words for theme names to avoid collisions ( try mymodule_special instead ).
Also note (though basic), that you also need to print the return value of theme(), it does not get automatically printed. So for instance,
print theme('special', $link);

Load view template on module activation

I have developed a blogger-like archive feature (you know, from the feature module).
I want to edit the .module file in order to automatically load the view-template (which is bundled in the feature) into the theme. Is there a way to do it?
On a general level: you should think "features = modules" and leaving theming for... themes! This does not mean that you shouldn't include a template with your feature, but that you should evaluate whether the template you have built suits a general use of your feature or it is specific for your currently used theme. If it is the latter case, you should not package your template file with the feature, but leave it with the theme instead. Just think to how the views module works, to get an idea of what I mean.
[Maybe you are already aware of this and made your considerations to this regards, in which case simply disregard what above. I thought about writing it because your sentence "I want the tpl.php to be actually available for the feature to use it (just as if it were in the active theme folder)" surprised me as general-use templates do not live in the theme folder but in the their module one, and moreover views already provide a "general use" template.]
That said, the way you normally tell drupal to use a given template, is via implementing hook_theme() in your module. In this case - though - given that you are going to override the template defined by views you should implement hook_theme_registry_alter() instead.
Somebody actually already did it. Here's the code snippet from the linked page:
function MYMODULE_theme_registry_alter(&$theme_registry) {
$my_path = drupal_get_path('module', 'MYMODULE');
$hooks = array('node'); // you can do this to any number of template theme hooks
// insert our module
foreach ($hooks as $h) {
_MYMODULE_insert_after_first_element($theme_registry[$h]['theme paths'], $my_path);
}
}
function _MYMODULE_insert_after_first_element(&$a, $element) {
$first_element = array_shift($a);
array_unshift($a, $first_element, $element);
}
Of course you will have to alter the theme registry for your view, rather than for a node (the original example refers to a CCK type).
As on using the template in the views_ui, I am not sure weather the features module already empty the theming cache when you install a feature (in which case you should be good to go). If not, you can trigger it manually by invoking cache_clear_all() from your install file. If emptying the entire cache is too much, you should dig into the views module on how to flush the cache relatively to a single views.
Hope this helps!
Try to add this to your feature .module file
/**
* Implementation of hook_theme_registry_alter().
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
$theme_registry['theme paths']['views'] = drupal_get_path('module', 'MYMODULE');
}
On the .install file use this
/**
* Implementation of hook_enable().
*/
function MYMODULE_enable() {
drupal_rebuild_theme_registry();
}
Here is my snippet to declare views templates stored in the "template" folder of my "custom_module":
/**
* Implements hook_theme_registry_alter().
*/
function custom_module_theme_registry_alter(&$theme_registry) {
$extension = '.tpl.php';
$module_path = drupal_get_path('module', 'custom_module');
$files = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');
foreach ($files as $file) {
$template = drupal_basename($file->filename, $extension);
$theme = str_replace('-', '_', $template);
list($base_theme, $specific) = explode('__', $theme, 2);
// Don't override base theme.
if (!empty($specific) && isset($theme_registry[$base_theme])) {
$theme_info = array(
'template' => $template,
'path' => drupal_dirname($file->uri),
'variables' => $theme_registry[$base_theme]['variables'],
'base hook' => $base_theme,
// Other available value: theme_engine.
'type' => 'module',
'theme path' => $module_path,
);
$theme_registry[$theme] = $theme_info;
}
}
}
Hope it helps someone.

Resources