View source
<?php
class PERSIANTOOLS_CONST {
const RTL = 0;
const LTR = 1;
public static $FA_DIGITS = array(
'۰',
'۱',
'۲',
'۳',
'۴',
'۵',
'۶',
'۷',
'۸',
'۹',
);
const UN = 0;
const FA = 1;
const EN = 2;
const OPENING = 3;
const CLOSING = 4;
const DIGIT = 5;
const EOS = 6;
const SLASH = 7;
const WS = 8;
public static $OPENING_SYMS = array(
'(',
'{',
'[',
'"',
'\'',
);
public static $STATMENT_END = array(
'.',
'!',
';',
'?',
);
}
function persiantools_menu() {
$items['admin/config/persiantools'] = array(
'title' => 'Persian Tools',
'description' => 'Implements common features and missing fixes for the Perisan language.',
'position' => 'right',
'weight' => -5,
'page callback' => 'system_admin_menu_block_page',
'access arguments' => array(
'administer site configuration',
),
'file' => 'system.admin.inc',
'file path' => drupal_get_path('module', 'system'),
);
$items['admin/config/persiantools/settings'] = array(
'title' => 'Persian Tools Settings',
'description' => 'PersianTools features can be managed here!',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'persiantools_admin_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'persiantools.admin.inc',
);
return $items;
}
function persiantools_preprocess_html(&$variables) {
persiantools_convert_data($variables['page']['#children']);
}
function persiantools_convert_data(&$data) {
global $language;
$lang = $language->language;
if ($lang != 'fa' && $lang != 'ar') {
return;
}
$skip_tags = '(<(textarea|script|style)( [^>]*)?>(.*?)<\\/\\3>\\s*)';
$normal_tags = '(<\\/?[^>]+>\\s*)?([^<]*)(?=<)';
$chained_tags = '/(?s)(' . $skip_tags . '|' . $normal_tags . ')([^<]*)(?=<)/';
preg_match_all($chained_tags, $data, $matches);
$new_data = '';
for ($i = 0; $i < count($matches[0]); $i++) {
if (strlen($matches[7][$i]) + strlen($matches[8][$i]) > 0) {
$matches[7][$i] = persiantools_convert_sm($matches[7][$i] . $matches[8][$i]);
}
$new_data .= $matches[2][$i] . $matches[6][$i] . $matches[7][$i];
}
$data = $new_data;
}
function persiantools_ajax_render_alter(&$commands) {
foreach ($commands as &$item) {
if (array_key_exists('command', $item)) {
if ($item['command'] == "insert") {
if (array_key_exists('data', $item)) {
persiantools_convert_data($item['data']);
}
}
}
}
}
function persiantools_convert_sm($str) {
$is_all_en = TRUE;
$any_en = FALSE;
$digit_method = variable_get('persiantools_digit_method');
$rtl_ltr_fix = variable_get('persiantools_rtl_ltr_fix');
$closing_ch = '\\0';
$paren_state = 0;
$dir = PERSIANTOOLS_CONST::RTL;
$len = drupal_strlen($str);
for ($i = 0; $i < $len; $i = $i + 1) {
$ch = drupal_substr($str, $i, 1);
if ($ch == '&') {
for ($j = $i; $j < $len; $j = $j + 1) {
if (drupal_substr($str, $j, 1) == ';') {
$i = $j;
continue 2;
}
elseif ($j > $i + 9) {
break;
}
}
}
$type = persiantools_get_char_type($ch);
if ($type == PERSIANTOOLS_CONST::FA) {
$is_all_en = FALSE;
}
elseif ($ch == $closing_ch) {
$type = PERSIANTOOLS_CONST::CLOSING;
}
elseif ($type == PERSIANTOOLS_CONST::UN) {
if ($i != $len - 1) {
continue;
}
}
if ($rtl_ltr_fix) {
list($str, $changed) = persiantools_fix_mixed_path($str, $ch, $type, $i, $len);
if ($changed) {
$i += 5;
$len += 5;
}
}
switch ($type) {
case PERSIANTOOLS_CONST::DIGIT:
if ($digit_method == 'full' || $digit_method == 'smart' && $dir == PERSIANTOOLS_CONST::RTL && !($is_all_en && $any_en)) {
$new_digit = PERSIANTOOLS_CONST::$FA_DIGITS[$ch - '0'];
$str = drupal_substr($str, 0, $i) . $new_digit . drupal_substr($str, $i + 1);
$len += drupal_strlen($new_digit) - 1;
$i += drupal_strlen($new_digit) - 1;
}
break;
case PERSIANTOOLS_CONST::EN:
$dir = PERSIANTOOLS_CONST::LTR;
$any_en = TRUE;
break;
case PERSIANTOOLS_CONST::FA:
$dir = PERSIANTOOLS_CONST::RTL;
break;
case PERSIANTOOLS_CONST::OPENING:
$opening_pos = $i;
$paren_state = 1;
break;
}
if ($rtl_ltr_fix) {
switch ($paren_state) {
case 1:
$pre_open = $dir;
$closing_ch = persiantools_get_closing_char($ch);
$paren_state = 2;
break;
case 2:
if ($type == PERSIANTOOLS_CONST::CLOSING) {
if ($dir == PERSIANTOOLS_CONST::LTR) {
$str = persiantools_insert_str($str, '‎', $i + 1);
$len += 5;
$i += 5;
}
$paren_state = 0;
}
elseif ($type == PERSIANTOOLS_CONST::EN || $type == PERSIANTOOLS_CONST::FA) {
$post_open = $dir;
$paren_state = 3;
}
break;
case 3:
if ($type == PERSIANTOOLS_CONST::CLOSING) {
$pre_close = $dir;
$paren_state = 4;
$closed_pos = $i;
}
break;
case 4:
if ($type == PERSIANTOOLS_CONST::EN || $type == PERSIANTOOLS_CONST::FA) {
$post_close = $dir;
$paren_state = 5;
}
break;
}
if ($paren_state == 4 && $i == $len - 1) {
$post_close = PERSIANTOOLS_CONST::RTL;
$paren_state = 5;
}
if ($paren_state == 5) {
if ($pre_open == $post_open) {
$open_dir = $pre_open;
}
else {
$open_dir = PERSIANTOOLS_CONST::RTL;
}
if ($pre_close == $post_close) {
$close_dir = $pre_close;
}
else {
$close_dir = PERSIANTOOLS_CONST::RTL;
}
if ($open_dir != $close_dir) {
if ($pre_open == PERSIANTOOLS_CONST::RTL) {
$str = persiantools_insert_str($str, '‏', $closed_pos);
$len += 5;
$i += 5;
}
elseif ($pre_open == PERSIANTOOLS_CONST::LTR) {
$str = persiantools_insert_str($str, '‪', $opening_pos);
$str = persiantools_insert_str($str, '‬', $closed_pos + 8);
$len += 14;
$i += 14;
}
$paren_state = 0;
}
}
if ($is_all_en && $dir == PERSIANTOOLS_CONST::LTR && $type == PERSIANTOOLS_CONST::EOS) {
if ($i < $len - 1) {
$next_ch = drupal_substr($str, $i + 1, 1);
$next_type = persiantools_get_char_type($next_ch);
if ($next_type == PERSIANTOOLS_CONST::EN) {
continue;
}
}
$str = persiantools_insert_str($str, '‎', $i + 1);
$i += 5;
$len += 5;
}
}
}
return $str;
}
function persiantools_fix_mixed_path($str, $ch, $type, $i, $len) {
static $maybe_path = TRUE;
static $is_path = FALSE;
static $path_pos = -1;
$changed = FALSE;
if ($i == 0) {
$maybe_path = TRUE;
}
if ($type == PERSIANTOOLS_CONST::WS) {
$maybe_path = TRUE;
}
elseif ($is_path) {
if ($type == PERSIANTOOLS_CONST::EN) {
$str = persiantools_insert_str($str, '‎', $path_pos);
$changed = TRUE;
}
$path_pos = -1;
$is_path = FALSE;
}
elseif ($maybe_path) {
if ($type == PERSIANTOOLS_CONST::SLASH) {
$is_path = TRUE;
if ($path_pos < 0) {
$path_pos = $i;
}
}
elseif ($ch == '.') {
if ($path_pos < 0) {
$path_pos = $i;
}
}
else {
$maybe_path = FALSE;
$is_path = FALSE;
$path_pos = -1;
}
}
if ($type == PERSIANTOOLS_CONST::SLASH && $i > 0) {
$prev_ch = drupal_substr($str, $i - 1, 1);
$prev_ch_type = persiantools_get_char_type($prev_ch);
$is_last_char = $i == $len - 1;
if ($prev_ch_type == PERSIANTOOLS_CONST::EN && ($is_last_char || drupal_substr($str, $i + 1, 1) == ' ')) {
$str = persiantools_insert_str($str, '‎', $i + 1);
$changed = TRUE;
}
}
return array(
$str,
$changed,
);
}
function persiantools_get_char_type($ch) {
if ($ch >= 'آ' && $ch <= 'ي' || $ch == 'ی') {
$type = PERSIANTOOLS_CONST::FA;
}
elseif ($ch >= 'a' && $ch <= 'z' || $ch >= 'A' && $ch <= 'Z') {
$type = PERSIANTOOLS_CONST::EN;
}
elseif (in_array($ch, PERSIANTOOLS_CONST::$OPENING_SYMS)) {
$type = PERSIANTOOLS_CONST::OPENING;
}
elseif ($ch >= '0' && $ch <= '9') {
$type = PERSIANTOOLS_CONST::DIGIT;
}
elseif (in_array($ch, PERSIANTOOLS_CONST::$STATMENT_END)) {
$type = PERSIANTOOLS_CONST::EOS;
}
elseif ($ch == '/') {
$type = PERSIANTOOLS_CONST::SLASH;
}
elseif ($ch == ' ' || $ch == '\\n') {
$type = PERSIANTOOLS_CONST::WS;
}
else {
$type = PERSIANTOOLS_CONST::UN;
}
return $type;
}
function persiantools_get_closing_char($char) {
switch ($char) {
case '(':
return ')';
case '{':
return '}';
case '[':
return ']';
case '\'':
case '"':
return $char;
}
}
function persiantools_insert_str($str, $char, $pos) {
return drupal_substr($str, 0, $pos) . $char . drupal_substr($str, $pos);
}