You are here

static function RTLMaker::convert_sm in PersianTools 8

Main function for multiple features and fixes of persiantools module.

1 call to RTLMaker::convert_sm()
persiantools_post_render_rtl in ./persiantools.module

File

src/RTLMaker.php, line 38
Contains \Drupal\persiantools\RTLMaker.

Class

RTLMaker

Namespace

Drupal\persiantools

Code

static function convert_sm($str, $digit_method, $rtl_ltr_fix) {
  $is_all_en = TRUE;
  $any_en = FALSE;
  $closing_ch = '\\0';
  $paren_state = 0;
  $dir = RTLMaker::RTL;
  $len = Unicode::strlen($str);
  for ($i = 0; $i < $len; $i = $i + 1) {
    $ch = Unicode::substr($str, $i, 1);

    // Skip unicode characters, which might be mistaken for english characters
    // (e.g. &nbsp;).
    if ($ch == '&') {
      for ($j = $i; $j < $len; $j = $j + 1) {
        if (Unicode::substr($str, $j, 1) == ';') {
          $i = $j;
          continue 2;
        }
        elseif ($j > $i + 9) {
          break;
        }
      }
    }
    $type = RTLMaker::get_char_type($ch);
    if ($type == RTLMaker::FA) {
      $is_all_en = FALSE;
    }
    elseif ($ch == $closing_ch) {
      $type = RTLMaker::CLOSING;
    }
    elseif ($type == RTLMaker::UN) {

      // Last char should go through anyway, to wrap things up.
      if ($i != $len - 1) {
        continue;
      }
    }
    if ($rtl_ltr_fix) {
      list($str, $changed) = RTLMaker::fix_mixed_path($str, $ch, $type, $i, $len);
      if ($changed) {
        $i += 5;
        $len += 5;
      }
    }
    switch ($type) {
      case RTLMaker::DIGIT:
        if ($digit_method == 'full' || $digit_method == 'smart' && $dir == RTLMaker::RTL && !($is_all_en && $any_en)) {
          $new_digit = RTLMaker::$FA_DIGITS[$ch - '0'];
          $str = Unicode::substr($str, 0, $i) . $new_digit . Unicode::substr($str, $i + 1);
          $len += Unicode::strlen($new_digit) - 1;
          $i += Unicode::strlen($new_digit) - 1;
        }
        break;
      case RTLMaker::EN:
        $dir = RTLMaker::LTR;
        $any_en = TRUE;
        break;
      case RTLMaker::FA:
        $dir = RTLMaker::RTL;
        break;
      case RTLMaker::OPENING:
        $opening_pos = $i;
        $paren_state = 1;
        break;
    }

    // Fix misplaced enclosing chars, like paranthesis, bracket, quotation, ...
    if ($rtl_ltr_fix) {
      switch ($paren_state) {
        case 1:
          $pre_open = $dir;
          $closing_ch = RTLMaker::get_closing_char($ch);
          $paren_state = 2;
          break;
        case 2:
          if ($type == RTLMaker::CLOSING) {

            // Fix misplaced empty enclosing chars, like function calls, array
            // access, ...
            if ($dir == RTLMaker::LTR) {
              $str = RTLMaker::insert_str($str, '&lrm;', $i + 1);
              $len += 5;
              $i += 5;
            }
            $paren_state = 0;
          }
          elseif ($type == RTLMaker::EN || $type == RTLMaker::FA) {
            $post_open = $dir;
            $paren_state = 3;
          }
          break;
        case 3:
          if ($type == RTLMaker::CLOSING) {
            $pre_close = $dir;
            $paren_state = 4;
            $closed_pos = $i;
          }
          break;
        case 4:
          if ($type == RTLMaker::EN || $type == RTLMaker::FA) {
            $post_close = $dir;
            $paren_state = 5;
          }
          break;
      }
      if ($paren_state == 4 && $i == $len - 1) {
        $post_close = RTLMaker::RTL;
        $paren_state = 5;
      }
      if ($paren_state == 5) {
        if ($pre_open == $post_open) {
          $open_dir = $pre_open;
        }
        else {
          $open_dir = RTLMaker::RTL;
        }
        if ($pre_close == $post_close) {
          $close_dir = $pre_close;
        }
        else {
          $close_dir = RTLMaker::RTL;
        }
        if ($open_dir != $close_dir) {
          if ($pre_open == RTLMaker::RTL) {
            $str = RTLMaker::insert_str($str, '&rlm;', $closed_pos);
            $len += 5;
            $i += 5;
          }
          elseif ($pre_open == RTLMaker::LTR) {

            // &#8234; lre (Left to Right Embedding).
            // &#8236: pdf (Pop Directional Formatting).
            $str = RTLMaker::insert_str($str, '&#8234;', $opening_pos);
            $str = RTLMaker::insert_str($str, '&#8236;', $closed_pos + 8);
            $len += 14;
            $i += 14;
          }
          $paren_state = 0;
        }
      }

      // Fix misplaced dot in English Sentences inside RTL direction.
      if ($is_all_en && $dir == RTLMaker::LTR && $type == RTLMaker::EOS) {
        if ($i < $len - 1) {
          $next_ch = Unicode::substr($str, $i + 1, 1);
          $next_type = RTLMaker::get_char_type($next_ch);
          if ($next_type == RTLMaker::EN) {
            continue;
          }
        }
        $str = RTLMaker::insert_str($str, '&lrm;', $i + 1);
        $i += 5;
        $len += 5;
      }
    }
  }
  return $str;
}