first commit
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use TranslationProxy;
|
||||
|
||||
class ActivationAjax {
|
||||
|
||||
const NONCE_ACTION = 'translation_service_toggle';
|
||||
const REFRESH_TS_INFO_ACTION = 'refresh_ts_info';
|
||||
|
||||
/** @var \WPML_TP_Client */
|
||||
private $tp_client;
|
||||
|
||||
public function __construct( \WPML_TP_Client $tp_client ) {
|
||||
$this->tp_client = $tp_client;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'wp_ajax_translation_service_toggle', array( $this, 'translation_service_toggle' ) );
|
||||
add_action( 'wp_ajax_refresh_ts_info', array( $this, 'refresh_ts_info' ) );
|
||||
}
|
||||
|
||||
public function translation_service_toggle() {
|
||||
if ( $this->is_valid_request( self::NONCE_ACTION ) ) {
|
||||
|
||||
if ( ! isset( $_POST['service_id'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$service_id = (int) filter_var( $_POST['service_id'], FILTER_SANITIZE_NUMBER_INT );
|
||||
$enable = false;
|
||||
$response = false;
|
||||
|
||||
if ( isset( $_POST['enable'] ) ) {
|
||||
$enable = filter_var( $_POST['enable'], FILTER_SANITIZE_NUMBER_INT );
|
||||
}
|
||||
|
||||
if ( $enable ) {
|
||||
if ( $service_id !== TranslationProxy::get_current_service_id() ) {
|
||||
$response = $this->activate_service( $service_id );
|
||||
} else {
|
||||
$response = array( 'activated' => true );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $enable && $service_id === TranslationProxy::get_current_service_id() ) {
|
||||
TranslationProxy::clear_preferred_translation_service();
|
||||
$response = $this->deactivate_service();
|
||||
}
|
||||
|
||||
wp_send_json_success( $response );
|
||||
return;
|
||||
}
|
||||
|
||||
$this->send_invalid_nonce_error();
|
||||
}
|
||||
|
||||
public function refresh_ts_info() {
|
||||
if ( $this->is_valid_request( self::REFRESH_TS_INFO_ACTION ) ) {
|
||||
$active_service = $this->tp_client->services()->get_active( true );
|
||||
|
||||
if ( $active_service ) {
|
||||
$active_service = (object) (array) $active_service;
|
||||
TranslationProxy::build_and_store_active_translation_service( $active_service, $active_service->custom_fields_data );
|
||||
|
||||
$activeServiceTemplateRender = ActiveServiceTemplateFactory::createRenderer();
|
||||
|
||||
wp_send_json_success( [ 'active_service_block' => $activeServiceTemplateRender() ] );
|
||||
return;
|
||||
}
|
||||
|
||||
wp_send_json_error(
|
||||
array( 'message' => __( 'It was not possible to refresh the active translation service information.', 'wpml-translation-management' ) )
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->send_invalid_nonce_error();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $service_id
|
||||
*
|
||||
* @return array
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function activate_service( $service_id ) {
|
||||
$result = TranslationProxy::select_service( $service_id );
|
||||
$message = '';
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$message = $result->get_error_message();
|
||||
}
|
||||
|
||||
return array(
|
||||
'message' => $message,
|
||||
'reload' => 1,
|
||||
'activated' => 1,
|
||||
);
|
||||
}
|
||||
|
||||
private function deactivate_service() {
|
||||
TranslationProxy::deselect_active_service();
|
||||
|
||||
return array(
|
||||
'message' => '',
|
||||
'reload' => 1,
|
||||
'activated' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_valid_request( $action ) {
|
||||
if ( ! isset( $_POST['nonce'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return wp_verify_nonce( filter_var( $_POST['nonce'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ), $action );
|
||||
}
|
||||
|
||||
private function send_invalid_nonce_error() {
|
||||
$response = array(
|
||||
'message' => __( 'You are not allowed to perform this action.', 'wpml-translation-management' ),
|
||||
'reload' => 0,
|
||||
);
|
||||
|
||||
wp_send_json_error( $response );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class ActivationAjaxFactory implements \IWPML_Backend_Action_Loader {
|
||||
|
||||
/**
|
||||
* @return ActivationAjax
|
||||
*/
|
||||
public function create() {
|
||||
$tp_client_factory = new \WPML_TP_Client_Factory();
|
||||
return new ActivationAjax( $tp_client_factory->create() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
|
||||
use WPML\FP\Maybe;
|
||||
use function WPML\FP\invoke;
|
||||
|
||||
class ActiveServiceRepository {
|
||||
/**
|
||||
* @return \WPML_TP_Service|null
|
||||
*/
|
||||
public static function get() {
|
||||
global $sitepress;
|
||||
|
||||
$active_service = $sitepress->get_setting( 'translation_service' );
|
||||
|
||||
return $active_service ? new \WPML_TP_Service( $active_service ) : null;
|
||||
}
|
||||
|
||||
public static function getId() {
|
||||
return Maybe::fromNullable( self::get() )
|
||||
->map( invoke( 'get_id' ) )
|
||||
->getOrElse( null );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class ActiveServiceTemplate {
|
||||
|
||||
const ACTIVE_SERVICE_TEMPLATE = 'active-service.twig';
|
||||
const HOURS_BEFORE_TS_REFRESH = 24;
|
||||
|
||||
/**
|
||||
* @param callable $templateRenderer
|
||||
* @param \WPML_TP_Service $active_service
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function render( $templateRenderer, \WPML_TP_Service $active_service ) {
|
||||
return $templateRenderer( self::getModel( $active_service ), self::ACTIVE_SERVICE_TEMPLATE );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private static function getModel( \WPML_TP_Service $active_service ) {
|
||||
$model = [
|
||||
'strings' => [
|
||||
'title' => __( 'Active service:', 'wpml-translation-management' ),
|
||||
'deactivate' => __( 'Deactivate', 'wpml-translation-management' ),
|
||||
'modal_header' => sprintf(
|
||||
__(
|
||||
'Enter here your %s authentication details',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
$active_service->get_name()
|
||||
),
|
||||
'modal_tip' => $active_service->get_popup_message() ?
|
||||
$active_service->get_popup_message() :
|
||||
__( 'You can find API token at %s site', 'wpml-translation-management' ),
|
||||
'modal_title' => sprintf(
|
||||
__( '%s authentication', 'wpml-translation-management' ),
|
||||
$active_service->get_name()
|
||||
),
|
||||
'refresh_language_pairs' => __( 'Refresh language pairs', 'wpml-translation-management' ),
|
||||
'refresh_ts_info' => __( 'Refresh information', 'wpml-translation-management' ),
|
||||
'documentation_lower' => __( 'documentation', 'wpml-translation-management' ),
|
||||
'refreshing_ts_message' => __(
|
||||
'Refreshing translation service information...',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
],
|
||||
'active_service' => $active_service,
|
||||
'nonces' => [
|
||||
\WPML_TP_Refresh_Language_Pairs::AJAX_ACTION => wp_create_nonce( \WPML_TP_Refresh_Language_Pairs::AJAX_ACTION ),
|
||||
ActivationAjax::REFRESH_TS_INFO_ACTION => wp_create_nonce( ActivationAjax::REFRESH_TS_INFO_ACTION ),
|
||||
],
|
||||
'needs_info_refresh' => self::shouldRefreshData( $active_service ),
|
||||
];
|
||||
|
||||
$authentication_message = [];
|
||||
/* translators: sentence 1/3: create account with the translation service ("%1$s" is the service name) */
|
||||
$authentication_message[] = __(
|
||||
'To send content for translation to %1$s, you need to have an %1$s account.',
|
||||
'wpml-translation-management'
|
||||
);
|
||||
/* translators: sentence 2/3: create account with the translation service ("one" is "one account) */
|
||||
$authentication_message[] = __(
|
||||
"If you don't have one, you can create it after clicking the authenticate button.",
|
||||
'wpml-translation-management'
|
||||
);
|
||||
/* translators: sentence 3/3: create account with the translation service ("%2$s" is "documentation") */
|
||||
$authentication_message[] = __(
|
||||
'Please, check the %2$s page for more details.',
|
||||
'wpml-translation-management'
|
||||
);
|
||||
|
||||
$model['strings']['authentication'] = [
|
||||
'description' => implode( ' ', $authentication_message ),
|
||||
'authenticate_button' => __( 'Authenticate', 'wpml-translation-management' ),
|
||||
'de_authorize_button' => __( 'De-authorize', 'wpml-translation-management' ),
|
||||
'update_credentials_button' => __( 'Update credentials', 'wpml-translation-management' ),
|
||||
'is_authorized' => self::isAuthorizedText( $active_service->get_name() ),
|
||||
];
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
private static function isAuthorizedText( $serviceName ) {
|
||||
$query_args = [
|
||||
'page' => WPML_TM_FOLDER . \WPML_Translation_Management::PAGE_SLUG_MANAGEMENT,
|
||||
'sm' => 'dashboard',
|
||||
];
|
||||
|
||||
$href = add_query_arg( $query_args, admin_url( 'admin.php' ) );
|
||||
|
||||
$dashboard = '<a href="' . $href . '">' .
|
||||
__( 'Translation Dashboard', 'wpml-translation-management' ) .
|
||||
'</a>';
|
||||
|
||||
$isAuthorized = sprintf(
|
||||
__( 'Success! You can now send content to %s.', 'wpml-translation-management' ),
|
||||
$serviceName
|
||||
);
|
||||
$isAuthorized .= '<br/>';
|
||||
// translators: "%s" is replaced with the link to the "Translation Dashboard"
|
||||
$isAuthorized .= sprintf(
|
||||
__( 'Go to the %s to choose the content and send it to translation.', 'wpml-translation-management' ),
|
||||
$dashboard
|
||||
);
|
||||
|
||||
return $isAuthorized;
|
||||
}
|
||||
|
||||
private static function shouldRefreshData( \WPML_TP_Service $active_service ) {
|
||||
$refresh_time = time() - ( self::HOURS_BEFORE_TS_REFRESH * HOUR_IN_SECONDS );
|
||||
|
||||
return ! $active_service->get_last_refresh() || $active_service->get_last_refresh() < $refresh_time;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\partial;
|
||||
|
||||
class ActiveServiceTemplateFactory {
|
||||
/**
|
||||
* @return \Closure
|
||||
*/
|
||||
public static function createRenderer() {
|
||||
$activeService = ActiveServiceRepository::get();
|
||||
if ( $activeService ) {
|
||||
$templateRenderer = self::getTemplateRenderer();
|
||||
|
||||
return partial( ActiveServiceTemplate::class . '::render', [ $templateRenderer, 'show' ], $activeService );
|
||||
}
|
||||
|
||||
return function () {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \WPML_Twig_Template
|
||||
*/
|
||||
private static function getTemplateRenderer() {
|
||||
$paths = [ WPML_TM_PATH . '/templates/menus/translation-services/' ];
|
||||
$twigLoader = make( \WPML_Twig_Template_Loader::class, [ ':paths' => $paths ] );
|
||||
|
||||
return $twigLoader->get_template();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use WPML\TM\TranslationProxy\Services\AuthorizationFactory;
|
||||
|
||||
class AuthenticationAjax {
|
||||
|
||||
const AJAX_ACTION = 'translation_service_authentication';
|
||||
|
||||
/** @var AuthorizationFactory */
|
||||
protected $authorize_factory;
|
||||
|
||||
/**
|
||||
* @param AuthorizationFactory $authorize_factory
|
||||
*/
|
||||
public function __construct( AuthorizationFactory $authorize_factory ) {
|
||||
$this->authorize_factory = $authorize_factory;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'wp_ajax_translation_service_authentication', [ $this, 'authenticate_service' ] );
|
||||
add_action( 'wp_ajax_translation_service_update_credentials', [ $this, 'update_credentials' ] );
|
||||
add_action( 'wp_ajax_translation_service_invalidation', [ $this, 'invalidate_service' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate_service() {
|
||||
return $this->handle_action(
|
||||
function () {
|
||||
$this->authorize_factory->create()->authorize(
|
||||
json_decode( stripslashes( $_POST['custom_fields'] ) )
|
||||
);
|
||||
},
|
||||
[ $this, 'is_valid_request_with_params' ],
|
||||
__( 'Service activated.', 'wpml-translation-management' ),
|
||||
__(
|
||||
'The authentication didn\'t work. Please make sure you entered your details correctly and try again.',
|
||||
'wpml-translation-management'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function update_credentials() {
|
||||
return $this->handle_action(
|
||||
function () {
|
||||
$this->authorize_factory->create()->updateCredentials(
|
||||
json_decode( stripslashes( $_POST['custom_fields'] ) )
|
||||
);
|
||||
},
|
||||
[ $this, 'is_valid_request_with_params' ],
|
||||
__( 'Service credentials updated.', 'wpml-translation-management' ),
|
||||
__(
|
||||
'The authentication didn\'t work. Please make sure you entered your details correctly and try again.',
|
||||
'wpml-translation-management'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function invalidate_service() {
|
||||
return $this->handle_action(
|
||||
function () {
|
||||
$this->authorize_factory->create()->deauthorize();
|
||||
},
|
||||
[ $this, 'is_valid_request' ],
|
||||
__( 'Service invalidated.', 'wpml-translation-management' ),
|
||||
__( 'Unable to invalidate this service. Please contact WPML support.', 'wpml-translation-management' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $action
|
||||
* @param callable $request_validation
|
||||
* @param string $success_message
|
||||
* @param string $failure_message
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function handle_action(
|
||||
callable $action,
|
||||
callable $request_validation,
|
||||
$success_message,
|
||||
$failure_message
|
||||
) {
|
||||
if ( $request_validation() ) {
|
||||
try {
|
||||
$action();
|
||||
|
||||
return $this->send_success_response( $success_message );
|
||||
} catch ( \Exception $e ) {
|
||||
return $this->send_error_message( $failure_message );
|
||||
}
|
||||
} else {
|
||||
return $this->send_error_message( __( 'Invalid Request', 'wpml-translation-management' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $msg
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function send_success_response( $msg ) {
|
||||
wp_send_json_success(
|
||||
[
|
||||
'errors' => 0,
|
||||
'message' => $msg,
|
||||
'reload' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $msg
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function send_error_message( $msg ) {
|
||||
wp_send_json_error(
|
||||
[
|
||||
'errors' => 1,
|
||||
'message' => $msg,
|
||||
'reload' => 0,
|
||||
]
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_valid_request() {
|
||||
return isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], self::AJAX_ACTION );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function is_valid_request_with_params() {
|
||||
return isset( $_POST['service_id'], $_POST['custom_fields'] ) && $this->is_valid_request();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use function WPML\Container\make;
|
||||
|
||||
class AuthenticationAjaxFactory implements \IWPML_Backend_Action_Loader {
|
||||
/**
|
||||
* @return AuthenticationAjax
|
||||
*/
|
||||
public function create() {
|
||||
return make( AuthenticationAjax::class );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use WPML\DocPage;
|
||||
use WPML\LIB\WP\Nonce;
|
||||
use WPML\Setup\Option;
|
||||
use WPML\TM\Menu\TranslationServices\Endpoints\Activate;
|
||||
use WPML\TM\Menu\TranslationServices\Endpoints\Deactivate;
|
||||
use WPML\TM\Menu\TranslationServices\Endpoints\Select;
|
||||
use WPML\UIPage;
|
||||
|
||||
class MainLayoutTemplate {
|
||||
|
||||
const SERVICES_LIST_TEMPLATE = 'services-layout.twig';
|
||||
|
||||
/**
|
||||
* @param callable $templateRenderer
|
||||
* @param callable $activeServiceRenderer
|
||||
* @param bool $hasPreferredService
|
||||
* @param callable $retrieveServiceTabsData
|
||||
*/
|
||||
public static function render(
|
||||
$templateRenderer,
|
||||
$activeServiceRenderer,
|
||||
$hasPreferredService,
|
||||
$retrieveServiceTabsData
|
||||
) {
|
||||
echo $templateRenderer(
|
||||
self::getModel( $activeServiceRenderer, $hasPreferredService, $retrieveServiceTabsData ),
|
||||
self::SERVICES_LIST_TEMPLATE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $activeServiceRenderer
|
||||
* @param bool $hasPreferredService
|
||||
* @param callable $retrieveServiceTabsData
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getModel( $activeServiceRenderer, $hasPreferredService, $retrieveServiceTabsData ) {
|
||||
$services = $retrieveServiceTabsData();
|
||||
|
||||
$translationServicesUrl = 'https://wpml.org/documentation/translating-your-contents/professional-translation-via-wpml/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmltm';
|
||||
|
||||
/* Translators: %s is documentation link for Translation Services */
|
||||
$sectionDescription = sprintf(
|
||||
'WPML integrates with dozens of professional <a target="_blank" href="%s">translation services</a>. Connect to your preferred service to send and receive translation jobs from directly within WPML.',
|
||||
$translationServicesUrl
|
||||
);
|
||||
|
||||
return [
|
||||
'active_service' => $activeServiceRenderer(),
|
||||
'services' => $services,
|
||||
'has_preferred_service' => $hasPreferredService,
|
||||
'has_services' => ! empty( $services ),
|
||||
'translate_everything' => Option::shouldTranslateEverything(),
|
||||
'nonces' => [
|
||||
ActivationAjax::NONCE_ACTION => wp_create_nonce( ActivationAjax::NONCE_ACTION ),
|
||||
AuthenticationAjax::AJAX_ACTION => wp_create_nonce( AuthenticationAjax::AJAX_ACTION ),
|
||||
],
|
||||
'settings_url' => UIPage::getSettings(),
|
||||
'lsp_logo_placeholder' => WPML_TM_URL . '/res/img/lsp-logo-placeholder.png',
|
||||
'strings' => [
|
||||
'translation_services' => __( 'Translation Services', 'wpml-translation-management' ),
|
||||
'translation_services_description' => __( $sectionDescription, 'wpml-translation-management' ),
|
||||
'ts' => [
|
||||
'different' => __( 'Looking for a different translation service?', 'wpml-translation-management' ),
|
||||
'tell_us_url' => DocPage::addTranslationServiceForm(),
|
||||
'tell_us' => __( 'Tell us which one', 'wpml-translation-management' ),
|
||||
],
|
||||
],
|
||||
'endpoints' => [
|
||||
'selectService' => [
|
||||
'endpoint' => Select::class,
|
||||
'nonce' => Nonce::create( Select::class )
|
||||
],
|
||||
'deactivateService' => [
|
||||
'nonce' => Nonce::create( Deactivate::class ),
|
||||
'endpoint' => Deactivate::class
|
||||
],
|
||||
'activateService' => [
|
||||
'nonce' => Nonce::create( Activate::class ),
|
||||
'endpoint' => Activate::class
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class NoSiteKeyTemplate {
|
||||
|
||||
const TEMPLATE = 'no-site-key.twig';
|
||||
|
||||
/**
|
||||
* @param callable $templateRenderer
|
||||
*/
|
||||
public static function render( $templateRenderer ) {
|
||||
echo $templateRenderer( self::get_no_site_key_model(), self::TEMPLATE );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private static function get_no_site_key_model() {
|
||||
return [
|
||||
'registration' => [
|
||||
'link' => admin_url( 'plugin-install.php?tab=commercial#repository-wpml' ),
|
||||
'text' => __(
|
||||
'Please register WPML to enable the professional translation option',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class Resources implements \IWPML_Backend_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
if ( $this->is_active() ) {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function enqueue_styles() {
|
||||
wp_enqueue_style(
|
||||
'wpml-tm-ts-admin-section',
|
||||
WPML_TM_URL . '/res/css/admin-sections/translation-services.css',
|
||||
array(),
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'wpml-tm-translation-services',
|
||||
WPML_TM_URL . '/dist/css/translationServices/styles.css',
|
||||
[],
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpml-tm-ts-admin-section',
|
||||
WPML_TM_URL . '/res/js/translation-services.js',
|
||||
array(),
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpml-tm-translation-services',
|
||||
WPML_TM_URL . '/dist/js/translationServices/app.js',
|
||||
array(),
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'wpml-tp-api',
|
||||
WPML_TM_URL . '/res/js/wpml-tp-api.js',
|
||||
array( 'jquery', 'wp-util' ),
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
private function is_active() {
|
||||
return isset( $_GET['sm'] ) && 'translators' === $_GET['sm'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class Section implements \IWPML_TM_Admin_Section {
|
||||
const SLUG = 'translators';
|
||||
|
||||
/**
|
||||
* The SitePress instance.
|
||||
*
|
||||
* @var \SitePress
|
||||
*/
|
||||
private $sitepress;
|
||||
|
||||
/**
|
||||
* The WPML_WP_API instance.
|
||||
*
|
||||
* @var \WPML_WP_API
|
||||
*/
|
||||
private $wp_api;
|
||||
|
||||
/**
|
||||
* The template to use.
|
||||
*
|
||||
* @var mixed $template
|
||||
*/
|
||||
private $template;
|
||||
|
||||
/**
|
||||
* WPML_TM_Translation_Services_Admin_Section constructor.
|
||||
*
|
||||
* @param \SitePress $sitepress The SitePress instance.
|
||||
* @param callable $template The template to use.
|
||||
*/
|
||||
public function __construct(
|
||||
\SitePress $sitepress,
|
||||
$template
|
||||
) {
|
||||
$this->sitepress = $sitepress;
|
||||
$this->wp_api = $sitepress->get_wp_api();
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value which will be used for sorting the sections.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_order() {
|
||||
return 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the content of the section.
|
||||
*/
|
||||
public function render() {
|
||||
call_user_func( $this->template );
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to extend the logic for displaying/hiding the section.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_visible() {
|
||||
return ! $this->wp_api->constant( 'ICL_HIDE_TRANSLATION_SERVICES' ) && ( $this->wp_api->constant( 'WPML_BYPASS_TS_CHECK' ) || ! $this->sitepress->get_setting( 'translation_service_plugin_activated' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique slug of the sections which is used to build the URL for opening this section.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_slug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one or more capabilities required to display this section.
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public function get_capabilities() {
|
||||
return [ \WPML_Manage_Translations_Role::CAPABILITY, 'manage_options' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the caption to display in the section.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_caption() {
|
||||
return __( 'Translation Services', 'wpml-translation-management' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the callback responsible for rendering the content of the section.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function get_callback() {
|
||||
return array( $this, 'render' );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is hooked to the `admin_enqueue_scripts` action.
|
||||
*
|
||||
* @param string $hook The current page.
|
||||
*/
|
||||
public function admin_enqueue_scripts( $hook ) {}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use WPML\LIB\WP\Http;
|
||||
use WPML\TM\Geolocalization;
|
||||
use function WPML\Container\make;
|
||||
use function WPML\FP\partial;
|
||||
use function WPML\FP\partialRight;
|
||||
|
||||
class SectionFactory implements \IWPML_TM_Admin_Section_Factory {
|
||||
/**
|
||||
* @return Section
|
||||
*/
|
||||
public function create() {
|
||||
global $sitepress;
|
||||
|
||||
return new Section(
|
||||
$sitepress,
|
||||
$this->site_key_exists() ?
|
||||
$this->createServicesListRenderer() :
|
||||
partial( NoSiteKeyTemplate::class . '::render', $this->getTemplateRenderer() )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|string
|
||||
*/
|
||||
private function site_key_exists() {
|
||||
$site_key = false;
|
||||
|
||||
if ( class_exists( 'WP_Installer' ) ) {
|
||||
$repository_id = 'wpml';
|
||||
$site_key = \WP_Installer()->get_site_key( $repository_id );
|
||||
}
|
||||
|
||||
return $site_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WPML_Twig_Template_Loader $twig_loader
|
||||
* @param \WPML_TP_Client $tp_client
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
private function createServicesListRenderer() {
|
||||
/**
|
||||
* Section: "Partner services", "Other services" and "Translation Management Services"
|
||||
*/
|
||||
$getServicesTabs = partial(
|
||||
ServicesRetriever::class . '::get',
|
||||
$this->getTpApiServices(),
|
||||
Geolocalization::getCountryByIp( Http::post() ),
|
||||
partialRight(
|
||||
[ ServiceMapper::class, 'map' ],
|
||||
[ ActiveServiceRepository::class, 'getId' ]
|
||||
)
|
||||
);
|
||||
|
||||
return partial(
|
||||
MainLayoutTemplate::class . '::render',
|
||||
$this->getTemplateRenderer(),
|
||||
ActiveServiceTemplateFactory::createRenderer(),
|
||||
\TranslationProxy::has_preferred_translation_service(),
|
||||
$getServicesTabs
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
private function getTemplateRenderer() {
|
||||
$template = make(
|
||||
\WPML_Twig_Template_Loader::class,
|
||||
[
|
||||
':paths' => [
|
||||
WPML_TM_PATH . '/templates/menus/translation-services/',
|
||||
WPML_PLUGIN_PATH . '/templates/pagination/',
|
||||
],
|
||||
]
|
||||
)->get_template();
|
||||
|
||||
return [ $template, 'show' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \WPML_TP_API_Services
|
||||
*/
|
||||
private function getTpApiServices() {
|
||||
return make( \WPML_TP_Client_Factory::class )->create()->services();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
class ServiceMapper {
|
||||
/**
|
||||
* @param \WPML_TP_Service $service
|
||||
* @param callable $getActiveServiceId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function map( \WPML_TP_Service $service, $getActiveServiceId ) {
|
||||
$isActive = $service->get_id() === $getActiveServiceId();
|
||||
if ( $isActive ) {
|
||||
$service->set_custom_fields_data();
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $service->get_id(),
|
||||
'logo_url' => $service->get_logo_preview_url(),
|
||||
'name' => $service->get_name(),
|
||||
'description' => $service->get_description(),
|
||||
'doc_url' => $service->get_doc_url(),
|
||||
'active' => $isActive ? 'active' : 'inactive',
|
||||
'rankings' => $service->get_rankings(),
|
||||
'how_to_get_credentials_desc' => $service->get_how_to_get_credentials_desc(),
|
||||
'how_to_get_credentials_url' => $service->get_how_to_get_credentials_url(),
|
||||
'is_authorized' => ! empty( $service->get_custom_fields_data() ),
|
||||
'client_create_account_page_url' => $service->get_client_create_account_page_url(),
|
||||
'custom_fields' => $service->get_custom_fields(),
|
||||
'countries' => $service->get_countries(),
|
||||
'url' => $service->get_url(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices;
|
||||
|
||||
use WPML\FP\Fns;
|
||||
use WPML\FP\Logic;
|
||||
use WPML\FP\Lst;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\FP\Relation;
|
||||
use function WPML\FP\curryN;
|
||||
use function WPML\FP\invoke;
|
||||
use function WPML\FP\partialRight;
|
||||
use function WPML\FP\pipe;
|
||||
|
||||
class ServicesRetriever {
|
||||
public static function get( \WPML_TP_API_Services $servicesAPI, $getUserCountry, $mapService ) {
|
||||
$userCountry = $getUserCountry( isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null );
|
||||
|
||||
// $buildSection :: $services -> $header -> $showPopularity -> string
|
||||
$buildSection = self::buildSection( $mapService );
|
||||
|
||||
// $otherSection :: $services -> $header -> string
|
||||
$otherSection = $buildSection( Fns::__, Fns::__, false, true );
|
||||
|
||||
$buildPartnerServicesSections = self::buildPartnerServicesSections( $buildSection, $userCountry );
|
||||
$partnerServices = $servicesAPI->get_translation_services( true );
|
||||
$services = $buildPartnerServicesSections( $partnerServices );
|
||||
|
||||
$services[] = $otherSection(
|
||||
$servicesAPI->get_translation_services( false ),
|
||||
__( 'Other Translation Services', 'wpml-translation-management' )
|
||||
);
|
||||
|
||||
$services[] = $otherSection(
|
||||
$servicesAPI->get_translation_management_systems(),
|
||||
__( 'Translation Management System', 'wpml-translation-management' )
|
||||
);
|
||||
|
||||
return $services;
|
||||
}
|
||||
|
||||
// buildPartnerServicesSections :: \WPML_TP_Services[] -> string[]
|
||||
private static function buildPartnerServicesSections( $buildSection, $userCountry ) {
|
||||
$headers = [
|
||||
'regular' => __( 'Partner Translation Services', 'wpml-translation-management' ),
|
||||
'inCountry' => __(
|
||||
sprintf(
|
||||
'Partner Translation Services in %s',
|
||||
isset( $userCountry['name'] ) ? $userCountry['name'] : ''
|
||||
),
|
||||
'wpml-translation-management'
|
||||
),
|
||||
'otherCountries' => __(
|
||||
'Other Partner Translation Services from Around the World',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
];
|
||||
|
||||
// $partnerSection :: $services -> $header -> string
|
||||
$partnerSection = $buildSection( Fns::__, Fns::__, true, Fns::__ );
|
||||
|
||||
// $regularPartnerSection :: $services -> string
|
||||
$regularPartnerSection = $partnerSection( Fns::__, $headers['regular'], true );
|
||||
|
||||
// $partnersInCountry :: $services -> string
|
||||
$partnersInCountry = $partnerSection( Fns::__, $headers['inCountry'], false );
|
||||
|
||||
// $partnersOther :: $services -> string
|
||||
$partnersOther = $partnerSection( Fns::__, $headers['otherCountries'], true );
|
||||
|
||||
// $getServicesFromCountry :: [$servicesFromCountry, $otherServices] -> $servicesFromCountry
|
||||
$inUserCountry = Lst::nth( 0 );
|
||||
// $getServicesFromOtherCountries :: [$servicesFromCountry, $otherServices] -> $otherServices
|
||||
$inOtherCountries = Lst::nth( 1 );
|
||||
|
||||
// $splitSections :: [$servicesFromCountry, $otherServices] -> [string, string]
|
||||
$splitSections = Fns::converge(
|
||||
Lst::make(),
|
||||
[
|
||||
pipe( $inUserCountry, $partnersInCountry ),
|
||||
pipe( $inOtherCountries, $partnersOther ),
|
||||
]
|
||||
);
|
||||
|
||||
// $hasUserCountry :: [$servicesFromCountry, $otherServices] -> bool
|
||||
$hasUserCountry = pipe( $inUserCountry, Logic::isEmpty(), Logic::not() );
|
||||
|
||||
return pipe(
|
||||
Lst::partition( self::belongToUserCountry( $userCountry ) ),
|
||||
Logic::ifElse(
|
||||
$hasUserCountry,
|
||||
$splitSections,
|
||||
pipe( $inOtherCountries, $regularPartnerSection, Lst::make() )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $mapService
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
private static function buildSection( $mapService ) {
|
||||
return curryN(
|
||||
4,
|
||||
function ( $services, $header, $showPopularity, $pagination ) use ( $mapService ) {
|
||||
return [
|
||||
'services' => Fns::map( Fns::unary( $mapService ), $services ),
|
||||
'header' => $header,
|
||||
'showPopularity' => $showPopularity,
|
||||
'pagination' => $pagination,
|
||||
];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// belongToUserCountry :: \WPML_TP_Service -> bool
|
||||
private static function belongToUserCountry( $userCountry ) {
|
||||
return pipe(
|
||||
invoke( 'get_countries' ),
|
||||
Fns::map( Obj::prop( 'code' ) ),
|
||||
Lst::find( Relation::equals( Obj::prop( 'code', $userCountry ) ) ),
|
||||
Logic::isNotNull()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices\Endpoints;
|
||||
|
||||
use WPML\Ajax\IHandler;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\FP\Either;
|
||||
use WPML\FP\Logic;
|
||||
use WPML\FP\Obj;
|
||||
use WPML\TM\TranslationProxy\Services\AuthorizationFactory;
|
||||
|
||||
class Activate implements IHandler {
|
||||
|
||||
public function run( Collection $data ) {
|
||||
$serviceId = $data->get( 'service_id' );
|
||||
$apiTokenData = $data->get( 'api_token' );
|
||||
|
||||
$authorize = function ( $serviceId ) use ( $apiTokenData ) {
|
||||
$authorization = ( new AuthorizationFactory )->create();
|
||||
try {
|
||||
$authorization->authorize( (object) Obj::pickBy( Logic::isNotEmpty(), $apiTokenData ) );
|
||||
|
||||
return Either::of( $serviceId );
|
||||
} catch ( \Exception $e ) {
|
||||
$authorization->deauthorize();
|
||||
|
||||
return Either::left( $e->getMessage() );
|
||||
}
|
||||
};
|
||||
|
||||
return Either::of( $serviceId )
|
||||
->chain( [ Select::class, 'select' ] )
|
||||
->chain( $authorize );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices\Endpoints;
|
||||
|
||||
use WPML\Ajax\IHandler;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\FP\Either;
|
||||
|
||||
class Deactivate implements IHandler {
|
||||
|
||||
public function run( Collection $data ) {
|
||||
if ( \TranslationProxy::get_current_service_id() ) {
|
||||
\TranslationProxy::clear_preferred_translation_service();
|
||||
\TranslationProxy::deselect_active_service();
|
||||
}
|
||||
|
||||
return Either::of( 'OK' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices\Endpoints;
|
||||
|
||||
use WPML\Ajax\IHandler;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\FP\Either;
|
||||
|
||||
class Select implements IHandler {
|
||||
|
||||
public function run( Collection $data ) {
|
||||
$serviceId = $data->get( 'service_id' );
|
||||
|
||||
return self::select( $serviceId );
|
||||
}
|
||||
|
||||
public static function select( $serviceId ) {
|
||||
$deactivateOldService = function () {
|
||||
\TranslationProxy::clear_preferred_translation_service();
|
||||
\TranslationProxy::deselect_active_service();
|
||||
};
|
||||
|
||||
$activateService = function ( $serviceId ) {
|
||||
$result = \TranslationProxy::select_service( $serviceId );
|
||||
|
||||
return \is_wp_error( $result ) ? Either::left( $result->get_error_message() ) : Either::of( $serviceId );
|
||||
};
|
||||
|
||||
|
||||
$currentServiceId = \TranslationProxy::get_current_service_id();
|
||||
if ( $currentServiceId ) {
|
||||
if ( $currentServiceId === $serviceId ) {
|
||||
return Either::of( $serviceId );
|
||||
} else {
|
||||
$deactivateOldService();
|
||||
}
|
||||
}
|
||||
|
||||
return $activateService( $serviceId );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices\Troubleshooting;
|
||||
|
||||
class RefreshServices {
|
||||
|
||||
const TEMPLATE = 'refresh-services.twig';
|
||||
const AJAX_ACTION = 'wpml_tm_refresh_services';
|
||||
|
||||
/**
|
||||
* @var \IWPML_Template_Service
|
||||
*/
|
||||
private $template;
|
||||
|
||||
/**
|
||||
* @var \WPML_TP_API_Services
|
||||
*/
|
||||
private $tp_services;
|
||||
|
||||
public function __construct( \IWPML_Template_Service $template, \WPML_TP_API_Services $tp_services ) {
|
||||
$this->template = $template;
|
||||
$this->tp_services = $tp_services;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'after_setup_complete_troubleshooting_functions', array( $this, 'render' ), 1 );
|
||||
add_action( 'wp_ajax_' . self::AJAX_ACTION, array( $this, 'refresh_services_ajax_handler' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
|
||||
public function render() {
|
||||
echo $this->template->show( $this->get_model(), self::TEMPLATE );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function get_model() {
|
||||
return array(
|
||||
'button_text' => __( 'Refresh Translation Services', 'wpml-translation-management' ),
|
||||
'nonce' => wp_create_nonce( self::AJAX_ACTION ),
|
||||
);
|
||||
}
|
||||
|
||||
public function refresh_services_ajax_handler() {
|
||||
if ( $this->is_valid_request() ) {
|
||||
if ( $this->refresh_services() ) {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'message' => __( 'Services Refreshed.', 'wpml-translation-management' ),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __(
|
||||
'WPML cannot load the list of translation services. This can be a connection problem. Please wait a minute and reload this page.
|
||||
If the problem continues, please contact WPML support.',
|
||||
'wpml-translation-management'
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => __( 'Invalid Request.', 'wpml-translation-management' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function refresh_services() {
|
||||
return $this->tp_services->refresh_cache() && $this->refresh_active_service();
|
||||
}
|
||||
|
||||
private function refresh_active_service() {
|
||||
$active_service = $this->tp_services->get_active();
|
||||
|
||||
if ( $active_service ) {
|
||||
$active_service = (object) (array) $active_service; // Cast to stdClass
|
||||
\TranslationProxy::build_and_store_active_translation_service( $active_service, $active_service->custom_fields_data );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function is_valid_request() {
|
||||
return isset( $_POST['nonce'] ) && wp_verify_nonce( $_POST['nonce'], self::AJAX_ACTION );
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'wpml-tm-refresh-services',
|
||||
WPML_TM_URL . '/res/js/refresh-services.js',
|
||||
array(),
|
||||
WPML_TM_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\Menu\TranslationServices\Troubleshooting;
|
||||
|
||||
use function WPML\Container\make;
|
||||
|
||||
class RefreshServicesFactory implements \IWPML_Backend_Action_Loader {
|
||||
|
||||
/**
|
||||
* @return RefreshServices|null
|
||||
* @throws \Auryn\InjectionException
|
||||
*/
|
||||
public function create() {
|
||||
$hooks = null;
|
||||
|
||||
if ( $this->is_visible() ) {
|
||||
$hooks = $this->create_an_instance();
|
||||
}
|
||||
|
||||
return $hooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RefreshServices
|
||||
* @throws \Auryn\InjectionException
|
||||
*/
|
||||
public function create_an_instance() {
|
||||
$templateService = make(
|
||||
\WPML_Twig_Template_Loader::class,
|
||||
[ ':paths' => [ WPML_TM_PATH . '/templates/menus/translation-services' ] ]
|
||||
);
|
||||
|
||||
$tpClientFactory = make( \WPML_TP_Client_Factory::class );
|
||||
|
||||
return new RefreshServices( $templateService->get_template(), $tpClientFactory->create()->services() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function is_visible() {
|
||||
return ( isset( $_GET['page'] ) && 'sitepress-multilingual-cms/menu/troubleshooting.php' === $_GET['page'] ) ||
|
||||
( isset( $_POST['action'] ) && RefreshServices::AJAX_ACTION === $_POST['action'] );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user