first commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Plugin_Localization_Utils {
|
||||
|
||||
/** @return array */
|
||||
public function get_plugins() {
|
||||
$plugins = get_plugins();
|
||||
$mu_plugins = wp_get_mu_plugins();
|
||||
|
||||
if ( $mu_plugins ) {
|
||||
foreach ( $mu_plugins as $p ) {
|
||||
$plugin_file = basename( $p );
|
||||
$plugins[ $plugin_file ] = array( 'Name' => 'MU :: ' . $plugin_file );
|
||||
}
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $plugin_file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_plugin_active( $plugin_file ) {
|
||||
$active_plugins = get_option( 'active_plugins', array() );
|
||||
|
||||
if ( in_array( $plugin_file, $active_plugins, true ) ) {
|
||||
$is_active = true;
|
||||
} else {
|
||||
$wpmu_sitewide_plugins = (array) maybe_unserialize( get_site_option( 'active_sitewide_plugins' ) );
|
||||
$is_active = array_key_exists( $plugin_file, $wpmu_sitewide_plugins );
|
||||
}
|
||||
|
||||
return $is_active;
|
||||
}
|
||||
|
||||
public function get_plugins_by_status( $active ) {
|
||||
$plugins = $this->get_plugins();
|
||||
|
||||
foreach ( $plugins as $plugin_file => $plugin ) {
|
||||
if ( $active && ! $this->is_plugin_active( $plugin_file ) ) {
|
||||
unset( $plugins[ $plugin_file ] );
|
||||
} elseif ( ! $active && $this->is_plugin_active( $plugin_file ) ) {
|
||||
unset( $plugins[ $plugin_file ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Localization_Utils {
|
||||
|
||||
/** @return array */
|
||||
public function get_theme_data() {
|
||||
$themes = wp_get_themes();
|
||||
$theme_data = array();
|
||||
|
||||
foreach ( $themes as $theme_folder => $theme ) {
|
||||
$theme_data[ $theme_folder ] = array(
|
||||
'path' => $theme->get_theme_root() . '/' . $theme->get_stylesheet(),
|
||||
'name' => $theme->get( 'Name' ),
|
||||
'TextDomain' => $theme->get( 'TextDomain' ),
|
||||
);
|
||||
}
|
||||
|
||||
return $theme_data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Options_UI {
|
||||
/** @var array */
|
||||
private $st_settings;
|
||||
|
||||
/**
|
||||
* WPML_ST_Theme_Plugin_Localization_Options_UI constructor.
|
||||
*
|
||||
* @param array $st_settings
|
||||
*/
|
||||
public function __construct( $st_settings ) {
|
||||
$this->st_settings = $st_settings;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'wpml_localization_options_ui_model', array( $this, 'add_st_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $model
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_st_options( $model ) {
|
||||
$model['top_options'][] = array(
|
||||
'name' => 'use_theme_plugin_domain',
|
||||
'type' => 'checkbox',
|
||||
'value' => 1,
|
||||
'label' => __( 'Use theme or plugin text domains when gettext calls do not use a string literal', 'wpml-string-translation' ),
|
||||
'tooltip' => __( "Some themes and plugins don't properly set the textdomain (second argument) in GetText calls. When you select this option, WPML will assume that the strings found in GetText calls in the PHP files of the theme and plugin should have the textdomain with the theme/plugin's name.", 'wpml-string-translation' ),
|
||||
'checked' => checked( true, ! empty( $this->st_settings['use_header_text_domains_when_missing'] ), false ),
|
||||
);
|
||||
|
||||
return $model;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Options_Settings implements IWPML_Action {
|
||||
|
||||
public function add_hooks() {
|
||||
add_filter( 'wpml_localization_options_settings', array( $this, 'add_st_settings' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_st_settings( $settings ) {
|
||||
$settings[ WPML_ST_Themes_And_Plugins_Settings::OPTION_NAME ] = array(
|
||||
'settings_var' => WPML_ST_Themes_And_Plugins_Settings::OPTION_NAME,
|
||||
'filter' => FILTER_SANITIZE_NUMBER_INT,
|
||||
'type' => 'option',
|
||||
'st_setting' => false,
|
||||
);
|
||||
$settings['use_theme_plugin_domain'] = array(
|
||||
'settings_var' => 'use_header_text_domains_when_missing',
|
||||
'filter' => FILTER_SANITIZE_NUMBER_INT,
|
||||
'type' => 'setting',
|
||||
'st_setting' => true,
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Resources {
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
}
|
||||
|
||||
public function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'wpml-theme-plugin-localization-scan',
|
||||
WPML_ST_URL . '/res/js/theme-plugin-localization/theme-plugin-localization.js',
|
||||
array( 'jquery-ui-dialog' ),
|
||||
WPML_ST_VERSION
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'wpml-theme-plugin-localization-scan',
|
||||
WPML_ST_URL . '/res/css/theme-plugin-localization.css',
|
||||
array(),
|
||||
WPML_ST_VERSION
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'wpml-theme-plugin-localization-scan',
|
||||
'wpml_groups_to_scan',
|
||||
get_option( WPML_ST_Themes_And_Plugins_Updates::WPML_ST_ITEMS_TO_SCAN, [] )
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'wpml-theme-plugin-localization-scan',
|
||||
'wpml_active_plugins_themes',
|
||||
$this->get_active_items()
|
||||
);
|
||||
}
|
||||
|
||||
private function get_active_items() {
|
||||
$items = array();
|
||||
|
||||
foreach ( get_plugins() as $key => $plugin ) {
|
||||
if ( is_plugin_active( $key ) ) {
|
||||
$items['plugin'][] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
$items['theme'][] = wp_get_theme()->get_template();
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Plugin_Localization_UI_Factory {
|
||||
|
||||
/**
|
||||
* @return WPML_ST_Plugin_Localization_UI
|
||||
*/
|
||||
public function create() {
|
||||
global $wpdb;
|
||||
|
||||
$localization = new WPML_Localization( $wpdb );
|
||||
$utils = new WPML_ST_Plugin_Localization_Utils();
|
||||
|
||||
return new WPML_ST_Plugin_Localization_UI( $localization, $utils );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Localization_UI_Factory {
|
||||
|
||||
const TEMPLATE_PATH = '/templates/theme-plugin-localization/';
|
||||
|
||||
/**
|
||||
* @return WPML_ST_Theme_Localization_UI
|
||||
*/
|
||||
public function create() {
|
||||
global $wpdb;
|
||||
|
||||
$localization = new WPML_Localization( $wpdb );
|
||||
$utils = new WPML_ST_Theme_Localization_Utils();
|
||||
|
||||
return new WPML_ST_Theme_Localization_UI( $localization, $utils, self::TEMPLATE_PATH );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Options_Settings_Factory implements IWPML_Backend_Action_Loader {
|
||||
|
||||
public function create() {
|
||||
return new WPML_ST_Theme_Plugin_Localization_Options_Settings();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Options_UI_Factory implements IWPML_Backend_Action_Loader, IWPML_Deferred_Action_Loader {
|
||||
|
||||
/** @return WPML_ST_Theme_Plugin_Localization_Options_UI */
|
||||
public function create() {
|
||||
global $sitepress;
|
||||
|
||||
$hooks = null;
|
||||
$current_screen = get_current_screen();
|
||||
|
||||
if ( isset( $current_screen->id ) && WPML_PLUGIN_FOLDER . '/menu/theme-localization' === $current_screen->id ) {
|
||||
$hooks = new WPML_ST_Theme_Plugin_Localization_Options_UI( $sitepress->get_setting( 'st' ) );
|
||||
}
|
||||
|
||||
return $hooks;
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function get_load_action() {
|
||||
return 'current_screen';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Plugin_Localization_Resources_Factory implements IWPML_Backend_Action_Loader {
|
||||
|
||||
/** @return WPML_ST_Theme_Plugin_Localization_Resources */
|
||||
public function create() {
|
||||
return new WPML_ST_Theme_Plugin_Localization_Resources();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Plugin_Localization_UI implements IWPML_Theme_Plugin_Localization_UI_Strategy {
|
||||
|
||||
/** @var WPML_ST_Plugin_Localization_Utils */
|
||||
private $utils;
|
||||
|
||||
/** @var WPML_Localization */
|
||||
private $localization;
|
||||
|
||||
/** @var string */
|
||||
private $base_st_url;
|
||||
|
||||
/**
|
||||
* WPML_ST_Plugin_Localization_UI constructor.
|
||||
*
|
||||
* @param WPML_Localization $localization
|
||||
* @param WPML_ST_Plugin_Localization_Utils $utils
|
||||
*/
|
||||
public function __construct(
|
||||
WPML_Localization $localization,
|
||||
WPML_ST_Plugin_Localization_Utils $utils ) {
|
||||
|
||||
$this->localization = $localization;
|
||||
$this->utils = $utils;
|
||||
$this->base_st_url = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function get_model() {
|
||||
|
||||
$model = array(
|
||||
'section_label' => __( 'Strings in the plugins', 'wpml-string-translation' ),
|
||||
'scan_button_label' => __( 'Scan selected plugins for strings', 'wpml-string-translation' ),
|
||||
'completed_title' => __( 'Completely translated strings', 'wpml-string-translation' ),
|
||||
'needs_update_title' => __( 'Strings in need of translation', 'wpml-string-translation' ),
|
||||
'component' => __( 'Plugin', 'wpml-string-translation' ),
|
||||
'domain' => __( 'Textdomain', 'wpml-string-translation' ),
|
||||
'all_text' => __( 'All', 'wpml-string-translation' ),
|
||||
'active_text' => __( 'Active', 'wpml-string-translation' ),
|
||||
'inactive_text' => __( 'Inactive', 'wpml-string-translation' ),
|
||||
'type' => 'plugin',
|
||||
'components' => $this->get_components( $this->utils->get_plugins(), $this->localization->get_localization_stats( 'plugin' ) ),
|
||||
'stats_id' => 'wpml_plugin_scan_stats',
|
||||
'scan_button_id' => 'wpml_plugin_localization_scan',
|
||||
'section_class' => 'wpml_plugin_localization',
|
||||
'nonces' => array(
|
||||
'scan_folder' => array(
|
||||
'action' => WPML_ST_Theme_Plugin_Scan_Dir_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Theme_Plugin_Scan_Dir_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
'scan_files' => array(
|
||||
'action' => WPML_ST_Theme_Plugin_Scan_Files_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Theme_Plugin_Scan_Files_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
'update_hash' => array(
|
||||
'action' => WPML_ST_Update_File_Hash_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Update_File_Hash_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
),
|
||||
'status_count' => array(
|
||||
'active' => count( $this->utils->get_plugins_by_status( true ) ),
|
||||
'inactive' => count( $this->utils->get_plugins_by_status( false ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $plugins
|
||||
* @param array $plugin_stats
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_components( $plugins, $plugin_stats ) {
|
||||
$components = array();
|
||||
$no_domain_stats = array(
|
||||
'complete' => 0,
|
||||
'incomplete' => 0,
|
||||
);
|
||||
|
||||
foreach ( $plugins as $plugin_file => $plugin_data ) {
|
||||
$domains = array_key_exists( $plugin_file, $plugin_stats ) ? $plugin_stats[ $plugin_file ] : false;
|
||||
|
||||
$components[ $plugin_file ] = array(
|
||||
'id' => md5( plugin_dir_path( WP_PLUGIN_URL . '/' . $plugin_file ) ),
|
||||
'file' => basename( $plugin_file ),
|
||||
'component_name' => $plugin_data['Name'],
|
||||
'active' => $this->utils->is_plugin_active( $plugin_file ),
|
||||
);
|
||||
|
||||
$components[ $plugin_file ]['domains'] = array();
|
||||
|
||||
if ( $domains ) {
|
||||
foreach ( $domains as $domain => $stats ) {
|
||||
$components[ $plugin_file ]['domains'][ $domain ] = $this->get_component( $domain, $stats );
|
||||
}
|
||||
} else {
|
||||
if ( ! array_key_exists( 'TextDomain', $plugin_data ) ) {
|
||||
$plugin_data['TextDomain'] = __( 'No TextDomain', 'wpml-string-translation' );
|
||||
}
|
||||
$components[ $plugin_file ]['domains'][ $plugin_data['TextDomain'] ] = $this->get_component( $plugin_data['TextDomain'], $no_domain_stats );
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param array $stats
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_component( $domain, array $stats ) {
|
||||
return array(
|
||||
'translated' => $stats['complete'],
|
||||
'needs_update' => $stats['incomplete'],
|
||||
'needs_update_link' => add_query_arg(
|
||||
array(
|
||||
'context' => $domain,
|
||||
'status' => ICL_STRING_TRANSLATION_NOT_TRANSLATED,
|
||||
),
|
||||
$this->base_st_url
|
||||
),
|
||||
'translated_link' => add_query_arg(
|
||||
array(
|
||||
'context' => $domain,
|
||||
'status' => ICL_STRING_TRANSLATION_COMPLETE,
|
||||
),
|
||||
$this->base_st_url
|
||||
),
|
||||
'domain_link' => add_query_arg( array( 'context' => $domain ), $this->base_st_url ),
|
||||
'title_needs_translation' => sprintf( __( 'Translate strings in %s', 'wpml-string-translation' ), $domain ),
|
||||
'title_all_strings' => sprintf( __( 'All strings in %s', 'wpml-string-translation' ), $domain ),
|
||||
);
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function get_template() {
|
||||
return 'theme-plugin-localization-ui.twig';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
class WPML_ST_Theme_Localization_UI implements IWPML_Theme_Plugin_Localization_UI_Strategy {
|
||||
|
||||
private $utils;
|
||||
private $template_path;
|
||||
private $localization;
|
||||
|
||||
/**
|
||||
* WPML_ST_Theme_Localization_UI constructor.
|
||||
*
|
||||
* @param \WPML_Localization $localization
|
||||
* @param \WPML_ST_Theme_Localization_Utils $utils
|
||||
* @param string $template_path
|
||||
*/
|
||||
public function __construct(
|
||||
WPML_Localization $localization,
|
||||
WPML_ST_Theme_Localization_Utils $utils,
|
||||
$template_path ) {
|
||||
|
||||
$this->localization = $localization;
|
||||
$this->utils = $utils;
|
||||
$this->template_path = $template_path;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function get_model() {
|
||||
|
||||
$model = array(
|
||||
'section_label' => __( 'Strings in the themes', 'wpml-string-translation' ),
|
||||
'scan_button_label' => __( 'Scan selected themes for strings', 'wpml-string-translation' ),
|
||||
'completed_title' => __( 'Completely translated strings', 'wpml-string-translation' ),
|
||||
'needs_update_title' => __( 'Strings in need of translation', 'wpml-string-translation' ),
|
||||
'component' => __( 'Theme', 'wpml-string-translation' ),
|
||||
'domain' => __( 'Textdomain', 'wpml-string-translation' ),
|
||||
'all_text' => __( 'All', 'wpml-string-translation' ),
|
||||
'active_text' => __( 'Active', 'wpml-string-translation' ),
|
||||
'inactive_text' => __( 'Inactive', 'wpml-string-translation' ),
|
||||
'type' => 'theme',
|
||||
'components' => $this->get_components(),
|
||||
'stats_id' => 'wpml_theme_scan_stats',
|
||||
'scan_button_id' => 'wpml_theme_localization_scan',
|
||||
'section_class' => 'wpml_theme_localization',
|
||||
'nonces' => array(
|
||||
'scan_folder' => array(
|
||||
'action' => WPML_ST_Theme_Plugin_Scan_Dir_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Theme_Plugin_Scan_Dir_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
'scan_files' => array(
|
||||
'action' => WPML_ST_Theme_Plugin_Scan_Files_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Theme_Plugin_Scan_Files_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
'update_hash' => array(
|
||||
'action' => WPML_ST_Update_File_Hash_Ajax_Factory::AJAX_ACTION,
|
||||
'nonce' => wp_create_nonce( WPML_ST_Update_File_Hash_Ajax_Factory::AJAX_ACTION ),
|
||||
),
|
||||
),
|
||||
'status_count' => array(
|
||||
'active' => 1,
|
||||
'inactive' => count( $this->utils->get_theme_data() ) - 1,
|
||||
),
|
||||
);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
private function get_components() {
|
||||
$components = array();
|
||||
$theme_localization_status = $this->localization->get_localization_stats( 'theme' );
|
||||
|
||||
$status_counters = array(
|
||||
'complete' => 0,
|
||||
'incomplete' => 0,
|
||||
);
|
||||
|
||||
foreach ( $this->utils->get_theme_data() as $theme_folder => $theme_data ) {
|
||||
$domains = array_key_exists( $theme_folder, $theme_localization_status ) ? $theme_localization_status[ $theme_folder ] : false;
|
||||
|
||||
$components[ $theme_folder ] = array(
|
||||
'id' => md5( $theme_data['path'] ),
|
||||
'component_name' => $theme_data['name'],
|
||||
'active' => wp_get_theme()->get( 'Name' ) === $theme_data['name'],
|
||||
);
|
||||
|
||||
$components[ $theme_folder ]['domains'] = array();
|
||||
|
||||
if ( $domains ) {
|
||||
foreach ( $domains as $domain => $stats ) {
|
||||
$components[ $theme_folder ]['domains'][ $domain ] = $this->get_component( $domain, $stats );
|
||||
}
|
||||
} else {
|
||||
if ( ! array_key_exists( 'TextDomain', $theme_data ) ) {
|
||||
$theme_data['TextDomain'] = __( 'No TextDomain', 'wpml-string-translation' );
|
||||
}
|
||||
$components[ $theme_folder ]['domains'][ $theme_data['TextDomain'] ] = $this->get_component( $theme_data['TextDomain'], $status_counters );
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $domain
|
||||
* @param array $stats
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_component( $domain, array $stats ) {
|
||||
$base_st_url = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' );
|
||||
return array(
|
||||
'translated' => $stats['complete'],
|
||||
'needs_update' => $stats['incomplete'],
|
||||
'needs_update_link' => add_query_arg(
|
||||
array(
|
||||
'context' => $domain,
|
||||
'status' => ICL_STRING_TRANSLATION_NOT_TRANSLATED,
|
||||
),
|
||||
$base_st_url
|
||||
),
|
||||
'translated_link' => add_query_arg(
|
||||
array(
|
||||
'context' => $domain,
|
||||
'status' => ICL_STRING_TRANSLATION_COMPLETE,
|
||||
),
|
||||
$base_st_url
|
||||
),
|
||||
'domain_link' => add_query_arg( array( 'context' => $domain ), $base_st_url ),
|
||||
'title_needs_translation' => sprintf( __( 'Translate strings in %s', 'wpml-string-translation' ), $domain ),
|
||||
'title_all_strings' => sprintf( __( 'All strings in %s', 'wpml-string-translation' ), $domain ),
|
||||
);
|
||||
}
|
||||
|
||||
/** @return string */
|
||||
public function get_template() {
|
||||
return 'theme-plugin-localization-ui.twig';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user