list_state != LIST_NONE) { $lclose = $this->do_list( " ",true ); } $sclose = ""; switch ($state) { case STATE_PARAGRAPH: $sclose = "\n"; break; case STATE_BLOCKQUOTE: $sclose = "\n"; break; case STATE_PREFORM: $sclose = "\n"; break; case STATE_NOTIKI: $sclose = "\n"; break; } return $lclose . $sclose; } function do_replace( $line, $mark, $tag ) { // do the regex thingy for things like bold, italic etc // $mark is the magic character, and $tag the HTML tag to insert // BODGE: replace inline $mark characters in places where we want them ignored // they will be put back after main substitutue, stops problems with eg, and/or $bodge = chr(1); $line = eregi_replace( '([[:alnum:]])'.$mark.'([[:alnum:]])', '\\1'.$bodge.'\\2',$line ); $regex = '(^| |[(.,])'.$mark.'([^'.$mark.']*)'.$mark.'([^[:alnum:]]|$)'; $replace = '\\1<'.$tag.'>\\2\\3'; $line = eregi_replace( $regex, $replace, $line ); // BODGE: back we go $line = eregi_replace( $bodge, $mark, $line ); return $line; } function do_replace_markdown( $line, $mark, $tag ) { // do the regex thingy for things like bold, italic etc // $mark is the magic character, and $tag the HTML tag to insert // MARKDOWN version does not generate HTML tags, just straigt replace // BODGE: replace inline $mark characters in places where we want them ignored // they will be put back after main substitutue, stops problems with eg, and/or $bodge = chr(1); $line = eregi_replace( '([[:alnum:]])'.$mark.'([[:alnum:]])', '\\1'.$bodge.'\\2',$line ); $regex = '(^| |[(.,])'.$mark.'([^'.$mark.']*)'.$mark.'([^[:alnum:]]|$)'; $replace = '\\1'.$tag.'\\2'.$tag.'\\3'; $line = eregi_replace( $regex, $replace, $line ); // BODGE: back we go $line = eregi_replace( $bodge, $mark, $line ); return $line; } function do_replace_sub( $line, $mark, $tag ) { // do regex for subscript and superscript (slightly different) // $mark is the magic character and $tag the HTML tag to insert $regex = $mark.'([^'.$mark.']*)'.$mark; $replace = '<'.$tag.'>\\1'; return eregi_replace( $regex, $replace, $line ); } function do_list( $line, $blank=false ) { // handle line with list character on it // if blank line implies drop to level 0 // get magic character and then delete it from the line if not blank if ($blank) { $listchar=""; $count = 0; } else { $listchar = $line{0}; $count = strspn( $line, $listchar ); $line = eregi_replace( "^[".$listchar."]+ ", "", $line ); } // find what sort of list this character represents $list_tag = ""; $list_close_tag = ""; $item_tag = ""; $item_close_tag = ""; $list_style = LIST_NONE; switch ($listchar) { case '*': $list_tag = ""; $list_close_tag = ""; $item_tag = "*"; $item_close_tag = ""; $list_style = LIST_UNORDERED; break; case '#': $list_tag = ""; $list_close_tag = ""; $item_tag = "1."; $item_close_tag = ""; $list_style = LIST_ORDERED; break; case ';': $list_tag = "
"; $list_close_tag = "
"; $item_tag = "
"; $item_close_tag = "
"; $list_style = LIST_DEFINITION; break; case ':': $list_tag = "
"; $list_close_tag = "
"; $item_tag = "
"; $item_close_tag = "
"; $list_style = LIST_DEFINITION; break; } // tag opening/closing regime now - fun bit :-) $tags = ""; // if depth has reduced do number of closes to restore level for ($i=$this->list_depth; $i>$count; $i-- ) { $close_tag = array_pop( $this->list_backtrack ); $tags = $tags . $close_tag; } // if depth has increased do number of opens to balance for ($i=$this->list_depth; $i<$count; $i++ ) { array_push( $this->list_backtrack, "$list_close_tag" ); $tags = $tags . "$list_tag"; } // ok, so list state is now same as style and depth same as count $this->list_state = $list_style; $this->list_depth = $count; // get indent $indent = substr( " ",1,$count-1 ); if ($blank) { $newline = $tags; } else { $newline = $tags . $indent . "$item_tag " . $line . "$item_close_tag"; } return $newline; } function line_replace( $line ) { // return line after various formatting replacements // have been made - order is vital to stop them interfering with each other global $CFG; // ---- (at least) means a
// MARKDOWN: no change so leave // is this a list line (starts with * # ; :) if (eregi( "^([*]+|[#]+|[;]+|[:]+) ", $line )) { $line = $this->do_list( $line ); } // typographic conventions // MARKDOWN: no equiv. so convert to entity as before // $line = str_replace( "--", "—", $line ); // $line = str_replace( " - ", " – ", $line ); $line = str_replace( "...", " … ", $line ); $line = str_replace( "(R)", "®", $line ); $line = str_replace( "(r)", "®", $line ); $line = str_replace( "(TM)", "™", $line ); $line = str_replace( "(tm)", "™", $line ); $line = str_replace( "(C)", "©", $line ); $line = str_replace( "1/4", "¼", $line ); $line = str_replace( "1/2", "½", $line ); $line = str_replace( "3/4", "¾", $line ); $line = eregi_replace( "([[:digit:]]+[[:space:]]*)x([[:space:]]*[[:digit:]]+)", "\\1×\\2", $line ); // (digits) x (digits) - multiply // do formatting tags // NOTE: The / replacement *has* to be first, or it will screw the // HTML tags that are added by the other ones // MARKDOWN: only bold and italic change, rest are just HTML $line = $this->do_replace_markdown( $line, "\*", "**" ); $line = $this->do_replace_markdown( $line, "/", "*" ); $line = $this->do_replace( $line, "\+", "ins" ); // $line = $this->do_replace( $line, "-", "del" ); $line = $this->do_replace_sub( $line, "~", "sub" ); $line = $this->do_replace_sub( $line, "\^", "sup" ); $line = $this->do_replace( $line, "%", "code" ); $line = $this->do_replace( $line, "@", "cite" ); // convert urls into proper link with optional link text URL(text) // MARDOWN: HTML conversion should work fine $line = eregi_replace("([[:space:]]|^)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])\(([^)]+)\)", "\\1[\\5](\\2://\\3\\4)", $line); $line = eregi_replace("([[:space:]])www\.([^[:space:]]*)([[:alnum:]#?/&=])\(([^)]+)\)", "\\1[\\5](http://www.\\2\\3)", $line); // make urls (with and without httpd) into proper links $line = eregi_replace("([[:space:]]|^)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])", "\\1<\\2://\\3\\4>", $line); $line = eregi_replace("([[:space:]])www\.([^[:space:]]*)([[:alnum:]#?/&=])", "\\1", $line); // make email addresses into mailtos.... // MARKDOWN doesn't quite support this, so do as html $line = eregi_replace("([[:space:]]|^)([[:alnum:]._-]+@[[:alnum:]._-]+)\(([^)]+)\)", "\\1\\3", $line); // !# at the beginning of any lines means a heading // MARKDOWN: value (1-6) becomes number of hashes if (eregi( "^!([1-6]) (.*)$", $line, $regs )) { $depth = substr( $line, 1, 1 ); $out = substr( '##########', 0, $depth); $line = eregi_replace( "^!([1-6]) (.*)$", "$out \\2", $line ); } // acronym handing, example HTML(Hypertext Markyp Language) // MARKDOWN: no equiv. so just leave as HTML $line = ereg_replace( "([A-Z]+)\(([^)]+)\)", "\\1", $line ); // Replace resource link >>##(Description Text) // MARKDOWN: change to MD web link style $line = eregi_replace( " ([a-zA-Z]+):([0-9]+)\(([^)]+)\)", " [\\3](".$CFG->wwwroot."/mod/\\1/view.php?id=\\2) ", $line ); require_once($CFG->libdir.'/filelib.php'); $coursefileurl = get_file_url($this->courseid); // Replace picture resource link $line = eregi_replace( "/([a-zA-Z0-9./_-]+)(png|gif|jpg)\(([^)]+)\)", "![\\3](".$coursefileurl."/\\1\\2)", $line ); // Replace file resource link $line = eregi_replace( "file:/([[:alnum:]/._-]+)\(([^)]+)\)", "[\\2](".$coursefileurl."/\\1)", $line ); return $line; } function convert( $content,$courseid ) { // main entry point for processing Wiki-like text // $content is string containing text with Wiki-Like formatting // return: string containing Markdown formatting // initialisation stuff $this->output = ""; $this->block_state = STATE_NONE; $this->list_state = LIST_NONE; $this->list_depth = 0; $this->list_backtrack = array(); $this->spelling_on = false; $this->courseid = $courseid; // split content into array of single lines $lines = explode( "\n",$content ); $buffer = ""; // run through lines foreach( $lines as $line ) { // is this a blank line? $blank_line = eregi( "^[[:blank:]\r]*$", $line ); if ($blank_line) { // first end current block according to state $buffer = $buffer . $this->close_block( $this->block_state ); $this->block_state = STATE_NONE; continue; } // act now depending on current block state if ($this->block_state == STATE_NONE) { // first character of line defines block type if (eregi( "^> ",$line )) { // blockquote $buffer = $buffer . $this->line_replace( $line ). "\n"; $this->block_state = STATE_BLOCKQUOTE; } else if (eregi( "^ ",$line) ) { // preformatted text // MARKDOWN: no real equiv. so just use
          $buffer = $buffer . "
\n";
          $buffer = $buffer . $this->line_replace($line) . "\n";
          $this->block_state = STATE_PREFORM;
        }
        else 
        if (eregi("^\% ",$line) ) {
                // preformatted text - no processing
                // MARKDOWN: this is MD code form of a paragraph
                $buffer = $buffer . "    " . eregi_replace( "^\%","",$line) . "\n";
                $this->block_state = STATE_NOTIKI;
        }
        else {
          // ordinary paragraph
          $buffer = $buffer . $this->line_replace($line) . "\n";
          $this->block_state = STATE_PARAGRAPH; 
        }
        continue;
      }

      if (($this->block_state == STATE_PARAGRAPH) |
          ($this->block_state == STATE_BLOCKQUOTE) |
          ($this->block_state == STATE_PREFORM) ) {
        $buffer = $buffer . $this->line_replace($line) . "\n";
        continue;
      }
      elseif ($this->block_state == STATE_NOTIKI) {
        $buffer = $buffer . "    " .$line . "\n";
      }
    }

    // close off any block level tags
    $buffer = $buffer . $this->close_block( $this->block_state );

    //return $buffer;    
    return $buffer;
  }

  function update( $thing, $textfield, $formatfield, $coursesql='' ) {
    // converts the text in a particular activity (or sub-activity)
    // $thing = the database name for that 'thing' (eg, resource, choice)
    // $textfield = the name of the field that might hold the wiki-text
    // $formatfield = the name of the field that contains the format type
    // $coursesql = if supplied, the query to get the courseid, if not get from the 'course' field 
    //   ($id of record is tacked on right at the end, so phrase accordingly)
    // returns a count of records converted 
    $count = 0;
    if ($records = get_records( $thing,$formatfield,FORMAT_WIKI )) {
        foreach( $records as $record ) {
          $text = $record->$textfield;
          $id = $record->id;
          if (!$coursesql) {
            $courseid = $record->course;
          } else {
            $r = get_record_sql( $coursesql . "$id" );
            $courseid = $r->course;
          }
          $newtext = $this->convert( $text,$courseid );
      
          $record->$textfield = $newtext;
          $record->$formatfield = FORMAT_MARKDOWN;
          update_record( $thing, addslashes_object( $record ) );
          $count++;
        }
    }
    return $count; 
  }
}
?>