styles = array(
'decimal' => '1,2...10',
'decimal-leading-zero' => '01, 02...10',
'lower-alpha' => 'a,b...j',
'upper-alpha' => 'A,B...J',
'lower-roman' => 'i,ii...x',
'upper-roman' => 'I,II...X',
'symbol' => 'Symbol'
);
// Define default options
$this->default_options = array(
'pre_backlink'=>' [',
'backlink'=>'↩',
'post_backlink'=>']',
'pre_identifier'=>'',
'list_style_type'=>'decimal',
'list_style_symbol'=>'†',
'post_identifier'=>'',
'pre_footnotes'=>'',
'post_footnotes'=>''
);
// Get the current settings or setup some defaults if needed
$this->options = get_option('mp_wp_cpp_options');
if (!$this->options) {
$this->options = $this->default_options;
update_option('mp_wp_cpp_options', $this->options);
} else {
// Set any unset options
$updated = false;
foreach ($this->default_options as $key => $value) {
if (!isset($this->options[$key])) {
$this->options[$key] = $value;
$updated = true;
}
}
if ($updated) {
update_option('mp_wp_cpp_options', $this->options);
}
}
// Hook me up
add_action('the_content', array($this, 'process_codeblocks'), self::MP_WP_CODEBLOCKS_PRIORITY);
add_action('the_content', array($this, 'process_footnotes'), self::MP_WP_FOOTNOTES_PRIORITY);
add_filter('the_content', array($this, 'server_side_selection'));
add_action('wp_head', array($this, 'insert_styles'));
}
/**
* Finds the selection from the query params.
* @param $data string The content of the post.
* @return string The new content with the highlighted selection.
*/
function server_side_selection($data) {
//bookend code goes here
$b_code = '';
$b_code .= $_GET["b"];
$e_code = $_GET["e"].'';
//change page ; last to first to preserve indexes.
$b_pos = strpos($data,$_GET["b"]);
$e_pos = strpos($data,$_GET["e"], $b_pos);
if ($e_pos>0)
$data = substr_replace($data, $e_code, $e_pos, strlen($_GET["e"]));
if ($b_pos>0)
$data = substr_replace($data, $b_code, $b_pos, strlen($_GET["b"]));
return $data;
}
/**
* Searches the text and apply markup to codeblocks.
* Adds line number links and diff syntax highlighting.
* @param $data string The content of the post.
* @return string The new content with formatted codeblocks.
*/
function process_codeblocks($data) {
global $post;
// Regex extraction of all codeblocks (or return if there are none)
if ( !preg_match_all("/\[([a-z]+)\[(.*)(\]\])/Us", $data, $codeblocks, PREG_SET_ORDER) ) {
return $data;
}
for ($i = 0; $i < count($codeblocks); $i++) {
$codeblocks[$i]['snippet'] = $this->format_snippet($codeblocks[$i][2], $codeblocks[$i][1], $i+1);
}
foreach ($codeblocks as $key => $value) {
$data = substr_replace($data, $value['snippet'], strpos($data,$value[0]),strlen($value[0]));
}
return $data;
}
function format_snippet($snippet, $syntax, $snippet_number) {
$highlighting_functions = array(
'plaintext' => 'highlight_as_plain_text',
'diff' => 'highlight_as_diff'
);
if (is_null($highlighting_functions[$syntax])) {
$syntax = 'plaintext';
}
$code_lines = explode("\r\n", $snippet);
foreach ($code_lines as $idx => $line) {
$line_number = sprintf('S%d-L%d', $snippet_number, $idx+1);
$line_link = sprintf('%d', $line_number, $line_number, $idx+1);
$line_open = sprintf('
%s | ', $line_link);
$line_close = ' |
';
$code_lines[$idx] = $this->$highlighting_functions[$syntax]($line_open, $line, $line_close);
}
$formatted_snippet = implode("\n", $code_lines);
$formatted_snippet = sprintf(
'%s%s%s',
''
);
return $formatted_snippet;
}
function highlight_as_plain_text($line_open, $line, $line_close) {
return sprintf('%s%s%s', $line_open, $line, $line_close);
}
function highlight_as_diff($line_open, $line, $line_close) {
if (substr($line, 0, 5) == 'diff ') {
$highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close);
} elseif (substr($line, 0, 4) == '--- ' || substr($line, 0, 4) == '+++ ' || substr($line, 0, 3) == '@@ ') {
$highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close);
} elseif (substr($line, 0, 1) == '-') {
$highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close);
} elseif (substr($line, 0, 1) == '+') {
$highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close);
} else {
$highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close);
}
return $highlighted_line;
}
/**
* Searches the text and extracts footnotes.
* Adds the identifier links and creats footnotes list.
* @param $data string The content of the post.
* @return string The new content with footnotes generated.
*/
function process_footnotes($data) {
global $post;
// Check for and setup the starting number
$start_number = (preg_match("||",$data,$start_number_array)==1) ? $start_number_array[1] : 1;
// Regex extraction of all footnotes (or return if there are none)
if (!preg_match_all("/(".preg_quote(self::MP_WP_FOOTNOTES_OPEN)."|)(.*)(".preg_quote(self::MP_WP_FOOTNOTES_CLOSE)."|<\/footnote>)/Us", $data, $identifiers, PREG_SET_ORDER)) {
return $data;
}
$footnotes = array();
// Check if this post is using a different list style to the settings
if ( array_key_exists(get_post_meta($post->ID, 'footnote_style', true), $this->styles) ) {
$style = get_post_meta($post->ID, 'footnote_style', true);
} else {
$style = $this->options['list_style_type'];
}
// Create 'em
for ($i=0; $i $value) {
$id_id = "identifier_".$key."_".$post->ID;
$id_num = ($style == 'decimal') ? $value['use_footnote']+$start_number : $this->convert_num($value['use_footnote']+$start_number, $style, count($footnotes));
$id_href = ( ($use_full_link) ? get_permalink($post->ID) : '' ) . "#footnote_".$value['use_footnote']."_".$post->ID;
$id_title = str_replace('"', '`', strip_tags($value['text']));
$id_replace = ''.$this->options['pre_identifier'].''.$this->options['post_identifier'].'';
$data = substr_replace($data, $id_replace, strpos($data,$value[0]),strlen($value[0]));
}
// Display footnotes
$start = ($start_number != 1) ? 'start="'.$start_number.'" ' : '';
$data = $data.$this->options['pre_footnotes'];
$data = $data . '';
foreach ($footnotes as $key => $value) {
$data = $data.'';
}
$data = $data . '
' . $this->options['post_footnotes'];
return $data;
}
function insert_styles() {
?>
roman($num, 'lower');
case 'upper-roman' :
return $this->roman($num);
case 'lower-alpha' :
return $this->alpha($num, 'lower');
case 'upper-alpha' :
return $this->alpha($num);
case 'symbol' :
$sym = '';
for ($i = 0; $i<$num; $i++) {
$sym .= $this->options['list_style_symbol'];
}
return $sym;
}
}
/**
* Convert to a roman numeral.
*
* Thanks to Indi.in.the.Wired for the improved algorithm.
* http://plugins.trac.wordpress.org/ticket/1177
*
* @param int $num The number to convert.
* @param string $case Upper or lower case.
* @return string The roman numeral
*/
function roman($num, $case= 'upper') {
$num = (int) $num;
$conversion = array('M'=>1000, 'CM'=>900, 'D'=>500, 'CD'=>400, 'C'=>100, 'XC'=>90, 'L'=>50, 'XL'=>40, 'X'=>10, 'IX'=>9, 'V'=>5, 'IV'=>4, 'I'=>1);
$roman = '';
foreach ($conversion as $r => $d){
$roman .= str_repeat($r, (int)($num / $d));
$num %= $d;
}
return ($case == 'lower') ? strtolower($roman) : $roman;
}
function alpha($num, $case='upper') {
$j = 1;
for ($i = 'A'; $i <= 'ZZ'; $i++){
if ($j == $num){
if ($case == 'lower')
return strtolower($i);
else
return $i;
}
$j++;
}
}
}