Count nested shortcodes, then reset for next parent shortcode - php

Bit of an interesting question that's puzzling me, so I know how to count how many times a shortcode is called on a page using a static counter. However, I want to reset the counter whenever the parent shortcode is called:
<?php function gw_row($atts, $content = null) {
return '<div class="gw-row">'.do_shortcode($content).'</div>';
} add_shortcode("gw-row", "gw_row");
function gw_column($atts, $content = null) {
static $count = 0; $count++; if($count > 5){$count = 0}
return '<div class="column">'.do_shortcode( $content ).'</div>';
} add_shortcode("gw-column", "gw_column");?>
So explaining it further, there will be multiple [gw-row] shortcodes on a page, this is the 'Parent Shortcode'. Within this shortcode I use [gw-column]. I want to count how many columns are used on the page within each parent shortcode.
Example:
[gw-row]
[gw-column]$Count = 1[/gw-column]
[gw-column]$Count = 2[/gw-column]
[/gw-row]
Reset $count
[gw-row]
[gw-column]$Count = 1[/gw-column]
[gw-column]$Count = 2[/gw-column]
[gw-column]$Count = 3[/gw-column]
[/gw-row]
Reset $count
I've thought about making [gw-row] an object and resetting $count just after the closing of the <div> which might work, but I wonder if there's a better way?
My thoughts:
<?php function gw_row($atts, $content = null) {
global $count;
ob_start();?>
<div class="gw-row">
<?php do_shortcode($content);?>
</div><?php $count = 0;?>
<?php return ob_clean();
} add_shortcode("gw-row", "gw_row");
function gw_column($atts, $content = null) {
$count++; if($count > 5){$count = 0}
return '<div class="column">'.do_shortcode( $content ).'</div>';
} add_shortcode("gw-column", "gw_column");?>

Ok so I was seriously overthinking this, the solution is quite simple and close to what I suggested.
Simply define $count globally and set it to 0 in the [gw-row] shortcode. This will reset it every time it's called:
<?php function gw_row($atts, $content = null) {
global $count; $count = 0;
return '<div class="gw-row">'.do_shortcode($content).'</div>';
} add_shortcode("gw-row", "gw_row");
function gw_column($atts, $content = null) {
global $count; $count++; if($count > 5){$count = 0}
return '<div class="column">'.do_shortcode( $content ).'</div>';
} add_shortcode("gw-column", "gw_column");?>

Related

WordPress Facebook Comment Count in archive

I want to display the Facebook comment count on my blog archives.
My wordpress site has the following php function in function.php
// Get combined FB and WordPress comment count
function full_comment_count() {
global $post;
$url = get_permalink($post->ID);
$filecontent = file_get_contents('https://graph.facebook.com/?ids=' . $url);
$json = json_decode($filecontent);
$count = $json->$url->comments;
$wpCount = get_comments_number();
$realCount = $count + $wpCount;
if ($realCount == 0 || !isset($realCount)) {
$realCount = 0;
}
return $realCount;
}
This is how I am using the function on a template file inside a loop <?php echo full_comment_count(); ?>
Most of the time most of the articles show "0" comments. But sometime one or 2 of them work. what am i doing wrong
Try this
function full_comment_count() {
global $post;
$url = get_permalink($post->ID);
$filecontent = file_get_contents('https://graph.facebook.com/?ids=' . $url);
$json = json_decode($filecontent);
$count = $json->$url->comments;
if ($count == 0 || !isset($count)) {
$count = 0;
}
echo $count;
}

HTML - String containing color codes to color

I'm currently facing a problem here, I have many different strings like these:
"he#00ff00llo"
"#cc9200test"
And so on.
I'm outputting this on an HTML page (Grabbing it through my database)
Anyways, what I want to achieve is to read those #00ff00 and output it as the color itself.
EDIT:
these are usernames, and most of the time they go like this: #ff0000#SomeName | Which I then want to turn into <span style="color: #ff0000">#SomeName</span> oh and the there are usernames with several colorcodes.
EDIT:
My friend gave me this code which solved my problem. :)
IT WAS SOLVED IN PHP
ALSO THE CODE BELOW (Posted by Oriol) IS WORKING! :)
THIS CODE WORKS(PHP):
<?php
function colorCodesRenderProperly($name)
{
$name = htmlspecialchars($name);
if(preg_match('/^(#[0-9a-fA-F]{6})+$/', $name) === 1)
{
return $name;
}
preg_match_all('/#[0-9a-fA-F]{6}/', $name, $codes);
$replaced = array();
$codes_original = $codes;
$i = 0;
$count = 1;
foreach($codes[0] as &$code)
{
if(in_array($codes_original[0][$i], $replaced))
{
continue;
}
$code = sprintf('%02s', dechex((hexdec($code[1].$code[2])/255*128)))
.sprintf('%02s', dechex((hexdec($code[3].$code[4])/255*128)))
.sprintf('%02s', dechex((hexdec($code[5].$code[6])/255*128)));
$name = str_replace($codes_original[0][$i], "<span style=\"color: #$code;\">", $name, $count);
$replaced[] = $codes_original[0][$i];
$i++;
$count = 1;
}
while($i > 0)
{
$name .= "</span>";
$i--;
}
return $name;
}
?>
Try this:
var txt = document.createTextNode("he#00ff00llo"),
wrapper = document.createElement('span'),
regExp = /#[\da-f]{6}/i,
pos;
wrapper.appendChild(txt);
while(~(pos = txt.nodeValue.search(regExp))) {
txt = txt.splitText(pos);
var span = wrapper.cloneNode(false);
span.style.color = txt.nodeValue.substr(0,7);
txt.nodeValue = txt.nodeValue.substr(7);
span.appendChild(txt);
wrapper.appendChild(span);
}
// append wrapper to the DOM

Recursive function for comment and reply PHP application

I am having difficulty conceptualizing a recursive function for appending replies to comments, replies to replies, replies to replies to replies, etc.
This is my comments table:
Which SHOULD look something like this when rendered:
As it stands I can render each comment associated with the article_id (excluding those that are NOT NULL, of course):
$comments = $commentClass->fetch_article_comments($article_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
}
Now I'm assuming I need to add a recursive function at the end of the above foreach statement, but I have yet to come up with anything remotely successful in appending the comments replies and the replies to each reply.
Can anyone help me accomplish this or perhaps point me in the right direction. I am not entirely familiar with recursive functions. I have done some scanning of the internet and on stackoverflow looking for something that helps, but haven't found anything helpful yet.
I did come across this post which recommended using a hierarchical database system, but I think I would prefer to use a php recursive function for this.
Thanks.
edit
By using the below answers I am only returning the results first comment and then it iterates and displays that one comment indefinitely. I can't figure out why?
My php:
function display_comments($article_id, $parent_id=0, $level=0) {
global $comment;
global $member;
global $signed_in;
global $username;
$comments = $comment->fetch_article_comments($article_id, $parent_id);
foreach($comments as $data) {
$comment_id = $data['comment_id'];
$c_member_id = $data['member_id'];
$comment_text = $data['comment_text'];
$comment_timestamp = timeAgo($data['comment_timestamp']); //get time ago
$member_data = $member->fetch_member_data($c_member_id);
$c_member_username = $member_data['member_username'];
$c_member_avatar = $member_data['member_avatar'];
//render HTML here
$parent = $data['comment_parent'];
display_comments($article_id, $parent, $level+1);
}//end foreach
}//end display_comments()
and my PDO query:
public function fetch_article_comments($article_id, $parent_id) { //$page = (int)(!isset($_GET['page'])) ? 0 : $_GET['page'];
if ($parent_id > 0) {
$parent_id = "= $parent_id";
} else {
$parent_id = "IS NULL";
}
$query = $this->db->prepare("SELECT * FROM `comments2` WHERE `article_id` = $article_id AND `comment_parent` $parent_id ORDER BY `comment_timestamp` DESC");
try{
$query->execute();
$comments = $query->fetchAll(); //returns an array
$query->closeCursor();
return $comments;
} catch(PDOException $e){
die($e->getMessage());
}
}
The core of the problem is this:
$comments = $commentClass->fetch_article_comments($article_id);
I assume, this function somwhere creates and runs SQL, that is similar to SELECT ... WHERE comments.article_id=$article_id. This is not sufficient - you need something like
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
that translates into SQL similar to SELECT ... WHERE comments.article_id=$article_id AND comments.comment_parent ($parent_id>0)?"=$parent_id":"IS NULL"
Now you can write your PHP function:
function display_comments ($article_id, $parent_id=0, $level=0) {
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
//Use $level to render the intendation level
//Recurse
display_comments ($article_id, $comment_id, $level+1);
}
}
And finally call it with display_comments ($article_id);
You could do something like:
function getCommentsForParent($parent="") {
echo "<div class=\"comment\">";
$db = get("select your db logics where parent = $parent");
foreach ($db as $comment) {
echo "print your comment in a box and make a div around the hole comments"
getCommentsForParent($comment['parent_id']);
}
echo "</div>";
}
invoke function with getCommentsForParent()
With your code it should be something like:
function getCommentForParent($parent="") {
global $commentsClass, $article_id;
$comments = $commentClass->fetch_article_comments($article_id,$parent);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
getCommentForParent($comment['parent']);
}
}
Look closely, ive adjusted your fetch article_comments. It now has a listener for $parent. Make sure that when your $parent = "", the class will only select the comments with empty parent.
invoke with getCommentsForParent()
It will automatically loop through the parent. Ofcourse this is highly conceptual but given your code you should get the hang of it.

Joomla's Who's Online Counter - How to add thousand separator?

One of my sites frequently has more than 1000 concurrent visitors and just for consistency I want to add a thousands separator to the display so it shows like 1,000.
My initial thought was just to add number_format before the variable holding the guest count but this stops the counter working for some reason.
The function in helper.php counting the guests looks like this:
// show online count
static function getOnlineCount() {
$db = JFactory::getDbo();
// calculate number of guests and users
$result = array();
$user_array = 0;
$guest_array = 0;
$query = $db->getQuery(true);
$query->select('guest, usertype, client_id');
$query->from('#__session');
$query->where('client_id = 0');
$db->setQuery($query);
$sessions = (array) $db->loadObjectList();
if (count($sessions)) {
foreach ($sessions as $session) {
// if guest increase guest count by 1
if ($session->guest == 1 && !$session->usertype) {
$guest_array ++;
}
// if member increase member count by 1
if ($session->guest == 0) {
$user_array ++;
}
}
}
$result['user'] = $user_array;
$result['guest'] = $guest_array;
return $result;
}
And in the template the data is displayed using the following:
<?php if ($showmode == 0 || $showmode == 2) : ?>
<?php $guest = JText::plural('MOD_WHOSONLINE_GUESTS', $count['guest']); ?>
<?php $member = JText::plural('MOD_WHOSONLINE_MEMBERS', $count['user']); ?>
<p><?php echo JText::sprintf('MOD_WHOSONLINE_WE_HAVE', $guest, $member); ?></p>
Where do I put the number_format so the separator is added please?
does this not work?
$guest = JText::plural('MOD_WHOSONLINE_GUESTS',number_format($count['guest'],0,'.',','));

Global Variable Changes to Function's Return Value

On my website i have a PHP file which generates it's menus from an external PHP file (to make updating easier)
heres part of the PHP which outlines the problem:
$products = array("Kinetic","Key","Twister","Ellipse","Focus","Trix","Classic","Pod","Halo","Alu","Rotator","Canvas","Image","Flip","Executive","Torpedo","Nature","Wafer Card","Alloy Card","Bottle Opener","Ink Pen","Clip","Light","Tie Clip","Event Lanyard","Lizzard Wristband","Slap Wristband");
$others = array("Other 1","Other 2","Other 3","Other 4","Other 5");
function genMenu($product) {
global $products;
global $others;
$menu="<div class='titlebar'><div class='title'>USBs</div></div><div class='buttons'>";
for ($x=0;$x<count($products); $x++) {
$p=$products[$x];
$link=strtolower(str_replace(' ', '', $p)).".php";
if($product==$p) {$menu=$menu."<span class='activebutton'><span class='textspace'>» ".$p."</span></span>";}
else {$menu=$menu."<a href='".$link."'><span class='button'><span class='textspace'>» ".$p."</span></span></a>";}
if(count($products)>$x+1) {
$menu=$menu."<img src='layout/seperator.jpg' class='seperator' alt='' width='184' height='2' />";
}
}
$menu=$menu."</div><div class='titlebar'><div class='title'>Other Products</div></div><div class='buttons'>";
for ($y=0;$y<count($others); $y++) {
$o=$others[$y];
$link=strtolower(str_replace(' ', '', $o)).".php";
if($product==$o) {$menu=$menu."<span class='activebutton'><span class='textspace'>» ".$o."</span></span>";}
else {$menu=$menu."<a href='".$link."'><span class='button'><span class='textspace'>» ".$o."</span></span></a>";}
if(count($others)>$y+1) {
$menu=$menu."<img src='layout/seperator.jpg' class='seperator' alt='' width='184' height='2' />";
}
}
$menu=$menu."</div>";
return (string)$menu;
}
function genDrop($product) {
global $products;
global $others;
$drop=$products[12];
return $drop;
}
So, the menu generates using an array of products i have outside the function, enabling their use by making them global... The problem im having is that when the function returns $menu, it also changes $products value to the same. (but not $others)
therefore the second function (genDrop) returns 't' from $menu="<div class='t
is this meant to happen? how do i stop it?
PHP in the HTML that calls the functions:
<?php include("menufoot.php");
$product="Twister";
$products = genMenu($product);
$dropmenu = genDrop($product);
print $dropmenu;
$footer = genFoot($product);
$mobilefooter = genMobFoot($product);
?>

Categories