Hi,
I want to replace ticks in text with other text. This method usually works, but when adding three dots, I get php warning
ltrim(): Invalid '..'-range, no character to the right of '..' or invalid range needs to be incrementing.

I don't know where to look for error, except deleting dots.
Here is the code:

$code = "some text before block
´´´´code block1´´´´
text after block
´´´´code block2...´´´´"; // I want ticks to be replaced to this: <pre><code> code block1 </code></pre>

$pattern = "´´´´"; // we are using ticks
$countCodeBlock = substr_count($code, $pattern); // count how many times pattern is written

if ($countCodeBlock > 0 && $countCodeBlock %2 == 0) // check if is pair number of pattern
        {
            for ($i = 0; $i < $countCodeBlock; $i++)
            {
                if ($i%2 == 0) {

                    // first pattern - open a tag
                    // check if text exist before first pattern
                    $getIndex = strpos($code, $pattern);// this is the index of first char of pattern
                    // substr grabs text - input str, start location, length
                    $textBeforeBlock = substr($code, 0, $getIndex); // first text, before first pattern

                    // strlen count char in string
                    if (strlen($textBeforeBlock) > 0) {
                        // show text first
                        echo "<p>" . htmlentities($textBeforeBlock) . "</p>";
                    }
                    // then remove that text and first pattern block
                    // ltrim removes white space, or removes special charaters
                    // ltrim input string, optional character or numbers
                    echo "<pre><code>";
                    $code = ltrim($code, $textBeforeBlock); // first delete text
                    $code = ltrim($code, $pattern); // then delete thoose ticks
                }
                else {
                    // second pattern, and closing a tag
                    $getIndex = strpos($code, $pattern);
                    $textBeforeBlock = substr($code, 0, $getIndex);
                    if (strlen($textBeforeBlock) > 0) {
                        echo htmlentities($textBeforeBlock); // here is the essence of the code text
                    }
                    echo "</code></pre>";
                    $code = ltrim($code, $textBeforeBlock);
                    $code = ltrim($code, $pattern);

                }
            }
            // this is the end of code block, and if there is some rest of text, write it
            if (strlen($code) > 0) {
                echo "<p>" . htmlentities($code) . "</p>";
            }
            else 
                echo "<p></p>"; // this is intentional
        }
        else {
            // there are no ticks in the code variable
            echo "<p>" . "There is no code block:</p><br /><pre>" . htmlentities($code) . "</pre><p></p>";
        }
echo $code;

You can copy code into php sandbox and give a try.

Recommended Answers

All 4 Replies

Looks a bit complicated to me, so I'd do something like this...

    $raw_string = "´´´´Hello´´´´ !!!!Really??!!!! ´´´´nice´´´´"; //string to parse
    $tokens = [
      ["/´´´´/", "\n<pre>\n\t<code>\n","\n\t</code>\n</pre>\n"],
      ["/!!!!/","<b>","</b>"]
    ]; //[replacement text, open tags, close tags]

    $the_string = $raw_string; //could do something to it here
    foreach( $tokens as $tk ){
        $the_string = preg_replace_callback( $tk[0], function($match) use ($tk) { 
        static $toggle = 0;
        if ( $toggle )
        {
            $toggle = 0;
            return $tk[2];
        }
        $toggle = 1;
        return $tk[1];}, $the_string ); 
    }
    echo $the_string;

Initial idea from... https://stackoverflow.com/a/1072690

OK, it doesn't deal with the empty paragraph, but its a start :)

Demo: https://repl.it/@diafol/UnwillingGoldenDll

commented: Not bad, thank you. It has less code, but I try to avoid preg_replace this time :( +2

Ok, so you want to avoid preg. How about this...

$theString = "´´´´Hello´´´´ !!!!Really??!!!! ´´´´nice´´´´"; //string to parse
$tokens = [
  ["´´´´", "\n<pre>\n\t<code>\n","\n\t</code>\n</pre>\n"],
  ["!!!!","<b>","</b>"]
]; //[replacement text, open tags, close tags]

$pos = [];

foreach($tokens as $tk){
  $lastPos = 0;
  $xcount = 0;
  while (($lastPos = strpos($theString, $tk[0], $lastPos))!== false) {
      $len = strlen($tk[0]);
      $pos[$lastPos] = ($xcount % 2 !== 0) ? $tk[2] : $tk[1];
      $lastPos = $lastPos + $len;
      $xcount++;
  }
}
ksort($pos);
$search = array_column($tokens, 0);
$sprintString = str_replace($search, '%s', $theString);
$cleanString = htmlentities($sprintString);
$output = vsprintf($cleanString, $pos);
echo $output;

This allows htmlentities().

Demo: https://repl.it/@diafol/UnwillingGoldenDll-1

Probably can be further condensed and fiddled to get empty <p>.

commented: This is really helpful :) I will use this code. Thank you! +0

They could put a better button to mark questions as solved. Thanks!! :)

commented: No problem! But be aware - it is not production code. There would be issues with nested tags, e.g. <div><div>... would be parsed as <div></div> +6

They could put a better button to mark questions as solved. Thanks!! :)

Is it confusing?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.