4
\$\begingroup\$

I'm wondering if I could handle the following situation with a single function or regex call. Given the folowing input:

Some text

> Foo
> Bar
>> Baz
> Foo

The output should be:

Some text

<blockquote>
Foo
Bar
    <blockquote>
        Baz
    </blockquote>
Foo
</blockquote>

The following two functions do handle this situation, but I think there must be a more elegant way to handle it. I thought about regular expressions, but could not think of any pattern that replaces the input with the output (see above).

<?php
function toArray($str, $currLevel = 0, $i = 0) {
  $return = array();
  $lines = explode("\n", $str);
  for($j = count($lines); $i < $j; $i++) {
    $line = trim($lines[$i]);
    $level = preg_replace('/^((?:>|\s)+).*/','\1', $line);
    $level = substr_count($level, '>');
    if($level == $currLevel) {
      array_push($return, preg_replace('/^((?:>|\s)+)(.*)/','\2', $line));
    }
    else if($level > $currLevel) {
      array_push($return, toArray(join("\n", $lines), $currLevel  + 1, &$i));
    } else if($level < $currLevel) {
      $i--;
      return $return;
    }
  }

  return $return;
}

function toQuote($lines) {
  $return = "<blockquote>\n";
  foreach($lines as $line) {
    if(is_array($line)) {
      $return .= toQuote($line);
    }
    else {
      $return .= $line . "\n"; 
    }
  }
  $return .= "</blockquote>\n";
  return $return;
}

$str = <<<INPUT
  Some text

  > Foo
  > Bar
  >> Baz
  > Foo
INPUT;

echo toQuotes(toArray($str));
\$\endgroup\$
1
  • \$\begingroup\$ Don't know if it's of any help, but Markdown does this; however, only with a newline after the inner quote. \$\endgroup\$ – Sam Wilson May 30 '11 at 3:35
2
\$\begingroup\$

This isn't much more elegant, but maybe you like it:

$text = "Some text

> Foo
> Bar
>> Baz
> Foo
";

function clean($text) {
  $result = "";
  $lines = explode("\n", $text);
  foreach($lines as $key => $line) {
    $lines[$key] = preg_replace('/(>)+ /', '', $line);
  }
  return join("\n", $lines);
}

function quotes($text, $level = 1) {
  $search = str_repeat(">", $level);
  $fstpos = strpos($text, $search);
  $sndpos = strrpos($text, $search);
  $sndpos = strpos($text, "\n", $sndpos);
  $middle = substr($text, $fstpos, $sndpos + 1);
  if($fstpos === false or $sndpos === false)
    return clean($middle, $search);
  $fst = clean(substr($text, 0, $fstpos), $search);
  $snd = clean(substr($text, $sndpos), $search);
  return $fst . "<blockquote>\n" . quotes($middle, $level + 1)  . "</blockqoute>" . $snd;
}

echo quotes($text);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.