Stack Exchange
Trying to make sure html tags are not left open in php
I cannot figure out why this code is not working:
<?php
  $text = "<a><li><ul><ol>Hello";
  $tags = array('a', 'li', 'ul', 'ol');
  $tagcount = count($tags);
  $i = 0;

  while ($i < $tagcount) {
      $opentag = "<".$tags[$i];
      $closetag = "</".$tags[$i].">";

      if (stripos($text, $opentag)) {
          $lastopen = strripos($text, $opentag);
          $lastclose = strripos($text, $closetag);

          if ($lastopen > $lastclose) {
              $text = substr($text, 0, $lastopen);
              echo $tags[$i] . " tag was open. ";
          } else {
              echo $tags[$i] . " tag was closed. ";
      } else {
          echo $tags[$i] . " tag was not open. ";
      $i++;
  }
?>

What it should do is at least signify that all the tags in the $tags array are open. It's meant to use substr() to make sure none of the tags are open but it's not working. Running this gives:

a tag was not open. li tag was open. ul tag was not open. ol tag was not open.

even though they are all open. Any help would be greatly appreciated.

<a> is 'not open' because stripos will return the position of the first occurrence and the first occurrence is at index 0 (which evaluates to false). 
<li> is found to be open because its index is not zero. But then you truncate the search string so that the next iteration <ul> is found at zero index... 
Change your if to stripos($text, $opentag) === false and see if that allows you to find the a tag as being open. You will have to figure out what to do about the substr(...) since I think your business logic will most likely dictate that.

It seems your logic is flawed: strripos returns false if the needle is not found so in your inner if statement you are testing if a number is greater than false.
For your outer if statement, you need to test for false:
if (stripos($text, $opentag) !== false) {
  // found at position 0 or more...

Your inner if should be something like:
    if (($lastclose !== false) && ($lastopen > $lastclose)) {


Here's an example that works using regular expressions:
  $text = "<a><li><ul><ol>Hello";
  $tags = array('a', 'li', 'ul', 'ol');
  $tagcount = count($tags);
  $i = 0;
  $matches = array();
  foreach ($tags as $tag)
  {
    $closed = preg_match_all("/<\/".$tag.">/i", $text, $matches);
    $open = preg_match_all("/<".$tag.">/i", $text, $matches);

    if ($open == 0)
    {
        echo $tag." was not opened, ";
    }
    else if ($open > $closed)
    {
        echo $tag." was left open, ";
    }
    else
    {
        echo $tag." was closed properly, ";
    }
}


Parsing HTML is non-trivial, and there are some good libraries out there to do the work for you. The Tidy library has been available since PHP 5, and can be used to parse and tidy HTML fragments, or complete page output. There's a good article on devzone which shows how to use it, including how to combine it with output buffering.
With respect to the code you've posted, you shouldn't use strpos in an if statement like that. To quote the PHP manual:

Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "" . . . Use the === operator for testing the return value of this function.

So to test that a substring was not found in a string, do:
if(strpos($haystack, $needle) === FALSE)

And to test that a substring was found:
if(strpos($haystack, $needle) !== FALSE)

But I really, really would advise using a pre-existing library for HTML manipulation or validation, especially if it is security-sensitive (anti-XSS, for example).
