then( spreadArgs( NonPublicCPTPreview::allowReviewPostTypeQueryVar() ) ); Hooks::onFilter( 'request' ) ->then( spreadArgs( NonPublicCPTPreview::enforceReviewPostTypeIfSet() ) ); Hooks::onFilter( 'the_preview' ) ->then( Hooks::getArgs( [ 0 => 'post' ] ) ) ->then( $this->handleTranslationReview() ); } Hooks::onFilter( 'user_has_cap', 10, 3 ) ->then( spreadArgs( function ( $userCaps, $requiredCaps, $args ) { if ( Relation::propEq( 0, 'edit_post', $args ) ) { $translator = Translators::getCurrent(); if ( $translator->ID ) { $postId = $args[2]; $job = Jobs::getPostJob( $postId, Post::getType( $postId ), WPMLPost::getLang( $postId ) ); if ( ReviewStatus::doesJobNeedReview( $job ) && self::canEditLanguage( $translator, $job ) ) { return Lst::concat( $userCaps, Lst::zipObj( $requiredCaps, Lst::repeat( true, count( $requiredCaps ) ) ) ); } } return $userCaps; } return $userCaps; } ) ); Hooks::onFilter( 'wpml_tm_allowed_translators_for_job', 10, 2 ) ->then( spreadArgs( function ( $allowedTranslators, \WPML_Element_Translation_Job $job ) { $job = $job->to_array(); $translator = Translators::getCurrent(); if ( ReviewStatus::doesJobNeedReview( $job ) && self::canEditLanguage( $translator, $job ) ) { return array_merge( $allowedTranslators, [ $translator->ID ] ); } return $allowedTranslators; } ) ); } private static function canEditLanguage( $translator, $job ) { if ( ! $job ) { return false; } return Lst::includes( Obj::prop('language_code', $job), Obj::pathOr( [], [ 'language_pairs', Obj::prop('source_language_code', $job) ], $translator ) ); } /** * This will ensure to block the standard preview * for non-public CPTs. * * @return bool */ private static function hasValidNonce() { $get = Obj::prop( Fns::__, $_GET ); return (bool) \wp_verify_nonce( $get( 'preview_nonce' ), PreviewLink::getNonceName( (int) $get( 'preview_id' ) ) ); } public function handleTranslationReview() { return function ( $data ) { $post = Obj::prop( 'post', $data ); $jobId = filter_input( INPUT_GET, 'jobId', FILTER_SANITIZE_NUMBER_INT ); if ( $jobId ) { /** * This hooks is fired as soon as a translation review is about to be displayed. * * @since 4.5.0 * * @param int $jobId The job Id. * @param object|\WP_Post $post The job's related object to be reviewed. */ do_action( 'wpml_tm_handle_translation_review', $jobId, $post ); Hooks::onFilter( 'wp_redirect' ) ->then( [ __CLASS__, 'failGracefullyOnPreviewRedirection' ] ); Hooks::onAction( 'template_redirect', PHP_INT_MAX ) ->then( function () { Hooks::onAction( 'wp_footer' ) ->then( [ __CLASS__, 'printReviewToolbarAnchor' ] ); } ); show_admin_bar( false ); $enqueue = Resources::enqueueApp( 'translationReview' ); $enqueue( $this->getData( $jobId, $post ) ); } return $post; }; } public static function printReviewToolbarAnchor() { echo '
'; } /** * @return null This will stop the redirection. */ public static function failGracefullyOnPreviewRedirection() { do_action( 'wp_head' ); self::printReviewToolbarAnchor(); echo ''. sprintf(esc_html__( 'Click %sEdit Translation%s in the toolbar above to review your translation in the editor.', 'wpml-translation-management' ), '', '') .'