symfony 2 domCrawler how to get all child elements of <body> - symfony

Maybe this is a stupid question but I need to get an Object with all HTML nodes from a selected html Page. I have to make all nodes selectable, especially the opening tags. If anyone know the template Engine from TYPO3 TemplaVoila; I think this suits it best but I would like to rebuilt it by myself but I don't have any Idea how to get all opening Tags into an Object.
If anyone can push some Details, actually, I'm testing around with domCrawler like this but it is a bit confusing....
foreach ($crawler as $domElement) {
foreach ($domElement as $test){
var_dump($test->nodeName);
}
var_dump($domElement);
$html .= $domElement->ownerDocument->saveHTML($domElement);
}
So after some research, I am unsing HTMLPageDom and use it like that:
$css= new HtmlPage();
$css = new HtmlPage($head);
$cssNew = $css->filter('link')->each(function ($node) {
$node= $node->attr('href');
return $node;
});
So this works more or less but I'm thinking that I missunderstood something. How can I append data to $node->attr('href)?
With:
$node->attr('href')->append('data in front of linkuri');

You can try by this way:
/.../
$values = $crawler->filterXpath('//body')->each(function ($node) {
return $node->html();
});
/.../

SOLUTION:
Ok at least I was thinking too weired :)
It's just so simple:
$body->filter('img')->setAttribute('src', $this->absPath.$bodySource->filter('img')->attr('src') );

Related

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 modify the body of a node via a module in Drupal 8

I created a module to highlight the code samples in the articles based on the highlight.js library. This library require code samples to be embed in <pre><code> ... </code></pre> tags. I don't want to add the <pre> tag when I write an article, because other highlighter libraries don't need it and I want to be able to switch library without modifying the articles. So I need to dynamically wrap <code> tags with <pre>. I tried to implement _node_view( and _node_view_alter( hooks without success.
My code look like
function highlight_node_view($node, $view_mode, $langcode) {
$node->content['body']['und'][0]['safe_value'] = "test";
$node->body['und'][0]['safe_value'] = "test";
$node->content['body']['und'][0]['value'] = "test";
$node->body['und'][0]['value'] = "test";
}
function highlight_node_view_alter($build, $node) {
$build["body"]["#items"]["0"]["value"] = "TEST";
$build["body"]["#items"]["0"]["safe_value"] = "TEST";
$build["body"]["#formater"]["0"]["#markup"] = "TEST";
}
If I print the content in my template with
<pre>
<?php
ob_start("minimal_htmlspecialchars_callback");
print_r($content);
ob_end_flush();
?>
</pre>
I can confirm that all the values are correctly replaced by "test" but a call to
<?php print render($content['body']); ?>
still render the original content instead of "test"
What is the proper way to alter the content of an article from a module ?
I have successfully altered body field data, you have to place code in your module file like bellow. BTW I'm using drupal 8.2
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
/**
* Implements hook_ENTITY_TYPE_view() for node entities.
*/
function module_name_node_view(array &$build, EntityInterface $node, EntityViewDisplayInterface $display, $view_mode) {
$build['body'][0]['#text'] = 'test by ajay';
}
I finally found a solution in a previous stackoverflow question ( Modify how a node in drupal will look when viewed ) and the following code work fine.
function highlight_node_view($node, $view_mode, $langcode) {
$alteredBody = $node->body['und'][0]['safe_value'];
$alteredBody = str_replace("<code>", "<pre><code>", $alteredBody);
$alteredBody = str_replace("</code>", "</code></pre>", $alteredBody);
$node->content['body'] = array(
'#markup' => $node->body['und'][0]['safe_value'] = $alteredBody
);
}
But I'm still not sure to fully understand the rendering system. So if somebody have a better solution or a more detailed explanation, I'll appreciate it.

Get current page/url in a hook

In hook_css_alter, I want to disable style-sheets on specific pages.
Was ok for the front page requirement with following snippet:
function morin_css_alter(&$css) {
if(drupal_is_front_page()){
foreach ($css as $data => $item) {
unset($css[$data]);
}
}
}
Now I need to remove specific styles on a photo-album page. I have thought of a few ways to do this, but I'd like to do it the drupal way.
The closest function I have found to do this is drupal_get_destination() ,
I don't think it's meant for this but it does return the current path in an array, as shown by the following snippet added in css_alter hook.
echo " PATH = " . var_dump(drupal_get_destination());
Output: PATH = array(1) { ["destination"]=> string(6) "photos" }
Is this the recommended way of getting the path from inside a function/hook, or is there some variable in global namespace I should use instead?
You want http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/request_path/7.
For Drupal 6, one has to use $_GET['q'].

Make a visible primary link not clickable

On my Drupal site I've got a set of Primary Links. The ones that expand I'd like to make the parent not click able e.g
-home
-about
-history
-website
Only home, history, website should link to a page. If the user clicks on aboutnothing should happen. I've tried searching around the admin panels as well as leaving the field blank but it doesn't seem to be working. I'd assume I'd have to hardcode this? If so, how?
Try this module http://drupal.org/project/special_menu_items
Its probably the simplest way to achieve what you want.
If you can live with it, the easiest solution is to use js to disable clicks.
Adding a yourtheme_menu_item function in template.php seems to be the way to go for this. The documentation for the original function is at http://api.drupal.org/api/function/theme_menu_item
The function passes a $has_children variable and a $menu variable, so it should be pretty easy to adjust Primary Menu items with children as needed.
Some untested example code:
function yourtheme_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
// ... original theme code copy-pasted ...
if ($has_children) {
$modified_link_name = youtheme_write_menu_item_without_links($link);
return '<li class="'. $class .'">'. $modified_link_name ."</li>\n";
} else {
// From original function
return '<li class="'. $class .'">'. $link . $menu ."</li>\n";
}
}
You just need to add in the path the phrase <nolink>.
"You just need to add in the path the phrase <nolink>"
i used this before and it worked, but for some reason it didnĀ“t work for a different site that i am using now.
So i tried to write # in the path and worked fine for me.
Hug everybody.

How to hide Edit | View tabs?

Can I hide the
Edit | View
tabs on top of each node ?
I've searched for this option in theme settings (both global and standard theme but I couldn't find it).
I still want to be able my customer to edit / administer content, so I cannot just remove the permission for it.
thanks
here is a very easy solution for you. (Drupal 7)
Open your page.tpl.php in your current template and search for the $tabs variable.
Remove the render code if you want to hide it completely.
If you want to display it only to administrators use this code
<?php if ($tabs and $is_admin): ?>
<div class="tabs">
<?php print render($tabs); ?>
</div>
The above code checks if the user is administrator. If it is it will render the tabs. If not it wont render them.
This really is a presentational thing, not a functionality thing, so it should be done at the theme level.
The problem with overriding theme_menu_local_tasks() is that you override/take a hatchet to the entire local task display, when you really just want to get in there with a scalpel to remove two specific local tasks. So, you need to get a little more specific.
theme_menu_local_tasks() gets the current page's local tasks and passes them to menu_local_tasks(). Here, two theme functions are used:
theme_menu_item_link(), which gets the link markup for the task
theme_menu_local_task(), which gets the <li> element for the task.
So, you can get rid of the View and Edit local tasks in a really robust way by overriding theme_menu_item_link() and theme_menu_local_task() to include your check for them:
function mytheme_menu_item_link($link) {
// Local tasks for view and edit nodes shouldn't be displayed.
if ($link['type'] & MENU_LOCAL_TASK && ($link['path'] === 'node/%/edit' || $link['path'] === 'node/%/view')) {
return '';
}
else {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}
return l($link['title'], $link['href'], $link['localized_options']);
}
}
function mytheme_menu_local_task($link, $active = FALSE) {
// Don't return a <li> element if $link is empty
if ($link === '') {
return '';
}
else {
return '<li '. ($active ? 'class="active" ' : '') .'>'. $link ."</li>\n";
}
}
This way, you're relying on the menu router path, not modifying the menu router item, and achieving the result you want with minimal changes to core functionality or theming.
On the module side, you could do something that decouples the Edit's menu entry from the local tasks for the node:
function custom_menu_alter(&$items) {
$items['node/%node/edit']['type'] = MENU_CALLBACK;
}
The edit path is still there, but now it is not associated with the View tab. This includes the edit page itself--no View tab there.
there is a module for that: tab tamer allows to hide or disable tabs and rename them as well.
I use the following in template.php by theme (which is perhaps a little hacky, I feel I should be considering unsetting $tabs instead):
function THEME_NAME_menu_local_tasks() {
return '';
}
Or you could ommit:
if ($tabs) echo $tabs;
from your page.tpl.php...
View and Edit are functional features. They have a reason for being there.
The best way to "remove" them, is to "remove" that functionality alltogether. After all: why remove the interface of a piece of functionality, but not the functionality itself?
Besides, simply not printing the tabs, does not remove the url endpoints. In other words: if you don't print the edit tab, people can still access the edit page.
Again: best is to remove that functionality: The fact that you don't want the edit tab, sounds as if you don't want the edit functionality for certain users.
If so, then just remove that permission for that role. That is all. The tabs will be gone.
If, however, you simply wish to display these tabs differently, Drupal is your friends. As you may have noticed, they are called local tasks and not tabs. That is because the theme decides how to render them: The theme is the thing that decides to show them as tabs.
Simply override the theme_menu_local_tasks() to create your own HTML for the "local-tasks". And in your page-tpl, simply move the $tabs variable around to a place, where you want them.
But again: Don't try to change the behavior of the app, by removing interface-elements. That is not the right thing to do: you should change the behavior, in order to change the behavior :)
For all the people stumbling upon this question while looking for a D7 solution: As stated on https://drupal.stackexchange.com/a/77964/15055 it's hook_menu_local_tasks_alter()
/**
* Implements hook_menu_local_tasks_alter() to unset unwanted tabs
*/
function MYMODULE_menu_local_tasks_alter(&$data) {
foreach ($data['tabs'][0]['output'] as $key => $value) {
if ($value['#link']['path'] == 'node/%/view') {
unset($data['tabs'][0]['output'][$key]);
}
}
}
This is not the answer to the question of what the author asked. But somehow it might be useful for others user who facing the similar problem with me. Please let me know if this is not suitable to put in here.
I get the answer from #grayside and modified a bit to hide the view | edit tab from node based on the content type I want.
function MYMODULE_menu_alter(&$items) {
$items['node/%node/view']['access callback'] = 'MYMODULE_disable_node_view';
$items['node/%node/view']['access arguments'] = array(1);
}
function MYMODULE_disable_node_view($node){
if($node->type == 'product'){
return false;
}
}
product is the machine name of my content type, I don't want anywant to access it including root user.
The simplest solution to hide the tabs is to add this class in your theme css
.tabs{ display:none;}
Thanks for the last answer. But be aware of this detail: if you try it as-is it cannot work: literals should be just rounded with " or ', not both of them altogether. So it should be:
/**
* Implements hook_menu_local_tasks_alter() to unset unwanted tabs
*/
function MYMODULE_menu_local_tasks_alter(&$data) {
foreach ($data['tabs'][0]['output'] as $key => $value) {
if ($value['#link']['path'] == "node/%/view") {
unset($data['tabs'][0]['output'][$key]);
}
}
}
Once taken care of it, it works :)
D8 solution: If you want to hide all "local" tabs on certain pages, remember that "Tabs" is listed in the block library: find it in the "Content" region and exclude by content type, page URL or user role.

Resources