I am trying to make a module for Drupal 7 that provides a block and has certain configuration settings. Now what I want is that I want to provide 5 blocks to the user so that they can use different settings in each block. In other words, I want to provide each block a separate set of settings. How can I do that?
Edit:
Actually I have made a module that shows a single block. If you have used superfish menu module then you can see there that they allow us an option to choose how many block should be made available. So that for each block we can use different menu to show. I am talking about that functionality
Create a configuration page:
function my_module_admin_settings($form, &$form_state) {
$form['my_module_number_of_blocks'] = array(
'#title' => t('Post to Blog by default'),
'#description' => t('Should content post to blog by default or only when selected?'),
'#type' => 'select',
'#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10)),
'#default_value' => 2,
);
return system_settings_form($form);
}
You create blocks in a module using hook_block_info you define an array like:
hook_block_info() {
number_blocks = variable_get('my_module_number_of_blocks', 0);
$x=0
while ($x < number_of_blocks) {
$blocks['myblock-' . $x] = array(
'info' => t('Block ' . $x),
'cache' => DRUPAL_NO_CACHE,
);
}
return $blocks
}
You'll configure the values in hook_block_configure:
function hook_block_configure($delta = '') {
// This example comes from node.module.
$form = array();
$parts = explode($delta, '-');
if ($parts[0] == 'my_block') {
$form['my_block_' . $parts[1] . '_option1'] = array(
'#type' => 'select',
'#title' => t('Some option'),
'#default_value' => variable_get('my_block_' . $parts[1] . '_option1', 'first_option'),
'#options' => drupal_map_assoc(array('first option', 'second option')),
);
}
return $form;
}
Once you have defined your blocks you need to tell them how to display with hook_block_view. Something like:
function hook_block_view($delta = '') {
$block = array();
$parts = explode($delta, '-');
if ($parts[0] == 'myblock') {
$block['subject'] = t('Block' . $parts[1]);
$block['content'] = my_module_block_b_generate($parts[1]);
}
return $block;
}
Then you'll use the block number and configuration to determine the output:
my_module_block_b_generate($block_number) {
$option1 = variable_get('my_block_' . $block_number . '_option1', 'first_option');
return t('this is block ' . $block_number . '. It has chosen option ' . $option1 . ' for option1');
}
Related
Why am I getting sprintf(): Too few arguments here php error here while trying to use this in items_wrap on wp_nav_menu()?
$menu = wp_get_nav_menu_object('primary-menu');
$navId = $menu->term_id;
$menuId = 'menu_' . $navId;
$navUrl = get_field('social_media_url', $menuId);
$navImg = get_field('social_media_img', $menuId);
if ($navUrl && $navImg) {
$socialOption = '<ul id="%s" class="%s">%s<li class="menu-social-option"><img src="' . esc_attr($navImg['url']) . '"></li></ul>';
} else {
$socialOption = '<ul id="%1$s" class="%2$s">%3$s</ul>';
}
$navArray = array(
'theme_location' => 'primary', // Defined when registering the menu
'menu_id' => 'primary-menu',
'container' => false,
'depth' => 2,
'items_wrap' => $socialOption,
'menu_class' => 'navbar-nav ml-auto',
'walker' => new Bootstrap_NavWalker(), // This controls the display of the Bootstrap Navbar
'fallback_cb' => 'Bootstrap_NavWalker::fallback', // For menu fallback
);
wp_nav_menu($navArray);
When I remove esc_url($navUrl) then I get this type of error uncaught ValueError: Unknown format specifier "C" in. This only happens with PHP versions 7.4+
Cheers
My solution to this issue. Turns out I don't have to use sprintf again.
To wrap an extra item to wp_nav_menu with ACF variables I use this function. If any of ACF variables are empty then it just returns $items which is set by Wordpress.
function add_last_nav_item($items)
{
$menu = wp_get_nav_menu_object('primary-menu');
$navId = $menu->term_id;
$menuId = 'menu_' . $navId;
$navUrl = get_field('social_media_url', $menuId);
$navImg = get_field('social_media_img', $menuId);
if ($navUrl && $navImg) {
return $items .= '<li class="menu-social-option"><img src="' . esc_attr($navImg['url']) . '"></li>';
} else {
return $items;
}
}
add_filter('wp_nav_menu_items', 'add_last_nav_item');
$socialOption = '<ul id="%1$s" class="%2$s">%3$s</ul>';
Thank you #RiggsFolly for helping me figure this out
I have come across a problem that I hope is an easy fix but I am just not seeing it. I have wrote some code that targets a certain content type's field.. in that field if it is empty then I want the code to return the value of another field in that content type. I have reworked this several times but I am stuck. I am hoping someone can point out what I am doing wrong. Thanks
Here is the code:
function randomname_preprocess_node__events__sfa_teaser(&$variables) {
// Populates the title variable from the node revision being viewed.
$route_match = \Drupal::routeMatch();
$node = $route_match->getParameter('node');
if ($node) {
if (is_string($node)) {
$node = Node::load($node);
}
$content_type = $node->getType();
if ($content_type === 'randomcontenttypename') {
$parent_title = $node->title->value;
$generic_link = $node->get('field_generic')->uri;
$populated_link_text = $node->get('field_populated_link_text')->value;
if ($entity->get('populated_link_text')) {
$populated_link_text = $entity->get('populated_link_text')->entity;
$variables['populated_link_text'] = [
'#type' => 'link',
'#title' => $populated_link_text->value,
'#url' => $populated_link_text,
];
}
else {
if ($generic_link) {
$generic_link = Url::fromUri($generic_link);
$variables['generic_link'] = [
'#type' => 'link',
'#url' => $generic_link,
'#title' => t('This page will display #parent_title', ['#parent_title' => $parent_title]),
'#attributes' => ['class' => 'viewalllink'],
];
}
$variables['#cache']['max-age'] = 0;
}
}
}
thanks for any help that can be tossed my way.
How can I make this parser more efficient? I feel like these if statements are crazy! I'm thinking that a callback function would be able to get the job done.
However, most of my identifiers are wildly different and I need to go through many different keys. Should I make an array of tags and an array of DOM elements and create a callback function for each one to strip out the null values? I'm trying to put together a scraper for the first time and I'm really getting stumped by the logic here.
Any help would be seriously appreciated!
foreach($html->find('.b-card') as $article) {
$data[$y]['business'] = $article->find('h1', 0)->plaintext;
$data[$y]['address'] = $article->find('.address', 0)->plaintext;
if($article->find('.phone-num', 0)) {
$data[$y]['phone'] = $article->find('.phone-num', 0)->plaintext;
} else {
$data[$y]['phone'] = 'Number not listed.';
}
if($article->find('.link', 0)) {
$data[$y]['website'] = $article->find('.link', 0)->plaintext;
} else {
$data[$y]['website'] = 'Website not listed.';
}
if($article->find('.established', 0)) {
$data[$y]['years'] = str_replace("\r\n","",$article->find('.established', 0)->plaintext);
} else {
$data[$y]['years'] = 'Years established not listed.';
}
if($article->find('.open-hours', 0)) {
$data[$y]['hours'] = $article->find('.open-hours', 0)->plaintext;
} else {
$data[$y]['hours'] = 'Hours not listed.';
}
if($article->find('.categories a', 0)) {
$data[$y]['category'] = $article->find('.categories a', 0)->plaintext;
} else {
$data[$y]['category'] = 'Category not listed.';
}
$articles[] = $data[$y];
}
}
I feel like I could do something like this
function my_callback($element) {
// remove all null tags
if ($element->tag)
$article->find....;
}
Use an array that collects all the related information in each if block.
$selector_list = array(
array('selector' => '.phone-num', 'index' => 'phone', 'name' => 'Number'),
array('selector' => '.link', 'index'' => 'website', 'name' => 'Website'),
array('selector' => 'open-hours', 'index' => 'hours', 'name' => 'Hours'),
array('selector' => '.categories a', 'index' => 'category', 'name' => 'Category')
);
Then you can use a simple foreach loop with all the common code:
foreach ($selector_list as $sel) {
$found = $article->find($sel['selector'], 0);
if ($found) {
$data[$y][$sel['index']] = $found;
} else {
$data[$y][$sel['index']] = $sel['name'] . " not listed.";
}
}
// Special case for selector that doesn't follow the same pattern
$found = $article->find('.established', 0);
if ($found) {
$data[$y]['years'] = str_replace("\r\n", "", $found);
} else {
$data[$y]['years'] = Years established not listed.';
}
If you want the loop to be able to handle the one that requires special handling you could add a callback function to the array. But if it's just one weird case, that may be overkill.
Hi I am trying to add html to the "t('Older Posts')" and "t('Newer Posts')" Is this possible ? I can figure it out ????
I am in a Drupal 6 template.php file.
This is the code I am trying to add as html -
<span>Newer Posts</span>
<span>Older Posts</span>
I need to replace the above in these spots located in the full function below ?
t('Older Posts')
t('Newer Posts')
I want to create something like this
t('<span>Older Posts</span>')
t('<span>Newer Posts</span>')
Full Function
function theme_views_mini_pager($tags = array(), $limit = 10,
$element = 0, $parameters = array(), $quantity = 9) {
global $pager_page_array, $pager_total;
// Calculate various markers within this pager piece:
// Middle is used to "center" pages around the current page.
$pager_middle = ceil($quantity / 2);
// current is the page we are currently paged to
$pager_current = $pager_page_array[$element] + 1;
// max is the maximum page number
$pager_max = $pager_total[$element];
// End of marker calculations.
$li_previous = theme('pager_previous', (isset($tags[1]) ? $tags[1] :
t('Older Posts')), $limit, $element, 1, $parameters);
if (empty($li_previous)) {
$li_previous = " ";
}
$li_next = theme('pager_next', (isset($tags[3]) ? $tags[3] : t('Newer Posts')),
$limit,$element, 1, $parameters);
if (empty($li_next)) {
$li_next = " ";
}
if ($pager_total[$element] > 5) {
$items[] = array(
'class' => 'action back pager-previous',
'data' => $li_previous,
);
$items[] = array(
'class' => 'action pager-next',
'data' => $li_next,
);
return theme('item_list', $items, NULL, 'ul', array('class' => 'pager'));
}
}
I am trying to figure out if this is possible I have tried many things and nothing has worked yet.
You can use
$link = '<span>' . t('Older Posts') . '</span>';
OR
$link = t('!link_startOlder Posts!link_end', array(
'!link_start' => '<a href="" class="action back"><span>',
'!link_end' => '</span></a>',
));
I am trying to theme particular pagers on the site and no matter what id I try it doesn't seem to get picked up. This is what I am using to theme all pagers now.
function Subtle_Hightlights_views_mini_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
global $pager_page_array, $pager_total;
// Calculate various markers within this pager piece:
// Middle is used to "center" pages around the current page.
$pager_middle = ceil($quantity / 2);
// current is the page we are currently paged to
$pager_current = $pager_page_array[$element] + 1;
// max is the maximum page number
$pager_max = $quantity;
// End of marker calculations.
$li_previous = theme('pager_previous', (isset($tags[1]) ? $tags[1] : t('')), $limit, $element, 1, $parameters);
if (empty($li_previous)) {
$li_previous = "";
}
$li_next = theme('pager_next', (isset($tags[3]) ? $tags[3] : t('')), $limit, $element, 1, $parameters);
if (empty($li_next)) {
$li_next = "";
}
if ($pager_total[$element] > 1) {
$items[] = array(
'class' => 'pager-previous-mini',
'data' => $li_previous,
);
if ($pager_current == 9){
$li_next = "";
}
$items[] = array(
'class' => 'pager-current-mini',
'data' => t('#current of #max', array('#current' => $pager_current, '#max' => $pager_max)),
);
$items[] = array(
'class' => 'pager-next-mini',
'data' => $li_next,
);
return theme('item_list', $items, NULL, 'ul', array('class' => 'pager'));
}
}
now this works to theme all mini pagers but when I try to apply the name of the view and block like this.
function Subtle_Hightlights_views_mini_pager__news_items__block_2($tags = array(), $limit = ``10, $element = 0, $parameters = array(), $quantity = 9) {
does nothing acts as though the code isnt there anymore. Anyone else tried this and it actually worked?
There is a good step by step instructions on how you can overwrite the pager (mini or full). The only step that I would suggest that you do different is when you get to list of theme function names that you can use to override your views pager inside your template.php file, just use this module: Theme developer. Once it's enabled it will provide in a much easier way the suggestions. If that fails, then just try the article's methods.
Drupal 6 Override views pager theme function