Make WordPress Core

Changeset 23804


Ignore:
Timestamp:
03/27/2013 08:31:12 AM (11 years ago)
Author:
markjaquith
Message:

Extract chats as structured data.

  • add_chat_detection_format() — to add a chat regex pattern
  • get_content_chat() — to grab a chat from content
  • get_the_chat() — grab the chat from the current (or passed) post
  • the_chat() — output the chat in formatted HTML
  • paginate_content() — puts the <!--nextpage--> splitting stuff into a function
  • get_paged_content() — grabs a page of raw content, needed to paginate chats properly

see #23625. props wonderboymusic, lancewillett.

Location:
trunk/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/post-formats.php

    r23789 r23804  
    393393
    394394/**
     395 * Add chat detection support to the `get_content_chat()` chat parser
     396 *
     397 * @since 3.6.0
     398 *
     399 * @global array $_wp_chat_parsers
     400 * @param string $name Unique identifier for chat format. Example: IRC
     401 * @param string $newline_regex RegEx to match the start of a new line, typically when a new "username:" appears
     402 *  The parser will handle up to 3 matched expressions
     403 *  $matches[0] = the string before the user's message starts
     404 *  $matches[1] = the time of the message, if present
     405 *  $matches[2] = the author/username
     406 *  OR
     407 *  $matches[0] = the string before the user's message starts
     408 *  $matches[1] = the author/username
     409 * @param string $delimiter_regex RegEx to determine where to split the username syntax from the chat message
     410 */
     411function add_chat_detection_format( $name, $newline_regex, $delimiter_regex ) {
     412    global $_wp_chat_parsers;
     413
     414    if ( empty( $_wp_chat_parsers ) )
     415        $_wp_chat_parsers = array();
     416
     417    $_wp_chat_parsers = array( $name => array( $newline_regex, $delimiter_regex ) ) + $_wp_chat_parsers;
     418}
     419add_chat_detection_format( 'IM', '#^([^:]+):#', '#[:]#' );
     420add_chat_detection_format( 'Skype', '#^(\[.+?\])\s([^:]+):#', '#[:]#' );
     421
     422/**
     423 * Deliberately interpret passed content as a chat transcript that is optionally
     424 * followed by commentary
     425 *
     426 * If the content does not contain username syntax, assume that it does not contain
     427 * chat logs and return
     428 *
     429 * @since 3.6.0
     430 *
     431 * Example:
     432 *
     433 * One stanza of chat:
     434 * Scott: Hey, let's chat!
     435 * Helen: No.
     436 *
     437 * $stanzas = array(
     438 *     array(
     439 *         array(
     440 *             'time' => '',
     441 *             'author' => 'Scott',
     442 *             'messsage' => "Hey, let's chat!"
     443 *         ),
     444 *         array(
     445 *             'time' => '',
     446 *             'author' => 'Helen',
     447 *             'message' => 'No.'
     448 *         )
     449 *     )
     450 * )
     451 * @param string $content A string which might contain chat data.
     452 * @param boolean $remove Whether to remove the found data from the passed content.
     453 * @return array A chat log as structured data
     454 */
     455function get_content_chat( &$content, $remove = false ) {
     456    global $_wp_chat_parsers;
     457
     458    $trimmed = trim( $content );
     459    if ( empty( $trimmed ) )
     460        return array();
     461
     462    $has_match = false;
     463    $matched_parser = false;
     464    foreach ( $_wp_chat_parsers as $parser ) {
     465        @list( $newline_regex ) = $parser;
     466        if ( preg_match( $newline_regex, $trimmed ) ) {
     467            $has_match = true;
     468            $matched_parser = $parser;
     469            break;
     470        }
     471    }
     472
     473    if ( false === $matched_parser )
     474        return array();
     475
     476    @list( $newline_regex, $delimiter_regex ) = $parser;
     477
     478    $last_index = 0;
     479    $stanzas = array();
     480    $lines = explode( "\n", make_clickable( $trimmed ) );
     481
     482    $author = $time = '';
     483    $data = array();
     484    $stanza = array();
     485
     486    foreach ( $lines as $index => $line ) {
     487        $line = trim( $line );
     488
     489        if ( empty( $line ) ) {
     490            if ( ! empty( $author ) ) {
     491                $stanza[] = array(
     492                    'time' => $time,
     493                    'author' => $author,
     494                    'message' => join( ' ', $data )
     495                );
     496            }
     497
     498            $stanzas[] = $stanza;
     499            $last_index = $index;
     500            $stanza = array();
     501            $author = $time = '';
     502            $data = array();
     503            if ( ! empty( $lines[$index + 1] ) && ! preg_match( $delimiter_regex, $lines[$index + 1] ) )
     504                break;
     505        }
     506
     507        $matches = array();
     508        $matched = preg_match( $newline_regex, $line, $matches );
     509        $author_match = empty( $matches[2] ) ? $matches[1] : $matches[2];
     510        // assume username syntax if no whitespace is present
     511        $no_ws = $matched && ! preg_match( '#\s#', $author_match );
     512        // allow script-like stanzas
     513        $has_ws = $matched && preg_match( '#\s#', $author_match ) && empty( $lines[$index + 1] ) && empty( $lines[$index - 1] );
     514        if ( $matched && ( ! empty( $matches[2] ) || ( $no_ws || $has_ws ) ) ) {
     515            if ( ! empty( $author ) ) {
     516                $stanza[] = array(
     517                    'time' => $time,
     518                    'author' => $author,
     519                    'message' => join( ' ', $data )
     520                );
     521                $data = array();
     522            }
     523
     524            $time = empty( $matches[2] ) ? '' : $matches[1];
     525            $author = $author_match;
     526            $data[] = trim( str_replace( $matches[0], '', $line ) );
     527        } elseif ( preg_match( '#\S#', $line ) ) {
     528            $data[] = $line;
     529        }
     530    }
     531
     532    if ( ! empty( $author ) ) {
     533        $stanza[] = array(
     534            'time' => $time,
     535            'author' => $author,
     536            'message' => trim( join( ' ', $data ) )
     537        );
     538    }
     539
     540    if ( ! empty( $stanza ) )
     541        $stanzas[] = $stanza;
     542
     543    if ( $remove )
     544        $content = trim( join( "\n", array_slice( $lines, $last_index ) ) );
     545
     546    return $stanzas;
     547}
     548
     549/**
     550 * Retrieve structured chat data from the current or passed post
     551 *
     552 * @since 3.6.0
     553 *
     554 * @param int $id Optional. Post ID
     555 * @return array
     556 */
     557function get_the_chat( $id = 0 ) {
     558    $post = empty( $id ) ? clone get_post() : get_post( $id );
     559    if ( empty( $post ) )
     560        return array();
     561
     562    $data = get_content_chat( get_paged_content( $post->post_content ) );
     563    if ( empty( $data ) )
     564        return array();
     565
     566    return $data;
     567}
     568
     569/**
     570 * Output HTML for a given chat's structured data. Themes can use this as a
     571 * template tag in place of the_content() for Chat post format templates.
     572 *
     573 * @since 3.6.0
     574 *
     575 * @uses get_the_chat()
     576 *
     577 * @print HTML
     578 */
     579function the_chat() {
     580    $output = '<dl class="chat-transcript">';
     581
     582    $stanzas = get_the_chat();
     583
     584    foreach ( $stanzas as $stanza ) {
     585        foreach ( $stanza as $row ) {
     586            $time = '';
     587            if ( ! empty( $row['time'] ) )
     588                $time = sprintf( '<time>%s</time>', esc_html( $row['time'] ) );
     589
     590            $output .= sprintf(
     591                '<dt class="chat-author chat-author-%1$s vcard">%2$s <cite class="fn">%3$s</cite>: </dt>
     592                    <dd class="chat-text">%4$s</dd>
     593                ',
     594                esc_attr( strtolower( $row['author'] ) ), // Slug.
     595                $time,
     596                esc_html( $row['author'] ),
     597                esc_html( $row['message'] )
     598            );
     599        }
     600    }
     601
     602    $output .= '</dl><!-- .chat-transcript -->';
     603
     604    echo $output;
     605}
     606
     607/**
    395608 * Extract a URL from passed content, if possible
    396609 * Checks for a URL on the first line of the content or the first encountered href attribute.
  • trunk/wp-includes/query.php

    r23554 r23804  
    36223622    endif;
    36233623}
     3624/**
     3625 * Split the passed content by <!--nextpage-->
     3626 *
     3627 * @since 3.6.0
     3628 *
     3629 * @param string $content Content to split
     3630 * @return array Paged content
     3631 */
     3632function paginate_content( $content ) {
     3633    $content = str_replace( "\n<!--nextpage-->\n", '<!--nextpage-->', $content );
     3634    $content = str_replace( "\n<!--nextpage-->", '<!--nextpage-->', $content );
     3635    $content = str_replace( "<!--nextpage-->\n", '<!--nextpage-->', $content );
     3636    return explode( '<!--nextpage-->', $content);
     3637}
     3638
     3639/**
     3640 * Return content offset by $page
     3641 *
     3642 * @since 3.6.0
     3643 *
     3644 * @param string $content
     3645 * @return string
     3646 */
     3647function get_paged_content( $content = null, $paged = null ) {
     3648    global $page;
     3649    if ( empty( $page ) )
     3650        $page = 1;
     3651
     3652    if ( empty( $paged ) )
     3653        $paged = $page;
     3654
     3655    if ( empty( $content ) ) {
     3656        $post = get_post();
     3657        if ( empty( $post ) )
     3658            return;
     3659
     3660        $content = $post->post_content;
     3661    }
     3662
     3663    $pages = paginate_content( $content );
     3664    if ( isset( $pages[$paged - 1] ) )
     3665        return $pages[$paged - 1];
     3666
     3667    return reset( $pages );
     3668}
    36243669
    36253670/**
Note: See TracChangeset for help on using the changeset viewer.