WordPress.org

Make WordPress Core

Ticket #36824: 36824.10.diff

File 36824.10.diff, 14.9 KB (added by birgire, 13 months ago)
  • src/wp-includes/comment.php

    diff --git src/wp-includes/comment.php src/wp-includes/comment.php
    index 4c78eb9..ccf11fe 100644
    function discover_pingback_server_uri( $url, $deprecated = '' ) { 
    25732573 * Perform all pingbacks, enclosures, trackbacks, and send to pingback services.
    25742574 *
    25752575 * @since 2.1.0
    2576  *
    2577  * @global wpdb $wpdb WordPress database abstraction object.
    25782576 */
    25792577function do_all_pings() {
    2580         global $wpdb;
     2578        // Determine which classes support trackbacks and pingbacks.
     2579        $ping_types = get_post_types_by_support( 'trackbacks' );
     2580
     2581        // Do pingbacks.
     2582        $pings = get_posts(
     2583                array(
     2584                        'post_type'        => $ping_types,
     2585                        'suppress_filters' => false,
     2586                        'nopaging'         => true,
     2587                        'meta_value'       => '_pingme',
     2588                        'fields'           => 'ids',
     2589                )
     2590        );
    25812591
    2582         // Do pingbacks
    2583         while ( $ping = $wpdb->get_row( "SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1" ) ) {
    2584                 delete_metadata_by_mid( 'post', $ping->meta_id );
    2585                 pingback( $ping->post_content, $ping->ID );
     2592        foreach ( $pings as $ping ) {
     2593                delete_post_meta( $ping, '_pingme' );
     2594                pingback( null, $ping );
    25862595        }
    25872596
    2588         // Do Enclosures
    2589         while ( $enclosure = $wpdb->get_row( "SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1" ) ) {
    2590                 delete_metadata_by_mid( 'post', $enclosure->meta_id );
    2591                 do_enclose( $enclosure->post_content, $enclosure->ID );
     2597        // Do enclosures.
     2598        $enclosures = get_posts(
     2599                array(
     2600                        'post_type'        => get_post_types( array( 'publicly_queryable' => true ) ),
     2601                        'suppress_filters' => false,
     2602                        'nopaging'         => true,
     2603                        'meta_key'         => '_encloseme',
     2604                        'fields'           => 'ids',
     2605                )
     2606        );
     2607
     2608        foreach ( $enclosures as $enclosure ) {
     2609                delete_post_meta( $enclosure, '_encloseme' );
     2610                do_enclose( null, $enclosure );
    25922611        }
    25932612
    2594         // Do Trackbacks
    2595         $trackbacks = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'" );
    2596         if ( is_array( $trackbacks ) ) {
    2597                 foreach ( $trackbacks as $trackback ) {
    2598                         do_trackbacks( $trackback );
    2599                 }
     2613        // Do trackbacks.
     2614        $trackbacks = get_posts(
     2615                array(
     2616                        'post_type'        => $ping_types,
     2617                        'suppress_filters' => false,
     2618                        'nopaging'         => true,
     2619                        'meta_key'          => '_tbme',
     2620                        'fields'           => 'ids',
     2621                )
     2622        );
     2623
     2624        foreach ( $trackbacks as $trackback ) {
     2625                do_trackbacks( $trackback );
     2626                delete_post_meta( $trackback, '_tbme' );
    26002627        }
    26012628
    2602         //Do Update Services/Generic Pings
     2629        //Do Update Services/Generic Pings.
    26032630        generic_ping();
    26042631}
    26052632
  • src/wp-includes/functions.php

    diff --git src/wp-includes/functions.php src/wp-includes/functions.php
    index 60229ee..a592f75 100644
    function wp_extract_urls( $content ) { 
    562562 * pingbacks and trackbacks.
    563563 *
    564564 * @since 1.5.0
     565 * @since 4.9.7 `$post` can be a WP_Post object.
    565566 *
    566567 * @global wpdb $wpdb WordPress database abstraction object.
    567568 *
    568  * @param string $content Post Content.
    569  * @param int    $post_ID Post ID.
    570  */
    571 function do_enclose( $content, $post_ID ) {
     569 * @param string      $content Post Content. If empty will retrieve from post.
     570 * @param int|WP_Post $post    Post object or ID.
     571 * @return false|void False if no post found. Else void.
     572*/
     573function do_enclose( $content, $post ) {
    572574        global $wpdb;
    573575
     576        $post = get_post( $post );
     577        if ( ! $post ) {
     578                return false;
     579        }
     580
     581        if ( ! $content ) {
     582                $content = $post->post_content;
     583        }
     584
    574585        //TODO: Tidy this ghetto code up and make the debug code optional
    575586        include_once( ABSPATH . WPINC . '/class-IXR.php' );
    576587
    577588        $post_links = array();
    578589
    579         $pung = get_enclosed( $post_ID );
     590        $pung = get_enclosed( $post->ID );
    580591
    581592        $post_links_temp = wp_extract_urls( $content );
    582593
    583594        foreach ( $pung as $link_test ) {
    584595                if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post
    585                         $mids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $link_test ) . '%' ) );
     596                        $mids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $link_test ) . '%' ) );
    586597                        foreach ( $mids as $mid ) {
    587598                                delete_metadata_by_mid( 'post', $mid );
    588599                        }
    function do_enclose( $content, $post_ID ) { 
    591602
    592603        foreach ( (array) $post_links_temp as $link_test ) {
    593604                if ( ! in_array( $link_test, $pung ) ) { // If we haven't pung it already
    594                         $test = @parse_url( $link_test );
     605                        $test = wp_parse_url( $link_test );
    595606                        if ( false === $test ) {
    596607                                continue;
    597608                        }
    function do_enclose( $content, $post_ID ) { 
    612623         * @since 4.4.0
    613624         *
    614625         * @param array $post_links An array of enclosure links.
    615          * @param int   $post_ID    Post ID.
     626         * @param int   $post_id    Post ID.
    616627         */
    617         $post_links = apply_filters( 'enclosure_links', $post_links, $post_ID );
     628        $post_links = apply_filters( 'enclosure_links', $post_links, $post->ID );
    618629
    619630        foreach ( (array) $post_links as $url ) {
    620                 if ( $url != '' && ! $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post_ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
     631                if ( $url != '' && ! $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
    621632
    622633                        if ( $headers = wp_get_http_headers( $url ) ) {
    623634                                $len           = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
    function do_enclose( $content, $post_ID ) { 
    640651                                }
    641652
    642653                                if ( in_array( substr( $type, 0, strpos( $type, '/' ) ), $allowed_types ) ) {
    643                                         add_post_meta( $post_ID, 'enclosure', "$url\n$len\n$mime\n" );
     654                                        add_post_meta( $post->ID, 'enclosure', "$url\n$len\n$mime\n" );
    644655                                }
    645656                        }
    646657                }
  • src/wp-includes/post.php

    diff --git src/wp-includes/post.php src/wp-includes/post.php
    index 3ae08c1..9b91404 100644
    function _publish_post_hook( $post_id ) { 
    64066406        }
    64076407        add_post_meta( $post_id, '_encloseme', '1' );
    64086408
     6409        $to_ping = get_to_ping( $post_id );
     6410        if ( ! empty( $to_ping ) ) {
     6411                add_post_meta( $post_id, '_tbme', '1' );
     6412        }
     6413
    64096414        if ( ! wp_next_scheduled( 'do_pings' ) ) {
    64106415                wp_schedule_single_event( time(), 'do_pings' );
    64116416        }
  • new file tests/phpunit/tests/functions/doEnclose.php

    diff --git tests/phpunit/tests/functions/doEnclose.php tests/phpunit/tests/functions/doEnclose.php
    new file mode 100644
    index 0000000..60c77f2
    - +  
     1<?php
     2/**
     3 * Test cases for the `do_enclose()` function.
     4 *
     5 * @package WordPress\UnitTests
     6 *
     7 * @since 4.9.7
     8 */
     9
     10/**
     11 * Tests_Functions_DoEnclose class.
     12 *
     13 * @group functions.php
     14 * @covers do_enclose
     15 *
     16 * @since 4.9.7
     17 */
     18class Tests_Functions_DoEnclose extends WP_UnitTestCase {
     19
     20        /**
     21         * Setup before each test method.
     22         *
     23         * @since 4.9.7
     24         */
     25        public function setUp() {
     26                parent::setUp();
     27                add_filter( 'pre_http_request', array( $this, 'fake_http_request' ), 10, 3 );
     28        }
     29
     30        /**
     31         * Cleanup after each test method.
     32         *
     33         * @since 4.9.7
     34         */
     35        public function tearDown() {
     36                parent::tearDown();
     37                remove_filter( 'pre_http_request', array( $this, 'fake_http_request' ) );
     38        }
     39
     40        /**
     41         * Test the function with an explicit content input.
     42         *
     43         * @since 4.9.7
     44         *
     45         * @dataProvider data_test_do_enclose
     46         */
     47        public function test_function_with_explicit_content_input( $content, $expected ) {
     48                $post_id = self::factory()->post->create();
     49
     50                do_enclose( $content, $post_id );
     51
     52                $actual = $this->get_enclosed_by_post_id( $post_id );
     53                $this->assertSame( $expected, $actual );
     54        }
     55
     56        /**
     57         * Test the function with an implicit content input.
     58         *
     59         * @since 4.9.7
     60         *
     61         * @dataProvider data_test_do_enclose
     62         */
     63        public function test_function_with_implicit_content_input( $content, $expected ) {
     64                $post_id = self::factory()->post->create(
     65                        array(
     66                                'post_content' => $content,
     67                        )
     68                );
     69
     70                do_enclose( null, $post_id );
     71
     72                $actual = $this->get_enclosed_by_post_id( $post_id );
     73                $this->assertSame( $expected, $actual );
     74        }
     75
     76        /**
     77         * Dataprovider for `test_function_with_explicit_content_input()`
     78         * and `test_function_with_implicit_content_input()`.
     79         *
     80         * @since 4.9.7
     81         *
     82         * @return array {
     83         *     @type array {
     84         *         @type string Post content.
     85         *         @type string Expected values.
     86         *     }
     87         * }
     88         */
     89        public function data_test_do_enclose() {
     90                return array(
     91                        'null'                  => array(
     92                                'content'  => null,
     93                                'expected' => '',
     94                        ),
     95                        'empty'                 => array(
     96                                'content'  => '',
     97                                'expected' => '',
     98                        ),
     99                        'single-bare-movie'     => array(
     100                                'content'  => 'movie.mp4',
     101                                'expected' => '',
     102                        ),
     103                        'single-bare-audio'     => array(
     104                                'content'  => 'audio.ogg',
     105                                'expected' => '',
     106                        ),
     107                        'single-relative-movie' => array(
     108                                'content'  => '/movie.mp4',
     109                                'expected' => "/movie.mp4\n123\nvideo/mp4\n",
     110                        ),
     111                        'single-relative-audio' => array(
     112                                'content'  => '/audio.ogg',
     113                                'expected' => "/audio.ogg\n321\naudio/ogg\n",
     114                        ),
     115                        'single-unknown'        => array(
     116                                'content'  => 'https://example.com/wp-content/uploads/2018/06/file.unknown',
     117                                'expected' => '',
     118                        ),
     119                        'single-movie'          => array(
     120                                'content'  => 'https://example.com/wp-content/uploads/2018/06/movie.mp4',
     121                                'expected' => "https://example.com/wp-content/uploads/2018/06/movie.mp4\n123\nvideo/mp4\n",
     122                        ),
     123                        'single-audio'          => array(
     124                                'content'  => 'https://example.com/wp-content/uploads/2018/06/audio.ogg',
     125                                'expected' => "https://example.com/wp-content/uploads/2018/06/audio.ogg\n321\naudio/ogg\n",
     126                        ),
     127                        'single-movie-query'    => array(
     128                                'content'  => 'https://example.com/wp-content/uploads/2018/06/movie.mp4?test=1',
     129                                'expected' => "https://example.com/wp-content/uploads/2018/06/movie.mp4?test=1\n123\nvideo/mp4\n",
     130                        ),
     131                        'multi'                 => array(
     132                                'content'  => "https://example.com/wp-content/uploads/2018/06/audio.ogg\n" .
     133                                                          'https://example.com/wp-content/uploads/2018/06/movie.mp4',
     134                                'expected' => "https://example.com/wp-content/uploads/2018/06/audio.ogg\n321\naudio/ogg\n" .
     135                                                          "https://example.com/wp-content/uploads/2018/06/movie.mp4\n123\nvideo/mp4\n",
     136                        ),
     137                );
     138        }
     139
     140        /**
     141         * The function should return false when the post ID input is invalid.
     142         *
     143         * @since 4.9.7
     144         */
     145        public function test_function_should_return_false_when_invalid_post_id() {
     146                $post_id = null;
     147                $result  = do_enclose( null, $post_id );
     148                $this->assertFalse( $result );
     149        }
     150
     151        /**
     152         * The function should delete an enclosed link when it's no longer in the post content.
     153         *
     154         * @since 4.9.7
     155         */
     156        public function test_function_should_delete_enclosed_link_when_no_longer_in_post_content() {
     157                $data = $this->data_test_do_enclose();
     158
     159                // Create a post with a single movie link.
     160                $post_id = self::factory()->post->create(
     161                        array(
     162                                'post_content' => $data['single-movie']['content'],
     163                        )
     164                );
     165
     166                do_enclose( null, $post_id );
     167
     168                $actual = $this->get_enclosed_by_post_id( $post_id );
     169                $this->assertSame( $data['single-movie']['expected'], $actual );
     170
     171                // Replace the movie link with an audio link.
     172                wp_update_post(
     173                        array(
     174                                'ID'           => $post_id,
     175                                'post_content' => $data['single-audio']['content'],
     176                        )
     177                );
     178
     179                do_enclose( null, $post_id );
     180
     181                $actual = $this->get_enclosed_by_post_id( $post_id );
     182                $this->assertSame( $data['single-audio']['expected'], $actual );
     183        }
     184
     185        /**
     186         * The function should support a post object input.
     187         *
     188         * @since 4.9.7
     189         */
     190        public function test_function_should_support_post_object_input() {
     191                $data = $this->data_test_do_enclose();
     192
     193                $post_object = self::factory()->post->create_and_get(
     194                        array(
     195                                'post_content' => $data['multi']['content'],
     196                        )
     197                );
     198
     199                do_enclose( null, $post_object );
     200
     201                $actual = $this->get_enclosed_by_post_id( $post_object->ID );
     202                $this->assertSame( $data['multi']['expected'], $actual );
     203        }
     204
     205        /**
     206         * The enclosure links should be filterable with the `enclosure_links` filter.
     207         *
     208         * @since 4.9.7
     209         */
     210        public function test_function_enclosure_links_should_be_filterable() {
     211                $data = $this->data_test_do_enclose();
     212
     213                $post_id = self::factory()->post->create(
     214                        array(
     215                                'post_content' => $data['multi']['content'],
     216                        )
     217                );
     218
     219                add_filter( 'enclosure_links', array( $this, 'filter_enclosure_links' ), 10, 2 );
     220                do_enclose( null, $post_id );
     221                remove_filter( 'enclosure_links', array( $this, 'filter_enclosure_links' ) );
     222
     223                $actual   = $this->get_enclosed_by_post_id( $post_id );
     224                $expected = str_replace( 'example.org', sprintf( 'example-%d.org', $post_id ), $data['multi']['expected'] );
     225                $this->assertSame( $expected, $actual );
     226        }
     227
     228        /**
     229         * A callback to filter the list of enclosure links.
     230         *
     231         * @since 4.9.7
     232         *
     233         * @param  array $post_links An array of enclosure links.
     234         * @param  int   $post_id    Post ID.
     235         * @return array $post_links An array of enclosure links.
     236         */
     237        public function filter_enclosure_links( $enclosure_links, $post_id ) {
     238                // Replace the link host to contain the post ID, to test both filter input arguments.
     239                foreach ( $enclosure_links as &$link ) {
     240                        $link = str_replace( 'example.org', sprintf( 'example-%d.org', $post_id ), $link );
     241                }
     242                return $enclosure_links;
     243        }
     244
     245        /**
     246         * Helper function to get all enclosure data for a given post.
     247         *
     248         * @since 4.9.7
     249         *
     250         * @param  int    $post_id Post ID.
     251         * @return string          All enclosure data for the given post.
     252         */
     253        protected function get_enclosed_by_post_id( $post_id ) {
     254                return join( (array) get_post_meta( $post_id, 'enclosure', false ), '' );
     255        }
     256
     257        /**
     258         * Fake the HTTP request response.
     259         *
     260         * @since 4.9.7
     261         *
     262         * @param bool   $false     False.
     263         * @param array  $arguments Request arguments.
     264         * @param string $url       Request URL.
     265         *
     266         * @return array            Header.
     267         */
     268        public function fake_http_request( $false, $arguments, $url ) {
     269
     270                // Video and audio headers.
     271                $fake_headers = array(
     272                        'mp4' => array(
     273                                'headers' => array(
     274                                        'content-length' => 123,
     275                                        'content-type'   => 'video/mp4',
     276                                ),
     277                        ),
     278                        'ogg' => array(
     279                                'headers' => array(
     280                                        'content-length' => 321,
     281                                        'content-type'   => 'audio/ogg',
     282                                ),
     283                        ),
     284                );
     285
     286                $path = parse_url( $url, PHP_URL_PATH );
     287
     288                if ( false !== $path ) {
     289                        $extension = pathinfo( $path, PATHINFO_EXTENSION );
     290                        if ( isset( $fake_headers[ $extension ] ) ) {
     291                                return $fake_headers[ $extension ];
     292                        }
     293                }
     294
     295                // Fallback header.
     296                return array(
     297                        'headers' => array(
     298                                'content-length' => 0,
     299                                'content-type'   => '',
     300                        ),
     301                );
     302        }
     303
     304}