Remove all empty elements but classed spans using HTML Purifier - php

I'm trying to remove every empty element in an input using HTML Purifier, but I want to keep the spans that meet a list of classes. So, for instance:
<div> </div><span class="color-gray"></span><div></div>
Should become:
<span class="color-gray"></span>
The configuration I'm using is:
'AutoFormat.RemoveEmpty.RemoveNbsp' => true,
'AutoFormat.RemoveEmpty' => true,
'CSS.AllowedProperties' => array(),
'Core.RemoveProcessingInstructions' => true,
'HTML.Allowed' => 'a[href|target],h1,h2,p,strong,em,b,i,ul,ol,li,span[class]'
But, as you may imagine, it is not what I expected, as it removes <span>, too. Do you have any idea on how to solve it?

Mm, you won't be able to do this directly, however, it should be a simple patch to RemoveEmpty; just add an extra check for an attribute at the beginning of handleElement.

Related

Using HTML in Mandrill handlebar merge variables

If I have a handlebar merge variable like {{message}} in my template, how can I have it render HTML output if given the following in PHP:
array(
'name' => 'message',
'content' => '<p>First paragraph.</p><p>Second paragraph.</p>'
)
Right now it outputs the content without parsing the paragraph tags.
If you're using Handlebars I think the proper way to do it is with triple braces, e.g:
{{{html_content}}}
I'm not sure it is ok to mix mc:edit with Handlebars in Mandrill:
Combining Handlebars with either mc:edit regions or merge tags in a single message isn't supported. You should pick Handlebars or mc:edit regions plus merge tags.
https://mandrill.zendesk.com/hc/en-us/articles/205582537-Using-Handlebars-for-dynamic-content
Actually when sending using mandrill the message variable has a field merge_language and when you change to this
'merge_language' => 'handlebars'
It works. For your case i think the value is default 'mailchimp' hence the need to use mc:edit
To answer my own question, I just added mc:edit="message" to the div containing the message, like this:
<div mc:edit="message"></div>
I then added this to my structure:
$template_content = array(
array(
'name' => 'message',
'content' => '<p>First paragraph.</p><p>Second paragraph.</p>'
),
);

cakephp element parameters with html

I want to render a cakephp element which contains static text. The element is supposed to contain help, text, images, ... etc. but it should show only the content relevant to the current page being rendered.
I thought of two ways, one of them is to simply pass html content as a parameter from the view as follows:
echo $this->element('help-bar-content', array(
'title' => 'Element title',
'help_text'=> '<div>
A lot of text and tags go here.
<br/>
<img class="img-class" src="/img/location"/>
</div>'
));
But it is ugly because it would mix html inside php which is inside html. The second way is to have a lot of elements each of them corresponding to a help_text parameter and use them as follows:
echo $this->element('help-bar-content', array(
'title' => 'Element title',
'help_text'=> element('help_element1')));
Which I think is better, But then I would have a LOT of non-reusable elements because I have a lot of views.
Is there a third (better) way to do this?
Put all the help texts in a switch statement or multiple ifs inside the element and give each one a string as identifier and pass that string to the element. Then display the text conditionally based on that string.
<?php if ($helpText === 'foo') : ?>
<p>foo</p>
<?php endif; ?>
Note $helpText follows the convention while $help_text doesnt.

Removing XML attributes with XML_Serializer

Hopefully there's one or two experienced users of the XML_Serializer PEAR class here
I'm parsing an XML file with XML_Serializer
I'm using this PEAR class so that I can grab the entire contents and put it into an array (why is another story for another time)
At the moment it is also taking the attributes and their values of the tags like so:
<prod id="88966064" pre_order="no" web_offer="no" in_stock="no" stock_quantity="0">
<pId>608</pId>
<isbn>0000000000000</isbn>
And adding them to the returned array like this:
XML_Serializer_Tag] => Array(
[id] => 88966064
[pre_order] => no
[web_offer] => no
[in_stock] => no
[stock_quantity] => 0
)
Are there any options in XML_Serializer that allows me to use the XML data without the attributes and just the tags and the data inbetween them, ie only?
<pId>608</pId>
<isbn>0000000000000</isbn>
The data is dynamic so a solution of removing them individually is no goer
XML_Unserializer defaults its 'parseAttributes' option to FALSE [1]. Try to explicitly set it to FALSE and see if that helps.
[1] -- https://pear.php.net/manual/en/package.xml.xml-serializer.xml-unserializer.options.php

Parsing CSV file into array with comments at top

Here is a template of a possible text file I might need to import into my database:
#NAME:"Test"
#REV:"rev1"
#PRODUCT:"product1","description1","option1"
#PRODUCT:"product2","description2","option1","option2"
"A1","key1","DALI"
"B1","key2",""
"B2","key3","option2"
"C1","key4",""
The first 4 lines is a new addition to the format of these files. I was importing the comma separated data itself successfully before the addition of the comment lines on top.
I was wondering if someone can provide me the most efficient way to put all the values in the comment lines into variables in PHP.
I always have a little trouble when it comes to RegEx. I'm not sure how to best grab the lines starting with a #.
Essentially, I would like to have the following data available to me:
$csv['name']: "Test";
$csv['rev']: "rev1";
$csv['products']: array(
0 => array('name' => "product1", 'desc' => "description1", 'options' => "option1"),
1 => array('name' => "product2", 'desc' => "description2", 'options' => "option1,option2"),
);
$csv['data']: The rest of the data in text file
There could be multiple #PRODUCTS defined, so that is why it would be nice to have an array made from those lines.
Thanks for your help.
Are you using php 5.3? If so, then you can simply read your file using fgets() and detect comments using substr($line, 0, 1). If you don't detect a #,it means it a data line, then pass it on to str_getcsv()...
Cheers
To match something started with #, just use ^ at the beginning of regexp (outside of group)

reduce CSS rules to their lowest common denominator

I have a templating engine in PHP wich allows you to set style attributes to objects prior to rendering.
During development time, I want these attributes to be inline so I can find them and change them easily. However, for production, I want to extract them and cache them in a css file. I also want to extract inline styles from any html element in the template.
The extracting, as well as ordering in arrays part is done. So I have a bunch or arrays that are structured as follow
array(
'tag' =>'div',
'id' =>'myDiv',
'class'=>array('container','wrapper'),
'style'=>array('background'=>'#CCCCCC',/*rules...*/)
);
Note that 'id' and 'class' keys are not necessarily set on all elements, but at least one of both is always set.
The part that renders this array as a css file is also done.
What I need to do is re-shuffle around the 'style' part of the array so common elements are grouped together. Optimization is not an issue since this process will be called only once then cached.
But I tried to design some pseudo-code and I'm just stuck. I am guessing that some part of the process at least will have to make "as-smart-as-possible guesses", but even that I don't see clearly.
Last recourse would be to just create the full string, then run the string itself through a css-minifier, but as far as what I could read, none does this "reducing to the lowest common denominator" thing.
Any suggestion?
[edit]
In answer to comments, here is more clarification:
if my array is presented like so:
array(
array(
'tag' =>'div',
'id' =>'myDiv',
'style'=>array('background'=>'#CCCCCC','font-size'=>'24px','color'=>'#FF0000')
),
array(
'tag' =>'div',
'class'=>array('container','hasBorder'),
'style'=>array('background'=>'#CCCCCC','border'=>'1px solid black')
),
array(
'tag' =>'div',
'class'=>array('wrapper','hasBorder'),
'style'=>array('color'=>'#FF0000','border'=>'1px solid black')
)
);
My CSS should be rendered as such:
#myDiv{font-size:24px;}
#myDiv, .container{background:#CCCCCC;}
#myDiv, .wrapper{color:#FF0000;}
.hasBorder{border:1px solid black}
The output could be different; I don't care what the exact logic for defining how rules are set is; But what I want to avoid is what I currently have:
#myDiv{background:#CCCCCC;font-size:24px;color:#FF0000;}
.container{background:#CCCCCC;border:1px solid black;}
.wrapper{color:#FF0000';border:1px solid black;}
This is a simple example, but I have lots of repeated rules all over that make no sense; the generated CSS is not only bloated, it is not humanely maintainable. What I want is to generate a base CSS that designers can use to work with.
css lint http://csslint.net/
watch out, she'll hurt your feelings

Categories