I18N_Arabic

# Source for file Arabic.php

Documentation is available at Arabic.php

1. <?php
2. /**
3. * ----------------------------------------------------------------------
4. *
5. * Copyright (c) 2006-2016 Khaled Al-Shamaa.
6. *
7. * http://www.ar-php.org
8. *
9. * PHP Version 5
10. *
11. * ----------------------------------------------------------------------
12. *
13. * LICENSE
14. *
15. * This program is open source product; you can redistribute it and/or
16. * modify it under the terms of the GNU Lesser General Public License (LGPL)
17. * as published by the Free Software Foundation; either version 3
18. * of the License, or (at your option) any later version.
19. *
20. * This program is distributed in the hope that it will be useful,
21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23. * GNU Lesser General Public License for more details.
24. *
25. * You should have received a copy of the GNU Lesser General Public License
26. * along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
27. *
28. * ----------------------------------------------------------------------
29. *
30. * Class Name: PHP and Arabic Language
31. *
32. * Filename: Arabic.php
33. *
34. * Original Author(s): Khaled Al-Sham'aa <khaled@ar-php.org>
35. *
36. * Purpose: Set of PHP classes developed to enhance Arabic web
37. * applications by providing set of tools includes stem-based searching,
38. * translitiration, soundex, Hijri calendar, charset detection and
39. * converter, spell numbers, keyboard language, Muslim prayer time,
40. * auto-summarization, and more...
41. *
42. * ----------------------------------------------------------------------
43. *
44. * @desc Set of PHP classes developed to enhance Arabic web
45. * applications by providing set of tools includes stem-based searching,
46. * translitiration, soundex, Hijri calendar, charset detection and
47. * converter, spell numbers, keyboard language, Muslim prayer time,
48. * auto-summarization, and more...
49. *
50. * @category I18N
51. * @package I18N_Arabic
52. * @author Khaled Al-Shamaa <khaled@ar-php.org>
53. * @copyright 2006-2016 Khaled Al-Shamaa
54. *
55. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
56. * @version 4.0 released in Jan 8, 2016
57. * @link http://www.ar-php.org
58. */
60. /**
61. * Core PHP and Arabic language class
62. *
63. * @category I18N
64. * @package I18N_Arabic
65. * @author Khaled Al-Shamaa <khaled@ar-php.org>
66. * @copyright 2006-2016 Khaled Al-Shamaa
67. *
68. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
69. * @link http://www.ar-php.org
70. */
71. class I18N_Arabic
72. {
73. private $_inputCharset = 'utf-8';
74. private $_outputCharset = 'utf-8';
75. private $_compatible = array();
76. private $_lazyLoading = array();
77. private $_useAutoload;
78. private $_useException;
79. private $_compatibleMode;
81. /**
82. * @ignore
83. */
84. public $myObject;
86. /**
87. * @ignore
88. */
89. public $myClass;
91. /**
92. * @ignore
93. */
94. public $myFile;
96. /**
97. * Load selected library/Arabic class you would like to use its functionality
98. *
99. * @param string $library [AutoSummarize|CharsetC|CharsetD|Date|Gender|
100. * Glyphs|Identifier|KeySwap|Numbers|Query|Salat|
101. * Soundex|StrToTime|WordTag|CompressStr|Mktime|
102. * Transliteration|Stemmer|Standard|Normalise]
103. * @param boolean $useAutoload True to use Autoload (default is false)
104. * @param boolean $useException True to use Exception (default is false)
105. * @param boolean $compatibleMode True to support old naming style before
106. * version 3.0 (default is true)
107. *
108. * @desc Load selected library/class you would like to use its functionality
109. * @author Khaled Al-Shamaa <khaled@ar-php.org>
110. */
111. public function __construct(
112. $library, $useAutoload=false, $useException=false, $compatibleMode=true
113. ) {
114. $this->_useAutoload = $useAutoload;
115. $this->_useException = $useException;
116. $this->_compatibleMode = $compatibleMode;
118. $xml = simplexml_load_file(dirname(__FILE__).'/Arabic/data/config.xml');
120. foreach ($xml->xpath("//compatible/case") as $case) {
121. $this->_compatible["{$case['old']}"] = (string)$case;
122. }
124. foreach ($xml->xpath("//lazyLoading/case") as $case) {
125. $this->_lazyLoading["{$case['method']}"] = (string)$case;
126. }
128. /* Set internal character encoding to UTF-8 */
129. mb_internal_encoding("utf-8");
131. if ($this->_useAutoload) {
132. // It is critical to remember that as soon as spl_autoload_register() is
133. // called, __autoload() functions elsewhere in the application may fail
134. // to be called. This is safer initial call (PHP 5 >= 5.1.2):
135. if (false === spl_autoload_functions()) {
136. if (function_exists('__autoload')) {
137. spl_autoload_register('__autoload', false);
138. }
139. }
141. spl_autoload_extensions('.php,.inc,.class');
142. spl_autoload_register('I18N_Arabic::autoload', false);
143. }
145. if ($this->_useException) {
146. set_error_handler('I18N_Arabic::myErrorHandler');
147. }
149. if ($library) {
150. if ($this->_compatibleMode
151. && array_key_exists($library, $this->_compatible)
152. ) {
153. $library = $this->_compatible[$library];
154. }
156. $this->load($library);
157. }
158. }
160. /**
161. * Include file that include requested class
162. *
163. * @param string $className Class name
164. *
165. * @return null
166. * @author Khaled Al-Shamaa <khaled@ar-php.org>
167. */
168. public static function autoload($className)
169. {
170. include self::getClassFile($className);
171. }
173. /**
174. * Error handler function
175. *
176. * @param int $errno The level of the error raised
177. * @param string $errstr The error message
178. * @param string $errfile The filename that the error was raised in
179. * @param int $errline The line number the error was raised at
180. *
181. * @return boolean FALSE
182. * @author Khaled Al-Shamaa <khaled@ar-php.org>
183. */
184. public static function myErrorHandler($errno, $errstr, $errfile, $errline)
185. {
186. if ($errfile == __FILE__
187. || file_exists(
188. dirname(__FILE__).DIRECTORY_SEPARATOR.'Arabic'.
189. DIRECTORY_SEPARATOR.basename($errfile)
190. )
191. ) {
192. $msg = '<b>Arabic Class Exception:</b> ';
193. $msg .= $errstr;
194. $msg .= " in <b>$errfile</b>";
195. $msg .= " on line <b>$errline</b><br />";
197. throw new ArabicException($msg, $errno);
198. }
200. // If the function returns false then the normal error handler continues
201. return false;
202. }
204. /**
205. * Load selected Arabic library and create an instance of its class
206. *
207. * @param string $library Library name
208. *
209. * @return null
210. * @author Khaled Al-Shamaa <khaled@ar-php.org>
211. */
212. public function load($library)
213. {
214. if ($this->_compatibleMode
215. && array_key_exists($library, $this->_compatible)
216. ) {
217. $library = $this->_compatible[$library];
218. }
220. $this->myFile = $library;
221. $this->myClass = 'I18N_Arabic_' . $library;
222. $class = 'I18N_Arabic_' . $library;
224. if (!$this->_useAutoload) {
225. include self::getClassFile($this->myFile);
226. }
228. $this->myObject = new $class();
229. $this->{$library} = &$this->myObject;
230. }
232. /**
233. * Magic method __call() allows to capture invocation of non existing methods.
234. * That way __call() can be used to implement user defined method handling that
235. * depends on the name of the actual method being called.
236. *
237. * @param string $methodName Method name
238. * @param array $arguments Array of arguments
239. *
240. * @method Call a method from loaded sub class and take care of needed
241. * character set conversion for both input and output values.
242. *
243. * @return The value returned from the __call() method will be returned to
244. * the caller of the method.
245. * @author Khaled Al-Shamaa <khaled@ar-php.org>
246. */
247. public function __call($methodName, $arguments)
248. {
249. if ($this->_compatibleMode
250. && array_key_exists($methodName, $this->_compatible)
251. ) {
252. $methodName = $this->_compatible[$methodName];
253. }
255. // setMode & getMode [Date*|Query], setLang [Soundex*|CompressStr]
256. if ('I18N_Arabic_'.$this->_lazyLoading[$methodName] != $this->myClass) {
257. $this->load($this->_lazyLoading[$methodName]);
258. }
260. // Create an instance of the ReflectionMethod class
261. $method = new ReflectionMethod($this->myClass, $methodName);
263. $params = array();
264. $parameters = $method->getParameters();
266. foreach ($parameters as $parameter) {
267. $name = $parameter->getName();
268. $value = array_shift($arguments);
270. if (is_null($value) && $parameter->isDefaultValueAvailable()) {
271. $value = $parameter->getDefaultValue();
272. }
274. if ($methodName == 'decompress'
275. || ($methodName == 'search' && $name == 'bin')
276. || ($methodName == 'length' && $name == 'bin')
277. ) {
278. $params[$name] = $value;
279. } else {
280. $params[$name] = iconv($this->getInputCharset(), 'utf-8', $value);
281. }
282. }
284. $value = call_user_func_array(array(&$this->myObject, $methodName), $params);
286. if ($methodName == 'tagText') {
287. $outputCharset = $this->getOutputCharset();
288. foreach ($value as $key=>$text) {
289. $value[$key][0] = iconv('utf-8', $outputCharset, $text[0]);
290. }
291. } elseif ($methodName == 'compress'
292. || $methodName == 'getPrayTime'
293. || $methodName == 'str2graph'
294. ) {
295. } else {
296. $value = iconv('utf-8', $this->getOutputCharset(), $value);
297. }
299. return $value;
300. }
302. /**
303. * Garbage collection, release child objects directly
304. *
305. * @author Khaled Al-Shamaa <khaled@ar-php.org>
306. */
307. public function __destruct()
308. {
309. $this->_inputCharset = null;
310. $this->_outputCharset = null;
311. $this->myObject = null;
312. $this->myClass = null;
313. }
315. /**
316. * Set charset used in class input Arabic strings
317. *
318. * @param string $charset Input charset [utf-8|windows-1256|iso-8859-6]
319. *
320. * @return TRUE if success, or FALSE if fail
321. * @author Khaled Al-Shamaa <khaled@ar-php.org>
322. */
323. public function setInputCharset($charset)
324. {
325. $flag = true;
327. $charset = strtolower($charset);
328. $charsets = array('utf-8', 'windows-1256', 'cp1256', 'iso-8859-6');
330. if (in_array($charset, $charsets)) {
331. if ($charset == 'windows-1256') {
332. $charset = 'cp1256';
333. }
334. $this->_inputCharset = $charset;
335. } else {
336. $flag = false;
337. }
339. return $flag;
340. }
342. /**
343. * Set charset used in class output Arabic strings
344. *
345. * @param string $charset Output charset [utf-8|windows-1256|iso-8859-6]
346. *
347. * @return boolean TRUE if success, or FALSE if fail
348. * @author Khaled Al-Shamaa <khaled@ar-php.org>
349. */
350. public function setOutputCharset($charset)
351. {
352. $flag = true;
354. $charset = strtolower($charset);
355. $charsets = array('utf-8', 'windows-1256', 'cp1256', 'iso-8859-6');
357. if (in_array($charset, $charsets)) {
358. if ($charset == 'windows-1256') {
359. $charset = 'cp1256';
360. }
361. $this->_outputCharset = $charset;
362. } else {
363. $flag = false;
364. }
366. return $flag;
367. }
369. /**
370. * Get the charset used in the input Arabic strings
371. *
372. * @return string return current setting for class input Arabic charset
373. * @author Khaled Al-Shamaa <khaled@ar-php.org>
374. */
375. public function getInputCharset()
376. {
377. if ($this->_inputCharset == 'cp1256') {
378. $charset = 'windows-1256';
379. } else {
380. $charset = $this->_inputCharset;
381. }
383. return $charset;
384. }
386. /**
387. * Get the charset used in the output Arabic strings
388. *
389. * @return string return current setting for class output Arabic charset
390. * @author Khaled Al-Shamaa <khaled@ar-php.org>
391. */
392. public function getOutputCharset()
393. {
394. if ($this->_outputCharset == 'cp1256') {
395. $charset = 'windows-1256';
396. } else {
397. $charset = $this->_outputCharset;
398. }
400. return $charset;
401. }
403. /**
404. * Get sub class file path to be included (mapping between class name and
405. * file name/path become independent now)
406. *
407. * @param string $class Sub class name
408. *
409. * @return string Sub class file path
410. * @author Khaled Al-Shamaa <khaled@ar-php.org>
411. */
412. protected static function getClassFile($class)
413. {
414. $dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Arabic';
415. $file = $dir . DIRECTORY_SEPARATOR . $class . '.php';
417. return $file;
418. }
420. /**
421. * Send/set output charset in several output media in a proper way
422. *
423. * @param string $mode [http|html|mysql|mysqli|pdo|text_email|html_email]
424. * @param resource $conn The MySQL connection handler/the link identifier
425. *
426. * @return string header formula if there is any (in cases of html,
427. * text_email, and html_email)
428. * @author Khaled Al-Shamaa <khaled@ar-php.org>
429. */
430. public function header($mode = 'http', $conn = null)
431. {
432. $mode = strtolower($mode);
433. $head = '';
435. switch ($mode) {
436. case 'http':
437. header('Content-Type: text/html; charset=' . $this->_outputCharset);
438. break;
440. case 'html':
441. $head .= '<meta http-equiv="Content-type" content="text/html; charset=';
442. $head .= $this->_outputCharset . '" />';
443. break;
445. case 'text_email':
446. $head .= 'MIME-Version: 1.0\r\nContent-type: text/plain; charset=';
447. $head .= $this->_outputCharset . '\r\n';
448. break;
450. case 'html_email':
451. $head .= 'MIME-Version: 1.0\r\nContent-type: text/html; charset=';
452. $head .= $this->_outputCharset . '\r\n';
453. break;
455. case 'mysql':
456. if ($this->_outputCharset == 'utf-8') {
457. mysql_set_charset('utf8');
458. } elseif ($this->_outputCharset == 'windows-1256') {
459. mysql_set_charset('cp1256');
460. }
461. break;
463. case 'mysqli':
464. if ($this->_outputCharset == 'utf-8') {
465. $conn->set_charset('utf8');
466. } elseif ($this->_outputCharset == 'windows-1256') {
467. $conn->set_charset('cp1256');
468. }
469. break;
471. case 'pdo':
472. if ($this->_outputCharset == 'utf-8') {
473. $conn->exec('SET NAMES utf8');
474. } elseif ($this->_outputCharset == 'windows-1256') {
475. $conn->exec('SET NAMES cp1256');
476. }
477. break;
478. }
480. return $head;
481. }
483. /**
484. * Get web browser chosen/default language using ISO 639-1 codes (2-letter)
485. *
486. * @return string Language using ISO 639-1 codes (2-letter)
487. * @author Khaled Al-Shamaa <khaled@ar-php.org>
488. */
489. public static function getBrowserLang()
490. {
491. $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); // ar, en, etc...
493. return $lang;
494. }
496. /**
497. * There is still a lack of original, localized, high-quality content and
498. * well-structured Arabic websites; This method help in tag HTML result pages
499. * from Arabic forum to enable filter it in/out.
500. *
501. * @param string $html The HTML content of the page in question
502. *
503. * @return boolean True if the input HTML is belong to a forum page
504. * @author Khaled Al-Shamaa <khaled@ar-php.org>
505. */
506. public static function isForum($html)
507. {
508. $forum = false;
510. if (strpos($html, 'vBulletin_init();') !== false) {
511. $forum = true;
512. }
514. return $forum;
515. }
516. }
518. /**
519. * Arabic Exception class defined by extending the built-in Exception class.
520. *
521. * @category I18N
522. * @package I18N_Arabic
523. * @author Khaled Al-Shamaa <khaled@ar-php.org>
524. * @copyright 2006-2013 Khaled Al-Shamaa
525. *
526. * @license LGPL <http://www.gnu.org/licenses/lgpl.txt>
527. * @link http://www.ar-php.org
528. */
529. class ArabicException extends Exception
530. {
531. /**
532. * Make sure everything is assigned properly
533. *
534. * @param string $message Exception message
535. * @param int $code User defined exception code
536. */
537. public function __construct($message, $code=0)
538. {
539. parent::__construct($message, $code);
540. }
541. }

Documentation generated on Fri, 01 Jan 2016 10:25:49 +0200 by phpDocumentor 1.4.0