close

Plugin Directory

Changeset 3431360


Ignore:
Timestamp:
01/03/2026 12:12:34 AM (5 months ago)
Author:
xavivars
Message:

Overview, better preview, REST API bugfixes

Location:
xv-random-quotes/trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • xv-random-quotes/trunk/changelog.txt

    r3430809 r3431360  
    11== XV Random Quotes ==
     2
     3= 2.2.0 =
     4Bugfix: migration progress text shows correct migrated count
     5Bugfix: quote content key in REST API response
     6Bugfix: after_all/before_all wrappers not used on every quote
     7Improvement: Overview page added back
     8Improvement: Better quote title/preview in admin list
    29
    310= 2.1.0 =
  • xv-random-quotes/trunk/js/migration.js

    r3430809 r3431360  
    124124            const $text = $progressNotice.querySelector('.xv-migration-progress-text');
    125125            if ($text) {
    126                 $text.textContent = `Migrated ${result.migrated} of ${result.total} quotes (${percentage}%)`;
     126                $text.textContent = `Migrated ${result.offset} of ${result.total} quotes (${percentage}%)`;
    127127            }
    128128        }
  • xv-random-quotes/trunk/readme.txt

    r3430809 r3431360  
    66Tested up to: 6.9
    77Requires PHP: 7.4
    8 Stable tag: 2.1.0
     8Stable tag: 2.2.0
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
  • xv-random-quotes/trunk/src/Output/QuoteOutput.php

    r3430809 r3431360  
    4040        $this->quote_queries = new QuoteQueries();
    4141        $this->renderer = new QuoteRenderer();
     42    }
     43
     44    /**
     45     * Get renderer instance
     46     *
     47     * @return QuoteRenderer
     48     */
     49    public function get_renderer() {
     50        return $this->renderer;
    4251    }
    4352
  • xv-random-quotes/trunk/src/PostTypes/QuotePostType.php

    r3429335 r3431360  
    9393     */
    9494    public function add_custom_columns( $columns ) {
    95         // Insert source column after author (taxonomy)
     95        // Remove the default title column
     96        unset( $columns['title'] );
     97       
     98        // Insert custom quote column at the beginning (after checkbox)
    9699        $new_columns = array();
    97100        foreach ( $columns as $key => $value ) {
    98             $new_columns[ $key ] = $value;
     101            if ( 'cb' === $key ) {
     102                $new_columns[ $key ] = $value;
     103                $new_columns['quote_preview'] = __( 'Quote', 'xv-random-quotes' );
     104            } else {
     105                $new_columns[ $key ] = $value;
     106            }
     107           
     108            // Insert source column after author (taxonomy)
    99109            if ( 'taxonomy-quote_author' === $key ) {
    100110                $new_columns['quote_source'] = __( 'Quote Source', 'xv-random-quotes' );
     
    111121     */
    112122    public function render_custom_column( $column, $post_id ) {
     123        if ( 'quote_preview' === $column ) {
     124            $post = get_post( $post_id );
     125            $title = $post->post_title;
     126            $content = wp_strip_all_tags( $post->post_content );
     127           
     128            $edit_link = get_edit_post_link( $post_id );
     129           
     130            // Start the preview link
     131            echo '<a class="row-title" href="' . esc_url( $edit_link ) . '" style="display: flex; align-items: center; gap: 10px;">';
     132           
     133            // Show image if available (featured image or first image in content)
     134            if ( has_post_thumbnail( $post_id ) ) {
     135                $first_image = get_the_post_thumbnail( $post_id, array( 50, 50 ), array( 'style' => 'display: block; flex-shrink: 0;' ) );
     136                echo wp_kses_post( $first_image );
     137            } elseif ( $first_image = $this->get_first_image_from_content( $post->post_content ) ) {
     138                $first_image = preg_replace( '/(width|height)="\d*"\s*/i', '', $first_image );
     139                $first_image = str_replace( '<img', '<img style="width:50px;height:50px;object-fit:cover;flex-shrink:0;"', $first_image );
     140                echo wp_kses_post( $first_image );
     141            }
     142           
     143            // Show text (title or content excerpt)
     144            if ( ! empty( trim( $title ) ) ) {
     145                echo '<strong>' . esc_html( $title ) . '</strong>';
     146            } elseif ( ! empty( trim( $content ) ) ) {
     147                echo '<span>' . esc_html( wp_trim_words( $content, 10 ) ) . '</span>';
     148            } elseif ( $this->get_alt_text( $first_image ) ) {
     149                echo '<span>' . esc_html( $this->get_alt_text( $first_image ) ) . '</span>';
     150            } else {
     151                echo '<span>' . esc_html__( '(no content)', 'xv-random-quotes' ) . '</span>';
     152            }
     153           
     154            echo '</a>';
     155        }
     156       
    113157        if ( 'quote_source' === $column ) {
    114158            $source = get_post_meta( $post_id, '_quote_source', true );
     
    123167
    124168    /**
     169     * Get alt text from an image HTML string
     170     *
     171     * @param string $image_html Image HTML.
     172     * @return string|null Alt text or null if not found.
     173     */
     174    private function get_alt_text( $image_html ) {
     175        if ( preg_match( '/alt=["\']([^"\']*)["\']/', $image_html, $matches ) ) {
     176            return $matches[1];
     177        }
     178        return null;
     179    }
     180
     181    /**
    125182     * Make custom columns sortable
    126183     *
     
    156213        }
    157214    }
     215
     216    /**
     217     * Get the first image tag from post content
     218     *
     219     * @param string $content Post content.
     220     * @return string|null First image HTML or null if none found.
     221     */
     222    private function get_first_image_from_content( $content ) {
     223        preg_match( '/<img[^>]+>/i', $content, $matches );
     224        return ! empty( $matches ) ? $matches[0] : null;
     225    }
    158226}
  • xv-random-quotes/trunk/src/Rendering/LegacyRenderer.php

    r3430809 r3431360  
    8080        }
    8181
    82         // Wrap in outer container if not disabled
    83         if ( ! $disable_aspect ) {
     82        // Only wrap with before_all/after_all when rendering a single quote
     83        // For multiple quotes, these wrappers are applied in render_multiple_quotes()
     84        if ( ! $disable_aspect && ! $is_multi ) {
    8485            $output = wp_kses_post( $wrappers['before_all'] ) . $output . wp_kses_post( $wrappers['after_all'] );
    8586        }
     
    9495     * @return array Wrapper settings.
    9596     */
    96     private function get_wrappers( $disable_aspect ) {
     97    public function get_wrappers( $disable_aspect ) {
    9798        if ( $disable_aspect ) {
    9899            return array(
  • xv-random-quotes/trunk/src/Rendering/QuoteRenderer.php

    r3430809 r3431360  
    114114        $output .= '</ul>';
    115115
     116        // Wrap with before_all/after_all for legacy mode
     117        if ( ! $disable_aspect ) {
     118            $wrappers = $this->legacy_renderer->get_wrappers( $disable_aspect );
     119            $output = wp_kses_post( $wrappers['before_all'] ) . $output . wp_kses_post( $wrappers['after_all'] );
     120        }
     121
    116122        return $output;
    117123    }
  • xv-random-quotes/trunk/src/RestAPI/QuoteEndpoint.php

    r3430809 r3431360  
    9797        $contributor   = $request->get_param( 'contributor' );
    9898
    99         // Use QuoteOutput class
    100         $quote_output = new QuoteOutput();
    101         $html = $quote_output->get_random_quotes(
    102             array(
    103                 'categories'    => $categories,
    104                 'sequence'      => $sequence,
    105                 'multi'         => $multi,
    106                 'offset'        => 0,
    107                 'disableaspect' => $disableaspect,
    108                 'contributor'   => $contributor,
    109             )
    110         );
    111 
    112         // Check if we got any quotes
    113         if ( empty( $html ) ) {
    114             return new \WP_Error(
    115                 'no_quotes',
    116                 'No quotes found matching the criteria',
    117                 array( 'status' => 404 )
    118             );
    119         }
    120 
    121         // Get quote data for metadata
     99        // Get quotes first (before rendering)
    122100        $quote_queries = new QuoteQueries();
    123101       
     
    125103        $categories_array = ! empty( $categories ) ? explode( ',', $categories ) : array();
    126104       
    127         // Get quotes for metadata
     105        // Build query args
     106        $query_args = array(
     107            'posts_per_page' => $multi,
     108        );
     109       
     110        // Add ordering
     111        if ( $sequence ) {
     112            $query_args['orderby'] = 'date';
     113            $query_args['order'] = 'ASC';
     114        } else {
     115            $query_args['orderby'] = 'rand';
     116        }
     117       
     118        // Get quotes
    128119        if ( ! empty( $categories_array ) ) {
    129             $quotes = $quote_queries->get_quotes_by_categories(
    130                 $categories_array,
    131                 array(
    132                     'posts_per_page' => $multi,
    133                     'orderby'        => $sequence ? 'rand' : 'date',
    134                 )
    135             );
     120            $quotes = $quote_queries->get_quotes_by_categories( $categories_array, $query_args );
    136121        } else {
    137             $quotes = $quote_queries->get_all_quotes(
    138                 array(
    139                     'posts_per_page' => $multi,
    140                     'orderby'        => $sequence ? 'rand' : 'date',
    141                 )
    142             );
     122            $quotes = $quote_queries->get_all_quotes( $query_args );
    143123        }
    144124
     
    150130                array( 'status' => 500 )
    151131            );
     132        }
     133       
     134        // Check if we got any quotes
     135        if ( empty( $quotes ) ) {
     136            return new \WP_Error(
     137                'no_quotes',
     138                'No quotes found matching the criteria',
     139                array( 'status' => 404 )
     140            );
     141        }
     142
     143        // Render HTML from the same quotes we'll use for metadata
     144        $quote_output = new QuoteOutput();
     145        $renderer = $quote_output->get_renderer();
     146       
     147        if ( $multi > 1 ) {
     148            $html = $renderer->render_multiple_quotes( $quotes, $disableaspect );
     149        } else {
     150            $html = $renderer->render_quote( $quotes[0], false, $disableaspect );
    152151        }
    153152
     
    161160            $quote = $quotes[0];
    162161           
    163             $response_data['quote_id']   = $quote->ID;
    164             $response_data['quote_text'] = $quote->post_title;
     162            $response_data['quote_id']      = $quote->ID;
     163            $response_data['quote_text']    = wp_strip_all_tags( $quote->post_content );
     164            $response_data['quote_content'] = $quote->post_content;
    165165           
    166166            // Get author
     
    183183        } else {
    184184            // For multi-quote, provide basic metadata
    185             $response_data['quote_id']   = 0;
    186             $response_data['quote_text'] = '';
    187             $response_data['author']     = '';
    188             $response_data['source']     = '';
    189             $response_data['categories'] = array();
     185            $response_data['quote_id']      = 0;
     186            $response_data['quote_text']    = '';
     187            $response_data['quote_content'] = '';
     188            $response_data['author']        = '';
     189            $response_data['source']        = '';
     190            $response_data['categories']    = array();
    190191        }
    191192
  • xv-random-quotes/trunk/vendor/composer/installed.php

    r3429831 r3431360  
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => '1e7b2c70a5d3f77696f34428e28ff6df9eba2ecc',
     6        'reference' => '6458b7b024b57cfcfe7728209c7cc038570ed3c3',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1414            'pretty_version' => 'dev-main',
    1515            'version' => 'dev-main',
    16             'reference' => '1e7b2c70a5d3f77696f34428e28ff6df9eba2ecc',
     16            'reference' => '6458b7b024b57cfcfe7728209c7cc038570ed3c3',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
  • xv-random-quotes/trunk/xv-random-quotes.php

    r3430809 r3431360  
    55Author: Xavi Ivars
    66Author URI: https://xavi.ivars.me/
    7 Version: 2.1.0
     7Version: 2.2.0
    88Requires at least: 6.0
    99Requires PHP: 7.4
Note: See TracChangeset for help on using the changeset viewer.