Plugin Directory

Changeset 3482605


Ignore:
Timestamp:
03/14/2026 03:33:55 PM (2 weeks ago)
Author:
lastsplash
Message:

Update to version 1.0.5 from GitHub

Location:
mode7-game-log
Files:
28 edited
1 copied

Legend:

Unmodified
Added
Removed
  • mode7-game-log/tags/1.0.5/assets/css/admin.css

    r3406333 r3482605  
    3939/* Game Filters */
    4040.game-filters {
     41    display: flex;
    4142    background: #f1f1f1;
    4243    border-radius: 4px;
     44    gap: 10px;
     45}
     46
     47.game-filters input[type="text"] {
     48    min-width: 200px;
    4349}
    4450
    4551/* Game Log List */
     52
     53.game-log-list {
     54    margin-block-start: 10px;
     55}
    4656
    4757.game-log-list th {
     
    5666/* Game Search Modal */
    5767
     68#game-search-modal::backdrop {
     69    -webkit-backdrop-filter: blur(4px);
     70    backdrop-filter: blur(4px);
     71    background: rgba(0, 0, 0, 0.25);
     72}
     73
    5874.game-search-modal {
    59     display: flex;
    60     align-items: center;
    61     justify-content: center;
     75    background-color: #fff;
    6276    border-color: #eee;
    6377    border-radius: 4px;
    6478    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    65     padding: 0;
    66     margin: 0;
    67     background-color: #fff;
    6879    margin: auto;
    6980    padding: 0;
     
    104115    max-height: 60vh;
    105116    overflow-y: auto;
     117}
     118
     119.game-search-modal-notice {
     120    display: none;
     121    margin-bottom: 15px;
     122}
     123
     124.game-search-modal-notice.notice-error,
     125.game-search-modal-notice.notice-success {
     126    display: block;
     127}
     128
     129.game-search-modal-notice.notice-success {
     130    border-left-color: #00a32a;
    106131}
    107132
     
    381406}
    382407
     408ul.page-numbers {
     409    display: flex;
     410    gap: 10px
     411}
     412
     413.page-numbers .current {
     414    display: inline-block;
     415    text-decoration: none;
     416    font-size: 13px;
     417    line-height: 2.15384615;
     418    min-height: 30px;
     419    margin: 0;
     420    padding: 0 10px;
     421    cursor: pointer;
     422    border-width: 1px;
     423    border-style: solid;
     424    -webkit-appearance: none;
     425    border-radius: 3px;
     426    white-space: nowrap;
     427    box-sizing: border-box;
     428}
     429
    383430/* Responsive Design */
    384431@media (max-width: 768px) {
     
    403450        flex-direction: column;
    404451    }
    405 }
     452    .game-filters {
     453        flex-direction: column;
     454    }
     455
     456    .game-filters input[type="text"], .game-filters select, .game-search-form input {
     457        min-width: 100%;
     458    }
     459}
     460
     461@media (max-width: 782px) {
     462    .page-numbers .current {
     463        padding: 0 14px;
     464        line-height: 2.71428571;
     465        font-size: 14px;
     466    }
     467}
  • mode7-game-log/tags/1.0.5/assets/js/admin.js

    r3406333 r3482605  
    3939                const modal = document.getElementById('game-search-modal');
    4040                if (modal) {
    41                     modal.style.display = 'block';
     41                    modal.showModal();
    4242                }
    4343                if (searchInput) {
     
    8383        function closeModal() {
    8484            if (modal) {
    85                 modal.style.display = 'none';
     85                modal.close();
    8686            }
    8787            const searchInput = document.getElementById('game-search-input');
     
    369369                }
    370370               
    371                 // Show success message
    372                 showNotice('success', gameLogAjax.strings.gameAdded);
    373                
    374                 // Refresh the page after a short delay to show the success state
    375                 setTimeout(function() {
    376                     window.location.reload();
    377                 }, 1500);
     371                // Show success message in modal or on page
     372                if (button.closest('#game-search-modal')) {
     373                    showNoticeInModal(gameLogAjax.strings.gameAdded, 'success');
     374                    // Redirect to default games list so the new game appears in the list
     375                    setTimeout(function() {
     376                        window.location.href = gameLogAjax.gamesListUrl;
     377                    }, 1500);
     378                } else {
     379                    showNotice('success', gameLogAjax.strings.gameAdded);
     380                    setTimeout(function() {
     381                        window.location.reload();
     382                    }, 1500);
     383                }
    378384            } else {
    379385                button.disabled = false;
    380386                button.textContent = 'Add Game';
    381                 showNotice('error', data.data.message || gameLogAjax.strings.error);
     387                const msg = data.data && data.data.message ? data.data.message : gameLogAjax.strings.error;
     388                if (button.closest('#game-search-modal')) {
     389                    showNoticeInModal(msg);
     390                } else {
     391                    showNotice('error', msg);
     392                }
    382393            }
    383394        })
     
    386397            button.disabled = false;
    387398            button.textContent = 'Add Game';
    388             showNotice('error', gameLogAjax.strings.error);
    389         });
     399            const msg = gameLogAjax.strings.error;
     400            if (button.closest('#game-search-modal')) {
     401                showNoticeInModal(msg);
     402            } else {
     403                showNotice('error', msg);
     404            }
     405        });
     406    }
     407
     408    /**
     409     * Show notice inside the game search modal
     410     * @param {string} message - Message text
     411     * @param {string} type - 'success' or 'error' (default 'error')
     412     */
     413    function showNoticeInModal(message, type) {
     414        const container = document.getElementById('game-search-modal-notice');
     415        if (!container) return;
     416        type = type || 'error';
     417        const noticeClass = type === 'success' ? 'notice-success' : 'notice-error';
     418        container.innerHTML = '<p>' + message + '</p>';
     419        container.className = 'game-search-modal-notice notice ' + noticeClass + ' is-dismissible';
     420        container.style.display = '';
     421
     422        setTimeout(function() {
     423            container.style.opacity = '0';
     424            container.style.transition = 'opacity 0.5s ease-out';
     425            setTimeout(function() {
     426                container.innerHTML = '';
     427                container.className = 'game-search-modal-notice';
     428                container.style.display = 'none';
     429                container.style.opacity = '';
     430            }, 500);
     431        }, 5000);
    390432    }
    391433   
  • mode7-game-log/tags/1.0.5/includes/class-game-log-admin.php

    r3406333 r3482605  
    1010 * @since 1.0.0
    1111 */
     12
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1217
    1318/**
     
    258263           
    259264            <!-- Game Search Modal -->
    260             <dialog id="game-search-modal" class="game-search-modal" style="display: none;">
     265            <dialog id="game-search-modal" class="game-search-modal">
    261266
    262267                    <div class="game-search-modal-header">
     
    265270                    </div>
    266271                    <div class="game-search-modal-body">
     272                        <div id="game-search-modal-notice" class="game-search-modal-notice" role="alert" aria-live="polite"></div>
    267273                        <p><?php esc_html_e( 'Search the Internet Gaming Database for to add a game to your log.', 'mode7-game-log' ); ?></p>   
    268274                        <div class="game-search-form">
     
    340346        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    341347        $current_status = isset( $_GET['game_status'] ) ? sanitize_text_field( wp_unslash( $_GET['game_status'] ) ) : '';
     348        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     349        $current_search = isset( $_GET['s'] ) && is_string( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
    342350
    343351        ?>
    344352        <form method="get" class="game-filters">
    345353            <input type="hidden" name="page" value="mode7-game-log" />
     354            <label for="game-log-search-input" class="screen-reader-text"><?php esc_html_e( 'Search games', 'mode7-game-log' ); ?></label>
     355            <input type="text" name="s" id="game-log-search-input" value="<?php echo esc_attr( $current_search ); ?>" placeholder="<?php esc_attr_e( 'Search by title…', 'mode7-game-log' ); ?>" class="regular-text" />
    346356            <select name="game_status" id="game_status_filter">
    347357                <option value=""><?php esc_html_e( 'All Statuses', 'mode7-game-log' ); ?></option>
     
    361371     */
    362372    private function display_games_list(): void {
     373        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only pagination, no data modification
     374        $current_page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1;
     375        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     376        $current_status = isset( $_GET['game_status'] ) && is_string( $_GET['game_status'] ) ? sanitize_text_field( wp_unslash( $_GET['game_status'] ) ) : '';
     377        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     378        $current_search = isset( $_GET['s'] ) && is_string( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
     379
    363380        $args = array(
    364381            'post_type'      => 'game',
    365382            'post_status'    => 'publish',
    366383            'posts_per_page' => 20,
    367             'paged'          => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
    368         );
     384            'paged'          => $current_page,
     385        );
     386
     387        if ( ! empty( $current_search ) ) {
     388            $args['s'] = $current_search;
     389        }
    369390
    370391        // Add status filter if selected.
    371         // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    372         if ( isset( $_GET['game_status'] ) && ! empty( $_GET['game_status'] ) ) {
     392        if ( ! empty( $current_status ) ) {
    373393            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for filtering games by status
    374394            $args['tax_query'] = array(
     
    376396                    'taxonomy' => 'game_status',
    377397                    'field'    => 'slug',
    378                     // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    379                     'terms'    => sanitize_text_field( wp_unslash( $_GET['game_status'] ) ),
     398                    'terms'    => $current_status,
    380399                ),
    381400            );
     
    465484            <?php
    466485            // Pagination.
     486            $base = add_query_arg( 'page', 'mode7-game-log', admin_url( 'admin.php' ) );
     487            if ( ! empty( $current_status ) ) {
     488                $base = add_query_arg( 'game_status', $current_status, $base );
     489            }
     490            if ( ! empty( $current_search ) ) {
     491                $base = add_query_arg( 's', $current_search, $base );
     492            }
    467493            $pagination_args = array(
    468494                'total'        => $games->max_num_pages,
    469                 'current'      => max( 1, get_query_var( 'paged' ) ),
    470                 'format'       => '?paged=%#%',
     495                'current'      => $current_page,
     496                'base'         => $base . '&paged=%#%',
     497                'format'       => '',
    471498                'show_all'     => false,
    472499                'type'         => 'list',
     
    480507            );
    481508
     509            $pagination_links = paginate_links( $pagination_args );
     510            if ( $pagination_links ) {
     511                $pagination_links = str_replace( ' class="next page-numbers"', ' class="button next page-numbers"', $pagination_links );
     512                $pagination_links = str_replace( ' class="prev page-numbers"', ' class="button prev page-numbers"', $pagination_links );
     513                $pagination_links = str_replace( '<a class="page-numbers"', '<a class="button page-numbers"', $pagination_links );
     514            }
    482515            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    483             echo paginate_links( $pagination_args );
     516            echo $pagination_links;
    484517            ?>
    485518
     
    487520        } else {
    488521            ?>
    489             <p><?php esc_html_e( 'No games found.', 'mode7-game-log' ); ?></p>
     522            <p><?php echo ! empty( $current_search ) ? esc_html__( 'No games match your search.', 'mode7-game-log' ) : esc_html__( 'No games found.', 'mode7-game-log' ); ?></p>
    490523            <?php
    491524        }
  • mode7-game-log/tags/1.0.5/includes/class-game-log-ajax-handler.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-default-page.php

    r3406333 r3482605  
    1111 */
    1212
    13 declare(strict_types=1);
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1417
    1518/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-igdb-api.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-meta-fields.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-patterns.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-post-type.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-stats-block.php

    r3406333 r3482605  
    1111 */
    1212
    13 declare(strict_types=1);
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1417
    1518/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log-taxonomy.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/tags/1.0.5/includes/class-game-log.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
     
    6770            'gameLogAjax',
    6871            array(
    69                 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    70                 'nonce'   => wp_create_nonce( 'game_log_nonce' ),
     72                'ajaxUrl'       => admin_url( 'admin-ajax.php' ),
     73                'gamesListUrl'  => add_query_arg( 'page', 'mode7-game-log', admin_url( 'admin.php' ) ),
     74                'nonce'         => wp_create_nonce( 'game_log_nonce' ),
    7175                'strings' => array(
    7276                    'searching'  => __( 'Searching...', 'mode7-game-log' ),
  • mode7-game-log/tags/1.0.5/mode7-game-log.php

    r3406333 r3482605  
    44 * Plugin URI: https://www.bobmatyas.com
    55 * Description: A WordPress plugin to track video games you've played, are playing, or want to play using IGDB.com database.
    6  * Version: 1.0.4
     6 * Version: 1.0.5
    77 * Author: Bob Matyas
    88 * License: GPL v2 or later
     
    1818
    1919// Define plugin constants.
    20 define( 'GAME_LOG_VERSION', '1.0.4' );
     20define( 'GAME_LOG_VERSION', '1.0.5' );
    2121define( 'GAME_LOG_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    2222define( 'GAME_LOG_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
  • mode7-game-log/tags/1.0.5/readme.txt

    r3406333 r3482605  
    55Tested up to: 6.9
    66Requires PHP: 8.2
    7 Stable tag: 1.0.4
     7Stable tag: 1.0.5
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    9191== Changelog ==
    9292
     93= 1.0.5 =
     94
     95* Fix pagination.
     96* Move error notice to inside modal.
     97* Add modal backdrop.
     98* Add search filter.
     99* Add direct file access check.
     100* Refresh admin page when adding game.
     101* Update mobile and pagination styles.
     102
    93103= 1.0.4 =
    94104
  • mode7-game-log/trunk/assets/css/admin.css

    r3406333 r3482605  
    3939/* Game Filters */
    4040.game-filters {
     41    display: flex;
    4142    background: #f1f1f1;
    4243    border-radius: 4px;
     44    gap: 10px;
     45}
     46
     47.game-filters input[type="text"] {
     48    min-width: 200px;
    4349}
    4450
    4551/* Game Log List */
     52
     53.game-log-list {
     54    margin-block-start: 10px;
     55}
    4656
    4757.game-log-list th {
     
    5666/* Game Search Modal */
    5767
     68#game-search-modal::backdrop {
     69    -webkit-backdrop-filter: blur(4px);
     70    backdrop-filter: blur(4px);
     71    background: rgba(0, 0, 0, 0.25);
     72}
     73
    5874.game-search-modal {
    59     display: flex;
    60     align-items: center;
    61     justify-content: center;
     75    background-color: #fff;
    6276    border-color: #eee;
    6377    border-radius: 4px;
    6478    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
    65     padding: 0;
    66     margin: 0;
    67     background-color: #fff;
    6879    margin: auto;
    6980    padding: 0;
     
    104115    max-height: 60vh;
    105116    overflow-y: auto;
     117}
     118
     119.game-search-modal-notice {
     120    display: none;
     121    margin-bottom: 15px;
     122}
     123
     124.game-search-modal-notice.notice-error,
     125.game-search-modal-notice.notice-success {
     126    display: block;
     127}
     128
     129.game-search-modal-notice.notice-success {
     130    border-left-color: #00a32a;
    106131}
    107132
     
    381406}
    382407
     408ul.page-numbers {
     409    display: flex;
     410    gap: 10px
     411}
     412
     413.page-numbers .current {
     414    display: inline-block;
     415    text-decoration: none;
     416    font-size: 13px;
     417    line-height: 2.15384615;
     418    min-height: 30px;
     419    margin: 0;
     420    padding: 0 10px;
     421    cursor: pointer;
     422    border-width: 1px;
     423    border-style: solid;
     424    -webkit-appearance: none;
     425    border-radius: 3px;
     426    white-space: nowrap;
     427    box-sizing: border-box;
     428}
     429
    383430/* Responsive Design */
    384431@media (max-width: 768px) {
     
    403450        flex-direction: column;
    404451    }
    405 }
     452    .game-filters {
     453        flex-direction: column;
     454    }
     455
     456    .game-filters input[type="text"], .game-filters select, .game-search-form input {
     457        min-width: 100%;
     458    }
     459}
     460
     461@media (max-width: 782px) {
     462    .page-numbers .current {
     463        padding: 0 14px;
     464        line-height: 2.71428571;
     465        font-size: 14px;
     466    }
     467}
  • mode7-game-log/trunk/assets/js/admin.js

    r3406333 r3482605  
    3939                const modal = document.getElementById('game-search-modal');
    4040                if (modal) {
    41                     modal.style.display = 'block';
     41                    modal.showModal();
    4242                }
    4343                if (searchInput) {
     
    8383        function closeModal() {
    8484            if (modal) {
    85                 modal.style.display = 'none';
     85                modal.close();
    8686            }
    8787            const searchInput = document.getElementById('game-search-input');
     
    369369                }
    370370               
    371                 // Show success message
    372                 showNotice('success', gameLogAjax.strings.gameAdded);
    373                
    374                 // Refresh the page after a short delay to show the success state
    375                 setTimeout(function() {
    376                     window.location.reload();
    377                 }, 1500);
     371                // Show success message in modal or on page
     372                if (button.closest('#game-search-modal')) {
     373                    showNoticeInModal(gameLogAjax.strings.gameAdded, 'success');
     374                    // Redirect to default games list so the new game appears in the list
     375                    setTimeout(function() {
     376                        window.location.href = gameLogAjax.gamesListUrl;
     377                    }, 1500);
     378                } else {
     379                    showNotice('success', gameLogAjax.strings.gameAdded);
     380                    setTimeout(function() {
     381                        window.location.reload();
     382                    }, 1500);
     383                }
    378384            } else {
    379385                button.disabled = false;
    380386                button.textContent = 'Add Game';
    381                 showNotice('error', data.data.message || gameLogAjax.strings.error);
     387                const msg = data.data && data.data.message ? data.data.message : gameLogAjax.strings.error;
     388                if (button.closest('#game-search-modal')) {
     389                    showNoticeInModal(msg);
     390                } else {
     391                    showNotice('error', msg);
     392                }
    382393            }
    383394        })
     
    386397            button.disabled = false;
    387398            button.textContent = 'Add Game';
    388             showNotice('error', gameLogAjax.strings.error);
    389         });
     399            const msg = gameLogAjax.strings.error;
     400            if (button.closest('#game-search-modal')) {
     401                showNoticeInModal(msg);
     402            } else {
     403                showNotice('error', msg);
     404            }
     405        });
     406    }
     407
     408    /**
     409     * Show notice inside the game search modal
     410     * @param {string} message - Message text
     411     * @param {string} type - 'success' or 'error' (default 'error')
     412     */
     413    function showNoticeInModal(message, type) {
     414        const container = document.getElementById('game-search-modal-notice');
     415        if (!container) return;
     416        type = type || 'error';
     417        const noticeClass = type === 'success' ? 'notice-success' : 'notice-error';
     418        container.innerHTML = '<p>' + message + '</p>';
     419        container.className = 'game-search-modal-notice notice ' + noticeClass + ' is-dismissible';
     420        container.style.display = '';
     421
     422        setTimeout(function() {
     423            container.style.opacity = '0';
     424            container.style.transition = 'opacity 0.5s ease-out';
     425            setTimeout(function() {
     426                container.innerHTML = '';
     427                container.className = 'game-search-modal-notice';
     428                container.style.display = 'none';
     429                container.style.opacity = '';
     430            }, 500);
     431        }, 5000);
    390432    }
    391433   
  • mode7-game-log/trunk/includes/class-game-log-admin.php

    r3406333 r3482605  
    1010 * @since 1.0.0
    1111 */
     12
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1217
    1318/**
     
    258263           
    259264            <!-- Game Search Modal -->
    260             <dialog id="game-search-modal" class="game-search-modal" style="display: none;">
     265            <dialog id="game-search-modal" class="game-search-modal">
    261266
    262267                    <div class="game-search-modal-header">
     
    265270                    </div>
    266271                    <div class="game-search-modal-body">
     272                        <div id="game-search-modal-notice" class="game-search-modal-notice" role="alert" aria-live="polite"></div>
    267273                        <p><?php esc_html_e( 'Search the Internet Gaming Database for to add a game to your log.', 'mode7-game-log' ); ?></p>   
    268274                        <div class="game-search-form">
     
    340346        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    341347        $current_status = isset( $_GET['game_status'] ) ? sanitize_text_field( wp_unslash( $_GET['game_status'] ) ) : '';
     348        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     349        $current_search = isset( $_GET['s'] ) && is_string( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
    342350
    343351        ?>
    344352        <form method="get" class="game-filters">
    345353            <input type="hidden" name="page" value="mode7-game-log" />
     354            <label for="game-log-search-input" class="screen-reader-text"><?php esc_html_e( 'Search games', 'mode7-game-log' ); ?></label>
     355            <input type="text" name="s" id="game-log-search-input" value="<?php echo esc_attr( $current_search ); ?>" placeholder="<?php esc_attr_e( 'Search by title…', 'mode7-game-log' ); ?>" class="regular-text" />
    346356            <select name="game_status" id="game_status_filter">
    347357                <option value=""><?php esc_html_e( 'All Statuses', 'mode7-game-log' ); ?></option>
     
    361371     */
    362372    private function display_games_list(): void {
     373        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only pagination, no data modification
     374        $current_page = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1;
     375        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     376        $current_status = isset( $_GET['game_status'] ) && is_string( $_GET['game_status'] ) ? sanitize_text_field( wp_unslash( $_GET['game_status'] ) ) : '';
     377        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
     378        $current_search = isset( $_GET['s'] ) && is_string( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
     379
    363380        $args = array(
    364381            'post_type'      => 'game',
    365382            'post_status'    => 'publish',
    366383            'posts_per_page' => 20,
    367             'paged'          => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
    368         );
     384            'paged'          => $current_page,
     385        );
     386
     387        if ( ! empty( $current_search ) ) {
     388            $args['s'] = $current_search;
     389        }
    369390
    370391        // Add status filter if selected.
    371         // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    372         if ( isset( $_GET['game_status'] ) && ! empty( $_GET['game_status'] ) ) {
     392        if ( ! empty( $current_status ) ) {
    373393            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for filtering games by status
    374394            $args['tax_query'] = array(
     
    376396                    'taxonomy' => 'game_status',
    377397                    'field'    => 'slug',
    378                     // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET form for filtering, no data modification
    379                     'terms'    => sanitize_text_field( wp_unslash( $_GET['game_status'] ) ),
     398                    'terms'    => $current_status,
    380399                ),
    381400            );
     
    465484            <?php
    466485            // Pagination.
     486            $base = add_query_arg( 'page', 'mode7-game-log', admin_url( 'admin.php' ) );
     487            if ( ! empty( $current_status ) ) {
     488                $base = add_query_arg( 'game_status', $current_status, $base );
     489            }
     490            if ( ! empty( $current_search ) ) {
     491                $base = add_query_arg( 's', $current_search, $base );
     492            }
    467493            $pagination_args = array(
    468494                'total'        => $games->max_num_pages,
    469                 'current'      => max( 1, get_query_var( 'paged' ) ),
    470                 'format'       => '?paged=%#%',
     495                'current'      => $current_page,
     496                'base'         => $base . '&paged=%#%',
     497                'format'       => '',
    471498                'show_all'     => false,
    472499                'type'         => 'list',
     
    480507            );
    481508
     509            $pagination_links = paginate_links( $pagination_args );
     510            if ( $pagination_links ) {
     511                $pagination_links = str_replace( ' class="next page-numbers"', ' class="button next page-numbers"', $pagination_links );
     512                $pagination_links = str_replace( ' class="prev page-numbers"', ' class="button prev page-numbers"', $pagination_links );
     513                $pagination_links = str_replace( '<a class="page-numbers"', '<a class="button page-numbers"', $pagination_links );
     514            }
    482515            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    483             echo paginate_links( $pagination_args );
     516            echo $pagination_links;
    484517            ?>
    485518
     
    487520        } else {
    488521            ?>
    489             <p><?php esc_html_e( 'No games found.', 'mode7-game-log' ); ?></p>
     522            <p><?php echo ! empty( $current_search ) ? esc_html__( 'No games match your search.', 'mode7-game-log' ) : esc_html__( 'No games found.', 'mode7-game-log' ); ?></p>
    490523            <?php
    491524        }
  • mode7-game-log/trunk/includes/class-game-log-ajax-handler.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log-default-page.php

    r3406333 r3482605  
    1111 */
    1212
    13 declare(strict_types=1);
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1417
    1518/**
  • mode7-game-log/trunk/includes/class-game-log-igdb-api.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log-meta-fields.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log-patterns.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log-post-type.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log-stats-block.php

    r3406333 r3482605  
    1111 */
    1212
    13 declare(strict_types=1);
     13// Prevent direct access.
     14if ( ! defined( 'ABSPATH' ) ) {
     15    exit;
     16}
    1417
    1518/**
  • mode7-game-log/trunk/includes/class-game-log-taxonomy.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
  • mode7-game-log/trunk/includes/class-game-log.php

    r3406333 r3482605  
    77 */
    88
    9 declare(strict_types=1);
     9// Prevent direct access.
     10if ( ! defined( 'ABSPATH' ) ) {
     11    exit;
     12}
    1013
    1114/**
     
    6770            'gameLogAjax',
    6871            array(
    69                 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    70                 'nonce'   => wp_create_nonce( 'game_log_nonce' ),
     72                'ajaxUrl'       => admin_url( 'admin-ajax.php' ),
     73                'gamesListUrl'  => add_query_arg( 'page', 'mode7-game-log', admin_url( 'admin.php' ) ),
     74                'nonce'         => wp_create_nonce( 'game_log_nonce' ),
    7175                'strings' => array(
    7276                    'searching'  => __( 'Searching...', 'mode7-game-log' ),
  • mode7-game-log/trunk/mode7-game-log.php

    r3406333 r3482605  
    44 * Plugin URI: https://www.bobmatyas.com
    55 * Description: A WordPress plugin to track video games you've played, are playing, or want to play using IGDB.com database.
    6  * Version: 1.0.4
     6 * Version: 1.0.5
    77 * Author: Bob Matyas
    88 * License: GPL v2 or later
     
    1818
    1919// Define plugin constants.
    20 define( 'GAME_LOG_VERSION', '1.0.4' );
     20define( 'GAME_LOG_VERSION', '1.0.5' );
    2121define( 'GAME_LOG_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    2222define( 'GAME_LOG_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
  • mode7-game-log/trunk/readme.txt

    r3406333 r3482605  
    55Tested up to: 6.9
    66Requires PHP: 8.2
    7 Stable tag: 1.0.4
     7Stable tag: 1.0.5
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    9191== Changelog ==
    9292
     93= 1.0.5 =
     94
     95* Fix pagination.
     96* Move error notice to inside modal.
     97* Add modal backdrop.
     98* Add search filter.
     99* Add direct file access check.
     100* Refresh admin page when adding game.
     101* Update mobile and pagination styles.
     102
    93103= 1.0.4 =
    94104
Note: See TracChangeset for help on using the changeset viewer.