This is part of the PHP that is outputting HTML from a function I'm working on. I'm getting stuck on the if/else state where I need to check if a parameter is set to true or false.
If it's set to true, I have HTML I want to output, if it's false, nothing needs to happen.
<?php
/**
*
*
* #param array $settings
*
* #return string
*/
function PCStandardTextBlock( $settings = array() ) {
//---- Get Settings ----
//The functions default settings will be merged with what's passed in.
$settingsDefault = array(
'small_heading' => '',
'large_heading' => '',
'text' => '',
'text_mode' => 'basic', //or advanced
'big_first_p' => false,
'link_url' => '',
'link_text' => '',
'link_new_tab' => false,
'link_style' => 'action_link', //or button
'photo' => '', //cloudinary id
'image_alt_text' => '',
'crop_gravity' => 'face',
'icon' => '', //icn-class
'color_scheme' => 'white', //or accent1, accent2, accent4
'container_id' => '',
'container_class' => '',
'special_feature' => 'camplife_links', //or link_modal, hidden_content
'modal_id' => '',
'hidden_content_location' => 'another_block', //or in_this_block (see day-camps.php)
'hidden_text' => '',
'hidden_content_id' => '',
);
$settings = array_merge($settingsDefault, $settings);
//---- Set Variables ----
//These will allow the markup buildup to be as clean as possible.
$has_photo = strlen($settings['photo']) > 0;
$has_icon = strlen($settings['icon']) > 0;
$has_small_heading = strlen($settings['small_heading']) > 0;
$has_image_alt_text = strlen($settings['image_alt_text']) > 0;
//Note to Sal: If text mode is basic, wrap it in a <p> tag, if advanced, don't.
//If container_id is set, prepare the attribute
$has_container_id = strlen($settings['container_id']) > 0;
$possible_container_id_attribute = ($has_container_id) ? " id='{$settings['container_id']}'" : "";
//Handle the color scheme setting
switch( $settings['color_scheme'] ) {
case 'accent1': // blue
$gcol_color_class = 'bg-color-accent1-C';
$small_heading_color_class = 'color-white';
$icon_color_class = 'color-white';
break;
case 'accent2': // green
$gcol_color_class = 'bg-color-accent2-C';
$small_heading_color_class = 'color-white';
$icon_color_class = 'color-white';
break;
case 'accent4': // yellow
$gcol_color_class = 'bg-color-accent4-D';
$small_heading_color_class = 'color-accent1-9';
$icon_color_class = 'color-accent1-9';
break;
default; //white
$gcol_color_class = ''; // empty
$small_heading_color_class = 'color-base-A';
$icon_color_class = 'color-accent1-9';
}
// Handle the special feature setting
switch( $settings['special_feature']) {
case 'camplife_links':
$special_feature_display = '<div class="spacer"></div>
<div class="grid">
<div class="gcol">
<a target="_blank" href="https://itunes.apple.com/us/app/pine-cove-camplife/id991165025?mt=8&ign-mpt=uo%3D4">
<img class="width-100" src="/images/logos/badges/app-store-badge.png" alt="Download on the App Store" />
</a>
</div>
<div class="gcol">
<a target="_blank" href="https://play.google.com/store/apps/details?id=com.pinecove.camplife">
<img class="width-100" src="/images/logos/badges/google-play-badge.png" alt="Get it on Google Play" />
</a>
</div>
</div>';
break;
default; // don't show anything
$special_feature_display = ''; // Empty
}
$has_special_feature = strlen( $settings['special_feature'] ) > 0;
// Settings to call PCResponsiveImage with output set to false to save the results to a variable for inclusion in the output
$responsive_image_settings = array(
'cloudinary_ID' => $settings['photo'],
'aspect_ratios' => '1x1',
'crop_gravity' => $settings['crop_gravity'],
'screen_portion' => 'partial',
'style_profile' => 'style4',
'output' => false,
);
// If image alt text has been set, us it, otherwise don't set anything so responsive image can do it's thing (it sets the alt text to the filename).
if ( $has_image_alt_text ) {
$responsive_image_settings['alt_text'] = $settings['image_alt_text'];
}
//Save PCResponsiveImage markup to a variable
$responsive_image_html = PCResponsiveImage( $responsive_image_settings );
//---- Build Output ----
//Line by line, concatenating strings with new line and tab characters.
$output = "\n<!-- Standard Text Block -->";
$output .= "\n<div class='gcol-md-1-2 {$gcol_color_class} {$settings['container_class']}'{$possible_container_id_attribute}>";
$output .= "\n\t<div class='padbox-standard-content'>";
if( $has_photo ) {
$output .= "\n\t<div class='small-heading-image'>";
$output .= "\n\t\t{$responsive_image_html}";
$output .= "\n\t</div>";
} elseif( $has_icon ) {
$output .= "<span class='icn {$settings['icon']} $icon_color_class width-90'></span>";
}
if( $has_small_heading ) {
$output .= "\n\t<h1 class='small-heading $small_heading_color_class'>{$settings['small_heading']}</h1>";
}
$output .= "\n\t<h2 class='heading-extended'>{$settings['large_heading']}</h2>";
if ( $settings['text_mode'] == 'basic' ) {
$output .= "\n\t\t\t\t<p>{$settings['text']}</p>"; // basic version
} elseif ( $settings['big_first_p'] === true ) {
$output .= "\n\t\t\t\t<p class='big-p'>{$settings['text']}</p>";
} else {
$output .= "\n\t\t\t\t{$settings['text']}"; // advanced text mode; not big-p
}
if( $has_special_feature ) {
$output .= "\n\t\t\t$special_feature_display";
}
$output .= "\n\t</div><!-- END padbox-standard-content -->";
$output .= "\n</div><!-- END gcol-md-1-2 -->";
//---- Return Output ----
return $output;
}
This is the function on the page where it calls the function (I've left off some parameters in the function call above to save space):
<?php echo PCStandardTextBlock(
array(
'small_heading' => 'Small Heading',
'large_heading' => 'Large Heading',
'text' => 'This is example text that is just basic text. If this was advanced text, then it would be multiple paragraphs.',
'text_mode' => 'basic',
'big_first_p' => true,
'photo' => '',
'image_alt_text' => '',
'icon' => '',
'color_scheme' => 'white',
'special_feature' => '',
'container_id' => '',
'container_class' => '',
)
); ?>
It looks like you were checking a non-existent array key: $settings['big_first_p']. Here it is corrected:
$settingsDefault = array(
'big_first_p' => false,
);
if ( $settingsDefault['text_mode'] == 'basic' ) {
$output .= "\n\t\t\t\t<p>{$settings['text']}</p>"; // basic version
} elseif ( $settingsDefault['big_first_p'] === true ) {
$output .= "\n\t\t\t\t<p class='big-p'>{$settings['text']}</p>";
} else {
$output .= "\n\t\t\t\t{$settings['text']}";
}
Update:
So, you are passing in 'text_mode' => 'basic',, which is why the basic version is getting appended to $output in your if/elseif/else statement. Your code is functioning correctly.
If you want the big-p class one to be chosen, you need to place that block first in your if/elseif/else clause, or change the text_mode value you are passing into the function initially to something other than 'basic'.
Related
I have two custom fields which I hooked into the Ultimate Member - User Profile & Membership Plugin for Wordpress..
"username" => "Username",
"license_keys" => "License Key",
The foreach loop creates the fields perfectly, but I want to have the value of the license key field auto generated by $rand_str = generateRandomString();.
The first obvious thing is it's in a foreach loop, so both value fields on the outputted HTML become random strings and also change every time the page refreshes it changes to a new value.
I also tried if ($value = "License Key") statement to output a different $html if returned true, but since I'm in the foreach loop it applied the different $html to both fields anyhow.
So how can I control both fields outside the loop and apply individual logic to each?
/* make our new tab hookable */
add_action('um_account_tab__license', 'um_account_tab__license');
function um_account_tab__license($info) {
global $ultimatemember;
extract($info);
$output = $ultimatemember->account->get_tab_output('license');
if ($output) {
echo $output;
}
}
/* Finally we add some content in the tab */
add_filter('um_account_content_hook_license', 'um_account_content_hook_license');
function um_account_content_hook_license($output) {
ob_start();
function generateRandomString($length = 15) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$custom_fields = [
"username" => "Username",
"license_keys" => "License Key",
];
$rand_str = generateRandomString();
foreach ($custom_fields as $key => $value) {
$fields[$key] = array(
'title' => $value,
'metakey' => $key,
'type' => 'select',
'label' => $value,
);
global $ultimatemember;
$id = um_user('ID');
$field_value = get_user_meta(um_user('ID'), $key, true) ? : '';
$html = '<div class="um-field um-field-'.$key.'" data-key="'.$key.'">
<div class="um-field-label">
<label for="'.$key.'">'.$value.'</label>
<div class="um-clear"></div>
</div>
<div class="um-field-area">
<input class="um-form-field valid "
type="text" name="'.$key.'"
id="'.$key.'" value="'.$field_value.'"
placeholder=""
data-validate="" data-key="'.$key.'">
</div>
</div>';
echo $html;
}
$fields = apply_filters( 'um_account_secure_fields', $fields, $id );
$output .= ob_get_contents();
ob_end_clean();
return $output;
}
UPDATED CODE: The problem with this is that it returns only the last item in the $field_value array
foreach ($custom_fields as $key => $value) {
$fields[$key] = array(
'title' => $value,
'metakey' => $key,
'type' => 'select',
'label' => $value,
);
//$field_value = get_user_meta(um_user('ID'), $key, true) ? : '';
$field_value = [
'username' => [
'fieldvalue' => get_user_meta($id, $key, true) ? : '',
//etc
],
'license_key' => [
'fieldvalue' => generateRandomString(),
// etc
],
];
foreach ($field_value as $i => $field){
//echo um_profile_id();
$fieldsvalue[$i] = array(
'field_value' => $field,
);
$html = '<div class="um-field um-field-'.$value['label'].'" data-
key="'.$value['label'].'">
<div class="um-field-label">
<label for="'.$value['label'].'">'.$value['name'].'</label>
<div class="um-clear"></div>
</div>
<div class="um-field-area">
<input class="um-form-field valid "
type="text" name="'.$value['label'].'"
id="'.$value['label'].'" value="'.$field['fieldvalue'].'"
placeholder=""
data-validate="" data-key="'.$value['label'].'">
</div>
</div>';
}
echo $html;
}
So they way your code is now you'd need to fill it with IFs and ELSEs to cater for each value in the $custom_fields array which is looped. As you need to set numerous variables based on which thing you have, such as if is username then do this else if is license_key do this.
This is a bad design and the answer to your question using that code would be a lot of changes.
So instead I suggest a slight refactor.
Adding another dimension to the $custom_fields array, so each initial key are your main items (license_key, username etc) then each value for those keys is a sub array containing all the values you need for each item.
For example:
$custom_fields = [
'username' => [
'name' => 'Username',
'field_value' => set_user_meta(um_user('ID'), $key, true) ?: '',
'label' => 'Username',
'title' => 'Username',
//etc
],
'license_key' => [
'name' => 'License Key',
'field_value' => generateRandomString(),
'label' => 'License Key',
'title' => 'License Key',
// etc
],
];
foreach ($custom_fields as $key => $values) {
// The code
}
Then in your loop to satisfy the values you need, such as in the HTML, you'd access the same sub array key names for each one, such as $values['field_value'] and $values['label'] etc.
So on each loop it doesn't matter what the current item is in the loop (license_key, username etc), because you already set the data for each item before the loop, so the things in the loop are generic and named the same for all items (and obviously have different values).
You can remove items and add items to and from the array, and the loop will just use them as required.
I'm looking to add a Phone number field to the Woocommerce settings page. I can get the field to add to the settings list, but it gets appended to the bottom of the entire tab. Ideally I'd like to add the field in the Store Address sections on the general tab.
Here's what I'm using now (trimmed down):
add_filter('woocommerce_general_settings', 'woocommerce_add_phone');
function woocommerce_add_phone($settings) {
$settings[] = array(
'title' => 'Phone Number',
'type' => 'text',
);
$sections[] = array( 'type' => 'sectionend', 'id' => 'store_address' );
return $settings;
}
I made an attempt at using array_splice but couldn't get anywhere with it.
Any advice would be greatly appreciated.
This can be done in a simple way targeting the woocommerce_store_postcode field ID to insert the Store phone custom field in this general settings at the right location:
add_filter('woocommerce_general_settings', 'general_settings_shop_phone');
function general_settings_shop_phone($settings) {
$key = 0;
foreach( $settings as $values ){
$new_settings[$key] = $values;
$key++;
// Inserting array just after the post code in "Store Address" section
if($values['id'] == 'woocommerce_store_postcode'){
$new_settings[$key] = array(
'title' => __('Phone Number'),
'desc' => __('Optional phone number of your business office'),
'id' => 'woocommerce_store_phone', // <= The field ID (important)
'default' => '',
'type' => 'text',
'desc_tip' => true, // or false
);
$key++;
}
}
return $new_settings;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and work… You will get something like:
LoicTheAztec code works fine but I wanted to find a solution without looping. Here is my version:
function add_phone_number_settings($settings) {
// Search array for the id you want
$key = array_search('woocommerce_store_postcode', array_column($settings, 'id')) + 1;
$custom_setting[] = array(
'title' => __('Phone Number'),
'desc' => __("Enter shop phone number"),
'id' => 'woocommerce_store_phone_number',
'default' => '',
'type' => 'text',
'desc_tip' => true,
);
// Merge with existing settings at the specified index
$new_settings = array_merge(array_slice($settings, 0, $key), $custom_setting, array_slice($settings, $key));
return $new_settings;
}
add_filter('woocommerce_general_settings', 'add_phone_number_settings');
This code will add your phone number after the post code element in the Store Address section. I borrowed the splice function from here.
add_filter('woocommerce_general_settings', 'woocommerce_general_settings_add_phone_number');
function woocommerce_general_settings_add_phone_number($settings) {
$phone_number = array(
'title' => __( 'Phone Number', 'woocommerce' ),
'desc' => __( 'Add your phone number.', 'woocommerce' ),
'id' => 'woocommerce_store_phone_number',
'default' => '',
'type' => 'text',
'desc_tip' => false,
);
$array_pos = 0;
foreach ($settings as $key => $value) {
if ( $value['id'] == 'woocommerce_store_postcode' ) {
$array_pos = $key;
break;
}
}
$settings = array_insert( $settings, $phone_number, $array_pos + 1 );
return $settings;
}
/*
Array insert
#array the array to add an element to
#element the element to add to the array
#position the position in the array to add the element
*/
if(!function_exists('array_insert')) {
function array_insert($array, $element, $position) {
// if the array is empty just add the element to it
if(empty($array)) {
$array[] = $element;
// if the position is a negative number
} elseif(is_numeric($position) && $position < 0) {
// if negative position after count
if(count($array) + $position < 0) {
$position = 0;
} else {
$position = count($array) + $position;
}
// try again with a positive position
$array = array_insert($array, $element, $position);
// if array position already set
} elseif(isset($array[$position])) {
// split array into two parts
$split1 = array_slice($array, 0, $position, true);
$split2 = array_slice($array, $position, null, true);
// add new array element at between two parts
$array = array_merge($split1, array($position => $element), $split2);
// if position not set add to end of array
} elseif(is_null($position)) {
$array[] = $element;
// if the position is not set
} elseif(!isset($array[$position])) {
$array[$position] = $element;
}
// clean up indexes
$array = array_values($array);
return $array;
}
}
I'm trying to pass variable to the view and this one is very weird as the naming and directory structure is correct. Below is the function in my controller:
public function validate_apply_link(){
App::uses('CakeEmail', 'Network/Email');
$this->layout = 'blank';
$listings = $this->CareersAndJob->query("
SELECT l.sid, l.title, lp.value, u.CompanyName, u.WebSite
FROM listings l
LEFT JOIN listings_properties lp
ON lp.object_sid = l.sid
LEFT JOIN users u
ON u.sid = l.user_sid
WHERE l.active = 1
AND lp.add_parameter = 2
AND l.JobGateSenderReference IS NULL
AND u.CompanyName != 'AECOM'
ORDER BY u.CompanyName ASC
LIMIT 5
");
$doc = new DOMDocument();
ob_start();
$listing_count = count($listings);
echo nl2br("Checking $listing_count active jobs...\n\n");
$i=0;
foreach($listings as $listing){
$sid = $listing['l']['sid'];
$url = $listing['lp']['value'];
$company_name = $listing['u']['CompanyName'];
$title = htmlspecialchars($listing['l']['title']);
$length = strpos($title, "-");
if($length != 0){
$title = substr($title, 0, $length-1);
}
$title = substr($title, 0, $length-1);
$title = substr($title, 0, 10);
$data = $this->curl($url);
$check_pdf = strpos($data['info']['content_type'], "pdf");
if($check_pdf != false){
$outputs['data'][$i]['url'] = $url;
$outputs['data'][$i]['sid'] = $sid;
$outputs['data'][$i]['title'] = $title;
$outputs['data'][$i]['company_name'] = $company_name;
$outputs['data'][$i]['our_link'] = "http://careersandjobs.com.au/display-job/{$sid}";
$outputs['data'][$i]['content_type'] = $data['info']['content_type'];
$outputs['data'][$i]['data_type'] = 'pdf';
$i++;
continue;
}
#$doc->loadHTML($data['results']);
$html = $doc->saveHTML();
$xpath = new DOMXpath($doc);
$body = $doc->getElementsByTagName('body')->item(0);
$parsed_url = parse_url($url);
switch($parsed_url['host']){
case "www.michaelpage.com.au":
parse_str($url);
$exist = $xpath->query("//*[contains(#value,'{$ref}')]");
break;
case "https://vacancies.mackay.qld.gov.au":
parse_str($url);
$exist = $xpath->query("//*[contains(#value,'{$title}')]");
break;
default:
$exist = $xpath->query("//*[contains(text(),'{$title}')]");
break;
}
if($exist->length == 0){
if(strpos($url, '#') == false){
$outputs['data'][$i]['url'] = $url;
$outputs['data'][$i]['sid'] = $sid;
$outputs['data'][$i]['title'] = $title;
$outputs['data'][$i]['company_name'] = $company_name;
$outputs['data'][$i]['our_link'] = "http://careersandjobs.com.au/display-job/{$sid}";
$outputs['data'][$i]['content_type'] = $data['info']['content_type'];
$response_code = $this->http_response_codes($data['info']['http_code']);
$outputs['data'][$i]['response_code'] = $response_code;
$outputs['data'][$i]['data_type'] = 'title_not_found';
}else{
$outputs['data'][$i]['data_type'] = 'no_iframe';
}
$i++;
}
flush();
ob_flush();
}
$this->set(compact('outputs'));
}
I can do pr on the outputs variable in the view but this outputs to NULL but when I delete the entire bunch of code inside the controller function and just pass a test variable through it works.
Is there something wrong with the function that I am not aware of?
No errors were found in the above function by the way
app/Controller/CareersAndJobsController.php (line 1048)
array(
'data' => array(
(int) 0 => array(
'url' => 'http://bawbawshire.currentjobs.com.au/cvbuilder/apply+for+this+job/no/1225055',
'sid' => '3649',
'title' => 'Graduate P',
'company_name' => 'Baw Baw Shire Council',
'our_link' => 'http://careersandjobs.com.au/display-job/3649',
'content_type' => 'text/html; charset=utf-8',
'response_code' => 'OK',
'data_type' => 'title_not_found'
),
(int) 1 => array(
'url' => 'http://bawbawshire.currentjobs.com.au/cvbuilder/apply+for+this+job/no/1225724',
'sid' => '3726',
'title' => 'Program &a',
'company_name' => 'Baw Baw Shire Council',
'our_link' => 'http://careersandjobs.com.au/display-job/3726',
'content_type' => 'text/html; charset=utf-8',
'response_code' => 'OK',
'data_type' => 'title_not_found'
),
(int) 2 => array(
'url' => 'http://bawbawshire.currentjobs.com.au/cvbuilder/apply+for+this+job/no/1225826',
'sid' => '3727',
'title' => 'Road Netwo',
'company_name' => 'Baw Baw Shire Council',
'our_link' => 'http://careersandjobs.com.au/display-job/3727',
'content_type' => 'text/html; charset=utf-8',
'response_code' => 'OK',
'data_type' => 'title_not_found'
)
)
)
This is what I am getting from outputs variable just before it gets set by the set function in controller
Any reason you chose to use CakePHP? Because you seem to not make use of its functionality!
You're using literal SQL queries, therefore basically skipping the Models functionality.
You're outputting your content from your Controller? Be careful when using output buffering, this may conflict with CakePHP's inner workings, which also relies on output buffering in many cases. Because you're already outputting the content here (ob_flush()), you'll be outputting your content before your View is reached..
Normally I would point to specific points in the manual, however, because there's so much wrong here, I would suggest to start reading at the beginning
I am trying to add some html code before each tag printed as an array element.
My code:
$term_links = array();
foreach ($vars['node']->taxonomy as $term)
{
$term_links[] = l($term->name, 'taxonomy/term/' . $term->tid,
array(
'attributes' => array(
'title' => $term->description
)));
}
$vars['node_terms'] = implode(', ', $term_links);
At the moment the tags are printed seperated by a comma. I would like to add a small image before each tag element using img src="tag.png" How can I do this?
EDIT - My current Code, still not working.
if (module_exists('taxonomy')) {
$img = 'some html';
$text = $img . $term->name;
$path = 'taxonomy/term/' . $term->tid;
$term_links = array();
foreach ($vars['node']->taxonomy as $term) {
$term_links[] = l($text, $path, array(
'html' => TRUE,
'attributes' => array(
'title' => $term->description
)));
}
$vars['node_terms'] = implode(', ', $term_links);
}
}
Dupal's l() function has an option "html" you can set it to TRUE and use IMG + TITLE as a title.
Here is the example:
$img = '<img src="..." />';
$text = $img . $term->name;
$path = 'taxonomy/term/' . $term->tid;
$term_links[] = l($text, $path, array(
'html' => TRUE,
'attributes' => array(
'title' => $term->description
)
));
I have some PHP code I've been working on for a good few days now. I'm trying to generate a formatted list of rules from a flat array. I got help here before on how to turn the flat array into a tree array, but I'm having difficulty writing a recursive function that can go through it and successfully break it down at points at such depths where I'd like the rules to be members of an unordered list from the markup that gets printed.
<?php
$data = array(
'0' => 'Introduction',
'4' => 'General',
'4.1' => 'Chat',
'4.1.1' => 'Do',
'4.1.1.9' => 'This',
'4.1.1.10' => 'That',
'4.1.1.11' => 'Other',
);
$struct = array(
'children' => array()
);
foreach ($data as $ruleID => $content)
{
$parent =& $struct;
foreach (explode('.', $ruleID) as $val)
{
if (!isset($parent['children'][$val]))
{
$parent['children'][$val] = array(
'content' => '',
'children' => array()
);
}
$parent =& $parent['children'][$val];
}
$parent['content'] = $content;
}
$out = '';
$rules = array_pop($struct);
format_rule($rules);
var_dump($rules);
echo $out;
function format_rule($arr, $depth=0)
{
global $out;
echo "depth: $depth\n";
foreach($arr as $key => $val)
{
switch($depth)
{
case 0:
$out .= '<h1>'.$val['content']."</h1><br />\n";
break;
case 1:
$out .= '<h2>'.$val['content']."</h2><br />\n";
break;
case 2:
$out .= '<h3>'.$val['content']."</h3><br />\n";
break;
default:
$out .= '<li>'.$val['content']."</li>\n";
break;
}
if(isset($val['children']) && count($val['children']) > 0)
{
if($depth > 2)
{
$out .= '<ul>';
format_rule($val['children'], ++$depth);
$out .= '</ul>';
}
else
{
format_rule($val['children'], ++$depth);
}
}
}
}
The output at the moment is:
<h1>Introduction</h1><br />
<h1>General</h1><br />
<h2>Chat</h2><br />
<h3>Do</h3><br />
<li>This</li><br />
<li>That</li><br />
<li>Other</li><br />
Which is great, except from my code I'm pretty sure the section under 'Do' should have a <ul> around it.
change your code to :
if($depth >= 2)
note: remember the count starts at 0, not 1.
Try this:
<?php
$data = array(
'0' => 'Introduction',
'4' => 'General',
'4.1' => 'Chat',
'4.1.1' => 'Do',
'4.1.1.9' => 'This',
'4.1.1.10' => 'That',
'4.1.1.11' => 'Other',
);
function get_level($key){
return count(explode(".",$key));
}
function set_tag(&$array,$key,$item,&$ul_started){
$level = get_level($key);
switch($level){
case 1:
case 2:
case 3:
if($ul_started){
$array[$key] = "</ul><h".$level.">".$item."</h".$level."><br>";
$ul_started=false;
}else{
$array[$key] = "<h".$level.">".$item."</h".$level."><br>";
}
break;
default:
if(!$ul_started){
$array[$key] = "<ul><li><strong>".$item."</strong></li><br>";
$ul_started=true;
}else{
$array[$key] = "<li><strong>".$item."</strong></li><br>";
}
break;
}
}
$ul_started = false;
foreach($data as $key=>$item){
set_tag($data,$key,$item,$ul_started);
}
if($ul_started){
$keys = array_keys($data);
$data[$keys[count($data)-1]] .= "</ul>";
}
echo implode("",$data);
?>