PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/code/cake/app/webroot/cp/wp-content/plugins/commentpress-core/commentpress-core/class_commentpress_parser.php

https://github.com/DigitalPaulScholtenProject/DPSP-Platform
PHP | 2251 lines | 620 code | 876 blank | 755 comment | 124 complexity | 8cacd7f6942befdf7167882a25bd60f3 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php /*
  2. ================================================================================
  3. Class CommentpressCoreParser
  4. ================================================================================
  5. AUTHOR: Christian Wach <needle@haystack.co.uk>
  6. --------------------------------------------------------------------------------
  7. NOTES
  8. =====
  9. This class is a wrapper for parsing content and comments.
  10. The aim is to migrate parsing of content to DOM parsing instead of regex.
  11. When converted to DOM parsing, the class will two other classes, which help with
  12. oddities in DOMDocument. These can be found in `inc/dom-helpers`.
  13. --------------------------------------------------------------------------------
  14. */
  15. /*
  16. ================================================================================
  17. Class Name
  18. ================================================================================
  19. */
  20. class CommentpressCoreParser {
  21. /*
  22. ============================================================================
  23. Properties
  24. ============================================================================
  25. */
  26. // parent object reference
  27. var $parent_obj;
  28. // init text_signatures
  29. var $text_signatures = array();
  30. // all comments
  31. var $comments_all = array();
  32. // approved comments
  33. var $comments_approved = array();
  34. // sorted comments
  35. var $comments_sorted = array();
  36. /**
  37. * @description: initialises this object
  38. * @param object $parent_obj a reference to the parent object
  39. * @return object
  40. * @todo:
  41. *
  42. */
  43. function __construct( $parent_obj ) {
  44. // store reference to parent
  45. $this->parent_obj = $parent_obj;
  46. // init
  47. $this->_init();
  48. // --<
  49. return $this;
  50. }
  51. /**
  52. * @description: PHP 4 constructor
  53. */
  54. function CommentpressCoreParser( $parent_obj ) {
  55. // is this php5?
  56. if ( version_compare( PHP_VERSION, "5.0.0", "<" ) ) {
  57. // call php5 constructor
  58. $this->__construct( $parent_obj );
  59. }
  60. // --<
  61. return $this;
  62. }
  63. /**
  64. * @description: set up all items associated with this object
  65. * @todo:
  66. *
  67. */
  68. function initialise() {
  69. }
  70. /**
  71. * @description: if needed, destroys all items associated with this object
  72. * @todo:
  73. *
  74. */
  75. function destroy() {
  76. }
  77. //##############################################################################
  78. /*
  79. ============================================================================
  80. PUBLIC METHODS
  81. ============================================================================
  82. */
  83. /**
  84. * @description: call
  85. * @todo:
  86. *
  87. */
  88. function the_content( $content ) {
  89. // reference our post
  90. global $post;
  91. // retrieve all comments and store...
  92. // we need this data multiple times and only need to get it once
  93. $this->comments_all = $this->parent_obj->db->get_all_comments( $post->ID );
  94. // strip out <!--shortcode--> tags
  95. $content = $this->_strip_shortcodes( $content );
  96. // check for our quicktag
  97. $has_quicktag = $this->_has_comment_block_quicktag( $content );
  98. // if it hasn't...
  99. if ( !$has_quicktag ) {
  100. // auto-format content accordingly
  101. // get action to take
  102. $action = apply_filters(
  103. // hook
  104. 'cp_select_content_formatter',
  105. // default
  106. 'tag'
  107. );
  108. // act on it
  109. switch( $action ) {
  110. // for poetry, for example, line by line commenting formatter is better
  111. case 'line' :
  112. // set constant - okay, since we never return here
  113. if ( !defined( 'COMMENTPRESS_BLOCK' ) )
  114. define( 'COMMENTPRESS_BLOCK', 'line' );
  115. // generate text signatures array
  116. $this->text_signatures = $this->_generate_line_signatures( $content );
  117. //print_r( $this->text_signatures ); die();
  118. // only continue parsing if we have an array of sigs
  119. if ( !empty( $this->text_signatures ) ) {
  120. // filter content by <br> and <br /> tags
  121. $content = $this->_parse_lines( $content );
  122. }
  123. break;
  124. // for general prose, existing formatter is fine
  125. case 'tag' :
  126. // set constant
  127. if ( !defined( 'COMMENTPRESS_BLOCK' ) )
  128. define( 'COMMENTPRESS_BLOCK', 'tag' );
  129. // generate text signatures array
  130. $this->text_signatures = $this->_generate_text_signatures( $content, 'p|ul|ol' );
  131. //print_r( $this->text_signatures ); die();
  132. // only continue parsing if we have an array of sigs
  133. if ( !empty( $this->text_signatures ) ) {
  134. // filter content by <p>, <ul> and <ol> tags
  135. $content = $this->_parse_content( $content, 'p|ul|ol' );
  136. }
  137. break;
  138. }
  139. } else {
  140. // set constant
  141. if ( !defined( 'COMMENTPRESS_BLOCK' ) )
  142. define( 'COMMENTPRESS_BLOCK', 'block' );
  143. // generate text signatures array
  144. $this->text_signatures = $this->_generate_block_signatures( $content );
  145. //print_r( $this->text_signatures ); die();
  146. // only parse content if we have an array of sigs
  147. if ( !empty( $this->text_signatures ) ) {
  148. // filter content by <!--commentblock--> quicktags
  149. $content = $this->_parse_blocks( $content );
  150. }
  151. }
  152. // store text sigs
  153. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  154. // --<
  155. return $content;
  156. }
  157. /**
  158. * @description: get comments sorted by text signature and paragraph
  159. * @param integer $post_ID the ID of the post
  160. * @return array $_comments
  161. * @todo:
  162. *
  163. */
  164. function get_sorted_comments( $post_ID ) {
  165. // have we already sorted the comments?
  166. if ( !empty( $this->comments_sorted ) ) {
  167. // --<
  168. return $this->comments_sorted;
  169. }
  170. // --<
  171. return $this->_get_sorted_comments( $post_ID );
  172. }
  173. //##############################################################################
  174. /*
  175. ============================================================================
  176. PRIVATE METHODS
  177. ============================================================================
  178. */
  179. /**
  180. * @description: object initialisation
  181. * @todo:
  182. *
  183. */
  184. function _init() {
  185. }
  186. /**
  187. * @description: parses the content by tag
  188. * @param string $content the post content
  189. * @param string $tag the tag to filter by
  190. * @return string $content the parsed content
  191. * @todo:
  192. *
  193. */
  194. function _parse_content( $content, $tag = 'p|ul|ol' ) {
  195. /*
  196. print_r( array(
  197. 'c' => $content
  198. ) );
  199. die();
  200. */
  201. // parse standalone captioned images
  202. $content = $this->_parse_captions( $content );
  203. // get our paragraphs
  204. $matches = $this->_get_text_matches( $content, $tag );
  205. //print_r( $matches ); die();
  206. // kick out if we don't have any
  207. if( !count( $matches ) ) {
  208. // --<
  209. return $content;
  210. }
  211. // reference our post
  212. global $post;
  213. // get sorted comments and store
  214. $this->comments_sorted = $this->_get_sorted_comments( $post->ID );
  215. //print_r( $this->comments_sorted ); die();
  216. // we already have our text signatures, so set flag
  217. $sig_key = 0;
  218. // run through 'em...
  219. foreach( $matches AS $paragraph ) {
  220. // get a signature for the paragraph
  221. $text_signature = $this->text_signatures[ $sig_key ];
  222. // increment
  223. $sig_key++;
  224. // get comment count
  225. $comment_count = count( $this->comments_sorted[ $text_signature ] );
  226. // get comment icon
  227. $comment_icon = $this->parent_obj->display->get_comment_icon(
  228. $comment_count,
  229. $text_signature,
  230. 'auto',
  231. $sig_key
  232. );
  233. // get paragraph icon
  234. $paragraph_icon = $this->parent_obj->display->get_paragraph_icon(
  235. $comment_count,
  236. $text_signature,
  237. 'auto',
  238. $sig_key
  239. );
  240. // set pattern by first tag
  241. switch ( substr( $paragraph, 0 , 2 ) ) {
  242. case '<p': $tag = 'p'; break;
  243. case '<o': $tag = 'ol'; break;
  244. case '<u': $tag = 'ul'; break;
  245. }
  246. /*
  247. --------------------------------------------------------------------
  248. NOTES
  249. --------------------------------------------------------------------
  250. There's a temporary fix to exclude <param> and <pre> tags by excluding subsequent 'a' and
  251. 'r' chars - this regex needs more attention so that only <p> and <p ...> are captured.
  252. In HTML5 there is also the <progress> tag, but this is excluded along with <pre>
  253. Also, the WordPress visual editor inserts styles into <p> tags for text justification,
  254. so we need to feed this regex with enhanced tags to capture the following:
  255. <p style="text-align:left;">
  256. <p style="text-align:right;">
  257. <p style="text-align:center;">
  258. <p style="text-align:justify;">
  259. AND
  260. <p style="text-align:left">
  261. <p style="text-align:right">
  262. <p style="text-align:center">
  263. <p style="text-align:justify">
  264. --------------------------------------------------------------------
  265. */
  266. // further checks when there's a <p> tag
  267. if ( $tag == 'p' ) {
  268. // set pattern by TinyMCE tag attribute, if we have one...
  269. if ( substr( $paragraph, 0 , 17 ) == '<p style="text-al' ) {
  270. // test for left
  271. if ( substr( $paragraph, 0 , 27 ) == '<p style="text-align:left;"' ) {
  272. $tag = 'p style="text-align:left;"';
  273. } elseif ( substr( $paragraph, 0 , 26 ) == '<p style="text-align:left"' ) {
  274. $tag = 'p style="text-align:left"';
  275. } elseif ( substr( $paragraph, 0 , 28 ) == '<p style="text-align: left;"' ) {
  276. $tag = 'p style="text-align: left;"';
  277. } elseif ( substr( $paragraph, 0 , 27 ) == '<p style="text-align: left"' ) {
  278. $tag = 'p style="text-align: left"';
  279. }
  280. // test for right
  281. if ( substr( $paragraph, 0 , 28 ) == '<p style="text-align:right;"' ) {
  282. $tag = 'p style="text-align:right;"';
  283. } elseif ( substr( $paragraph, 0 , 27 ) == '<p style="text-align:right"' ) {
  284. $tag = 'p style="text-align:right"';
  285. } elseif ( substr( $paragraph, 0 , 29 ) == '<p style="text-align: right;"' ) {
  286. $tag = 'p style="text-align: right;"';
  287. } elseif ( substr( $paragraph, 0 , 28 ) == '<p style="text-align: right"' ) {
  288. $tag = 'p style="text-align: right"';
  289. }
  290. // test for center
  291. if ( substr( $paragraph, 0 , 29 ) == '<p style="text-align:center;"' ) {
  292. $tag = 'p style="text-align:center;"';
  293. } elseif ( substr( $paragraph, 0 , 28 ) == '<p style="text-align:center"' ) {
  294. $tag = 'p style="text-align:center"';
  295. } elseif ( substr( $paragraph, 0 , 30 ) == '<p style="text-align: center;"' ) {
  296. $tag = 'p style="text-align: center;"';
  297. } elseif ( substr( $paragraph, 0 , 29 ) == '<p style="text-align: center"' ) {
  298. $tag = 'p style="text-align: center"';
  299. }
  300. // test for justify
  301. if ( substr( $paragraph, 0 , 30 ) == '<p style="text-align:justify;"' ) {
  302. $tag = 'p style="text-align:justify;"';
  303. } elseif ( substr( $paragraph, 0 , 29 ) == '<p style="text-align:justify"' ) {
  304. $tag = 'p style="text-align:justify"';
  305. } elseif ( substr( $paragraph, 0 , 31 ) == '<p style="text-align: justify;"' ) {
  306. $tag = 'p style="text-align: justify;"';
  307. } elseif ( substr( $paragraph, 0 , 30 ) == '<p style="text-align: justify"' ) {
  308. $tag = 'p style="text-align: justify"';
  309. }
  310. } // end check for text-align
  311. // test for Simple Footnotes para "heading"
  312. if ( substr( $paragraph, 0 , 16 ) == '<p class="notes"' ) {
  313. $tag = 'p class="notes"';
  314. }
  315. // if we fall through to here, treat it like it's just a <p> tag above.
  316. // This will fail if there are custom attributes set in the HTML editor,
  317. // but I'm not sure how to handle that without migrating to an XML parser
  318. //print_r( $tag ); //die();
  319. }
  320. /*
  321. --------------------------------------------------------------------
  322. NOTES
  323. --------------------------------------------------------------------
  324. There are also flaws with parsing nested lists, both ordered and unordered. The WordPress
  325. Unit Tests XML file reveals these, though the docs are hopefully clear enough that people
  326. won't use nested lists. However, the severity is such that I'm contemplating migrating to
  327. a DOM parser such as:
  328. phpQuery <https://github.com/TobiaszCudnik/phpquery>
  329. Simple HTML DOM <http://sourceforge.net/projects/simplehtmldom/>
  330. Others <http://stackoverflow.com/questions/3577641/how-to-parse-and-process-html-with-php>
  331. There are so many examples of people saying "don't use regex with HTML" that this probably
  332. ought to be done when time allows.
  333. --------------------------------------------------------------------
  334. */
  335. // further checks when there's a <ol> tag
  336. if ( $tag == 'ol' ) {
  337. // set pattern by TinyMCE tag attribute
  338. switch ( substr( $paragraph, 0 , 21 ) ) {
  339. // compat with WP Footnotes
  340. case '<ol class="footnotes"': $tag = 'ol class="footnotes"'; break;
  341. // see notes for p tag above
  342. }
  343. }
  344. // assign icons to paras
  345. $pattern = array('#<('.$tag.'[^a^r>]*)>#');
  346. $replace = array(
  347. $this->parent_obj->display->get_para_tag(
  348. $text_signature,
  349. $paragraph_icon.$comment_icon,
  350. $tag
  351. )
  352. );
  353. $block = preg_replace( $pattern, $replace, $paragraph );
  354. // NB: because str_replace() has no limit to the replacements, I am switching to
  355. // preg_replace() because that does have a limit
  356. //$content = str_replace( $paragraph, $block, $content );
  357. // prepare paragraph for preg_replace
  358. $prepared_para = preg_quote( $paragraph );
  359. // because we use / as the delimiter, we need to escape all /s
  360. $prepared_para = str_replace( '/', '\/', $prepared_para );
  361. // protect all dollar numbers
  362. $block = str_replace( "$", "\\\$", $block );
  363. // only once please
  364. $limit = 1;
  365. // replace the paragraph in the original context, preserving all other content
  366. $content = preg_replace(
  367. //array($paragraph),
  368. '/'.$prepared_para.'/',
  369. $block,
  370. $content,
  371. $limit
  372. );
  373. /*
  374. print_r( array(
  375. //'p' => $paragraph,
  376. 'p' => $prepared_para,
  377. 'b' => $block,
  378. 'c' => $content
  379. ) ); //die();
  380. */
  381. }
  382. /*
  383. print_r( array(
  384. //'d' => $duplicates,
  385. 't' => $this->text_signatures,
  386. 'c' => $content
  387. ) );
  388. */
  389. //die();
  390. //*/
  391. // --<
  392. return $content;
  393. }
  394. /**
  395. * @description: splits the content into an array by tag
  396. * @param string $content the post content
  397. * @param string $tag the tag to filter by
  398. * @return array $matches the ordered array of matched items
  399. * @todo:
  400. *
  401. */
  402. function _get_text_matches( $content, $tag = 'p|ul|ol' ) {
  403. // filter out embedded tweets
  404. $content = $this->_filter_twitter_embeds( $content );
  405. // get our paragraphs (needed to split regex into two strings as some IDEs
  406. // don't like PHP closing tags, even they are part of a regex and not actually
  407. // closing tags at all)
  408. //preg_match_all( '/<('.$tag.')[^>]*>(.*?)(<\/('.$tag.')>)/', $content, $matches );
  409. preg_match_all( '#<('.$tag.')[^>]*?'.'>(.*?)</('.$tag.')>#si', $content, $matches );
  410. //print_r( $matches[0] ); print_r( $matches[1] ); exit();
  411. // kick out if we don't have any
  412. if( !empty($matches[0]) ) {
  413. // --<
  414. return $matches[0];
  415. } else {
  416. // --<
  417. return array();
  418. }
  419. }
  420. /**
  421. * @description: parses the content by tag and builds text signatures array
  422. * @param string $content the post content
  423. * @param string $tag the tag to filter by
  424. * @return array $text_signatures the ordered array of text signatures
  425. * @todo:
  426. *
  427. */
  428. function _generate_text_signatures( $content, $tag = 'p|ul|ol' ) {
  429. // don't filter if a password is required
  430. if ( post_password_required() ) {
  431. // store text sigs array in global
  432. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  433. // --<
  434. return $this->text_signatures;
  435. }
  436. // parse standalone captioned images
  437. $content = $this->_parse_captions( $content );
  438. // get our paragraphs
  439. $matches = $this->_get_text_matches( $content, $tag );
  440. // kick out if we don't have any
  441. if( !count( $matches ) ) {
  442. // store text sigs array in global
  443. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  444. // --<
  445. return $this->text_signatures;
  446. }
  447. // init ( array( 'text_signature' => n ), where n is the number of duplicates )
  448. $duplicates = array();
  449. // run through 'em...
  450. foreach( $matches AS $paragraph ) {
  451. // get a signature for the paragraph
  452. $text_signature = $this->_generate_text_signature( $paragraph );
  453. // do we have one already?
  454. if ( in_array( $text_signature, $this->text_signatures ) ) {
  455. // is it in the duplicates array?
  456. if ( array_key_exists( $text_signature, $duplicates ) ) {
  457. // add one
  458. $duplicates[ $text_signature ]++;
  459. } else {
  460. // add it
  461. $duplicates[ $text_signature ] = 1;
  462. }
  463. // add number to end of text sig
  464. $text_signature .= '_'.$duplicates[ $text_signature ];
  465. }
  466. // add to signatures array
  467. $this->text_signatures[] = $text_signature;
  468. }
  469. // store text sigs array in global
  470. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  471. // --<
  472. return $this->text_signatures;
  473. }
  474. /**
  475. * @description: parse the content by line (<br />)
  476. * @param string $content the post content
  477. * @return string $content the parsed content
  478. * @todo:
  479. *
  480. */
  481. function _parse_lines( $content ) {
  482. // parse standalone captioned images
  483. $content = $this->_parse_captions( $content );
  484. // get our lines
  485. $matches = $this->_get_line_matches( $content );
  486. //print_r( $matches ); die();
  487. // kick out if we don't have any
  488. if( !count( $matches ) ) {
  489. // --<
  490. return $content;
  491. }
  492. // reference our post
  493. global $post;
  494. // get sorted comments and store
  495. $this->comments_sorted = $this->_get_sorted_comments( $post->ID );
  496. //print_r( $this->comments_sorted ); die();
  497. // we already have our text signatures, so set flag
  498. $sig_key = 0;
  499. // init our content array
  500. $content_array = array();
  501. // run through 'em...
  502. foreach( $matches AS $line ) {
  503. // is there any content?
  504. if ( $line != '' ) {
  505. // check for paras
  506. if ( $line == '<p>' OR $line == '</p>' ) {
  507. // do we want to allow commenting on verses?
  508. // add to content array
  509. $content_array[] = $line;
  510. } else {
  511. // line commenting
  512. // get a signature for the line
  513. $text_signature = $this->text_signatures[ $sig_key ];
  514. // increment
  515. $sig_key++;
  516. // get comment count
  517. // NB: the sorted array contains whole page as key 0, so we use the incremented value
  518. $comment_count = count( $this->comments_sorted[ $text_signature ] );
  519. // get paragraph icon
  520. $paragraph_icon = $this->parent_obj->display->get_paragraph_icon(
  521. $comment_count,
  522. $text_signature,
  523. 'line',
  524. $sig_key
  525. );
  526. // get opening tag markup for this line
  527. $opening_tag = $this->parent_obj->display->get_para_tag(
  528. $text_signature,
  529. $paragraph_icon,
  530. 'span'
  531. );
  532. // assign opening tag markup to line
  533. $line = $opening_tag.$line;
  534. // get comment icon
  535. $comment_icon = $this->parent_obj->display->get_comment_icon(
  536. $comment_count,
  537. $text_signature,
  538. 'line',
  539. $sig_key
  540. );
  541. //_cpdie( $commenticon );
  542. // replace inline html comment with comment_icon
  543. $line = str_replace( '<!-- line-end -->', ' '.$comment_icon, $line );
  544. // add to content array
  545. $content_array[] = $line;
  546. }
  547. }
  548. }
  549. //print_r( $this->text_signatures ); //die();
  550. //print_r( $duplicates ); die();
  551. //print_r( $content_array ); die();
  552. //die();
  553. // rejoin and exclude quicktag
  554. $content = implode( '', $content_array );
  555. // --<
  556. return $content;
  557. }
  558. /**
  559. * @description: splits the content into an array by line
  560. * @param string $content the post content
  561. * @param string $tag the tag to filter by
  562. * @return array $matches the ordered array of matched items
  563. * @todo:
  564. *
  565. */
  566. function _get_line_matches( $content ) {
  567. // filter out embedded tweets
  568. $content = $this->_filter_twitter_embeds( $content );
  569. // wrap all lines with spans
  570. // get all instances
  571. $pattern = array(
  572. '/<br>/',
  573. '/<br\/>/',
  574. '/<br \/>/',
  575. '/<br>\n/',
  576. '/<br\/>\n/',
  577. '/<br \/>\n/',
  578. '/<p>/',
  579. '/<\/p>/'
  580. );
  581. // define replacements
  582. $replace = array(
  583. '<!-- line-end --></span><br>',
  584. '<!-- line-end --></span><br/>',
  585. '<!-- line-end --></span><br />',
  586. '<br>'."\n".'<span class="cp-line">',
  587. '<br/>'."\n".'<span class="cp-line">',
  588. '<br />'."\n".'<span class="cp-line">',
  589. '<p><span class="cp-line">',
  590. '<!-- line-end --></span></p>'
  591. );
  592. // do replacement
  593. $content = preg_replace( $pattern, $replace, $content );
  594. /*
  595. print_r( array(
  596. 'content' => $content,
  597. ) ); die();
  598. */
  599. // explode by <span>
  600. $output_array = explode( '<span class="cp-line">', $content );
  601. //print_r( $output_array ); die();
  602. // kick out if we have an empty array
  603. if ( empty( $output_array ) ) {
  604. // --<
  605. return array();
  606. }
  607. // --<
  608. return $output_array;
  609. }
  610. /**
  611. * @description: parses the content by line (<br />) and builds text signatures array
  612. * @param string $content the post content
  613. * @return array $text_signatures the ordered array of text signatures
  614. * @todo:
  615. *
  616. */
  617. function _generate_line_signatures( $content ) {
  618. // don't filter if a password is required
  619. if ( post_password_required() ) {
  620. // store text sigs array in global
  621. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  622. // --<
  623. return $this->text_signatures;
  624. }
  625. // wrap all lines with spans
  626. // parse standalone captioned images
  627. $content = $this->_parse_captions( $content );
  628. // explode by <span>
  629. $output_array = $this->_get_line_matches( $content );
  630. //print_r( $output_array ); die();
  631. // kick out if we have an empty array
  632. if ( empty( $output_array ) ) {
  633. // store text sigs array in global
  634. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  635. // --<
  636. return $this->text_signatures;
  637. }
  638. // reference our post
  639. global $post;
  640. // init our content array
  641. $content_array = array();
  642. // init ( array( 'text_signature' => n ), where n is the number of duplicates )
  643. $duplicates = array();
  644. // run through 'em...
  645. foreach( $output_array AS $paragraph ) {
  646. // is there any content?
  647. if ( $paragraph != '' ) {
  648. // check for paras
  649. if ( $paragraph == '<p>' OR $paragraph == '</p>' ) {
  650. // do we want to allow commenting on verses?
  651. } else {
  652. // line commenting
  653. // get a signature for the paragraph
  654. $text_signature = $this->_generate_text_signature( $paragraph );
  655. // do we have one already?
  656. if ( in_array( $text_signature, $this->text_signatures ) ) {
  657. // is it in the duplicates array?
  658. if ( array_key_exists( $text_signature, $duplicates ) ) {
  659. // add one
  660. $duplicates[ $text_signature ]++;
  661. } else {
  662. // add it
  663. $duplicates[ $text_signature ] = 1;
  664. }
  665. // add number to end of text sig
  666. $text_signature .= '_'.$duplicates[ $text_signature ];
  667. }
  668. // add to signatures array
  669. $this->text_signatures[] = $text_signature;
  670. }
  671. }
  672. }
  673. //print_r( $this->text_signatures ); //die();
  674. //print_r( $duplicates ); die();
  675. //die();
  676. // store text sigs array in global
  677. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  678. // --<
  679. return $this->text_signatures;
  680. }
  681. /**
  682. * @description: parses the content by comment block
  683. * @param string $content the post content
  684. * @return string $content the parsed content
  685. * @todo: this is probably mighty slow - review preg_replace patterns
  686. *
  687. */
  688. function _parse_blocks( $content ) {
  689. // parse standalone captioned images
  690. $content = $this->_parse_captions( $content );
  691. // get our lines
  692. $matches = $this->_get_block_matches( $content );
  693. //print_r( $matches ); die();
  694. // kick out if we don't have any
  695. if( !count( $matches ) ) {
  696. // --<
  697. return $content;
  698. }
  699. // reference our post
  700. global $post;
  701. // get sorted comments and store
  702. $this->comments_sorted = $this->_get_sorted_comments( $post->ID );
  703. //print_r( $this->comments_sorted ); die();
  704. // we already have our text signatures, so set flag
  705. $sig_key = 0;
  706. // init content array
  707. $content_array = array();
  708. // run through 'em...
  709. foreach( $matches AS $paragraph ) {
  710. // is there any content?
  711. if ( $paragraph != '' ) {
  712. // get a signature for the paragraph
  713. $text_signature = $this->text_signatures[ $sig_key ];
  714. // increment
  715. $sig_key++;
  716. // get comment count
  717. // NB: the sorted array contains whole page as key 0, so we use the incremented value
  718. $comment_count = count( $this->comments_sorted[ $text_signature ] );
  719. // get comment icon
  720. $comment_icon = $this->parent_obj->display->get_comment_icon(
  721. $comment_count,
  722. $text_signature,
  723. 'block',
  724. $sig_key
  725. );
  726. // get paragraph icon
  727. $paragraph_icon = $this->parent_obj->display->get_paragraph_icon(
  728. $comment_count,
  729. $text_signature,
  730. 'block',
  731. $sig_key
  732. );
  733. // get comment icon markup
  734. $icon_html = $this->parent_obj->display->get_para_tag(
  735. $text_signature,
  736. $paragraph_icon.$comment_icon,
  737. 'div'
  738. );
  739. // assign icons to blocks
  740. $paragraph = $icon_html.$paragraph.'</div>'."\n\n\n\n";
  741. // add to content array
  742. $content_array[] = $paragraph;
  743. }
  744. }
  745. //print_r( $this->text_signatures ); //die();
  746. //print_r( $duplicates ); die();
  747. // rejoin and exclude quicktag
  748. $content = implode( '', $content_array );
  749. // --<
  750. return $content;
  751. }
  752. /**
  753. * @description: splits the content into an array by block
  754. * @param string $content the post content
  755. * @param string $tag the tag to filter by
  756. * @return array $matches the ordered array of matched items
  757. * @todo:
  758. *
  759. */
  760. function _get_block_matches( $content ) {
  761. // filter out embedded tweets
  762. $content = $this->_filter_twitter_embeds( $content );
  763. // wp_texturize() does an okay job with creating paragraphs, but comments tend
  764. // to screw things up. let's try and fix...
  765. //print_r( array( 'before' => $content ) );
  766. // first, replace all instances of ' <!--commentblock--> ' with
  767. // '<p><!--commentblock--></p>\n'
  768. $content = preg_replace(
  769. '/\s+<!--commentblock-->\s+/',
  770. '<p><!--commentblock--></p>'."\n",
  771. $content
  772. );
  773. // next, replace all instances of '<p><!--commentblock-->fengfnefe' with
  774. // '<p><!--commentblock--></p>\n<p>fengfnefe'
  775. $content = preg_replace(
  776. '/<p><!--commentblock-->/',
  777. '<p><!--commentblock--></p>'."\n".'<p>',
  778. $content
  779. );
  780. // next, replace all instances of 'fengfnefe<!--commentblock--></p>' with
  781. // 'fengfnefe</p>\n<p><!--commentblock--></p>'
  782. $content = preg_replace(
  783. '/<!--commentblock--><\/p>/',
  784. '</p>'."\n".'<p><!--commentblock--></p>'."\n",
  785. $content
  786. );
  787. // replace all instances of '<br />\n<!--commentblock--><br />\n' with
  788. // '</p>\n<p><!--commentblock--></p>\n<p>'
  789. $content = preg_replace(
  790. '/<br \/>\s+<!--commentblock--><br \/>\s+/',
  791. '</p>'."\n".'<p><!--commentblock--></p>'."\n".'<p>',
  792. $content
  793. );
  794. // next, replace all instances of '<br />\n<!--commentblock--></p>\n' with
  795. // '</p>\n<p><!--commentblock--></p>\n<p>'
  796. $content = preg_replace(
  797. '/<br \/>\s+<!--commentblock--><\/p>\s+/',
  798. '</p>'."\n".'<p><!--commentblock--></p>'."\n",
  799. $content
  800. );
  801. // next, replace all instances of '<p><!--commentblock--><br />\n' with
  802. // '<p><!--commentblock--></p>\n<p>'
  803. $content = preg_replace(
  804. '/<p><!--commentblock--><br \/>\s+/',
  805. '<p><!--commentblock--></p>'."\n".'<p>',
  806. $content
  807. );
  808. // repair some oddities: empty newlines with whitespace after:
  809. $content = preg_replace(
  810. '/<p><br \/>\s+/',
  811. '<p>',
  812. $content
  813. );
  814. // repair some oddities: empty newlines without whitespace after:
  815. $content = preg_replace(
  816. '/<p><br \/>/',
  817. '<p>',
  818. $content
  819. );
  820. // repair some oddities: empty paragraphs with whitespace inside:
  821. $content = preg_replace(
  822. '/<p>\s+<\/p>\s+/',
  823. '',
  824. $content
  825. );
  826. // repair some oddities: empty paragraphs without whitespace inside:
  827. $content = preg_replace(
  828. '/<p><\/p>\s+/',
  829. '',
  830. $content
  831. );
  832. // repair some oddities: any remaining empty paragraphs:
  833. $content = preg_replace(
  834. '/<p><\/p>/',
  835. '',
  836. $content
  837. );
  838. //print_r( array( 'after' => $content ) ); die();
  839. // explode by <p> version to temp array
  840. $output_array = explode( '<p><'.'!--commentblock--></p>', $content );
  841. // kick out if we have an empty array
  842. if ( empty( $output_array ) ) {
  843. // --<
  844. return array();
  845. }
  846. // --<
  847. return $output_array;
  848. }
  849. /**
  850. * @description: parses the content by comment block and generates text signature array
  851. * @param string $content the post content
  852. * @return array $text_signatures the ordered array of text signatures
  853. * @todo: this is probably mighty slow - review preg_replace patterns
  854. *
  855. */
  856. function _generate_block_signatures( $content ) {
  857. // don't filter if a password is required
  858. if ( post_password_required() ) {
  859. // store text sigs array in global
  860. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  861. // --<
  862. return $this->text_signatures;
  863. }
  864. // parse standalone captioned images
  865. $content = $this->_parse_captions( $content );
  866. // get blocks array
  867. $matches = $this->_get_block_matches( $content );
  868. // init ( array( 'text_signature' => n ), where n is the number of duplicates )
  869. $duplicates = array();
  870. // run through 'em...
  871. foreach( $matches AS $paragraph ) {
  872. // is there any content?
  873. if ( $paragraph != '' ) {
  874. // get a signature for the paragraph
  875. $text_signature = $this->_generate_text_signature( $paragraph );
  876. // do we have one already?
  877. if ( in_array( $text_signature, $this->text_signatures ) ) {
  878. // is it in the duplicates array?
  879. if ( array_key_exists( $text_signature, $duplicates ) ) {
  880. // add one
  881. $duplicates[ $text_signature ]++;
  882. } else {
  883. // add it
  884. $duplicates[ $text_signature ] = 1;
  885. }
  886. // add number to end of text sig
  887. $text_signature .= '_'.$duplicates[ $text_signature ];
  888. }
  889. // add to signatures array
  890. $this->text_signatures[] = $text_signature;
  891. }
  892. }
  893. //print_r( $this->text_signatures ); die();
  894. //print_r( $duplicates ); die();
  895. // store text sigs array in global
  896. $this->parent_obj->db->set_text_sigs( $this->text_signatures );
  897. // --<
  898. return $this->text_signatures;
  899. }
  900. /**
  901. * @description: utility to check if the content has our custom quicktag
  902. * @param string $content the post content
  903. * @return string $content modified post content
  904. * @todo:
  905. *
  906. */
  907. function _has_comment_block_quicktag( $content ) {
  908. // init
  909. $return = false;
  910. // look for < !--commentblock--> comment
  911. if ( strstr( $content, '<!--commentblock-->' ) !== false ) {
  912. // yep
  913. $return = true;
  914. }
  915. // --<
  916. return $return;
  917. }
  918. /**
  919. * @description: utility to remove our custom quicktag
  920. * @param string $content the post content
  921. * @return string $content modified post content
  922. * @todo:
  923. *
  924. */
  925. function _strip_comment_block_quicktag( $content ) {
  926. // look for < !--commentblock--> comment
  927. if ( preg_match('/<'.'!--commentblock--><br \/>/', $content, $matches) ) {
  928. // derive list
  929. $content = explode( $matches[0], $content, 2 );
  930. // rejoin to exclude shortcode
  931. $content = implode( '', $content );
  932. }
  933. // look for < !--commentblock--> comment
  934. if ( preg_match('/<p><'.'!--commentblock--><\/p>/', $content, $matches) ) {
  935. // derive list
  936. $content = explode( $matches[0], $content, 2 );
  937. // rejoin to exclude shortcode
  938. $content = implode( '', $content );
  939. }
  940. // --<
  941. return $content;
  942. }
  943. /**
  944. * @description: utility to strip out shortcodes from content otherwise they get formatting
  945. * @param string $content the post content
  946. * @return string $content modified post content
  947. * @todo:
  948. *
  949. */
  950. function _strip_shortcodes( $content ) {
  951. /*
  952. ------------------------------------------------------------------------
  953. Notes added: 08 Mar 2012
  954. ------------------------------------------------------------------------
  955. Here's how these quicktags work...
  956. http://codex.wordpress.org/Customizing_the_Read_More
  957. -------------
  958. More Quicktag
  959. -------------
  960. However, we cannot be sure of how the quicktags has been inserted. For example (1):
  961. <p>Here&#8217;s the teaser<br />
  962. <span id="more-689"></span><br />
  963. Here&#8217;s the rest of the post</p>
  964. Is the intention here that the teaser is a paragraph? I'd say so.
  965. What about (2):
  966. <p>Here&#8217;s the teaser</p>
  967. <p><span id="more-689"></span></p>
  968. <p>Here&#8217;s the rest of the post</p>
  969. I'd say the same as above.
  970. And then these two possibilities (3) & (4):
  971. <p>Here&#8217;s the teaser<span id="more-689"></span><br />
  972. Here&#8217;s the rest of the post</p>
  973. <p>Here&#8217;s the teaser<br />
  974. <span id="more-689"></span>Here&#8217;s the rest of the post</p>
  975. Now, for our purposes, since we currently use the excerpt in the blog archives, only
  976. (1) and (2) are truly problematic - because they cause visible formatting. (3) & (4)
  977. do not currently get filtered out because the spans are inline - but they do imply
  978. that the content before and after should be self-contained. As a result, I think it
  979. is probably better to add a statement about correct usage in to the help text so that
  980. we can reliably parse the content.
  981. -----------------
  982. NoTeaser Quicktag
  983. -----------------
  984. The Codex says "Include <!--noteaser--> in the post text, immediately after the <!--more-->"
  985. which really means *on the same line*. When this is done, our content looks like this (1):
  986. <p><span id="more-691"></span><!--noteaser--></p>
  987. <p>And this is the rest of the post blah</p>
  988. Or (2):
  989. <p><span id="more-691"></span><!--noteaser--><br />
  990. And this is the rest of the post blah</p>
  991. ------------------------------------------------------------------------
  992. */
  993. //print_r( $content ); die();
  994. // look for inline <!--more--> span
  995. if ( preg_match('/<span id="more-(.*?)?'.'><\/span><br \/>/', $content, $matches) ) {
  996. // derive list
  997. $content = explode( $matches[0], $content, 2 );
  998. // rejoin to exclude shortcode
  999. $content = implode( '', $content );
  1000. }
  1001. // look for separated <!--more--> span
  1002. if ( preg_match('/<p><span id="more-(.*?)?'.'><\/span><\/p>/', $content, $matches) ) {
  1003. // derive list
  1004. $content = explode( $matches[0], $content, 2 );
  1005. // rejoin to exclude shortcode
  1006. $content = implode( '', $content );
  1007. }
  1008. // look for inline <!--more--> span correctly followed by <!--noteaser-->
  1009. if ( preg_match('/<span id="more-(.*?)?'.'><\/span><!--noteaser--><br \/>/', $content, $matches) ) {
  1010. // derive list
  1011. $content = explode( $matches[0], $content, 2 );
  1012. // rejoin to exclude shortcode
  1013. $content = implode( '', $content );
  1014. }
  1015. // look for separated <!--more--> span correctly followed by <!--noteaser-->
  1016. if ( preg_match('/<p><span id="more-(.*?)?'.'><\/span><!--noteaser--><\/p>/', $content, $matches) ) {
  1017. // derive list
  1018. $content = explode( $matches[0], $content, 2 );
  1019. // rejoin to exclude shortcode
  1020. $content = implode( '', $content );
  1021. }
  1022. // look for incorrectly placed inline <!--noteaser--> comment
  1023. if ( preg_match('/<'.'!--noteaser--><br \/>/', $content, $matches) ) {
  1024. // derive list
  1025. $content = explode( $matches[0], $content, 2 );
  1026. // rejoin to exclude shortcode
  1027. $content = implode( '', $content );
  1028. }
  1029. // look for incorrectly placed separated <!--noteaser--> comment
  1030. if ( preg_match('/<p><'.'!--noteaser--><\/p>/', $content, $matches) ) {
  1031. // derive list
  1032. $content = explode( $matches[0], $content, 2 );
  1033. // rejoin to exclude shortcode
  1034. $content = implode( '', $content );
  1035. }
  1036. // this gets the additional text... (not used)
  1037. if ( !empty($matches[1]) ) {
  1038. //$more_link_text = strip_tags(wp_kses_no_null(trim($matches[1])));
  1039. }
  1040. //print_r( $content ); die();
  1041. // --<
  1042. return $content;
  1043. }
  1044. /**
  1045. * @description: generates a text signature based on the content of a paragraph
  1046. * @param string $text the text of a paragraph
  1047. * @param integer $position paragraph position in a post
  1048. * @return string $sig the generated text signature
  1049. * @todo: implement some kind of paragraph identifier to distiguish identical paragraphs?
  1050. *
  1051. */
  1052. function _generate_text_signature( $text, $position = null ) {
  1053. // get an array of words from the text
  1054. $words = explode( ' ', ereg_replace( '[^A-Za-z]', ' ', html_entity_decode($text) ) );
  1055. // store unique words
  1056. // NB: this may be a mistake for poetry, which can use any words in any order
  1057. $unique_words = array_unique( $words );
  1058. // init sig
  1059. $text_signature = null;
  1060. // run through our unique words
  1061. foreach( $unique_words AS $key => $word ) {
  1062. // add first letter
  1063. $text_signature .= substr( $word, 0, 1 );
  1064. // limit to 250 chars
  1065. // NB: this is because we have changed the format of text signatures by adding numerals
  1066. // when there are duplicates. Duplicates add at least 2 characters, so there is the
  1067. // (admittedly remote) possibility of exceeding the varchar(255) character limit.
  1068. if( $key > 250 ) { break; }
  1069. }
  1070. // get sig - think this through (not used, as position always null
  1071. $sig = ($position) ?
  1072. $position . ':' . $text_signature :
  1073. $text_signature;
  1074. // --<
  1075. return $sig;
  1076. }
  1077. /**
  1078. * @description: removes embedded tweets (new in WP 3.4)
  1079. * @param string $content the post content
  1080. * @return string $content the filtered post content
  1081. * @todo: make these commentable
  1082. *
  1083. */
  1084. function _filter_twitter_embeds( $content ) {
  1085. // test for a WP 3.4 function
  1086. if ( function_exists( 'wp_get_themes' ) ) {
  1087. // look for Embedded Tweet <blockquote>
  1088. if ( preg_match('#<(blockquote class="twitter-tweet)[^>]*?'.'>(.*?)</(blockquote)>#si', $content, $matches) ) {
  1089. // derive list
  1090. $content = explode( $matches[0], $content, 2 );
  1091. // rejoin to exclude from content to be parsed
  1092. $content = implode( '', $content );
  1093. // also remove twitter script
  1094. $content = str_replace(
  1095. '<p><script src="//platform.twitter.com/widgets.js" charset="utf-8"></script></p>',
  1096. '',
  1097. $content
  1098. );
  1099. }
  1100. }
  1101. // --<
  1102. return $content;
  1103. }
  1104. /**
  1105. * @description: wraps standalone captions (ie, not inside <p> tags) in <p>
  1106. * @param string $content the post content
  1107. * @return string $content the filtered post content
  1108. * @todo:
  1109. *
  1110. */
  1111. function _parse_captions( $content ) {
  1112. // filter captioned images that are *not* inside other tags
  1113. $pattern = array(
  1114. '/\n<!-- cp_caption_start -->/',
  1115. '/<!-- cp_caption_end -->\n/'
  1116. );
  1117. // define replacements
  1118. $replace = array(
  1119. "\n".'<p><!-- cp_caption_start -->',
  1120. '<!-- cp_caption_end --></p>'."\n"
  1121. );
  1122. // do replacement
  1123. $content = preg_replace( $pattern, $replace, $content );
  1124. /*
  1125. print_r( array(
  1126. 'c' => $content
  1127. ) );
  1128. die();
  1129. */
  1130. // --<
  1131. return $content;
  1132. }
  1133. /**
  1134. * @description: get comments sorted by text signature and paragraph
  1135. * @param integer $post_ID the ID of the post
  1136. * @return array $_comments
  1137. * @todo:
  1138. *
  1139. */
  1140. function _get_sorted_comments( $post_ID ) {
  1141. // init return
  1142. $_comments = array();
  1143. // get all comments
  1144. $comments = $this->comments_all;
  1145. // filter out any multipage comments not on this page
  1146. $comments = $this->_multipage_comment_filter( $comments );
  1147. //print_r( $comments ); die();
  1148. // get our signatures
  1149. $_sigs = $this->parent_obj->db->get_text_sigs();
  1150. //print_r( $_sigs ); die();
  1151. // assign comments to text signatures
  1152. $_assigned = $this->_assign_comments( $comments, $_sigs );
  1153. // NB: $_assigned is an array with sigs as keys and array of comments as value
  1154. // it may be empty...
  1155. // we must have text signatures...
  1156. if ( !empty( $_sigs ) ) {
  1157. // if we have any comments on the whole page...
  1158. if ( isset( $_assigned[ 'WHOLE_PAGE_OR_POST_COMMENTS' ] ) ) {
  1159. // add them first
  1160. $_comments[ 'WHOLE_PAGE_OR_POST_COMMENTS' ] = $_assigned[ 'WHOLE_PAGE_OR_POST_COMMENTS' ];
  1161. } else {
  1162. // append empty array
  1163. $_comments[ 'WHOLE_PAGE_OR_POST_COMMENTS' ] = array();
  1164. }
  1165. // then add in the order of our text signatures
  1166. foreach( $_sigs AS $text_signature ) {
  1167. // if we have any assigned...
  1168. if ( isset( $_assigned[ $text_signature ] ) ) {
  1169. // append assigned comments
  1170. $_comments[ $text_signature ] = $_assigned[ $text_signature ];
  1171. } else {
  1172. // append empty array
  1173. $_comments[ $text_signature ] = array();
  1174. }
  1175. }
  1176. // if we have any pingbacks or trackbacks...
  1177. if ( isset( $_assigned[ 'PINGS_AND_TRACKS' ] ) ) {
  1178. // add them last
  1179. $_comments[ 'PINGS_AND_TRACKS' ] = $_assigned[ 'PINGS_AND_TRACKS' ];
  1180. } else {
  1181. // append empty array
  1182. $_comments[ 'PINGS_AND_TRACKS' ] = array();
  1183. }
  1184. }
  1185. //print_r( $_comments ); die();
  1186. // --<
  1187. return $_comments;
  1188. }
  1189. /**
  1190. * @description: filter comments to find comments for the current page of a multipage post
  1191. * @param array $comments array of comment objects
  1192. * @return array $filtered array of comments for the current page
  1193. * @todo:
  1194. *
  1195. */
  1196. function _multipage_comment_filter( $comments ) {
  1197. // access globals
  1198. global $post, $page, $multipage;
  1199. //print_r( $comments ); die();
  1200. // init return
  1201. $filtered = array();
  1202. // kick out if no comments
  1203. if( !is_array( $comments ) OR empty( $comments ) ) {
  1204. // --<
  1205. return $filtered;
  1206. }
  1207. // kick out if not multipage
  1208. if( !isset( $multipage ) OR !$multipage ) {
  1209. // --<
  1210. return $comments;
  1211. }
  1212. // now add only comments that are on this page or are page-level
  1213. foreach ( $comments AS $comment ) {
  1214. // if it has a text sig
  1215. if ( !is_null( $comment->comment_signature ) AND $comment->comment_signature != '' ) {
  1216. // set key
  1217. $key = '_cp_comment_page';
  1218. // does it have a comment meta value?
  1219. if ( get_comment_meta( $comment->comment_ID, $key, true ) != '' ) {
  1220. // get the page number
  1221. $page_num = get_comment_meta( $comment->comment_ID, $key, true );
  1222. // is it the current one?
  1223. if ( $page_num == $page ) {
  1224. // add it
  1225. $filtered[] = $comment;
  1226. }
  1227. }
  1228. } else {
  1229. // page-level comment: add it
  1230. $filtered[] = $comment;
  1231. }
  1232. }
  1233. // --<
  1234. return $filtered;
  1235. }
  1236. /**
  1237. * @description: filter comments by text signature
  1238. * @param array $comments array of comment objects
  1239. * @param array $text_signatures array of text signatures
  1240. * @param integer $confidence the confidence level of paragraph identity - default 90%
  1241. * @return array $assigned array with text signatures as keys and array of comments as values
  1242. * @todo:
  1243. *
  1244. */
  1245. function _assign_comments( $comments, $text_signatures, $confidence = 90 ) {
  1246. // init returned array
  1247. // NB: we use a very unlikely key for page-level comments: WHOLE_PAGE_OR_POST_COMMENTS
  1248. $assigned = array();
  1249. // kick out if no comments
  1250. if( !is_array( $comments ) OR empty( $comments ) ) {
  1251. // --<
  1252. return $assigned;
  1253. }
  1254. // kick out if no text_signatures
  1255. if( !is_array( $text_signatures ) OR empty( $text_signatures ) ) {
  1256. // --<
  1257. return $assigned;
  1258. }
  1259. /*
  1260. print_r( array(
  1261. 'comments' => $comments,
  1262. 'sigs' => $text_signatures
  1263. ) ); die();
  1264. */
  1265. // run through our comments...
  1266. foreach( $comments AS $comment ) {
  1267. // test for empty comment text signature
  1268. if ( !is_null( $comment->comment_signature ) AND $comment->comment_signature != '' ) {
  1269. // do we have an exact match in the text sigs array?
  1270. // NB: this will work, because we're already ensuring identical sigs are made unique
  1271. if ( in_array( $comment->comment_signature, $text_signatures ) ) {
  1272. // yes, assign to that key
  1273. $assigned[ $comment->comment_signature ][] = $comment;
  1274. } else {
  1275. // init possibles array
  1276. $possibles = array();
  1277. // find the nearest matching text signature
  1278. foreach( $text_signatures AS $text_signature ) {
  1279. // compare strings...
  1280. similar_text( $comment->comment_signature, $text_signature, $score );
  1281. //print_r( $score.'<br>' );
  1282. // add to possibles array if it passes
  1283. if( $score >= $confidence ) { $possibles[ $text_signature ] = $score; }
  1284. }
  1285. //die();
  1286. // did we get any?
  1287. if ( !empty( $possibles ) ) {
  1288. // sort them by score
  1289. arsort( $possibles );
  1290. //print_r( array_keys( $possibles ) ); die();
  1291. // let's use the sig with the highest score
  1292. $highest = array_pop( array_keys( $possibles ) );
  1293. // assign comment to that key
  1294. $assigned[ $highest ][] = $comment;
  1295. } else {
  1296. // set property in case we need it
  1297. $comment->orphan = true;
  1298. // clear text signature
  1299. $comment->comment_signature = '';
  1300. // is it a pingback or trackback?
  1301. if ( $comment->comment_type == 'trackback' OR $comment->comment_type == 'pingback' ) {
  1302. // we have one - assign to pings
  1303. $assigned[ 'PINGS_AND_TRACKS' ][] = $comment;
  1304. } else {
  1305. // we have comment with no text sig - assign to page
  1306. $assigned[ 'WHOLE_PAGE_OR_POST_COMMENTS' ][] = $comment;
  1307. }
  1308. }
  1309. }
  1310. } else {
  1311. // is it a pingback or trackback?
  1312. if ( $comment->comment_type == 'trackback' OR $comment->comment_type == 'pingback' ) {
  1313. // we have one - assign to pings
  1314. $assigned[ 'PINGS_AND_TRACKS' ][] = $comment;
  1315. } else {
  1316. // we have comment with no text sig - assign to page
  1317. $assigned[ 'WHOLE_PAGE_OR_POST_COMMENTS' ][] = $comment;
  1318. }
  1319. }
  1320. }
  1321. // let's have a look
  1322. //print_r( $assigned ); die();
  1323. // --<
  1324. return $assigned;
  1325. }
  1326. //##############################################################################
  1327. } // class ends
  1328. ?>