Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
Bidi
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
2 / 2
4
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 process
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace Wikimedia\Leximorph\Handler;
8
9use Wikimedia\Leximorph\Provider;
10
11/**
12 * Bidi
13 *
14 * The Bidi class applies bidirectional formatting to text by wrapping the input
15 * with directional isolation control characters. It detects the primary directionality
16 * (left-to-right or right-to-left) of the text and ensures that mixed-direction content
17 * is rendered correctly.
18 *
19 * Usage Example:
20 * <code>
21 *            echo $bidi->process( 'Hello World' );
22 * </code>
23 *
24 * @since     1.45
25 * @author    Doğu Abaris (abaris@null.net)
26 * @license   https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
27 */
28class Bidi {
29
30    /**
31     * Unicode LEFT-TO-RIGHT EMBEDDING character (U+202A).
32     */
33    public const LRE = "\xE2\x80\xAA";
34
35    /**
36     * Unicode RIGHT-TO-LEFT EMBEDDING character (U+202B).
37     */
38    public const RLE = "\xE2\x80\xAB";
39
40    /**
41     * Unicode POP DIRECTIONAL FORMATTING character (U+202C).
42     */
43    public const PDF = "\xE2\x80\xAC";
44
45    /**
46     * Initializes the Bidi handler with the provider.
47     *
48     * @param Provider $provider The provider instance to use.
49     *
50     * @since 1.45
51     */
52    public function __construct(
53        private readonly Provider $provider,
54    ) {
55    }
56
57    /**
58     * Applies bidirectional formatting to the provided text.
59     *
60     * This method determines the primary text direction (LTR or RTL) by
61     * examining the first strongly directional codepoint in the string.
62     * It then wraps the text with the appropriate directional control
63     * characters: LRE and PDF for left-to-right, RLE and PDF for right-to-left.
64     * If no strong directionality is detected, the text is returned
65     * unmodified.
66     *
67     * @param string $value The text to format.
68     *
69     * @since 1.45
70     * @return string The text with directional controls, or the original text.
71     */
72    public function process( string $value ): string {
73        $dir = $this->provider->getBidiProvider()->getDirection( $value );
74        if ( $dir === 'ltr' ) {
75            # Wrap in LEFT-TO-RIGHT EMBEDDING ... POP DIRECTIONAL FORMATTING
76            return self::LRE . $value . self::PDF;
77        }
78        if ( $dir === 'rtl' ) {
79            # Wrap in RIGHT-TO-LEFT EMBEDDING ... POP DIRECTIONAL FORMATTING
80            return self::RLE . $value . self::PDF;
81        }
82
83        # No strong directionality: return the text unmodified
84        return $value;
85    }
86}