ShoeLace1291 Posted March 3, 2014 Share Posted March 3, 2014 (edited) Ok, I wasn't sure what exactly to title this thread since it could be any number of factors causing this problem.... Anyway, I am trying to write a script for my custom CodeIgniter-powered forum that parses bbcodes... I almost have it working completely, except for one tiny problem... The content of the quote tags is being parsed twice... I cannot figure out why this is happening. The header displays absolutely fine, it's just the content of the quote(or body) is doubled. It could be the preg_replace_call_back, or just my poor coding structure... but I can't figure it out. This is my result: My String Helper: <?php function parse_bb($str){ $CI =& get_instance(); $str = nl2br($str); $str = strip_slashes($str); $find = array( "'\[b\](.*?)\[/b\]'is", "'\[i\](.*?)\[/i\]'is", "'\[u\](.*?)\[/u\]'is", "'\[s\](.*?)\[/s\]'is", "'\[img\](.*?)\[\/img\]'is", "'\[url\](.*?)\[/url\]'i", "'\[url=(.*?)\](.*?)\[/url\]'i", "'\[link\](.*?)\[/link\]'i", "'\[link=(.*?)\](.*?)\[/link\]'i", "'\[h1\](.*?)\[\/h1\]'is", "'\[h2\](.*?)\[\/h2\]'is", "'\[h3\](.*?)\[\/h3\]'is", "'\[ul\](.*?)\[\/ul\]'is", "'\[li\](.*?)\[\/li\]'is", "'\[p\](.*?)\[\/p\]'is" //"'(\[quote (thread_id|message_id)=([0-9]+)\](.*?)\[\/quote\])e'" ); $replace = array( '<strong>\1</strong>', '<em>\1</em>', '<u>\1</u>', '<s>\1</s>', '<img src="\1" \1alt="User Image" />', anchor('\1'), //'<a href="\1">\1</a>', anchor('\1', '\2'), //'<a href="\1">\2</a>', '<a href="\1">\1</a>', '<a href="\1">\2</a>', '<h1>\1</h1>', '<h2>\1</h2>', '<h3>\1</h3>', '<ul>\1</ul>', '<li>\1</li>', '<p>\1</p>' //parse_quote('\2', '\3') ); $str = preg_replace($find, $replace, $str); //var_dump($matches); $str = preg_replace_callback("^(\[quote (thread_id|message_id)=([0-9]+)\])^", 'parse_quote', $str); $str = preg_replace("^\[\/quote\]^", "\n</div>", $str); return $str; } function parse_quote($matches){ $post_type = $matches[2]; $post_id = $matches[3]; $CI =& get_instance(); if($post_type == "thread_id"){ $CI->load->model('forums/thread'); $CI->thread->get_info($post_id); if($CI->thread->error == NULL){ $thread = $CI->thread->info; $str = " <div class=\"quote\"> <div class=\"heading\"> <h1>Posted by ".$thread['author']['display_name']." about ".$thread['date_posted']." ago.</h1> </div> <div class=\"body\"> ".$thread['content_parsed']." </div> "; } else { show_error($CI->thread->error); } } else if($post_type == "message_id"){ $CI->load->model('forums/message'); $CI->message->get_info($post_id); if($CI->message->error == NULL){ $message = $CI->message->info; $str = " <div class=\"quote\"> <div class=\"heading\"> <h1>Posted by ".$message['author']['display_name']." about ".$message['date_posted']." ago.</h1> </div> <div class=\"body\"> ".$message['content_parsed']." </div> "; } } return $str; } Model thread->get_info() function get_info($thread_id){ $this->db->select('board_id, thread_id, author_id, title, content, UNIX_TIMESTAMP(date_posted) AS date_posted, views, status, type'); $this->db->from('forum_threads'); $this->db->where('thread_id', $thread_id); $this->db->limit(1); if($query_thread = $this->db->get()){ if($query_thread->num_rows() > 0){ $thread = $query_thread->row_array(); $this->member->get_info($thread['author_id']); $author = $this->member->info; $update = ''; /* Get the total number of replies to this thread, excluding the first message. */ $total_replies = 0; $this->db->select('thread_id, message_id'); $this->db->from('forum_messages'); $this->db->where('thread_id', $thread['thread_id']); if($query_replies = $this->db->get()){ $total_replies = $query_replies->num_rows(); } $thread_update = ""; /*Get the info of the thread's last message... */ $this->db->select('thread_id, message_id, author_id, date_posted, date_modified'); $this->db->from('forum_messages'); $this->db->where('thread_id', $thread['thread_id']); $this->db->order_by('message_id', 'desc'); $this->db->limit(1); if($query_last_msg = $this->db->get()){ if($query_last_msg->num_rows() > 0){ $last_msg = $query_last_msg->row_array(); $this->member->get_info($last_msg['author_id']); $author = $this->member->info; if($last_msg['date_modified'] == NULL){ $update_time = $last_msg['date_posted']; } else { $update_time = $last_msg['date_modified']; } $thread_update = $author['member_profile'].' posted about '.timespan(strtotime($update_time), time()).' ago.'; } } $has_new_posts = FALSE; /* Determine whether or not there are new messages in this thread for the current user... */ $this->db->select('mark_id, thread_id, member_id, UNIX_TIMESTAMP(date_marked) AS date_marked'); $this->db->from('forum_thread_marks'); $this->db->where('thread_id', $thread['thread_id']); $this->db->where('member_id', $this->user['id']); $this->db->order_by('date_marked', 'desc'); $this->db->limit(1); if($query_mark = $this->db->get()){ if($query_mark->num_rows() > 0){ $mark = $query_mark->row_array(); $this->db->select('message_id, thread_id, UNIX_TIMESTAMP(date_posted) AS date_posted'); $this->db->from('forum_messages'); $this->db->where('thread_id', $thread['thread_id']); $this->db->where('date_posted > '.$mark['date_marked']); if($query_new = $this->db->get()){ if($query_new->num_rows() > 0){ $has_new_posts = TRUE; } } } } /* Put it all together and we get... the array of information! */ $info = array( 'id' => $thread['thread_id'], 'title' => $thread['title'], 'author' => $author, 'content' => $thread['content'], 'content_parsed' => parse_bb($thread['content']), 'date_posted' => timespan(strtotime($thread['date_posted']), time()), 'board_id' => $thread['board_id'], 'status' => $thread['status'], 'update' => $thread_update, 'reply_count' => $total_replies, 'view_count' => $thread['views'], 'uri' => 'forums/threads/'.url_title($thread['title']).'/'.$thread['thread_id'], 'actions' => $this->actions($thread['thread_id']), 'has_new_posts' => $has_new_posts ); } else { $this->error = "The thread you have requested no longer exists in the database."; } } else { $this->error = "An error occurred while attempting to retrieve the data of the requested thread: ".$this->db->_error_message(); } $this->info = $info; }Model message->get_info() function get_info($message_id){ $this->db->select('message_id, thread_id, author_id, modifier_id, content, date_posted, date_modified'); $this->db->where('message_id', $message_id); $this->db->limit(1); if($query = $this->db->get('forum_messages')){ if($query->num_rows() > 0){ $message = $query->row_array(); $this->member->get_info($message['author_id']); $author = $this->member->info; $info = array( 'id' => $message['message_id'], 'thread_id' => $message['thread_id'], 'author' => $author, 'content' => $message['content'], 'content_parsed' => parse_bb($message['content']), 'date_posted' => timespan(strtotime($message['date_posted']), time()), 'actions' => $this->actions($message['message_id']) ); if($message['modifier_id'] == NULL){ $last_modified = ''; } else { $this->member->get_info($message['modifier_id']); $modifier = $this->member->info; $modification = array( 'by' => $modifier, 'date' => $message['date_modified'] ); } $this->info = $info; } else { $this->error = "The message you are attempting to retrieve does not exist in the database."; } } else { $this->error = $this->db->_error_message(); } } Edited March 3, 2014 by ShoeLace1291 Quote Link to comment https://forums.phpfreaks.com/topic/286670-preg-replace-callback-function-replacing-content-twice/ Share on other sites More sharing options...
requinix Posted March 3, 2014 Share Posted March 3, 2014 (edited) I figure the markup looks like [quote message_id=123]This is another test. This is only another test.[/quote]Right? When you replace the opening you automatically include the content of the message/thread being looked up. "<div class=\"body\"> ".$thread['content_parsed']." </div>"However the message/thread content is already present in the source string, so you end up with markup (with comments added for clarity) like <!-- [quote] --> <div class="quote"> <div class="heading"> <h1>Posted by HigH VolTagE about 1 Week, 4 Days, 1 Hour, 8 Minutes ago.</h1> </div> <div class="body"> This is another test. This is only another rest. </div> <!-- end of [quote] --> This is another test. This is only another rest. <!-- [/quote] --> </div> <!-- end of [/quote]-->Either1. Do not include the contents of the message/thread during the parsing and instead add in strictly the HTML markup needed to make the quote. In other words, <div class="quote"> <div class="heading"> <h1>Posted by * about * ago.</h1> </div> <div class="body">This is how quoting is normally done. 2. Use as a placeholder with no contents at all, and allow it to insert the quoted text automatically. [quote message_id=123]That's short and sweet but it has the significant downside that a poster cannot see what they're replying to. Edited March 3, 2014 by requinix Quote Link to comment https://forums.phpfreaks.com/topic/286670-preg-replace-callback-function-replacing-content-twice/#findComment-1471311 Share on other sites More sharing options...
ShoeLace1291 Posted March 4, 2014 Author Share Posted March 4, 2014 (edited) Your suggestion worked for one-level quotes, but the nested quotes are working almost the same way as before. The post body of the quote tag appears once per quote tag, but the whole quote tag(at the nested level) appears twice. Any ideas? [quote message_id=10] [quote message_id=9] [/quote] [/quote] Edited March 4, 2014 by ShoeLace1291 Quote Link to comment https://forums.phpfreaks.com/topic/286670-preg-replace-callback-function-replacing-content-twice/#findComment-1471388 Share on other sites More sharing options...
requinix Posted March 4, 2014 Share Posted March 4, 2014 If you went with method #1 then it should work. What's your parse_quote() look like now? Quote Link to comment https://forums.phpfreaks.com/topic/286670-preg-replace-callback-function-replacing-content-twice/#findComment-1471389 Share on other sites More sharing options...
ShoeLace1291 Posted March 4, 2014 Author Share Posted March 4, 2014 I removed the inside quote tag and it seems to work now! Thanks! Quote Link to comment https://forums.phpfreaks.com/topic/286670-preg-replace-callback-function-replacing-content-twice/#findComment-1471392 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.