Symfony DomCrawler get HTML without attributes / styles - symfony

I need a way to get a HTML from an email without attributes (class / styles).
Currently trying the following:
$crawler = new Crawler();
$crawler->addHtmlContent($mail->textHtml);
$html = '';
$nodes = $crawler->filter('body > *'); //only stuff inside body
foreach ($crawler as $domElement) {
//remove somehow class+styles ?
$html .= $domElement->ownerDocument->saveHTML($domElement);
}
echo $html; //outputs everything inside body (currently with attributes)
As I read on many questions already, regex is not a good solutions for something like this as it may break stuff.

Related

Wordpress: add custom params to all URLS

I have an addition to url e.g. /products/myproduct/?v=iphone-x/transparent/*/Green
So what I need is for wordpress to add the ?v=iphone-x/transparent/*/Green to all links on the page (only '<a href="">'s, no 'img src=""' or others)
I have managed to do that, but it's a little "dirty". Is there any neat function to add the parameter to all links?
The code I have is as follows:
function callback($buffer) {
// modify buffer here, and then return the updated code
$temp = explode('href="', $buffer);
$buffer = $temp[0];
array_shift($temp);
foreach($temp as $t){
$tt = explode('"', $t, 2);
$buffer .= 'href="'.$tt[0].'?v='.$_GET['v'].'"'.$tt[1];
}
return $buffer;
}
function buffer_start() { ob_start("callback"); }
function buffer_end() { ob_end_flush(); }
add_action('wp_head', 'buffer_start');
add_action('wp_footer', 'buffer_end');
One way you can achieve this is to hook into "the_content" filter. By using regexp with preg_replace_callback function you can get decent results.
function add_para( $content ) {
$content = preg_replace_callback(
"/href=(?>'|\")([^\"']+)(?>'|\")/",
function($m) {
print_r($m);
return "href='".$m[1]."/additional-param'";
},
$content);
return $content;
}
add_filter( 'the_content', 'add_para', 0 );
However, you might run into some issues particularly if your content is not formatted probably (extra spaces, missing tags .. etc).
So the alternative is either to us a JS approach (jQuery for example), or using PHP DOM parser like: PHP Simple HTML DOM Parser

DOM Crawler and The current node list is empty - how to get list

I need help with DOM Crawler in Symfony 3.2.
Here is my code:
$html = file_get_contents('http://www.wakacje.pl/wczasy/peru/');
$crawler = new Crawler($html);
$crawler = $crawler->filter('#gridWithPagination > div > div')->each(function (Crawler $node) {
return $node->filter('div.desc > a');
});
foreach ($crawler as $item) {
var_dump($item->attr('href'));
}
As you can see, I want to get the URI parameter from all occurrences on the list, but this code is returning only the first instance, and also an error:
The current node list is empty
What I've missed?
Thanks in advance for help.
Not sure why you needed to filter twice, but a more straightforward CSS selector seems to work for me:
use Symfony\Component\DomCrawler\Crawler;
$html = file_get_contents('http://www.wakacje.pl/wczasy/peru/');
$crawler = new Crawler($html);
$nodes = $crawler->filter('div#gridWithPagination div.desc a');
$nodes->each(function ($item) {
echo $item->attr('href').'<br>';
});

How can the last word of an element be styled?

Given a dynamically loaded heading (using PHP/WordPress) is there a pure CSS method of styling the final word? For instance:
<h1 class='featured'> This is my page title</h1>
Becomes
<h1 class='featured'> This is my page <span id="finalWord">title</span></h1>
If using CSS is not viable, is exploding the content of the <h1> tag the suggested way to do this?
AFAIK there is not a :last-word pseudo class in CSS (although that would be cool). You could use JavaScript for something like this, but if you have access to the <h1> server-side I'd do it with PHP. It's going to be part of the source code and probably easier.
A simple algorithm would be to find the last space in the string with strrpos() and use substr() to piece it back together wrapped in <span>.
I guess a really crude way would be to create a way to all the words and put it in a PHP array. Then echo all the values, and if it's the last one then put the <span id="finalWord"> before and the </span> after.
EX:
Step 1: Create the array
$your_text = "Your text goes here";
$pieces = explode(" ", $your_text);
Now you have all your data in a array. Each word is in it's object.
echo "<h1 class='featured'>";
$the_count = count($pieces);
foreach ($your_text as $i => $value) {
$i = $i + 1;
if ($i == $the_count) { echo "<span id='finalWord'>"; }
echo $value;
if ($i == $the_count) { echo "</span>"; }
}
echo "</h1>";
So basically what this code does is count how many objects are in your array and will check if the object being displayed is the last one. If it is, it will put the correct ID on it.
I just typed this code out real quick, so there could be some errors.
Coulton
is there a pure CSS method of styling
the final word
No such method in principle. CSS cannot modify the DOM.
Take text of dom element, find last word using your own criteria for the "word", wrap it into span and set innerHTML by the result.
Sorry for the follow up on an ancient post, this is the one that came up in my google searches for "wrap the last word in a string with a span tag using php" so I figured this is where I would put the solution I came up with.
Using the above as a starting point, I created this function to accomplish what I needed:
function wrap_last($string, $wrap_start = '<span class="font-bold">', $wrap_finish = '</span>') {
$string_array = explode(' ', $string);
$count = count($string_array);
$new_array = array();
foreach ($string_array as $i => $value) {
$i = $i + 1;
$array_part = '';
if ($i == $count) {
$array_part .= $wrap_start;
}
$array_part .= $value;
if ($i == $count) {
$array_part .= $wrap_finish;
}
$new_array[] = $array_part;
}
$new_string = implode(' ', $new_array);
return $new_string;
}

How to add a body class for the current node's taxonomy to a Drupal 7 theme

Does anyone know how or can guide me in the right direction on how to add a body css class for the current node's taxonomy term? i.e. <body class="term-dogs"> where "dogs" is the taxonomy term name. It could also be just the term ID. Either way is fine I just need a solution. This will be for a Drupal 7 zen sub-theme
This answer took longer than I expected to figure out. The hard part was collecting the terms on the node, since All taxonomy functions relating to nodes have been removed or refactored. Ultimately, page 355 of Pro Drupal 7 Development saved the day with a snippet that does the job previously handled by taxonomy_node_get_terms.
Below is the code that worked for me (look for the part that says "MAGIC BEGINS HERE"). Assuming you're creating a sub-theme of Zen, you'll want to move this to your sub-theme's template.php file and rename it to YOURSUBTHEMENAME_preprocess_html:
/**
* Override or insert variables into the html template.
*
* #param $vars
* An array of variables to pass to the theme template.
* #param $hook
* The name of the template being rendered ("html" in this case.)
*/
function zen_preprocess_html(&$vars, $hook) {
// If the user is silly and enables Zen as the theme, add some styles.
if ($GLOBALS['theme'] == 'zen') {
include_once './' . drupal_get_path('theme', 'zen') . '/zen-internals/template.zen.inc';
_zen_preprocess_html($vars, $hook);
}
// Classes for body element. Allows advanced theming based on context
// (home page, node of certain type, etc.)
if (!$vars['is_front']) {
// Add unique class for each page.
$path = drupal_get_path_alias($_GET['q']);
// Add unique class for each website section.
list($section, ) = explode('/', $path, 2);
if (arg(0) == 'node') {
if (arg(1) == 'add') {
$section = 'node-add';
}
elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
$section = 'node-' . arg(2);
}
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
$vars['classes_array'][] = strtolower($result['#title']);
}
}
// MAGIC ENDS HERE
}
$vars['classes_array'][] = drupal_html_class('section-' . $section);
}
if (theme_get_setting('zen_wireframes')) {
$vars['classes_array'][] = 'with-wireframes'; // Optionally add the wireframes style.
}
// Store the menu item since it has some useful information.
$vars['menu_item'] = menu_get_item();
switch ($vars['menu_item']['page_callback']) {
case 'views_page':
// Is this a Views page?
$vars['classes_array'][] = 'page-views';
break;
case 'page_manager_page_execute':
case 'page_manager_node_view':
case 'page_manager_contact_site':
// Is this a Panels page?
$vars['classes_array'][] = 'page-panels';
break;
}
}
I needed to know how to do this and Matt V's solution worked perfectly. I made a couple of additions to his work. I called drupal_html_class which replaces spaces and invalid characters. And I added in the term ID to allow you to target a term even if the name of the term changes.
// MAGIC BEGINS HERE
$node = node_load(arg(1));
$results = field_view_field('node', $node, 'field_tags', array('default'));
foreach ($results as $key => $result) {
if (is_numeric($key)) {
// Call drupal_html_class to make safe for a css class (remove spaces, invalid characters)
$vars['classes_array'][] = "taxonomy-" . strtolower(drupal_html_class( $result['#title']) );
// Add taxonomy ID. This will allow targeting of the taxonomy class even if the title changes
$vars['classes_array'][] = "taxonomy-id-" . $result['#options']['entity']->tid ;
}
}
// MAGIC ENDS HERE
Not sure what you mean with that body tag, but the classes on the node are generated here:
http://api.drupal.org/api/drupal/modules--node--node.module/function/template_preprocess_node/7
You can add more by implementing yourmodule_preprocess_node($vars) and then add whatever you want to $vars['classes_array']

Is it possible to *optionally* override a theme in Drupal 6?

I want to override the theming of only one (custom) menu. I can do this with phptemplate_menu_tree() but - of course - it overrides the rendering of all menus.
I've tried returning FALSE (an obvious technique IMO) if the menu is not the specific one I want to override - but this doesn't cause the overridden theme function to be called.
My only alternative (when the menu is anything other than the specific one) is to call the overridden function from within phptemplate_menu_tree() - but this seems to defeat the whole point of the override system, since the default rendering function will be hard-coded therein.
I hope the explanation is clear, and any help is greatly appreciated - tks.
UPDATE
For the sake of future reference, I'll explain how I solved this.
First off, the menu rendering starts with this function in menu.module:
function menu_block($op = 'list', $delta = 0) {
$menus = menu_get_menus();
// The Navigation menu is handled by the user module.
unset($menus['navigation']);
if ($op == 'list') {
$blocks = array();
foreach ($menus as $name => $title) {
// Default "Navigation" block is handled by user.module.
$blocks[$name]['info'] = check_plain($title);
// Menu blocks can't be cached because each menu item can have
// a custom access callback. menu.inc manages its own caching.
$blocks[$name]['cache'] = BLOCK_NO_CACHE;
}
return $blocks;
}
else if ($op == 'view') {
$data['subject'] = check_plain($menus[$delta]);
$data['content'] = menu_tree($delta);
return $data;
}
}
If you only want to override how individual item (links) are rendered then you can use the theme system (there are loads of references on how do this) - but if you want complete control on how the entire menu tree is rendered (for example, wrapping the output in nested DIVs so it can be centred on the page) then there is no way to override menu_block().
Therefore, I removed the menu I wanted to render differently from the administer blocks page (site building->blocks) and rendered the menu directly in my page.tpl.php using code something like this: (angle brackets removed)
$m = menu_tree_page_data('my-menu-id');
$o = "DIV";
foreach($m as $k => $v){
$o .= "SPAN {$v['link']['title']} /SPAN";
}
$o .= "/DIV";
echo $o;
I hope this helps.
I've had mixed success doing template.php menu overrides to force CSS classes and ids or HTML into the output.
You could make use of Block Theme when enabling the menu as a block, but I've never tried it.
http://drupal.org/project/blocktheme
If you want to tackle the template way, here are the zen menu override funcitons...
function zen_menu_item_link($link) {
if (empty($link['localized_options'])) {
$link['localized_options'] = array();
}
// If an item is a LOCAL TASK, render it as a tab
if ($link['type'] & MENU_IS_LOCAL_TASK) {
$link['title'] = '<span class="tab">' . check_plain($link['title']) . '</span>';
$link['localized_options']['html'] = TRUE;
}
return l($link['title'], $link['href'], $link['localized_options']);
}
function zen_menu_local_tasks() {
$output = '';
if ($primary = menu_primary_local_tasks()) {
$output .= '<ul class="tabs primary clear-block">' . $primary . '</ul>';
}
if ($secondary = menu_secondary_local_tasks()) {
$output .= '<ul class="tabs secondary clear-block">' . $secondary . '</ul>';
}
return $output;
}
You could use sections module, or look at how it switches theme for certain menu-items.
what I did was register a new theme function in my template.php called primary_links (because I wanted to only customize this menu in certain way) created the function mytheme_primary_links() in my template.php refreshed the cache so Drupal would add my theme function to the system then changed theme function on primary_links from links to my custom theme function primary_links - this allows me to customize only this 1 menu - could you do this and hook into where ever to change the theme function being called for your links?
Chris

Resources