short_desc = T_('BB formatting e-g [b]bold[/b]'); $this->long_desc = T_('Supported tags and the BB code toolbar are configurable. Supported tags by default are: [b] [i] [s] [color=...] [size=...] [font=...] [quote] [list=1] [list=a] [list] [*] [bg=] [clear]'); } /** * Define here default collection/blog settings that are to be made available in the backoffice. * * @param array Associative array of parameters. * @return array See {@link Plugin::GetDefaultSettings()}. */ function get_coll_setting_definitions( & $params ) { // TODO: Post and comment search/replace lists must be also converted to coll plugin settings $default_params = array_merge( $params, array( 'default_comment_rendering' => 'never' ) ); return array_merge( parent::get_coll_setting_definitions( $default_params ), array( 'coll_post_search_list' => array( 'label' => $this->T_( 'Search list for posts'), 'note' => $this->T_( 'This is the BBcode search array for posts (one per line) ONLY CHANGE THESE IF YOU KNOW WHAT YOU\'RE DOING' ), 'type' => 'html_textarea', 'rows' => 10, 'cols' => 60, 'defaultvalue' => '[b] #\[b](.+?)\[/b]#is [i] #\[i](.+?)\[/i]#is [s] #\[s](.+?)\[/s]#is [color] !\[color=(#?[A-Za-z0-9]+?)](.+?)\[/color]!is [size] #\[size=([0-9]+?)](.+?)\[/size]#is [font] #\[font=([A-Za-z0-9 ;\-]+?)](.+?)\[/font]#is #\[quote(=?)](.+?)\[/quote]#is #\[quote=([^\]\#]*?)\#([cp][0-9]+)](.+?)\[/quote]#is [quote] #\[quote=([^\]]*?)](.+?)\[/quote]#is [indent] #\[indent](.+?)\[/indent]#is [list=1] #\[list=1](.+?)\[/list]#is [list=a] #\[list=a](.+?)\[/list]#is [list] #\[list](.+?)\[/list]#is [*] #\[\*](.+?)(\n|\[/list\])#is [bg] !\[bg=(#?[A-Za-z0-9]+?)](.+?)\[/bg]!is [clear] #\[clear]#is', ), 'coll_post_replace_list' => array( 'label' => $this->T_( 'Replace list for posts'), 'note' => $this->T_( 'This is the replace array for posts (one per line) it must match the exact order of the search array' ), 'type' => 'html_textarea', 'rows' => 10, 'cols' => 60, 'defaultvalue' => '$1 $1 $1 $2 $2 $2
$2
$1 wrote earlier:
$3
$1 wrote:
$2
$1
    $1
    $1
  • $1
  • $2
    ', ), 'coll_comment_search_list' => array( 'label' => $this->T_( 'Search list for comments'), 'note' => $this->T_( 'This is the BBcode search array for COMMENTS (one per line) ONLY CHANGE THESE IF YOU KNOW WHAT YOU\'RE DOING' ), 'type' => 'html_textarea', 'rows' => 10, 'cols' => 60, 'defaultvalue' => '[b] #\[b](.+?)\[/b]#is [i] #\[i](.+?)\[/i]#is [s] #\[s](.+?)\[/s]#is [color] !\[color=(#?[A-Za-z0-9]+?)](.+?)\[/color]!is [size] #\[size=([0-9]+?)](.+?)\[/size]#is [font] #\[font=([A-Za-z0-9 ;\-]+?)](.+?)\[/font]#is #\[quote(=?)](.+?)\[/quote]#is #\[quote=([^\]\#]*?)\#([cp][0-9]+)](.+?)\[/quote]#is [quote] #\[quote=([^\]]*?)](.+?)\[/quote]#is [indent] #\[indent](.+?)\[/indent]#is [list=1] #\[list=1](.+?)\[/list]#is [list=a] #\[list=a](.+?)\[/list]#is [list] #\[list](.+?)\[/list]#is [*] #\[\*](.+?)(\n|\[/list\])#is [bg] !\[bg=(#?[A-Za-z0-9]+?)](.+?)\[/bg]!is [clear] #\[clear]#is', ), 'coll_comment_replace_list' => array( 'label' => $this->T_( 'Replace list for comments'), 'note' => $this->T_( 'This is the replace array for COMMENTS (one per line) it must match the exact order of the search array' ), 'type' => 'html_textarea', 'rows' => 10, 'cols' => 60, 'defaultvalue' => '$1 $1 $1 $2 $2 $2
    $2
    $1 wrote earlier:
    $3
    $1 wrote:
    $2
    $1
      $1
      $1
  • $1
  • $2
    ', ), ) ); } /** * Perform rendering * * @see Plugin::RenderItemAsHtml() */ function RenderItemAsHtml( & $params ) { $content = & $params['data']; $Item = $params['Item']; $item_Blog = & $Item->get_Blog(); if( !isset( $this->post_search_list ) ) { $this->post_search_list = $this->prepare_search_list( 'coll_post_search_list', $item_Blog ); } if( !isset( $this->post_replace_list ) ) { $this->post_replace_list = explode( "\n", str_replace( "\r", '', $this->get_coll_setting( 'coll_post_replace_list', $item_Blog ) ) ); } $content = replace_content_outcode( $this->post_search_list, $this->post_replace_list, $content, array( $this, 'parse_bbcode' ) ); return true; } /** * Perform rendering of Message content * * NOTE: Use default coll settings of comments as messages settings * * @see Plugin::RenderMessageAsHtml() */ function RenderMessageAsHtml( & $params ) { $content = & $params['data']; $Blog = NULL; if( !isset( $this->msg_search_list ) ) { $this->msg_search_list = $this->prepare_search_list( 'coll_comment_search_list', $Blog, true ); } if( !isset( $this->msg_replace_list ) ) { $this->msg_replace_list = explode( "\n", str_replace( "\r", '', $this->get_coll_setting( 'coll_comment_replace_list', $Blog, true ) ) ); } $content = replace_content_outcode( $this->msg_search_list, $this->msg_replace_list, $content, array( $this, 'parse_bbcode' ) ); return true; } /** * Parse BB code * ( The main purpose of this function is to parsing multilevel lists tags, * i.e. when one [list] is contained inside other [list] ) * * @param string Content * @param array Search list * @param array Replace list * @return string Content */ function parse_bbcode( $content, $search_list, $replace_list ) { if( empty( $content ) ) { // No content, Exit here return $content; } $complex = array(); $simple = array(); foreach( $search_list as $i => $search_text ) { // Split the masks to separate things preg_match( '#(\\\\\[.+\])\(.+\)(\\\\\[.+\])#is', $search_text, $search_tags ); preg_match( '#(<.+>)\$.+(<.+>)#is', $replace_list[ $i ], $replace_tags ); if( !empty( $search_tags ) ) { $complex[] = array( 's_full' => $search_text, 's_start' => '!^'.$search_tags[1].'!is', 's_end' => '!^'.$search_tags[2].'!is', 'r_full' => $replace_list[ $i ], 'r_start' => $replace_tags[1], 'r_end' => $replace_tags[2], ); } else { $simple[] = array( 's_full' => $search_text, 'r_full' => $replace_list[ $i ], ); } } //pre_dump($complex); foreach( $simple as $tag_info ) { // Make simple replacements $content = preg_replace( $tag_info['s_full'], $tag_info['r_full'], $content ); } // Complex parsing with multilevel tags structure $c_pos = 0; $content_length = strlen( $content ); $opened_tags = array(); $new_content = $content; while( $c_pos < $content_length - 2 ) { if( $content[ $c_pos ].$content[ $c_pos + 1 ] == '[/' ) { // Closed tag if( !empty( $opened_tags ) ) { // Get closed tag that was opened as last $sub_content = substr( $content, $c_pos ); $closed_tag_info = $complex[ $opened_tags[ count( $opened_tags ) - 1 ] ]; if( preg_match( $closed_tag_info['s_end'], $sub_content ) ) { $first_part = str_replace( $sub_content, '', $new_content ); $sub_content = preg_replace( $closed_tag_info['s_end'], $closed_tag_info['r_end'], $sub_content ); $new_content = $first_part.$sub_content; //pre_dump( 'CLOSE', $opened_tags, $closed_tag_info['r_end'], $closed_tag_info['s_end'], $new_content ); // Remove this tag from opened tags array array_pop( $opened_tags ); } } } elseif( $content[ $c_pos ] == '[' ) { // Opened tag $sub_content = substr( $content, $c_pos ); foreach( $complex as $tag_num => $tag_info ) { if( preg_match( $tag_info['s_start'], $sub_content ) ) { $first_part = str_replace( $sub_content, '', $new_content ); $sub_content = preg_replace( $tag_info['s_start'], $tag_info['r_start'], $sub_content ); $new_content = $first_part.$sub_content; // Add this tag to know what tag was opened as last $opened_tags[] = $tag_num; //pre_dump( 'OPEN', $opened_tags, $tag_info['s_start'], $new_content ); break; } } } $c_pos++; } //pre_dump($new_content); $new_content = $this->parse_anchor_links( $new_content ); return $new_content; } /** * Parse anchor links, Set absolute path for each link with relative anchor like * * @param string Content * @return string Content */ function parse_anchor_links( $content ) { if( preg_match_all( '/ href="#(c|p)([0-9]+)"/i', $content, $matches ) ) { $CommentCache = & get_CommentCache(); $ItemCache = & get_ItemCache(); foreach( $matches[0] as $m => $full_match ) { $object_ID = $matches[2][$m]; $new_url = ''; switch( $matches[1][$m] ) { // Object type: case 'p': // Item if( $Item = & $ItemCache->get_by_ID( $object_ID, false, false ) ) { // Replace anchor url with item permanent url $new_url = $Item->get_permanent_url().'#p'.$object_ID; } break; case 'c': // Comment if( $Comment = & $CommentCache->get_by_ID( $object_ID, false, false ) ) { // Replace anchor url with comment permanent url $new_url = $Comment->get_permanent_url(); } break; default: // Incorrect object type, Skip this url continue; } if( !empty( $new_url ) ) { // Replace relative anchor url with new absolute url $content = str_replace( $full_match, ' href="'.$new_url.'"', $content ); } } } return $content; } /** * Do the same as for HTML. * * @see RenderItemAsHtml() */ function RenderItemAsXml( & $params ) { $this->RenderItemAsHtml( $params ); } /** * * Render comments if required * * @see Plugin::FilterCommentContent() */ function FilterCommentContent( & $params ) { $Comment = & $params['Comment']; $comment_Item = & $Comment->get_Item(); $item_Blog = & $comment_Item->get_Blog(); if( in_array( $this->code, $Comment->get_renderers_validated() ) ) { // apply_comment_rendering is set to always render $content = & $params['data']; if( !isset( $this->comment_search_list ) ) { $this->comment_search_list = $this->prepare_search_list( 'coll_comment_search_list', $item_Blog ); } if( !isset( $this->comment_replace_list ) ) { $this->comment_replace_list = explode( "\n", str_replace( "\r", '', $this->get_coll_setting( 'coll_comment_replace_list', $item_Blog ) ) ); } $content = replace_content_outcode( $this->comment_search_list, $this->comment_replace_list, $content, array( $this, 'parse_bbcode' ) ); } } /** * Display a toolbar * * @param array Associative array of parameters * @return boolean did we display a toolbar? */ function AdminDisplayToolbar( & $params ) { return $this->DisplayCodeToolbar( $params ); } /** * Display a code toolbar * * @param array Associative array of parameters * @return boolean did we display a toolbar? */ function DisplayCodeToolbar( & $params ) { global $Hit; if( $Hit->is_lynx() ) { // let's deactivate quicktags on Lynx, because they don't work there. return false; } $params = array_merge( array( 'target_type' => 'Item' ), $params ); switch( $params['target_type'] ) { case 'Item': $search_list_setting_name = 'coll_post_search_list'; $Item = $params['Item']; $item_Blog = & $Item->get_Blog(); $apply_rendering = $this->get_coll_setting( 'coll_apply_rendering', $item_Blog ); $allow_null_blog = false; break; case 'Comment': $search_list_setting_name = 'coll_comment_search_list'; if( !empty( $params['Comment'] ) && !empty( $params['Comment']->item_ID ) ) { // Get Blog from Comment $Comment = & $params['Comment']; $comment_Item = & $Comment->get_Item(); $item_Blog = & $comment_Item->get_Blog(); } else if( !empty( $params['Item'] ) ) { // Get Blog from Item $comment_Item = & $params['Item']; $item_Blog = & $comment_Item->get_Blog(); } $apply_rendering = $this->get_coll_setting( 'coll_apply_comment_rendering', $item_Blog ); $allow_null_blog = false; break; case 'Message': $search_list_setting_name = 'coll_comment_search_list'; $apply_rendering = $this->get_msg_setting( 'msg_apply_rendering' ); $allow_null_blog = true; break; default: // Incorrect param return false; break; } if( $apply_rendering == 'never' ) { // Don't display a toolbar if plugin is disabled return false; } $search_list = trim( $this->get_coll_setting( $search_list_setting_name, $item_Blog, $allow_null_blog ) ); if( empty( $search_list ) ) { // No list defined return false; } $search_list = explode( "\n", str_replace( array( '\r\n', '\n\n' ), '\n', $search_list ) ); $bbButtons = array(); foreach( $search_list as $line ) { // Init buttons from regexp lines $line = explode( ' ', $line, 2 ); $button_name = $line[0]; $button_exp = $line[1]; if( !empty( $button_name ) && !empty( $button_exp ) ) { $start = preg_replace( '#(.+)\[([a-z0-1=\*\\\\]+)((\(.*\))*)\](.+)#is', '[$2]', $button_exp ); $end = preg_replace( '#(.+)\[\/(.+)\](.+)#is', '[/$2]', $button_exp ); $bbButtons[ $button_name ] = array( 'name' => $button_name, 'start' => str_replace( '\\', '', $start ), 'end' => $end == $button_exp ? '' : $end, 'title' => str_replace( array( '[', ']' ), '', $button_name ), ); } } if( empty( $bbButtons ) ) { // No buttons for toolbar return false; } // Load js to work with textarea require_js( 'functions.js', 'blog', true, true ); ?>get_template( 'toolbar_before', array( '$toolbar_class$' => $this->code.'_toolbar' ) ); ?>get_template( 'toolbar_after' ); return true; } /** * Event handler: Called when displaying editor toolbars. * * @param array Associative array of parameters * @return boolean did we display a toolbar? */ function DisplayCommentToolbar( & $params ) { if( !empty( $params['Comment'] ) ) { // Comment is set, get Blog from comment $Comment = & $params['Comment']; if( !empty( $Comment->item_ID ) ) { $comment_Item = & $Comment->get_Item(); $Blog = & $comment_Item->get_Blog(); } } if( !empty( $params['Item'] ) ) { // Get Blog from Item $comment_Item = & $params['Item']; $Blog = & $comment_Item->get_Blog(); } if( empty( $Blog ) ) { // Comment is not set, try global Blog global $Blog; if( empty( $Blog ) ) { // We can't get a Blog, this way "apply_comment_rendering" plugin collection setting is not available return false; } } if( $this->get_coll_setting( 'coll_apply_comment_rendering', $Blog ) ) { $params['target_type'] = 'Comment'; return $this->DisplayCodeToolbar( $params ); } return false; } /** * Event handler: Called when displaying editor toolbars for message. * * @param array Associative array of parameters * @return boolean did we display a toolbar? */ function DisplayMessageToolbar( & $params ) { if( $this->get_msg_setting( 'msg_apply_rendering' ) ) { $params['target_type'] = 'Message'; return $this->DisplayCodeToolbar( $params ); } return false; } /** * Prepare a search list * * @param string Setting name of search list (' post_search_list', 'comment_search_list' ) * @param object Blog * @param boolean Allow empty Blog * @return array Search list */ function prepare_search_list( $setting_name, $Blog = NULL, $allow_null_blog = false ) { $search_list = explode( "\n", str_replace( "\r", '', $this->get_coll_setting( $setting_name, $Blog, $allow_null_blog ) ) ); foreach( $search_list as $l => $line ) { // Remove button name from regexp string $line = explode( ' ', $line, 2 ); $regexp = $line[1]; if( empty( $regexp ) ) { // Bad format of search string unset( $search_list[ $l ] ); } else { // Replace this line with regexp value (to delete a button name) $search_list[ $l ] = $regexp; } } return $search_list; } } ?>