diff --git a/cyr-to-lat.php b/cyr-to-lat.php index ce1b58f..a19359a 100644 --- a/cyr-to-lat.php +++ b/cyr-to-lat.php @@ -10,7 +10,7 @@ * Plugin Name: Cyr-To-Lat * Plugin URI: https://wordpress.org/plugins/cyr2lat/ * Description: Convert Non-Latin characters in post and term slugs to Latin characters. Useful for creating human-readable URLs. Based on the original plugin by Anton Skorobogatov. - * Version: 5.1.0 + * Version: 5.2.0 * Requires at least: 5.1 * Requires PHP: 5.6.20 * Author: Sergey Biryukov, Mikhail Kobzarev, Igor Gergel @@ -36,7 +36,7 @@ /** * Plugin version. */ -define( 'CYR_TO_LAT_VERSION', '5.1.0' ); +define( 'CYR_TO_LAT_VERSION', '5.2.0' ); /** * Path to the plugin dir. diff --git a/readme.txt b/readme.txt index d42b2dd..1191056 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: SergeyBiryukov, mihdan, karevn, webvitaly, kaggdesign Tags: cyrillic, belorussian, ukrainian, bulgarian, macedonian, georgian, kazakh, latin, l10n, russian, cyr-to-lat, cyr2lat, rustolat, slugs, translations, transliteration Requires at least: 5.1 Tested up to: 5.8 -Stable tag: 5.1.0 +Stable tag: 5.2.0 Requires PHP: 5.6.20 Convert Non-Latin characters in post, page and term slugs to Latin characters. @@ -188,6 +188,9 @@ Yes you can! == Changelog == += 5.2.0 (27.07.2021) = +* Add support for categories and tags in other languages with wpml. + = 5.1.0 (19.07.2021) = * Fix issue-95 - 404 on localized terms created before plugin install. * Add cache flushing after batch conversion. diff --git a/src/php/Settings/Abstracts/SettingsBase.php b/src/php/Settings/Abstracts/SettingsBase.php index a7de44b..acf94f2 100644 --- a/src/php/Settings/Abstracts/SettingsBase.php +++ b/src/php/Settings/Abstracts/SettingsBase.php @@ -217,7 +217,6 @@ protected function parent_slug() { * Is this the main menu page. * * @return bool - * @noinspection PhpPureAttributeCanBeAddedInspection */ protected function is_main_menu_page() { // Main menu page should have empty string as parent slug. @@ -262,7 +261,7 @@ protected function is_tab() { * With Multisite active this can also include * 'network_active' and 'network_only' items. * - * @return array|mixed Plugin links + * @return array|string[] Plugin links */ public function add_settings_link( array $actions ) { $new_actions = [ diff --git a/src/php/Settings/Converter.php b/src/php/Settings/Converter.php index 980e334..db0c677 100644 --- a/src/php/Settings/Converter.php +++ b/src/php/Settings/Converter.php @@ -87,15 +87,6 @@ protected function section_title() { return ''; } - /** - * Get parent slug. - * - * @return string - */ - protected function parent_slug() { - return 'options-general.php'; - } - /** * Init class hooks. */ @@ -201,7 +192,7 @@ public function delayed_init_form_fields() { public function delayed_init_settings() { $this->delayed_init_form_fields(); - parent::init_settings(); + $this->init_settings(); } /** diff --git a/src/php/Settings/PluginSettingsBase.php b/src/php/Settings/PluginSettingsBase.php index fdc9177..f3b92ec 100644 --- a/src/php/Settings/PluginSettingsBase.php +++ b/src/php/Settings/PluginSettingsBase.php @@ -29,8 +29,6 @@ protected function plugin_basename() { * Get plugin url. * * @return string - * - * @noinspection PhpPureAttributeCanBeAddedInspection */ protected function plugin_url() { return constant( 'CYR_TO_LAT_URL' ); @@ -40,8 +38,6 @@ protected function plugin_url() { * Get plugin version. * * @return string - * - * @noinspection PhpPureAttributeCanBeAddedInspection */ protected function plugin_version() { return constant( 'CYR_TO_LAT_VERSION' ); diff --git a/src/php/Settings/Settings.php b/src/php/Settings/Settings.php index 7f603d3..ed37b73 100644 --- a/src/php/Settings/Settings.php +++ b/src/php/Settings/Settings.php @@ -48,6 +48,8 @@ public function __construct() { /** * Init class. + * + * @noinspection UnnecessaryCastingInspection */ protected function init() { // Allow to specify MENU_PAGES item as one class, not an array. diff --git a/src/php/Settings/Tables.php b/src/php/Settings/Tables.php index 16b48e8..d041058 100644 --- a/src/php/Settings/Tables.php +++ b/src/php/Settings/Tables.php @@ -96,16 +96,6 @@ protected function section_title() { return ''; } - /** - * Get parent slug. - * - * @return string - */ - protected function parent_slug() { - // Indicate that it is the main menu page. - return 'options-general.php'; - } - /** * Init locales. */ diff --git a/src/php/background-processes/class-conversion-process.php b/src/php/background-processes/class-conversion-process.php index 857b66f..a2bfb10 100644 --- a/src/php/background-processes/class-conversion-process.php +++ b/src/php/background-processes/class-conversion-process.php @@ -45,7 +45,7 @@ public function __construct( $main ) { * * @param mixed $item Queue item to iterate over. * - * @return mixed + * @return boolean */ protected function task( $item ) { return false; diff --git a/src/php/background-processes/class-post-conversion-process.php b/src/php/background-processes/class-post-conversion-process.php index c81b968..003e17a 100644 --- a/src/php/background-processes/class-post-conversion-process.php +++ b/src/php/background-processes/class-post-conversion-process.php @@ -52,7 +52,7 @@ public function __construct( $main ) { * * @param stdClass $post Queue item to iterate over. * - * @return mixed + * @return boolean * @noinspection PhpParameterNameChangedDuringInheritanceInspection */ protected function task( $post ) { diff --git a/src/php/background-processes/class-term-conversion-process.php b/src/php/background-processes/class-term-conversion-process.php index ac7c008..fa12fce 100644 --- a/src/php/background-processes/class-term-conversion-process.php +++ b/src/php/background-processes/class-term-conversion-process.php @@ -52,7 +52,7 @@ public function __construct( $main ) { * * @param stdClass $term Queue item to iterate over. * - * @return mixed + * @return boolean * @noinspection PhpParameterNameChangedDuringInheritanceInspection */ protected function task( $term ) { diff --git a/src/php/class-conversion-tables.php b/src/php/class-conversion-tables.php index 3be3f43..1603643 100644 --- a/src/php/class-conversion-tables.php +++ b/src/php/class-conversion-tables.php @@ -1203,7 +1203,6 @@ public static function get( $locale = '' ) { * On MacOS, files containing characters in the table, are sometimes encoded improperly. * * @return array - * @noinspection PhpArrayShapeAttributeCanBeAddedInspection */ public static function get_fix_table_for_mac() { /** diff --git a/src/php/class-main.php b/src/php/class-main.php index 8770e82..83d90ff 100644 --- a/src/php/class-main.php +++ b/src/php/class-main.php @@ -11,6 +11,8 @@ namespace Cyr_To_Lat; +use Polylang; +use SitePress; use WP_Error; use wpdb; use Exception; @@ -153,9 +155,15 @@ public function init_hooks() { add_filter( 'pre_insert_term', [ $this, 'pre_insert_term_filter' ], PHP_INT_MAX, 2 ); add_filter( 'get_terms_args', [ $this, 'get_terms_args_filter' ], PHP_INT_MAX, 2 ); - if ( class_exists( 'Polylang' ) ) { + if ( class_exists( Polylang::class ) ) { add_filter( 'locale', [ $this, 'pll_locale_filter' ] ); } + + if ( class_exists( SitePress::class ) ) { + // We cannot use locale filter here + // as WPML reverts locale at PHP_INT_MAX in \WPML\ST\MO\Hooks\LanguageSwitch::filterLocale. + add_filter( 'ctl_locale', [ $this, 'wpml_locale_filter' ], - PHP_INT_MAX ); + } } /** @@ -390,7 +398,7 @@ private function is_gutenberg_editor_active() { * @param array $data An array of slashed post data. * @param array $postarr An array of sanitized, but otherwise unmodified post data. * - * @return mixed + * @return array * @noinspection PhpUnusedParameterInspection */ public function sanitize_post_name( $data, $postarr = [] ) { @@ -579,6 +587,24 @@ private function pll_locale_filter_with_term() { return $pll_get_term_language; } + /** + * Locale filter for WPML. + * + * @param string $locale Locale. + * + * @return string + */ + public function wpml_locale_filter( $locale ) { + $language_code = wpml_get_current_language(); + $languages = apply_filters( 'wpml_active_languages', null ); + + if ( isset( $languages[ $language_code ] ) ) { + return $languages[ $language_code ]['default_locale']; + } + + return $locale; + } + /** * Changes array of items into string of items, separated by comma and sql-escaped * @@ -593,14 +619,15 @@ private function pll_locale_filter_with_term() { public function prepare_in( $items, $format = '%s' ) { global $wpdb; - $items = (array) $items; - $how_many = count( $items ); + $prepared_in = ''; + $items = (array) $items; + $how_many = count( $items ); + if ( $how_many > 0 ) { $placeholders = array_fill( 0, $how_many, $format ); $prepared_format = implode( ',', $placeholders ); - $prepared_in = $wpdb->prepare( $prepared_format, $items ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - } else { - $prepared_in = ''; + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $prepared_in = $wpdb->prepare( $prepared_format, $items ); } return $prepared_in; diff --git a/src/php/class-requirements.php b/src/php/class-requirements.php index 50dd72d..b3e3981 100644 --- a/src/php/class-requirements.php +++ b/src/php/class-requirements.php @@ -182,8 +182,6 @@ private function is_max_input_vars_required() { /** * Try to fix max_input_vars. - * - * @noinspection PhpStrFunctionsInspection */ protected function try_to_fix_max_input_vars() { $user_ini_filename = $this->get_user_ini_filename(); @@ -225,7 +223,6 @@ static function ( $line ) { * Get .user.ini filename. * * @return string - * @noinspection PhpPureAttributeCanBeAddedInspection */ private function get_user_ini_filename() { return ABSPATH . 'wp-admin/' . ini_get( 'user_ini.filename' ); @@ -238,7 +235,7 @@ private function ask_to_increase_max_input_vars() { $message = __( 'Please increase max input vars limit up to 1500.', 'cyr2lat' ); $message .= '
'; - $message .= __( 'See: Increasing max input vars limit.', 'cyr2lat' ); + $message .= __( 'See: Increasing max input vars limit.', 'cyr2lat' ); $this->admin_notices->add_notice( $message, diff --git a/tests/phpunit/bootstrap.php b/tests/phpunit/bootstrap.php index 93a64b6..4418110 100644 --- a/tests/phpunit/bootstrap.php +++ b/tests/phpunit/bootstrap.php @@ -42,7 +42,7 @@ /** * Plugin version. */ -define( 'CYR_TO_LAT_TEST_VERSION', '5.1.0' ); +define( 'CYR_TO_LAT_TEST_VERSION', '5.2.0' ); /** * Path to the plugin dir. diff --git a/tests/phpunit/tests/class-test-main.php b/tests/phpunit/tests/class-test-main.php index 6651f8f..34ff7f8 100644 --- a/tests/phpunit/tests/class-test-main.php +++ b/tests/phpunit/tests/class-test-main.php @@ -227,11 +227,12 @@ function ( $name ) { /** * Test init_hooks() * - * @param string $polylang Polylang is active. + * @param boolean $polylang Polylang is active. + * @param boolean $sitepress WPML is active. * * @dataProvider dp_test_init_hooks */ - public function test_init_hooks( $polylang ) { + public function test_init_hooks( $polylang, $sitepress ) { $subject = Mockery::mock( Main::class )->makePartial(); WP_Mock::expectFilterAdded( 'sanitize_title', [ $subject, 'sanitize_title' ], 9, 3 ); @@ -242,20 +243,31 @@ public function test_init_hooks( $polylang ) { FunctionMocker::replace( 'class_exists', - function ( $class ) use ( $polylang ) { + function ( $class ) use ( $polylang, $sitepress ) { if ( 'Polylang' === $class ) { return $polylang; } + if ( 'SitePress' === $class ) { + return $sitepress; + } + return null; } ); + if ( $polylang ) { WP_Mock::expectFilterAdded( 'locale', [ $subject, 'pll_locale_filter' ] ); } else { WP_Mock::expectFilterNotAdded( 'locale', [ $subject, 'pll_locale_filter' ] ); } + if ( $sitepress ) { + WP_Mock::expectFilterAdded( 'ctl_locale', [ $subject, 'wpml_locale_filter' ], - PHP_INT_MAX ); + } else { + WP_Mock::expectFilterNotAdded( 'ctl_locale', [ $subject, 'wpml_locale_filter' ] ); + } + $subject->init_hooks(); } @@ -266,8 +278,10 @@ function ( $class ) use ( $polylang ) { */ public function dp_test_init_hooks() { return [ - [ true ], - [ false ], + [ false, false ], + [ true, false ], + [ false, true ], + [ true, true ], ]; } @@ -1069,6 +1083,91 @@ function ( $type, $var_name, $filter ) use ( $term_lang_choice ) { self::assertSame( $pll_locale, $subject->pll_locale_filter( $locale ) ); } + /** + * Test wpml_locale_filter(). + * + * @param string $locale Current locale. + * @param string $language_code Current language code. + * @param string $expected Expected. + * + * @dataProvider dp_test_wpml_locale_filter + */ + public function test_wpml_locale_filter( $locale, $language_code, $expected ) { + $languages = [ + 'be' => + [ + 'code' => 'be', + 'id' => '64', + 'english_name' => 'Belarusian', + 'native_name' => 'Belarusian', + 'major' => '0', + 'active' => '1', + 'default_locale' => 'be_BY', + 'encode_url' => '0', + 'tag' => 'be', + 'display_name' => 'Belarusian', + ], + 'en' => + [ + 'code' => 'en', + 'id' => '1', + 'english_name' => 'English', + 'native_name' => 'English', + 'major' => '1', + 'active' => '1', + 'default_locale' => 'en_US', + 'encode_url' => '0', + 'tag' => 'en', + 'display_name' => 'English', + ], + 'ru' => + [ + 'code' => 'ru', + 'id' => '46', + 'english_name' => 'Russian', + 'native_name' => 'Русский', + 'major' => '1', + 'active' => '1', + 'default_locale' => 'ru_RU', + 'encode_url' => '0', + 'tag' => 'ru', + 'display_name' => 'Russian', + ], + 'uk' => + [ + 'code' => 'uk', + 'id' => '55', + 'english_name' => 'Ukrainian', + 'native_name' => 'Ukrainian', + 'major' => '0', + 'active' => '1', + 'default_locale' => 'uk', + 'encode_url' => '0', + 'tag' => 'uk', + 'display_name' => 'Ukrainian', + ], + ]; + + WP_Mock::userFunction( 'wpml_get_current_language' )->with()->andReturn( $language_code ); + WP_Mock::onFilter( 'wpml_active_languages' )->with( null )->reply( $languages ); + + $subject = Mockery::mock( Main::class )->makePartial(); + + self::assertSame( $expected, $subject->wpml_locale_filter( $locale ) ); + } + + /** + * Data provider for test_wpml_locale_filter(). + * + * @return array + */ + public function dp_test_wpml_locale_filter() { + return [ + 'Existing language code, return locale from wpml' => [ 'en_US', 'ru', 'ru_RU' ], + 'Not existing language code, return from current' => [ 'en_US', 'some', 'en_US' ], + ]; + } + /** * Test prepare_in() * diff --git a/tests/phpunit/tests/class-test-requirements.php b/tests/phpunit/tests/class-test-requirements.php index fdcdd90..20c17ab 100644 --- a/tests/phpunit/tests/class-test-requirements.php +++ b/tests/phpunit/tests/class-test-requirements.php @@ -283,7 +283,7 @@ public function test_vars_requirements_not_met( $within_timeout, $content, $expe $message = 'Please increase max input vars limit up to 1500.'; $message .= '
'; - $message .= 'See: Increasing max input vars limit.'; + $message .= 'See: Increasing max input vars limit.'; } $admin_notices->shouldReceive( 'add_notice' )->with( $message, 'notice notice-error', $screen_ids ); @@ -435,7 +435,7 @@ function ( $arg ) use ( $max_input_vars, $user_ini_filename, $ini_ttl ) { $message = 'Please increase max input vars limit up to 1500.'; $message .= '
'; - $message .= 'See: Increasing max input vars limit.'; + $message .= 'See: Increasing max input vars limit.'; $admin_notices->shouldReceive( 'add_notice' )->with( $message, 'notice notice-error', $screen_ids );