Drupal *_preprocess with a module - php

I'm new to Drupal dev, and was trying to add an existing region variable to my module's preprocessor function.
Basically, I've created a new region for my site (here's the definition from within side my theme's .info file):
regions[feeds] = Feeds
From Administer->Blocks, I've added the blocks I want to the new "Feeds" region.
Then, from another module, the "Advanced Front Page" module, I'm trying to add some PHP to my "front page" inside this module. The Advanced Front Page module just allows the site to have a landing page, instead of immediately viewing a list of other site content, etc. I've enabled PHP for the content area, and then added the following:
<div>
<?php print $feeds; ?>
</div>
It does not print the "Feeds" region, and I believe it's because that region variable is not accessible from outside of the page.tpl.php file. So after looking around, I came upon these links:
http://drupal.org/node/223430
http://drupal.org/node/237391
From there, I tried to add a preprocessor function for the module "Advanced Front Page", which has a module name of "front_page" (or possibly just "front", I'm not 100% sure). Here's my preprocessor function, that I tried to add to both my template.php file, and the /modules/front/front_page.module file (not at the same time, mind you):
function front_preprocess(&$vars)
{
$vars['feeds'] = theme('blocks', 'feeds');
}
Regardless of where I've placed this file (template.php or front_page.module) it doesn't seem to do anything. Any idea where I might be going wrong?

There are several points to address in your question:
I'd second googletorps answer in that you should approach this in a different way.
The *_preprocess functions can only be used to manipulate/inject variables for templates or theme functions, e.g. page.tpl.php, node.tpl.php, theme_links(), etc. As the front_page module does not use a theme function or (special) template to render its output, you can not make the $feed variable there by means of a *_preprocess function.
Sidenote: With *_preprocess functions, naming is crucial. You need to prefix the function name either with the exact module name or the theme name, depending on where you declare it. So in your example, if you want to add a preprocess function to the module, you'd prefix it with 'front_page_', if you add it to your themes template.php, you'd add 'yourThemeName_'.
You could achieve what you want by creating the blocks directly from code in your frontpage content area. Instead of trying to output the (not available) $feed variable, you could call:
theme('blocks', 'feeds')
This will cause Drupal to return the themed blocks for the given region ('feeds' in this case). Note that this is still not a good way to do it, as even if you don't use the region in your page.tpl.php, it still gets created for every page request made to your site!
So I would go with googletorps suggestion, adding the new region only if there are other uses for it also. If I'd just wanted to add some blocks to the frontpage, I would not create a new region, but configure the blocks to show in the content region and simply restrict them to show only for <front> in their visibility settings.

I haven't tried the advanced front page module, but when dealing with regions, you shouldn't do what you have done. It's a bit hacky and actually not needed. I don't know how the module hook into the templating system, but your problem is probably getting region variables into it's scope. But instead of trying to get the region into the frontpage using the module, you should instead get it into your page.tpl.php. You can actually do what you first tried, but I would suggest that you alter it a bit like this:
<?php if ($feeds): ?>
<div id="feeds">
<?php print $feeds; ?>
</div>
<?php endif; ?>
I have improved in two ways.
By adding the if statement, you don't add empty markup. So you wont get an empty div if $feeds doesn't contain anything.
Adding id's to regions is a good idea. It makes styling them or their content a lot easier, also it adds semantic to your page which html is all about.
Now if you only want your blocks to be shown in the front page you can set that up in each of the blocks settings. So you could possibly just use a region that already exist, unless you want your blocks display a outside an existing region. When adding regions it's not a good practice to only add a region to a single page, instead it's much better to control when it's content should be shown. It might be that you don't need to create a new region, but simply can use one that's already made. Also if you want to make some template changes to your front page, you can also create the front-page.tpl.php where you can create a different template layout for your front page if you so desire.

Related

Magento 2 - move product box HTML to another template

I'm trying to move the HTML that renders a product box (everything that's in the product-item-info div when products are rendered in a loop on list.phtml). This is on Magento 2.4.3-p1.
I need to do this as I want to re-use the same layout in a couple of places in the site - for example, to render a custom selection of products on the homepage and probably re-use the same box for related products when viewing a single product. Currently, I have to maintain the same code in two places.
I assumed I should be able to define a new block such as product.list.box by adding an entry into catalog_category_view.xml such as:
<block class="Magento\Framework\View\Element\Template" name="product.list.box" as="product_list_box" template="Magento_Catalog::product/product-box.phtml">
I would then reference in my list.phtml template such as echo($block->getBlockHtml('product_list_box'));.
However, this doesn't render anything, but I think also creates a problem that I need to inject a custom ViewModel, as well as setting the product to render and pass in other dependencies (such as the $viewMode, $imageDisplayArea and a bunch of other things the standard Luma theme needs to render a product).
So, what's the correct way to move the rendering of a product box into another template? As a relatively new Magento developer, this seems like it should be straightforward, but I can't get the right combination of code to achieve it.
If you define a new block, don't forget to define it's position. First, use <referenceBlock> or <referenceContainer> to define the place you want to put your block.
Then in your block, you can make good use of before or after attributes to define the position of your new block.
You can refer to Official Document for more usages and examples.

Drupal 8 - Getting dynamic content with view data into a page/template

I'm new to Drupal and Drupal 8 and I want to add areas(blocks?) that I can easily add to a page that pulls in and has access to selected view data and fields. What's the easiest way to get this done? It seems like it should be something that's easy to do but Drupal seems to make this really hard to achieve.
I've tried making custom blocks and types via the CMS but then it'd mean editing the content in 2 different places when we need to update areas or add new areas.
I've also tried building a block via a module but I cant seem to pass the information from a view into my template that way.
The blocks will potentially need to be added to more than one page if that' possible too.
What am I missing, why is this so difficult?
Thanks
Although the question is not so specific I would recommend to start from here Understanding Drupal > Overview > The Drupal flow and then move to Drupal Glossary (it is almost the same for 8.x).
This way it will be more easy to understand Drupal parts such as Theme, Region, Block, Template (using Twig for 8.x) etc.
Use the views module to create the block, then use the block layout page admin/structure/block to place the block in an appropriate region. Edit the block and configure the block and set its visibility settings.

Block positioning using admin section

In my admin section i have a block maker.
The block is very simple, block_title, block_content.
What is the simplest way to show / determine a themes layout in the admin section so the user can position the blocks?
One idea is to use numbers so, 1 = block area one, 2 = block area two etc
A function in the front end could look like this:
function showBlocksForArea(1) {
// Return blocks Array where block_area=1
}
Rendered in the theme / template as:
echo'<div id="block_area_one">';
foreach($view->showBlocksForArea(1) as $row) {
echo '
<div class="block_wrap">
<div class="block_title">'.$row['block_title'].'</div>
<div class="block_body">'.$row['block_body'].'</div>
</div>
';
}
echo '</div>';
This is fine, accept the user doesn't know without looking at the theme where those areas are.
The Admin Section
Something like this would be perfect if i could grab just the HTML of the layout:
Is there a simpler way?
The following is an answer based on the chat that occurred here: https://chat.stackexchange.com/rooms/18020/room-for-xdaevax-and-codex
Here is my understanding of your goals:
You are creating a type of CMS application used to create websites
The websites are modular and will allow administrators to easily customize both the look and feel of their website and the content, without having extensive code knowledge
To facilitate this, you've created a system of templates, and content, that can be combined in various ways to create these themed pages. This is driven primarily by a set of PHP functions that extract the template and block data from the DB.
As new themes are created, the admin is able to "just work" without any modification because the functions can pull in any theme and it can be combined with any template.
The templates will have to have a naming structure that is generic so that CSS can be easily swapped out.
Given this information, I would suggets doing the following:
Database Schema
I would set up a database structure to something that resembles this schema I made:
The idea here is that a Template record can have any number of "slots". The DB is agnostic in terms of where the slots go on the page (this is the responsibility of the theme), but the TemplateSlots are used to provide "place holders" for where content (Blocks) can be placed.
Each time a user creates a new Page, a Page record is added and the page is associated with a Template, from which it also has information about the slots. The Template also defines a file (a PHP file most likely) that specifies place holders where the slots are placed. The Page gets the Theme information from the Site which it is associated with. Each Theme can have a set of ThemeContents (multiple CSS files, js files, images, etc....).
Blocks can be created that could have content assigned to them. These blocks are independent of a Template initially, and the DB could be pre-populated with common building 'blocks'. These blocks can be associated with a Template and assigned a TemplateSlot once a block is assigned to a Page by having a PageBlock record created.
DB Conclusion
This structure allows a great deal of flexibility and allows the Database to handle many potentially complex user scenarios. By segmenting the Template and Slots into separate tables, you can dynamically create templates of all shapes and sizes without having to make any code changes.
PHP Admin
For your admin, you can use whatever mechanism you like to pull the data out of the DB. But the user workflow would look something like this:
Log in to admin
Select Operation (a-> Create New, b-> Update Existing)
Select Page Template
Assign content blocks to template slots
Preview
Compile changes (a -> Save New Page, b-> Update Existing)

Where to find a list of pages automatically renderable in Drupal and how it works?

In the pages .tpl.php of my theme i can find several lines like
render($action_links)
displaying whole pages with a single command. Sometime i saw that the render argument is a block from my theme .info, but other times i see arguments i cannot identify that render default pages or elements of drupal.
How it works? And where i can find a list of default displayable pages?
In particular, i needed to display the content of the default drupal page "add content" in one of my pages, and i'm pretty sure i can do it using this render method, but i cannot find the correct argument.
EDIT: I found something like
drupal_render(node_add('NODE_TYPE'));
that seems to allow the display of a node add form, but what i need is the main add content page, containing the list of all the type of nodes that a user can add.
Are you new to Drupal? When I read your post, I'm almost sure that you have missed something with the Drupal's working. The variables you found in render() functions are "calculated" somewhere else in the code (in the modules part for the most).
You cannot find a list of constant variables to display them just like this.
I found this article about these mysterious variables that are rendered and I hope it will help: http://newsignature.com/articles/the-magic-behind-drupals-render-elements
If you just want to display the "add content" form somewhere on your site, just call its path (node/add).
EDIT AFTER CLARIFICATIONS:
First of all, you can set on which page you want the user lands after login. (I don't know why you're still talking about user profile template. Maybe I missed something again.)
But if I did understand what you're trying to achieve, I'll do that:
Create a menu (or simply use the "Navigation" menu that seems to be exactly what you need) with all the actions users can do. And I'll place this menu in the main content region. Do create a menu, go to Administration>Structure>Menus>Add menu. And add links like "node/add/article" or "node/add/news" or "node/add/page" or whatever your content-types are.
Place this menu in the region you want. If you want it to be like the main content of the page, place it in the main container. To do so, go to Administration>Structure>Blocks> Drag and drop your menu in the right region and Save.
Configure this block to appear only on the front page (the first page on user arrives after logged in) if you want so. To do so, in the Blocks administration page, click on "Configure" next to your block and check "show block on specific pages: Only the listed pages" and write down <front>
Create roles and permissions for your different sorts of users. That will automatically show them the links they are allowed to see. To set permissions, go to Administration>People>Permissions and check in the "Node" section which content-type each role can create.
I hope I didn't forget anything. Please tell me if it is clear enough.

drupal: add search field to an article

how can I add the search field (searching for all content and tags in my webiste) to my article ?
I've already installed and activated the module, but I would like to add it to a single article instead of a block of my website
thanks
There are several ways of doing searching in Drupal, but I guess you refer to the search module that's in Drupal core. It's usually used as a block which makes it a bit tricky if you want to display it with the article content.
You can use the theme function to theme a block like this:
<?php print theme('block' $block); >?
Where $block is a block object with all the data needed. To use this in your case, you could make a custom template for the article, since you only want to display the search block on one article. You would also need to make a preprocess function for the article (preprocess_node) where you create the block object. You could also just create some logic in the preprocess function and make a generic node template where you only print the block when it's there.
It is possible to control when blocks are displayed, so you could just setup your search block to only be displayed on your chosen article. That is far less work, but you wont be able to display it with the article content.

Categories