Skip to content

Instantly share code, notes, and snippets.

@akirk
Last active November 29, 2016 08:35
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save akirk/ca2d5e6fe1b9a91e77290dfb31541cd0 to your computer and use it in GitHub Desktop.
<?php
/**
* Plugin Name: Cross-Locale PTE
* Plugin URI: https://meta.trac.wordpress.org/ticket/2000
* Description: Implements a user that can approve and import translations in all
* translation-sets of a project but cannot overwrite current translations by others.
*/
class CrossLocalePTE {
public static function init() {
add_filter( 'gp_pre_can_user', array( __CLASS__, 'gp_pre_can_user' ), 2, 2 );
add_filter( 'gp_translation_set_import_status', array( __CLASS__, 'gp_translation_set_import_status' ), 2, 3 );
}
/*
* Enforce not-overwriting current translation by others while importing.
*/
public static function gp_translation_set_import_status( $status, $new_translation, $old_translation ) {
if ( ! isset( $old_translation->translation_set_id ) ) {
return $status;
}
if ( 'current' !== $old_translation->translation_status ) {
return $status;
}
if ( GP::$permission->current_user_can( 'cross-pte', 'translation-set', $old_translation->translation_set_id ) ) {
// Set to waiting if a current translation exists by another user.
if ( intval( $old_translation->user_id ) !== intval( get_current_user_id() ) ) {
return 'waiting';
}
}
return $status;
}
/*
* A Cross-Locale PTE is defined through an entry in the permission table 'cross-pte' with the
* object_id referring to a project id.
* A user with this permission will have 'approve' rights for all translation-sets within this
* project. Usually having approval rights for a translation-set also means that the user has
* approval rights for all translations, but not a Cross-Locale PTE:
* If a current translation exists by another user then overwriting (through UI or import) is not
* possible.
*/
public static function gp_pre_can_user( $verdict, $args ) {
// echo $args['action'], ':', $args['object_type'], PHP_EOL;
if ( 'cross-pte' === $args['action'] ) {
$verdict = self::gp_pre_can_user_cross_pte( $verdict, $args );
if ( is_bool( $verdict ) ) {
return $verdict;
}
}
if ( 'approve' === $args['action'] ) {
if ( 'translation' === $args['object_type'] ) {
$verdict = self::gp_pre_can_user_approve_translation( $verdict, $args );
} elseif ( 'translation-set' === $args['object_type'] ) {
$verdict = self::gp_pre_can_user_approve_translation_set( $verdict, $args );
}
}
return $verdict;
}
public static function gp_pre_can_user_cross_pte( $verdict, $args ) {
if ( GP::$permission->user_can( $args['user'], 'admin' ) ) {
// Admins shouldn't have this because it will end up restricting them.
return false;
}
if ( 'translation-set' === $args['object_type'] ) {
if ( isset( $args['extra']['set']->id ) && $args['extra']['set']->id == $args['object_id'] ) {
$set = $args['extra']['set'];
} else {
$set = GP::$translation_set->get( $args['object_id'] );
}
// Allow on all translation-sets within the project.
if ( $set ) {
return GP::$permission->user_can( $args['user'], 'cross-pte', 'project', $set->project_id );
}
}
return $verdict;
}
public static function gp_pre_can_user_approve_translation( $verdict, $args ) {
if ( isset( $args['extra']['translation']->translation_set_id ) && $args['extra']['translation']->id == $args['object_id'] ) {
$translation = $args['extra']['translation'];
} else {
$translation = GP::$translation->get( $args['object_id'] );
}
if ( ! $translation ) {
return $verdict;
}
static $current_translation_by_user;
$cache_key = $args['user']->ID . '_' . $translation->original_id;
if ( isset( $current_translation_by_user[ $cache_key ] ) ) {
return $current_translation_by_user[ $cache_key ];
}
if ( GP::$permission->user_can( $args['user'], 'cross-pte', 'translation-set', $translation->translation_set_id ) ) {
$current_translation = GP::$translation->find_one( array( 'translation_set_id' => $translation->translation_set_id, 'original_id' => $translation->original_id, 'status' => 'current' ) );
if ( $current_translation && intval( $current_translation->user_id ) !== $args['user']->ID ) {
// Current translation was authored by someone else. Disallow setting to current.
return $current_translation_by_user[ $cache_key ] = false;
}
// No current translation exists or it was translated by me: allow.
return $current_translation_by_user[ $cache_key ] = true;
}
// Allows usage of the re-implementation below.
if ( GP::$permission->user_can( $args['user'], 'approve', 'translation-set', $translation->translation_set_id ) ) {
return true;
}
return $verdict;
}
public static function gp_pre_can_user_approve_translation_set( $verdict, $args ) {
// Re-implementation of gp_route_translation_set_permissions_to_validator_permissions().
if ( isset( $args['extra']['set']->id ) && $args['extra']['set']->id == $args['object_id'] ) {
$set = $args['extra']['set'];
} else {
$set = GP::$translation_set->get( $args['object_id'] );
}
if ( $set ) {
if ( GP::$permission->user_can( $args['user'], 'cross-pte', 'project', $set->project_id ) ) {
return true;
}
return GP::$permission->user_can( $args['user'], 'approve', GP::$validator_permission->object_type,
GP::$validator_permission->object_id( $set->project_id, $set->locale, $set->slug ) );
}
return $verdict;
}
}
CrossLocalePTE::init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment