Drupal 8 Delete layout prefix - drupal

I have a page, created via page manager with the layout type - "One Column". I placed blocks on the page and when I open this page, I see my blocks wrapped by a
<div class="block-region-content">
When I print content variable in twig template, I can see that this div is the value of #prefix property
content array(12)
'content' => array(4)
'#prefix' => string(34) "<div class="block-region-content">"
'#suffix' => string(6) "</div>"
How can I delete this properties?

You can implement hook_preprocess_HOOK to achieve this. For example, you should probably preprocess blocks within your theme (same can be done from a module though) :
function THEME_preprocess_block(&$vars) {
// Act on a specific block, eg. here the page title block
if ($vars['plugin_id'] === 'page_title_block') {
unset ($vars['content']['#prefix'], $vars['content']['#suffix']);
}
}

Related

How to add a Bootstrap grid to the wordpress Editor as a selection or dropdown menu

Problem: I'm looking to expand our WordPress theme(s)/websites to make it easier for our communications team to create posts and pages by adding in Bootstrap rows and columns.
My idea is to create A custom Field type with a selection to add in rows and columns to fit our themes pages.
Has anyone done something like this? We are using Divi Builder but that is a bit complicated for average users and we are not in arush to create a whole new theme for our 30+ websites.
Or would I need to create a custom plugin for that? I'd rather not use a third party plugin for security reasons
So are you wanting output bootstrap markup in your default wordpress editor to make rows and columns etc?
Short answer is no, the wysiwyg editor is only really built for paragraphs, headings, quotes, horizontal rules, lists, images, inline formatting etc...
In order integrate bootstraps block layout markup would require some extra level of builder addon. Elementor definitely could do the job with some super customisation, even ACF flexible content would do it, and i think even WP Gutenberg can do this natively... but would require customisation to use bootstrap markup.
But if you wanted to attempt and utilise the standard wordpress editor (not Gutenberg editor) using the element dropdown (paragraph, headings etc by default).
You could try this, however I recommend loading the same front end bootstrap css into the wysiwyg editor so you can instantly see changes.
Please note this method below is risky as the user would need to understand how bootstraps row/column structure should be formatted. The probability of html markup going wrong is highly likely. Hence using an actual block element builder (like Elementor or ACF) would be a safer choice.
Anyway, see below example of how to customise standard wordpress wysiwyg editor dropdown for wrapping html tags around content.
First load the same front end bootstrap css into the wysiwyg editor...
// editor stylesheet (containing the front end css for the post content)
add_editor_style('dist/css/editor.css');
Now lets add the styleselect dropdown to our wysiwyg editor...
// add the style select dropdown to our wysiwyg editor
add_filter('mce_buttons_2', 'formatting_dropdown');
/**
* #link https://developer.wordpress.org/reference/hooks/mce_buttons_2
* #param $buttons
* #return mixed
*/
function formatting_dropdown($buttons) {
// global post object
global $post;
// if no post return param
if(!$post) return $buttons;
// switch case for post types or type to run this on (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// reveal the hidden “Styles” dropdown in the advanced toolbar
array_unshift($buttons,'styleselect');
return $buttons;
default;
return $buttons;
}
}
And then add your bootstrap formatting settings using this filter below...
// init filter for handling the style select options
add_filter('tiny_mce_before_init', 'formatting_dropdown_options');
/**
* #link https://developer.wordpress.org/reference/hooks/tiny_mce_before_init/
* #param $mceInit
* #return mixed
*/
function formatting_dropdown_options($mceInit) {
// global post
global $post;
// if no post return param
if(!$post) return $mceInit;
// switch case for post type (page/post)
switch ($post->post_type) {
case 'page':
case 'post';
// new style array
$style_formats = [
[
'title' => 'row',
'block' => 'div',
'classes' => 'row'
],
[
'title' => 'col',
'block' => 'div',
'classes' => 'col'
]
];
// bs5 breakpoints
$breakpoints = ['xs','sm','md','lg','xl','xxl'];
// bs5 column grid
$grid = 12;
// add bs5 column classes to $style_formats array
foreach ($breakpoints as $breakpoint) {
foreach (range(1, $grid) as $column) {
$style_formats[] = [
'title' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column,
'block' => 'div',
'classes' => $breakpoint === 'xs' ? 'col-' . $column : 'col-' . $breakpoint . '-' . $column
]
}
}
// override style format with new style formats
$mceInit['style_formats'] = json_encode($style_formats);
// init array
return $mceInit;
break;
default;
// init array
return $mceInit;
}
}

Add Composer Control Output Block Pragrammatically

I'm creating pages programmatically and inserting content to a Content Block but after it has been created, I can't edit it via composer (because it's not a core_page_type_composer_control_output, it's a regular content block). Is there a way to add a block to a page programmatically and have it play nice in Composer?
Relevant code I'm using:
$page = Page::getByPath('/articles/xxx');
$block = BlockType::getByHandle('content');
$data = array(
'content' => 'the content',
);
$page->addBlock($block, 'Main', $data);
To achieve this, I would setup the pagetype as you would create the page with composer.
(add the content block to composer and the standard output of the pagetype)
After creating the page, you will notice the composer-linked content block is present on the page but completely empty. Then I would update the block instead of trying to create a new block in the 'Main' area.
Code example (not tested):
$page = Page::getByPath('/articles/xxx');
$blocks = $page->getBlocks('Main');
if(!empty($blocks)){
foreach($blocks as $block){
//check if the blocktype is content
if($block->getBlockTypeHandle() == 'content'){
//we are pretty sure this is the content block in the main area
//because it's the only content block present... updating the block content
$data = array(
'content' => 'the content',
);
$block->update($data)
}
}
}

In nodereference field of a content type, Is it possible to show the content type name added with the autocomplete results?

In nodereference field of a content type, Is it possible to show the content type name added with the autocomplete results ?
Example :
I have a content type named Article which has a node reference field (Related content -> field_related_documents), So that this article will referenced to other nodes.
While creating an article, by entering 'help' in 'field_related_documents' I am getting autocomplete results (titles of referenced nodes) like below
helpsystems - rules
Decision management Help
Using help menu
Help support glossary
Instead, I like to show results like below
Page | helpsystems - rules
HelpSystems | Decision management Help
Page | Using help menu
Document | Help support glossary
ie) autocomplete results should display title of other nodes added with their related content type.
How should i achieve this ? Is there any contributed modules available to achieve this?
I created a new custom Module nodereference_patch with below hook
/*
* Altering nodereference/autocomplete menu using menu alter
*/
function nodereference_patch_menu_alter(&$items) {
$items['nodereference/autocomplete']['page callback'] = 'nodereference_patch_new_nodereference_autocomplete';
}
Then, I copied the nodereference_autocomplete function into your custom module, changing it's name to nodereference_patch_new_nodereference_autocomplete.
Then I changed this line:
$matches[$row['title'] ." [nid:$id]"] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
to
$matches[$row['type'] . " | " . $row['title'] . " [nid:$id]"] = '<div class="reference-autocomplete">' . $row['type'] . " | " . $row['rendered'] . '</div>';
I copied _nodereference_potential_references function from nodereference.module to custom module and renamed it as _nodereference_patch_potential_references
Then I changed the following line as
$references = _nodereference_potential_references_standard($field, $string, $match, $ids, $limit);
to
$references = _nodereference_patch_potential_references_standard($field, $string, $match, $ids, $limit);
I copied _nodereference_potential_references_standard from nodereference.module to custom module and renamed it as _nodereference_patch_potential_references_standard
Then I added 'type' element to $references[]. ie) changed following array from
$references[$node->nid] = array(
'title' => $node->node_title,
'rendered' => check_plain($node->node_title),
);
to
$references[$node->nid] = array(
'title' => $node->node_title,
'type' => $node->node_type,
'rendered' => check_plain($node->node_title),
);
I'd be more inclined to use a different approach, using similar methods but rather than copying the full module and renaming this I'd create a new menu_hook and form_alters to update the autocomplete path.
If you're using entity reference rather than node reference you can use views to display the content, not my preferred route but will reduce the amount of custom code. Quick google of a demonstration of this gives the following video (http://codekarate.com/daily-dose-of-drupal/using-views-entity-reference-module-drupal-7)
Also, just a note, if you plan to copy the module out like the above answer I would strongly advise to remove some of the lines from the module info file. The information below '; Information added by drupal.org packaging script on' in the info file is used by the update module and increases the risk of this new module being replaced by the original module.

Drupal 7 Views custom view template fields

I've successfully created a custom view template for my Drupal 7 site but am having issues adding attributes to the content which is outputted. I've searched high and low for the answer to this but to no avail.
I have a view called: views-view-fields--homepage-articles.tpl.php
I am printing content like :
$fields['title']->content
This is fine and expected, and outputs:
Title
But I want to add classes to it - how? I'm thinking I need to write a hook, but I cannot find this documented anywhere. At the moment my solution is a string replace:
<?php print str_replace('<a ', '<a class="brand-blue uppercase nodecoration"', $fields['title']->content); ?>
As you can imagine, this is not a satisfactory or long-term solution.
Many thanks!
You should be able to add the classes to the field using template_preprocess_views_view_fields().
Edit: Couldn't do it the way I thought, but you can overwrite the output of the field like so:
function MY_THEME_preprocess_views_view_fields(&$vars) {
$view = $vars['view'];
if ($view->name == 'node_listing') {
foreach ($vars['fields'] as $id => $field) {
if ($id == 'title') {
$field_output = l($view->result[$view->row_index]->node_title, 'node/'. $view->result[$view->row_index]->nid, array('attributes' => array('class' => 'brand-blue uppercase nodecoration')));
$vars['fields'][$id]->content = $field_output;
}
}
}
}
Have you tried using Semantic Views? https://drupal.org/project/semanticviews - that way you can override the classes within the UI instead of template files, may suit your needs better.

How to alter a MENU_LOCAL_TASK tab menu in Drupal

I have built a tabbed menu in my custom Drupal 6 module. I want to position an html dropdown list to the right of the tabbed menu at the top of my module page. The list will fire some ajax events on change e.g. changing the LIMIT clause on SQL query by specifying 10,20,50,100 results. How can I achieve this in Drupal without hacking templates?
Thanks,
You could do this by overriding theme_menu_local_tasks() within your theme:
function yourTheme_menu_local_tasks() {
// Prepare empty dropdown to allow for unconditional addition to output below
$dropdown = '';
// Check if the dropdown should be added to this menu
$inject_dropdown = TRUE; // TODO: Add checking logic according to your needs, e.g. by inspecting the path via arg()
// Injection wanted?
if ($inject_dropdown) {
// Yes, build the dropdown using Forms API
$select = array(
'#type' => 'select',
'#title' => t('Number of results:'),
'#options' => array('10', '20', '50', '100'),
);
// Wrap rendered select in <li> tag to fit within the rest of the tabs list
$dropdown = '<li>' . drupal_render($select) . '</li>';
}
// NOTE: The following is just a copy of the default theme_menu_local_tasks(),
// with the addition of the (possibly empty) $dropdown variable output
$output = '';
if ($primary = menu_primary_local_tasks()) {
$output .= "<ul class=\"tabs primary\">\n". $primary . $dropdown . "</ul>\n";
}
if ($secondary = menu_secondary_local_tasks()) {
$output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
}
return $output;
}
(NOTE: Untested code - potential typos)
As you are referring to code to put in a module, then the module should implement hook_theme_registry_alter(), which would allow the module to override the function theme_menu_local_tasks(). The module should store the value of the previous callback, so that it could still call it in the case the page it not one that it should change.
Implementing a hook in the module allows you to have the normal menu tabs, once the module has been disabled; altering the current theme would require you to change it back when you want the functionality anymore, and if you are using a theme made from another person you should change the theme all time you download a new version. If you are using more than one theme, then you should make the change to each used theme.
In general, a modification to a theme that is required from a module should be done inside a module.

Resources