Making WordPress.org

Changeset 14885


Ignore:
Timestamp:
05/14/2026 02:57:35 PM (10 days ago)
Author:
amieiro
Message:

Translate: add validator opt-out for the translation editor top bar

  • new "Hide the validation top bar in the translation editor" checkbox at /settings/
  • visible only to validators (global admin, GTE, Locale Manager, PTE)
  • when checked, the top bar template and assets are not loaded on translation pages
Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/templates
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/templates/helper-functions.php

    r14882 r14885  
    188188        return false;
    189189    }
     190
     191    // Per-user opt-out: validators can hide the top bar persistently from /settings/.
     192    // Stored as `hide_validator_topbar => 'on'` inside the user's `gp_default_sort`
     193    // option (piggybacks on the existing settings form — see settings-edit.php).
     194    $default_sort = get_user_option( 'gp_default_sort' );
     195    if ( 'on' === gp_array_get( $default_sort, 'hide_validator_topbar', 'off' ) ) {
     196        return false;
     197    }
     198
    190199    return GP::$permission->current_user_can(
    191200        'approve',
     
    194203    );
    195204}
     205
     206/**
     207 * Returns true if the given user has the ability to approve translations on
     208 * at least one translation set — i.e., is a global GlotPress admin, a GTE,
     209 * a Locale Manager, or a PTE somewhere.
     210 *
     211 * @param int $user_id The user ID to check. 0 or missing returns false.
     212 * @return bool
     213 */
     214function wporg_translate_user_is_validator_anywhere( $user_id ) {
     215    static $cache = array();
     216
     217    $user_id = (int) $user_id;
     218    if ( $user_id <= 0 ) {
     219        return false;
     220    }
     221
     222    if ( array_key_exists( $user_id, $cache ) ) {
     223        return $cache[ $user_id ];
     224    }
     225
     226    $rosetta = \WordPressdotorg\GlotPress\Rosetta_Roles\Plugin::get_instance();
     227    if ( $rosetta->is_global_administrator( $user_id ) ) {
     228        $cache[ $user_id ] = true;
     229        return true;
     230    }
     231
     232    global $wpdb;
     233
     234    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- static-map cache is sufficient for this single-row existence check.
     235    $has_editor_row = $wpdb->get_var(
     236        $wpdb->prepare(
     237            "SELECT 1 FROM {$wpdb->wporg_translation_editors}
     238             WHERE user_id = %d LIMIT 1",
     239            $user_id
     240        )
     241    );
     242    // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
     243    if ( $has_editor_row ) {
     244        $cache[ $user_id ] = true;
     245        return true;
     246    }
     247
     248    // "{$wpdb->base_prefix}{$blog_id}_capabilities" (serialized arrays).
     249    $pattern = $wpdb->esc_like( $wpdb->base_prefix ) . '%\_capabilities';
     250    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- static-map cache is sufficient for this gated existence check.
     251    $meta_rows = $wpdb->get_col(
     252        $wpdb->prepare(
     253            "SELECT meta_value FROM {$wpdb->usermeta}
     254             WHERE user_id = %d
     255               AND meta_key LIKE %s",
     256            $user_id,
     257            $pattern
     258        )
     259    );
     260    // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
     261    foreach ( $meta_rows as $serialized ) {
     262        $caps = maybe_unserialize( $serialized );
     263        if ( is_array( $caps ) && (
     264            ! empty( $caps['general_translation_editor'] ) ||
     265            ! empty( $caps['locale_manager'] ) ||
     266            ! empty( $caps['translation_editor'] )
     267        ) ) {
     268            $cache[ $user_id ] = true;
     269            return true;
     270        }
     271    }
     272
     273    $cache[ $user_id ] = false;
     274    return false;
     275    }
    196276
    197277/**
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/templates/settings-edit.php

    r14608 r14885  
    268268        </td>
    269269    </tr>
     270    <?php if ( wporg_translate_user_is_validator_anywhere( get_current_user_id() ) ) : ?>
     271    <tr>
     272        <th>
     273            <h4><?php esc_html_e( 'Validator settings', 'glotpress' ); ?></h4>
     274        </th>
     275    </tr>
     276    <tr>
     277        <th>
     278            <label for="default_sort[hide_validator_topbar]">
     279                <?php esc_html_e( 'Hide the validation top bar in the translation editor', 'glotpress' ); ?>
     280            </label>
     281        </th>
     282        <td>
     283            <input type="hidden" name="default_sort[hide_validator_topbar]" value="off" />
     284            <input
     285                type="checkbox"
     286                id="default_sort[hide_validator_topbar]"
     287                name="default_sort[hide_validator_topbar]"
     288                <?php gp_checked( 'on' === gp_array_get( $gp_default_sort, 'hide_validator_topbar', 'off' ) ); ?>
     289            />
     290        </td>
     291    </tr>
     292    <?php endif; ?>
    270293</table>
Note: See TracChangeset for help on using the changeset viewer.