Last active
November 29, 2016 08:35
Star
You must be signed in to star a gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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