replace <h2> tags before strip_tags - strip-tags

I'm trying to replace the <h2> and </h2> tag from a string this way but it's not working:
$desc = get_post_meta($post_id , 'desc', true);
preg_replace("/<h2>/", '', $desc);
preg_replace("/</h2>/", ' - ', $desc);
Then I like to the strip all other tags this way strip_tags($desc)

Do it this way:
$trash_h2_tags = array("<h2>", "</h2>");
$desc = str_replace($trash_h2_tags, '', $desc);

Related

How to structure a multi array to process and sort WooCommerce Order Item data?

How can I extract details from an order into an array, while on the "Order Edit" page and then loop through them?
My array structure isn't correct as can't handle a 3rd item-detail. So each order item somehow needs to be placed into its own sub-array.
Then I want to be able to sort them on item-name and print them out with an echo.
How to achieve the correct array structure to input them and extract?
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'additional_admin_order_data_block_after_shipping_address', 100 );
function additional_admin_order_data_block_after_shipping_address(){
echo '</div><div class="order_data_column order_packing_column">
<h3>' . esc_html__( 'Packing Items', 'woocommerce' ) . '</h3>';
// here goes your code and content
//custom array to list products:
$products_array = array();
$product_tally = 0;
global $post; // <=== Alway at the beginning
// Get an instance of the WC_Order Object
$order = wc_get_order( $post->ID );
// let's decide what order item types we would like to get
$types = array( 'line_item');
// defaults to line_item which allows to get products from order
foreach( $order->get_items( $types ) as $item_id => $item ) {
// order ID
$item_order_id = $item->get_order_id();
// product only and no bundle 'summary' item
if( empty( $item['woosb_ids']) && $item->is_type( 'line_item' ) ) {
// order item name (product title, name of a shipping method or coupon code)
$item_name = $item->get_name();
if ( array_key_exists($item_name, $products_array)) {
$products_array[$item_name] += $item['qty'];
} else {
$products_array[$item_name] = $item['qty'];
}
$product_tally = $product_tally + $item->get_quantity();
}
}
arsort($products_array);
echo '<div class="woocommerce_order_items" id="packing-table">
<div class="thead">
<div class="tr">
<div class="item sortable">Product</div>
<div class="quantity sortable">Qty</div>
</div>
</div>
<div class="tbody" id="order_line_items">';
//display list:
foreach ($products_array as $title => $quantity) {
echo '<div class="lineitem">
<div class="item">';
echo $title.'</div>
<div class="quantity">'.$quantity.'</div>
</div>';
}
echo '<div class="lineitem tally">
<div class="item">Tally of Items</div>
<div class="quantity">'.$product_tally.'</div>
</div>';
echo '</div>
</div>';
}

Drupal Custom Module HTML

So I've only just begun to learn Drupal so If you believe I'm going about this the wrong way, please let me know.
I have a content type called Events. I'm basically just trying to output a snippet of the latest event on the home page. To do this, I've created a custom module following the Drupal tutorial Drupal doc's custom module tutorial
Here's my module's code
<?php
/**
* Implements hook_block_info().
*/
function latest_event_block_info() {
$blocks['latest_event'] = array(
// The name that will appear in the block list.
'info' => t('Latest Event'),
// Default setting.
'cache' => DRUPAL_CACHE_PER_ROLE,
);
return $blocks;
}
/**
* Custom content function.
*
* Set beginning and end dates, retrieve posts from database
* saved in that time period.
*
* #return
* A result set of the targeted posts.
*/
function latest_event_contents(){
//Get today's date.
$today = getdate();
//Calculate the date a week ago.
$start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);
//Get all posts from one week ago to the present.
$end_time = time();
//Use Database API to retrieve current posts.
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'event')
->propertyCondition('status', 1) // published == true
->propertyCondition('created', array($start_time, $end_time), 'BETWEEN')
->propertyOrderBy('created', 'DESC') //Most recent first.
->range(0, 1); //ony grab one item
return $query->execute();
}
/**
* Implements hook_block_view().
*
* Prepares the contents of the block.
*/
function latest_event_block_view($delta = '') {
switch ($delta) {
case 'latest_event':
$block['subject'] = t('Latest Event');
if (user_access('access content')) {
// Use our custom function to retrieve data.
$result = latest_event_contents();
$nodes = array();
if (!empty($result['node'])) {
$nodes = node_load_multiple(array_keys($result['node']));
}
// Iterate over the resultset and generate html.
foreach ($nodes as $node) {
//var_dump($node->field_date);
$items[] = array(
'data' => '<p>
<span class="text-color">Next Event</span> ' .
$node->field_date['und'][0]['value'] . ' ' .
'</p>' .
'<p>' .
$node->title . ' ' .
$node->field_location['und'][0]['value'] . ' ' .
'</p>'
);
}
// No content in the last week.
if (empty($nodes)) {
$block['content'] = t('No events available.');
}
else {
// Pass data through theme function.
$block['content'] = theme('item_list', array(
'items' => $items));
}
}
return $block;
}
}
I've added the block to a region, and it renders fine in my template page. However, the events are outputted in a list which is not what I want.
Here's how the block is being rendered in HTML
<div class="item-list">
<ul>
<li class="first last">
<p>
<span class="text-color">Next Event</span> June 23 2016 18:30 - 21:00 </p><p>Cancer Research UK Angel Building, 407 St John Street, London EC1V 4AD
</p>
</li>
</ul>
</div>
So assuming I'm going about this whole thing correctly, how can I modify this blocks html? Thanks!
I think first you need to understand the theme('item_list', ....). This always output a HTML list either UL or OL as given.
If you want to show your content without the HTML list wrapper, you could try this:
/**
* Implements hook_block_view().
*
* Prepares the contents of the block.
*/
function latest_event_block_view($delta = '') {
switch ($delta) {
case 'latest_event':
$block['subject'] = t('Latest Event');
if (user_access('access content')) {
// Use our custom function to retrieve data.
$result = latest_event_contents();
$nodes = array();
if (!empty($result['node'])) {
$nodes = node_load_multiple(array_keys($result['node']));
}
// Iterate over the resultset and generate html.
$output = '';
foreach ($nodes as $node) {
//var_dump($node->field_date);
$output .= '<p>
<span class="text-color">Next Event</span> ' .
$node->field_date['und'][0]['value'] . ' ' .
'</p>' .
'<p>' .
$node->title . ' ' .
$node->field_location['und'][0]['value'] . ' ' .
'</p>';
}
// No content in the last week.
if (empty($output)) {
$block['content'] = t('No events available.');
}
else {
// Pass data through theme function.
$block['content'] = $output;
}
}
return $block;
}
}
That is one way. Another way is to use your own custom them template and use the array to output through that. For eg.
// Pass data to template through theme function.
$block['content'] = theme('latest_event_block_template', $items);
Then define a hook_theme function to get this to a template, like:
function latest_event_theme() {
return array(
'latest_event_block_template' => array(
'arguments' => array('items' => NULL),
'template' => 'latest-event-block-template',
),
);
}
Now, you should have a template at the module's root directory with the name latest-event-block-template.tpl.php. On this template you will be able to get the $items array and adjust the HTML yourself. Don't forget to clear theme registry after creating the template.
Hope it helps!
It's outputting as a list because you are passing $block['content'] the item_list theme function.
What you could do instead is create your own custom theme template using hook_theme. This will let you use custom markup in a custom template file.
After, replace this:
// Pass data through theme function.
$block['content'] = theme('item_list', array('items' => $items));
With this:
// Pass data through theme function.
$block['content'] = theme('my_custom_theme', array('items' => $items));

Trying to figure out how to push specific links contained in each link of separate list of links into an array

GENERAL IDEA
Here is a snippet of what I'm working with:
my $url_temp;
my $page_temp;
my $p_temp;
my #temp_stuff;
my #collector;
foreach (#blarg_links) {
$url_temp = $_;
$page_temp = get( $url_temp ) or die $!;
$p_temp = HTML::TreeBuilder->new_from_content( $page_temp );
#temp_stuff = $p_temp->look_down(
_tag => 'foo',
class => 'bar'
);
foreach (#temp_stuff) {
push(#collector, "http://www.foobar.sx" . $1) if $_->as_HTML =~ m/href="(.*?)"/;
};
};
Hopefully it is clear that what I'm hopelessly trying to do is push the link endings found in each of a list of links into an array called #temp_stuff. So the first link in #blarg_links, when visited, has greater than or equal to 1 foo tag with an associated bar class that when acted on by as_HTML will match something I want in the href equality to then pump into an array of links which have the data I'm really after... Does that make sense?
ACTUAL DATA
my $url2 = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $page2 = get( $url2 ) or die $!;
my $p2 = HTML::TreeBuilder->new_from_content( $page2 );
my #stuff2 = $p2->look_down(
_tag => 'div',
class => 'year mini-day-on'
);
my #chem_links;
foreach (#stuff2) {
push(#chem_links, $1) if $_->as_HTML =~ m/(http:\/\/www\.chemistry\.ucla\.edu\/calendar-node-field-date\/day\/[0-9]{4}-[0-9]{2}-[0-9]{2})/;
};
my $url_temp;
my $page_temp;
my $p_temp;
my #temp_stuff;
my #collector;
foreach (#chem_links) {
$url_temp = $_;
$page_temp = get( $url_temp ) or die $!;
$p_temp = HTML::TreeBuilder->new_from_content( $page_temp );
#temp_stuff = $p_temp->look_down(
_tag => 'span',
class => 'field-content'
);
};
foreach (#temp_stuff) {
push(#collector, "http://www.chemistry.ucla.edu" . $1) if $_->as_HTML =~ m/href="(.*?)"/;
};
n.b. - I want to use HTML::TreeBuilder. I'm aware of alternatives.
This is a rough attempt at what I think you want.
It fetches all the links on the first page and visits each of them in turn, printing the link in each <span class="field-content"> element.
use strict;
use warnings;
use 5.010;
use HTML::TreeBuilder;
STDOUT->autoflush;
my $url = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $tree = HTML::TreeBuilder->new_from_url($url);
my #chem_links;
for my $div ( $tree->look_down( _tag => 'div', class => qr{\bmini-day-on\b} ) ) {
my ($anchor)= $div->look_down(_tag => 'a', href => qr{http://www\.chemistry\.ucla\.edu});
push #chem_links, $anchor->attr('href');
};
my #collector;
for my $url (#chem_links) {
say $url;
my $tree = HTML::TreeBuilder->new_from_url($url);
my #seminars;
for my $span ( $tree->look_down( _tag => 'span', class => 'field-content' ) ) {
my ($anchor) = $span->look_down(_tag => 'a', href => qr{/});
push #seminars, 'http://www.chemistry.ucla.edu'.$anchor->attr('href');
}
say " $_" for #seminars;
say '';
push #collector, #seminars;
};
For a more modern framework for parsing webpages, I would suggest you take a look at Mojo::UserAgent and Mojo::DOM. Instead of having to manually march through each section of your html tree, you can use the power of css selectors to zero in on the specific data that you want. There's a nice 8 minute introductory video on the framework at Mojocast Episode 5.
# Parses the UCLA Chemistry Calendar and displays all seminar links
use strict;
use warnings;
use Mojo::UserAgent;
use URI;
my $url = 'http://www.chemistry.ucla.edu/calendar-node-field-date/year';
my $ua = Mojo::UserAgent->new;
my $dom = $ua->get($url)->res->dom;
for my $dayhref ($dom->find('div.mini-day-on > a[href*="/day/"]')->attr('href')->each) {
my $dayurl = URI->new($dayhref)->abs($url);
print $dayurl, "\n";
my $daydom = $ua->get($dayurl->as_string)->res->dom;
for my $seminarhref ($daydom->find('span.field-content > a[href]')->attr('href')->each) {
my $seminarurl = URI->new($seminarhref)->abs($dayurl);
print " $seminarurl\n";
}
print "\n";
}
Output is identical to that of Borodin's solution using HTML::TreeBuilder:
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-06
http://www.chemistry.ucla.edu/seminars/nano-rheology-enzymes
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-09
http://www.chemistry.ucla.edu/seminars/imaging-approach-biology-disease-through-chemistry
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-10
http://www.chemistry.ucla.edu/seminars/arginine-methylation-%E2%80%93-substrates-binders-function
http://www.chemistry.ucla.edu/seminars/special-inorganic-chemistry-seminar
http://www.chemistry.ucla.edu/calendar-node-field-date/day/2014-01-13
http://www.chemistry.ucla.edu/events/robert-l-scott-lecture-0
...

Filter not registering on first character

I a user list that pops up when a user types # into a text field. When this happens I want the user list to be filtered for every letter typed after the # symbol. So if they typed "#s" all usernames starting with an "s" would show. I'm recording the text typed after the # and assigning it as the text to filter by, but the filter won't act until two characters have been typed. Can someone tell me why this would be happening? Thank you for your help.
HTML/SLIM:
/ USER LIST
.user-list.list-group [ng-show="usersShow"]
a.user.list-group-item [ng-repeat="user in users | filter:formattedUser"]
strong
| {{user.username}}
| {{' : ' + (user | fullName)}}
/ COMMENT FORM
= form_for Comment.new, html: {action: nil, name: 'newCommentForm', 'ng-submit' => 'createComment($event, comment)'} do |f|
= f.text_field :text, placeholder: 'Add comment...',
'ng-model' => 'comment.text', 'ng-change' => 'showUserList(comment.text)'
span.input-group-btn
button.btn type="submit" Add Comment
JS:
$scope.showUserList = function(comment) {
var USERNAME_PATTERN = /(?:^|\s)#\S*$/;
var comment = comment || '';
var userMatch = comment.match(USERNAME_PATTERN) || '';
if(userMatch) {
$scope.userFormatted = userMatch[0].replace('#', '').trim();
}
$scope.usersShow = USERNAME_PATTERN.test(comment);
};

Zend_Form array notation with no indices

I would like to create a form that allows the user to input any number of values, each in a separate text field using an array notation. The example expected HTML output is:
<dd id="dupa-element">
<input type="text" name="dupa[]" value="">
<input type="text" name="dupa[]" value="">
</dd>
However, I can't seem to find a way to introduce multiple input elements within a single element, using array notation without indices.
Currently, I do this:
$elt1 = new Zend_Form_Element_Text('1');
$elt1->setOptions(array('belongsTo' => 'dupa'));
$elt2 = new Zend_Form_Element_Textarea('2');
$elt2->setOptions(array('belongsTo' => 'dupa'));
While this works, Zend_Form treats these as independent elements (which can have different sets of validators and filters - that's sort of cool) and the resulting HTML is something along these lines:
<dd id="dupa-1-element">
<input type="text" name="dupa[1]" id="dupa-1" value="">
</dd>
<dd id="dupa-2-element">
<input type="text" name="dupa[2]" id="dupa-2" value="">
</dd>
Is there a (preferably simple) way to achieve the indexless array notation I'm after?
I would follow MWOP's tutorial on creating composite elements. More work, but it's less Trial&Error then akond's solution. Basic idea for me would be extending the Zend_Form_Element_Multi (what you want is how Zend_Form_Element_Multiselect/MultiCheckbox works).
I managed to do this by having a "container subform", and then adding subforms to that "container" e.g.:
$container = new Zend_Form_SubForm();
$subform1 = new Zend_Form_SubForm();
$container->addSubForm($subform1, '1');
$subform2 = new Zend_Form_SubForm();
$subform2->addSubForm($subform1, '2');
$mainForm = new Zend_Form();
$mainForm->addSubform($container,'mysubforms');
Hope that helps.
You need a custom view helper for that.
class Zend_View_Helper_FormMySelect extends Zend_View_Helper_Abstract
{
function formMySelect ($name, $value = null, $attribs = null, $options = null, $listsep = "<br />\n")
{
$result = array ();
foreach ($options as $option)
{
$result [] = sprintf ('<input type="text" name="%s[]" value="">', $name);
}
return join ($listsep, $result);
}
}
Than have in your form something like that:
$form = new Zend_Form();
$form->addElement ('select', 'test', array (
'label' => 'Test',
'multioptions' => array (
'test 1',
'test 2',
'test 3',
),
));
$form->test->helper = 'formMySelect';

Resources