<?php

    class HTMLUtils {
        
        public static function closeUnclosedTags($html) {
            
            $aloneTags = array('area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'isindex', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr');
            $endNameTagSymbols = array('>', ' ', "\n", "\r", "\t");
            $openedTagsStack = array();
            $currentTag = '';
            $insideOpenTag = false;
            $insideCloseTag = false;
            $waitForTagEnd = false;
            $closedBrake = false;
            
            $html = preg_replace('%<!-[^>]*->%', '', $html);
            
            for ($i = 0; $i < strlen($html); $i++) {
                
                if ($html[$i] == '<') {
                    
                    if (!$insideOpenTag && !$insideCloseTag) {
                        
                        if ($html[$i + 1] == '/') {
                            $insideCloseTag = true;
                            $i++;
                        } else {
                            $insideOpenTag = true;
                        }
                        
                    }
                    
                } elseif ($waitForTagEnd) {
                    
                    if ($html[$i] == '>') {
                                
                        $insideOpenTag = false;
                        $insideCloseTag = false;
                        $waitForTagEnd = false;
                        
                    } else continue;
                    
                } elseif ($insideOpenTag || $insideCloseTag) {
                    
                    if (!in_array($html[$i], $endNameTagSymbols)) {
                        
                        $currentTag .= $html[$i];
                        
                    } else {
                        
                        if ($html[$i] == '>') {
                        
                            $closedBrake = true;
                            
                        }
                        
                        if ($insideOpenTag) {
                            
                            if (!in_array($currentTag, $aloneTags))
                                $openedTagsStack[] = $currentTag;
                            
                        } else {
                            
                            if (!in_array($currentTag, $openedTagsStack)) {
                                
                                $html = substr($html, 0, $i - strlen($currentTag) - 2) . substr($html, strpos($html, '>', $i) + 1);
                                $i -= strlen($currentTag) + 3;
                                
                                $closedBrake = true; // костыль
                                
                            } else {
                                    
                                $lastOpenedTag = array_pop($openedTagsStack);
                                $needToInsert = '';
                                
                                while ($lastOpenedTag != $currentTag) {
                                    
                                    $needToInsert .= '</' . $lastOpenedTag . '>';
                                    $lastOpenedTag = array_pop($openedTagsStack);
                                    
                                }
                                
                                $html = substr($html, 0, $i - strlen($currentTag) - 2) . $needToInsert . substr($html, $i - strlen($currentTag) - 2);
                                
                                $i += strlen($needToInsert);
                                
                            }
                            
                        }
                        
                        $currentTag = '';
                        
                        if ($closedBrake) {
                                    
                            $insideOpenTag = false;
                            $insideCloseTag = false;
                            $closedBrake = false;
                            
                        } else {
                            
                            $waitForTagEnd = true;
                            
                        }
                        
                    }
                    
                    
                    
                } elseif (!$insideOpenTag && !$insideCloseTag && $html[$i] == '>') {
                    
                    $html = substr($html, 0, $i) . '&gt;' . substr($html, $i + 1);
                    $i += 3;
                    
                }
                
            }
            
            if ($insideOpenTag || $insideCloseTag)
                $html = substr($html, 0, strrpos($html, '<'));
            
            if (!empty($openedTagsStack)) {
                
                for ($i = count($openedTagsStack) - 1; $i >= 0; $i--)
                    $html .= '</' . $openedTagsStack[$i] . '>';
                
            }
            
            return $html;
            
        }
        // логика - закрывает все теги, закрытые без открытых удаляет
        
    }
    
    $html = '<b class="baka"><!-- --><b top="kek"><i hui><img lal><stro>ng><i>k</b></strong )))></i></stro';
    
    echo $html . "\n";
    
    echo HTMLUtils::closeUnclosedTags($html);