Page 1 of 1

highlight_string through preg_replace?

Posted: Sat Dec 05, 2009 5:04 am
by Weiry
Im working on a piece of code that recognizes a code tag, and the highlights the string inside the tags. Only problem is, its not working :D

Code: Select all

function encode($string){
     $search = array( '/\[code\](.*?)\[\/code\]/is', '/\[php\](.*?)\[\/php\]/is' );
     $replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>$1</div></div>", $this->colourCode('$1') );
     return preg_replace($search, $replace, $string);
}
function colourCode($string){
    $string = highlight_string($string);
    return "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>{$string}</div></div>";
}
The first combination outputs fine, and is formatted as ive specified for it.
However if i attempt to call formatPHP as a replacement string, it cracks it and outputs " $1 ".
Although if i change the second replacement from the function to , "$1"
it prints out the same formatted code as the first combination.
It seems as if the moment i call any sort of function, even just highlight_string("$1") as the replacement, it still doesn't work.

Any ideas how to achieve this?

Re: highlight_string through preg_replace?

Posted: Sun Dec 06, 2009 5:26 am
by Weiry
Well this is a follow up, i still haven't managed to implement any sort of highlighting, although the class is nearly complete.

So now i have 2 problems:
1. Highlighting fails
2. if the code receives a $1 etc as in the preg_replace, it repeats the code being passed to it rather than displaying "$1"

Here is the class:

Code: Select all

<?php
#
#   VNCode Class
#       version 1.0
#       Weiry(c)
#
#       NOTE: You are free to use this code, however
#             you must leave any and all references
#             to my work.
#
#   Contents:
#
#   1. Introduction
#   2. Requirements
#   3. The VNCode Class
#   4. Creating Custom Tags
#
#
#   // 1. Introduction //
#
#   This class deals with strings which hold BBCode tags
#   or custom tags the user wishes to create. To create
#   custom tags, the user must have some knowledge of
#   regular expressions.
#
#
#
#   // 2. Requirements //
#
#       This class requires the css file which is
#       associated with each of the div tags.
#       Files:
#           codequote.css
#
#
#
#   // 3. The VNCode Class //
#
 
class VNCode{
 
    #
    #   Encode Function
    #
    #   This is the only public function and
    #   is used to encode the desired string.
    #
    public function encode($string){
        // If the string is not empty
        if(!empty($string)){
        // Create the regex array for tags
            $search = array( 
                '/\[b\](.*?)\[\/b\]/is', 
                '/\[i\](.*?)\[\/i\]/is', 
                '/\[u\](.*?)\[\/u\]/is', 
                '/\[quote\](.*?)\[\/quote\]/is', 
                '/\[quote\=(.*?)\](.*?)\[\/quote\]/is',
                '/\[img\](.*?)\[\/img\]/is', 
                '/\[url\](.*?)\[\/url\]/is',
                '/\[url\=(.*?)\](.*?)\[\/url\]/is',
                '/\n/s',
                '/\t/s'); 
        // Create the replacement HTML array tags
            $replace = array( 
                '<strong>$1</strong>', 
                '<em>$1</em>', 
                '<u>$1</u>', 
                '<div class="quotecontent">$1</div>',
                '<div class="quotetitle">$1 wrote:</div><div class="quotecontent">$2</div>',
                '<img src="$1" />', 
                '<a href="$1">$1</a>', 
                '<a href="$1">$2</a>',
                '<br>',
                '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'); 
        // Convert any html characters to encoded characters
            $string = htmlspecialchars($string);
        // Create the code language array
            $languages = $this->getLanguages();
        // Create the code boxes
            foreach($languages as $lang){
                // Split each tag
                $codeArr = preg_split($lang['tag'], $string, -1, PREG_SPLIT_OFFSET_CAPTURE);
                // Remove anything other than the tags
                array_splice($codeArr, 0, 1);
                
                foreach($codeArr as $code){
                    // Replace the existing text with the new code box
                    $string = preg_replace($lang['regex'], $this->formatCode($code[0],$lang['lang']), $string);
                }
            }
        // Return the final encoded string
            return preg_replace($search, $replace, $string);
        }else{
            // Return false if no string was sent
            return false;
        }
    }
 
    #
    #   FormatCode Function
    #
    #   This function is responsible for replacing
    #   any specified code tags into code boxes.
    #   All tags are pre-specified.
    #
    private function formatCode($string,$type){
        if(!empty($string)){
            // Check each language available and set the appropreate language
            foreach($this->getLanguages() as $language){
                if(in_array($type, $language)){
                    $code = $language['lang'];
                }
            }
            // Split the code into lines
            $codeArr = preg_split('/\\n/s', $string);
            
            // Create the code box header
            $newCodeArr[] = "<div class='codebox'><div class='codeheader'>{$code}</div><div class='codeholder' style='max-height: 300px;'>";
            
            
            for($i = 0,$j = 1; $i <= count($codeArr); $i++,$j++){
                if($i % 2){
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li2'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] = "<div class='li2'>$j. {$codeArr[$i]}</div>";
                }else{
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li1'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] .= "<div class='li1'>$j. {$codeArr[$i]}</div>";
                }
            }
            // Close the code box
            $newCodeArr[] = "</div></div>";
            
            // Return the HTML code for the code box
            return implode($newCodeArr);
        }else{
            // Return false if no code was submitted
            return false;
        }
    }
    
    #
    #   getLanguages Function
    #
    #   This function defines languages and
    #   regular expressions used in order to
    #   determine the current tag being processed.
    #
    private function getLanguages(){
        return array(
                "php"       => array( "lang" => "php",  "tag" => '/\[php\]/sx',         "regex" => '/\[php\](.*?)\[\/php\]/is'),
                "html"      => array( "lang" => "html", "tag" => '/\[html\]/sx',        "regex" => '/\[html\](.*?)\[\/html\]/is'),
                "sql"       => array( "lang" => "sql",  "tag" => '/\[sql\]/sx',         "regex" => '/\[sql\](.*?)\[\/sql\]/is'),
                "code"      => array( "lang" => "code", "tag" => '/\[code\]/sx',        "regex" => '/\[code\](.*?)\[\/code\]/is'),
                "code=php"  => array( "lang" => "php",  "tag" => '/\[code\=php\]/sx',   "regex" => '/\[code\=php\](.*?)\[\/code\]/is'),
                "code=sql"  => array( "lang" => "sql",  "tag" => '/\[code\=sql\]/sx',   "regex" => '/\[code\=sql\](.*?)\[\/code\]/is'),
                "code=html" => array( "lang" => "html", "tag" => '/\[code\=html\]/sx',  "regex" => '/\[code\=html\](.*?)\[\/code\]/is')
            );
    }
};?>
This is an example of what i mean in point 2.

Code: Select all

1. function encode($string){
2. $search = array( '/\[code\](.*?)\[\/code\]/is', '/\[php\](.*?)\[\/php\]/is' );
3. $replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>function encode($string){ 
$search = array( '/\[code\](.*?)\[\/code\]/is', '/\[php\](.*?)\[\/php\]/is' ); 
$replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>$1</div></div>", $this->colourCode('$1') ); 
return preg_replace($search, $replace, $string); 
} 
function colourCode($string){ 
$string = highlight_string($string); 
return "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>{$string}</div></div>"; 
}</div></div>", $this->colourCode('function encode($string){ 
$search = array( '/\[code\](.*?)\[\/code\]/is', '/\[php\](.*?)\[\/php\]/is' ); 
$replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>$1</div></div>", $this->colourCode('$1') ); 
return preg_replace($search, $replace, $string); 
} 
function colourCode($string){ 
$string = highlight_string($string); 
return "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>{$string}</div></div>"; 
}') );
4. return preg_replace($search, $replace, $string);
5. }
6. function colourCode($string){
7. $string = highlight_string($string);
8. return "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>{$string}</div></div>";
9. }
You will notice that on line 3:
3. $replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>function encode($string){

But you will see that there is a "function encode($string){" at the very end, this should only be displaying:

Code: Select all

$replace = array( "<div class='codebox'><div class='codeheader'>Code: </div><div class='codeholder'>$1</div></div>", $this->colourCode('$1') );
Which can be clearly seen correctly on line 5.

Would appreciate any help, as i have been stuck on this for a while now.

Re: highlight_string through preg_replace?

Posted: Sun Dec 06, 2009 2:09 pm
by AbraCadaver
I haven't looked deeply into your code, but it seems that you are trying to pass a function to the replace param of preg_replace(). That won't work. What you need to do is a preg_match_all() on your input and then loop through the matches and highlight and then replace.

HTH
-Shawn

Re: highlight_string through preg_replace?

Posted: Sun Dec 06, 2009 7:25 pm
by Weiry
AbraCadaver wrote:What you need to do is a preg_match_all()
And that (i think) solved my repetition problem.
EDIT:: Problem still exists.
EDIT:: Updated Class to use preg_match_all()

Code: Select all

class VNCode{
 
    #
    #   Encode Function
    #
    #   This is the only public function and
    #   is used to encode the desired string.
    #
    public function encode($string){
        // If the string is not empty
        if(!empty($string)){
        // Create the regex array for tags
            $search = array( 
                '/\[b\](.*?)\[\/b\]/is', 
                '/\[i\](.*?)\[\/i\]/is', 
                '/\[u\](.*?)\[\/u\]/is', 
                '/\[quote\](.*?)\[\/quote\]/is', 
                '/\[quote\=(.*?)\](.*?)\[\/quote\]/is',
                '/\[img\](.*?)\[\/img\]/is', 
                '/\[url\](.*?)\[\/url\]/is',
                '/\[url\=(.*?)\](.*?)\[\/url\]/is',
                '/\n/s',
                '/\t/s'); 
        // Create the replacement HTML array tags
            $replace = array( 
                '<strong>$1</strong>', 
                '<em>$1</em>', 
                '<u>$1</u>', 
                '<div class="quotecontent">$1</div>',
                '<div class="quotetitle">$1 wrote:</div><div class="quotecontent">$2</div>',
                '<img src="$1" />', 
                '<a href="$1">$1</a>', 
                '<a href="$1">$2</a>',
                '<br>',
                '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'); 
        // Convert any html characters to encoded characters
            $string = htmlspecialchars($string);
        // Loop through the code language array
            foreach($this->getLanguages() as $lang){
            // Create the code boxes
                // Split each tag
                $codeArr = preg_split($lang['tag'], $string, -1, PREG_SPLIT_OFFSET_CAPTURE);
                // Remove anything other than the tags
                array_splice($codeArr, 0, 1);
                
                // Find all tag matches and remove entries without [tag]'s
                preg_match_all($lang['regex'], $string, $matches);
                array_splice($matches, 1, 2);
                
                // Loop through the matches
                foreach($matches[0] as $match){
                    // Replace the existing text with the new code box
                    $codeBox[0][] = $lang['regex'];
                    $codeBox[1][] = $this->formatCode(preg_replace($lang['tag'], '', $match),$lang['lang']);
                }
            }
        // Return the final encoded string
        
            $string = preg_replace($codeBox[0], $codeBox[1], $string);
            return preg_replace($search, $replace, $string);
        }else{
            // Return false if no string was sent
            return false;
        }
    }
 
    #
    #   FormatCode Function
    #
    #   This function is responsible for replacing
    #   any specified code tags into code boxes.
    #   All tags are pre-specified.
    #
    private function formatCode($string,$type){
        if(!empty($string)){
            // Check each language available and set the appropreate language
            foreach($this->getLanguages() as $language){
                if(in_array($type, $language)){
                    $code = $language['lang'];
                }
            }
            // Split the code into lines
            $codeArr = preg_split('/\\n/s', $string);
            // Create the code box header
            $newCodeArr[] = "<div class='codebox'><div class='codeheader'>{$code}</div><div class='codeholder' style='max-height: 300px;'>";
            
            for($i = 0,$j = 1; $i <= count($codeArr); $i++,$j++){
                if($i % 2){
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li2'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] = "<div class='li2'>$j. {$codeArr[$i]}</div>";
                }else{
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li1'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] .= "<div class='li1'>$j. {$codeArr[$i]}</div>";
                }
            }
            // Close the code box
            $newCodeArr[] = "</div></div>";
            
            // Return the HTML code for the code box
            return implode($newCodeArr);
        }else{
            // Return false if no code was submitted
            return false;
        }
    }
    
    #
    #   getLanguages Function
    #
    #   This function defines languages and
    #   regular expressions used in order to
    #   determine the current tag being processed.
    #
    private function getLanguages(){
        return array(
                "php"       => array( "lang" => "php",  "tag" => '/\[php\]/sx',         "regex" => '/\[php\](.*?)\[\/php\]/is'),
                "html"      => array( "lang" => "html", "tag" => '/\[html\]/sx',        "regex" => '/\[html\](.*?)\[\/html\]/is'),
                "sql"       => array( "lang" => "sql",  "tag" => '/\[sql\]/sx',         "regex" => '/\[sql\](.*?)\[\/sql\]/is'),
                "code"      => array( "lang" => "code", "tag" => '/\[code\]/sx',        "regex" => '/\[code\](.*?)\[\/code\]/is'),
                "code=php"  => array( "lang" => "php",  "tag" => '/\[code\=php\]/sx',   "regex" => '/\[code\=php\](.*?)\[\/code\]/is'),
                "code=sql"  => array( "lang" => "sql",  "tag" => '/\[code\=sql\]/sx',   "regex" => '/\[code\=sql\](.*?)\[\/code\]/is'),
                "code=html" => array( "lang" => "html", "tag" => '/\[code\=html\]/sx',  "regex" => '/\[code\=html\](.*?)\[\/code\]/is')
            );
    }
};


However the highlight_string() still fails. This is the portion of code which *should* highlight the string:

Code: Select all

// Split the code into lines
            $codeArr = preg_split('/\\n/s', $string);
            // Create the code box header
            $newCodeArr[] = "<div class='codebox'><div class='codeheader'>{$code}</div><div class='codeholder' style='max-height: 300px;'>";
            
            for($i = 0,$j = 1; $i <= count($codeArr); $i++,$j++){
                if($i % 2){
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li2'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] = "<div class='li2'>$j. {$codeArr[$i]}</div>";
                }else{
                    // For each line of code, check for a close tag
                    if(preg_match('/\[\/(.*?)\]/i', $codeArr[$i], $matches, PREG_OFFSET_CAPTURE)){
                        $newCodeArr[] = "<div class='li1'>$j. ".preg_replace('/\[\/(.*?)\]/is', '', $codeArr[$i])."</div>";
                        break;
                    }
                    // If no close tag exists, store the new line of code.
                    $newCodeArr[] .= "<div class='li1'>$j. ".highlight_string("{$codeArr[$i]}")."</div>";
                }
            }
            // Close the code box
            $newCodeArr[] = "</div></div>";
Now i have only modified the line where if there is no close tag for every odd line. This is the output:

Code: Select all

1. 1
2.      public function addBlog($blogTitle,$blogText){
3. 1
4.                $this->error->setError();
5. 1
6.           }else{
7. 1
8.                $q = "INSERT INTO `".TBL_BLOG."` (`title`, `blog`) VALUES ('{$blogTitle}','{$blogText}')";
9. 1
10.                if(!$r){
11. 1
12.                     return ERROR_BLOG_ADD;
13. 1
14.                     return true;
15. 1
16.           }
17.      }
Any ideas?