Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V6.0.8 #150

Merged
merged 6 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cyr-to-lat.php
Original file line number Diff line number Diff line change
Expand Up @@ -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: 6.0.7
* Version: 6.0.8
* Requires at least: 5.1
* Requires PHP: 7.0.0
* Author: Sergey Biryukov, Mikhail Kobzarev, Igor Gergel
Expand Down Expand Up @@ -43,7 +43,7 @@
/**
* Plugin version.
*/
define( 'CYR_TO_LAT_VERSION', '6.0.7' );
define( 'CYR_TO_LAT_VERSION', '6.0.8' );

/**
* Path to the plugin dir.
Expand Down
6 changes: 5 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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: 6.4
Stable tag: 6.0.7
Stable tag: 6.0.8
Requires PHP: 7.0.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Expand Down Expand Up @@ -221,6 +221,10 @@ Yes, you can!

== Changelog ==

= 6.0.8 (14.02.2024) =
* Improved detection of the Gutenberg editor.
* Fixed processing of product attributes.

= 6.0.7 (11.02.2024) =
* Tested with WooCommerce 8.5.
* Added redirect from the cyrillic post title when creating a new post.
Expand Down
65 changes: 27 additions & 38 deletions src/php/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ public function woocommerce_after_template_part_filter() {
* @noinspection PhpUndefinedFunctionInspection
*/
protected function is_wc_attribute_taxonomy( string $title ): bool {
$title = str_replace( 'pa_', '', $title );
$title = preg_replace( '/^pa_/', '', $title );

foreach ( wc_get_attribute_taxonomies() as $attribute_taxonomy ) {
if ( $title === $attribute_taxonomy->attribute_name ) {
Expand All @@ -396,22 +396,28 @@ protected function is_wc_attribute_taxonomy( string $title ): bool {
}

/**
* Check if title is a product attribute.
* Check if title is a product not converted attribute.
*
* @param string $title Title.
*
* @return bool
* @noinspection PhpUndefinedFunctionInspection
*/
protected function is_wc_product_attribute( string $title ): bool {
protected function is_wc_product_not_converted_attribute( string $title ): bool {

global $product;

if ( null === $product ) {
if ( ! is_a( $product, 'WC_Product' ) ) {
return false;
}

foreach ( $product->get_attributes() as $attribute ) {
if ( $title === $attribute->get_name() ) {
// We have to get attributes from postmeta here to see the converted slug.
$attributes = (array) get_post_meta( $product->get_id(), '_product_attributes', true );

foreach ( $attributes as $slug => $attribute ) {
$name = $attribute['name'] ?? '';

if ( $name === $title && sanitize_title_with_dashes( $title ) === $slug ) {
return true;
}
}
Expand All @@ -432,7 +438,7 @@ protected function is_wc_attribute( string $title ): bool {
return false;
}

return $this->is_wc_attribute_taxonomy( $title ) || $this->is_wc_product_attribute( $title );
return $this->is_wc_attribute_taxonomy( $title ) || $this->is_wc_product_not_converted_attribute( $title );
}

/**
Expand Down Expand Up @@ -536,48 +542,31 @@ public function transliterate( string $str ): string {
}

/**
* Check if Classic Editor plugin is active.
*
* @link https://kagg.eu/how-to-catch-gutenberg/
* Check if the Block Editor is active.
* Must only be used after plugins_loaded action is fired.
*
* @return bool
* @noinspection PhpUndefinedFunctionInspection
*/
private function is_classic_editor_plugin_active(): bool {
private function is_gutenberg_editor_active(): bool {
// Gutenberg plugin is installed and activated.
// This filter was removed in WP 5.5.
if ( has_filter( 'replace_editor', 'gutenberg_init' ) ) {
return true;
}

// @codeCoverageIgnoreStart
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once ABSPATH . 'wp-admin/includes/plugin.php';
}

// @codeCoverageIgnoreEnd

return is_plugin_active( 'classic-editor/classic-editor.php' );
}

/**
* Check if Block Editor is active.
* Must only be used after plugins_loaded action is fired.
*
* @link https://kagg.eu/how-to-catch-gutenberg/
*
* @return bool
*/
private function is_gutenberg_editor_active(): bool {

// Gutenberg plugin is installed and activated.
$gutenberg = ! ( false === has_filter( 'replace_editor', 'gutenberg_init' ) );

// Block editor since 5.0.
$block_editor = version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' );

if ( ! $gutenberg && ! $block_editor ) {
return false;
if ( is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
return in_array( get_option( 'classic-editor-replace' ), [ 'no-replace', 'block' ], true );
}

if ( $this->is_classic_editor_plugin_active() ) {
$editor_option = get_option( 'classic-editor-replace' );
$block_editor_active = [ 'no-replace', 'block' ];

return in_array( $editor_option, $block_editor_active, true );
if ( is_plugin_active( 'disable-gutenberg/disable-gutenberg.php' ) ) {
return ! disable_gutenberg();
}

return true;
Expand Down
111 changes: 74 additions & 37 deletions tests/unit/MainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class MainTest extends CyrToLatTestCase {
public function tearDown(): void {
// phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:disable WordPress.Security.NonceVerification.Recommended
unset( $GLOBALS['wp_version'], $GLOBALS['wpdb'], $GLOBALS['current_screen'], $GLOBALS['product'], $_POST, $_GET );
unset( $GLOBALS['wpdb'], $GLOBALS['current_screen'], $GLOBALS['product'], $_POST, $_GET );
// phpcs:enable WordPress.Security.NonceVerification.Recommended
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
Expand Down Expand Up @@ -779,36 +779,30 @@ static function ( $function_name ) use ( $is_wc ) {
}

/**
* Test is_wc_product_attribute().
* Test is_wc_product_not_converted_attribute().
*
* @param string $title Title.
* @param bool $is_product Whether it is a product page.
* @param array $names Attribute names.
* @param array $attributes Attribute names.
* @param bool $expected Expected result.
*
* @dataProvider dp_test_is_wc_product_attribute
* @throws ReflectionException ReflectionException.
*/
public function test_is_wc_product_attribute( string $title, bool $is_product, array $names, bool $expected ) {
$method = 'is_wc_product_attribute';
$subject = $this->get_subject();
public function test_is_wc_product_not_converted_attribute( string $title, bool $is_product, array $attributes, bool $expected ) {
$product_id = 5;
$method = 'is_wc_product_not_converted_attribute';
$subject = $this->get_subject();

$this->set_method_accessibility( $subject, $method );

$attributes = [];

foreach ( $names as $name ) {
$attribute = Mockery::mock( 'WC_Product_Attribute' );

$attribute->shouldReceive( 'get_name' )->andReturn( $name );

$attributes[] = $attribute;
}

$product = Mockery::mock( 'WC_Product' );
$product->shouldReceive( 'get_attributes' )->andReturn( $attributes );
$product->shouldReceive( 'get_id' )->andReturn( $product_id );
$GLOBALS['product'] = $is_product ? $product : null;

WP_Mock::userFunction( 'get_post_meta' )->with( $product_id, '_product_attributes', true )->andReturn( $attributes );
WP_Mock::passthruFunction( 'sanitize_title_with_dashes' );

self::assertSame( $expected, $subject->$method( $title ) );
}

Expand All @@ -821,8 +815,16 @@ public function dp_test_is_wc_product_attribute(): array {
return [
'not a product page' => [ 'атрибут 1', false, [], false ],
'no attributes' => [ 'атрибут 1', true, [], false ],
'no matching' => [ 'атрибут 1', true, [ 'some' ], false ],
'matching' => [ 'атрибут 1', true, [ 'some', 'атрибут 1' ], true ],
'no matching' => [ 'атрибут 1', true, [ 'some' => [ 'name' => 'some' ] ], false ],
'matching' => [
'атрибут 1',
true,
[
'some' => [ 'name' => 'some' ],
'атрибут 1' => [ 'name' => 'атрибут 1' ],
],
true,
],
];
}

Expand Down Expand Up @@ -1135,8 +1137,6 @@ public static function dp_test_min_suffix(): array {
* Test that sanitize_post_name() does nothing if no Block/Gutenberg editor is active
*/
public function test_sanitize_post_name_without_gutenberg() {
$subject = Mockery::mock( Main::class )->makePartial()->shouldAllowMockingProtectedMethods();

$data = [ 'something' ];

WP_Mock::userFunction(
Expand All @@ -1146,13 +1146,6 @@ public function test_sanitize_post_name_without_gutenberg() {
'return' => false,
]
);

// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$GLOBALS['wp_version'] = '4.9';
self::assertSame( $data, $subject->sanitize_post_name( $data ) );

FunctionMocker::replace( 'function_exists', true );

WP_Mock::userFunction(
'is_plugin_active',
[
Expand All @@ -1161,7 +1154,6 @@ public function test_sanitize_post_name_without_gutenberg() {
'return' => true,
]
);

WP_Mock::userFunction(
'get_option',
[
Expand All @@ -1171,8 +1163,45 @@ public function test_sanitize_post_name_without_gutenberg() {
]
);

// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$GLOBALS['wp_version'] = '5.0';
$subject = Mockery::mock( Main::class )->makePartial()->shouldAllowMockingProtectedMethods();

self::assertSame( $data, $subject->sanitize_post_name( $data ) );
}

/**
* Test that sanitize_post_name() does nothing if Disable Gutenberg plugin is active
*/
public function test_sanitize_post_name_with_disable_gutenberg_plugin() {
$data = [ 'something' ];

WP_Mock::userFunction(
'has_filter',
[
'args' => [ 'replace_editor', 'gutenberg_init' ],
'return' => false,
]
);
WP_Mock::userFunction(
'is_plugin_active',
[
'times' => 1,
'args' => [ 'classic-editor/classic-editor.php' ],
'return' => false,
]
);
WP_Mock::userFunction(
'is_plugin_active',
[
'times' => 1,
'args' => [ 'disable-gutenberg/disable-gutenberg.php' ],
'return' => true,
]
);

$subject = Mockery::mock( Main::class )->makePartial()->shouldAllowMockingProtectedMethods();

FunctionMocker::replace( 'disable_gutenberg', true );

self::assertSame( $data, $subject->sanitize_post_name( $data ) );
}

Expand All @@ -1190,9 +1219,6 @@ public function test_sanitize_post_name_not_post_edit_screen() {
]
);

// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$GLOBALS['wp_version'] = '5.0';

$subject = Mockery::mock( Main::class )->makePartial()->shouldAllowMockingProtectedMethods();
FunctionMocker::replace( 'function_exists', true );

Expand All @@ -1203,6 +1229,13 @@ public function test_sanitize_post_name_not_post_edit_screen() {
'return' => false,
]
);
WP_Mock::userFunction(
'is_plugin_active',
[
'args' => [ 'disable-gutenberg/disable-gutenberg.php' ],
'return' => false,
]
);

$current_screen = Mockery::mock( WP_Screen::class );
$current_screen->base = 'not post';
Expand All @@ -1226,9 +1259,6 @@ public function test_sanitize_post_name_not_post_edit_screen() {
*/
public function test_sanitize_post_name( array $data, array $expected ) {

// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$GLOBALS['wp_version'] = '5.0';

$subject = Mockery::mock( Main::class )->makePartial()->shouldAllowMockingProtectedMethods();
FunctionMocker::replace( 'function_exists', true );

Expand All @@ -1239,6 +1269,13 @@ public function test_sanitize_post_name( array $data, array $expected ) {
'return' => false,
]
);
WP_Mock::userFunction(
'is_plugin_active',
[
'args' => [ 'disable-gutenberg/disable-gutenberg.php' ],
'return' => false,
]
);

$current_screen = Mockery::mock( WP_Screen::class );
$current_screen->base = 'post';
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
/**
* Plugin version.
*/
const CYR_TO_LAT_TEST_VERSION = '6.0.7';
const CYR_TO_LAT_TEST_VERSION = '6.0.8';

/**
* Path to the plugin dir.
Expand Down
Loading