[ Index ]
 

Code source de DokuWiki 2006-11-06

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/inc/ -> aspell.php (source)

   1  <?php
   2  /**
   3   * Aspell interface
   4   *
   5   * This library gives full access to aspell's pipe interface. Optionally it
   6   * provides some of the functions from the pspell PHP extension by wrapping
   7   * them to calls to the aspell binary.
   8   *
   9   * It can be simply dropped into code written for the pspell extension like
  10   * the following
  11   *
  12   * if(!function_exists('pspell_suggest')){
  13   *   define('PSPELL_COMP',1);
  14   *   require_once ("pspell_comp.php");
  15   * }
  16   *
  17   * Define the path to the aspell binary like this if needed:
  18   *
  19   * define('ASPELL_BIN','/path/to/aspell');
  20   *
  21   * @author   Andreas Gohr <andi@splitbrain.org>
  22   * @todo     Not all pspell functions are supported
  23   *
  24   */
  25  
  26  // path to your aspell binary
  27  if(!defined('ASPELL_BIN')) define('ASPELL_BIN','aspell');
  28  
  29  
  30  // different spelling modes supported by aspell
  31  if(!defined('PSPELL_FAST'))         define(PSPELL_FAST,1);         # Fast mode (least number of suggestions)
  32  if(!defined('PSPELL_NORMAL'))       define(PSPELL_NORMAL,2);       # Normal mode (more suggestions)
  33  if(!defined('PSPELL_BAD_SPELLERS')) define(PSPELL_BAD_SPELLERS,3); # Slow mode (a lot of suggestions)
  34  if(!defined('ASPELL_ULTRA'))        define(ASPELL_ULTRA,4);        # Ultra fast mode (not available in Pspell!)
  35  
  36  
  37  
  38  /**
  39   * You can define PSPELL_COMP to use this class as drop in replacement
  40   * for the pspell extension
  41   */
  42  if(defined('PSPELL_COMP')){
  43      // spelling is not supported by aspell and ignored
  44      function pspell_config_create($language, $spelling=null, $jargon=null, $encoding='iso8859-1'){
  45          return new Aspell($language, $jargon, $encoding);
  46      }
  47  
  48      function pspell_config_mode(&$config, $mode){
  49          return $config->setMode($mode);
  50      }
  51  
  52      function pspell_new_config(&$config){
  53          return $config;
  54      }
  55  
  56      function pspell_check(&$dict,$word){
  57          return $dict->check($word);
  58      }
  59  
  60      function pspell_suggest(&$dict, $word){
  61          return $dict->suggest($word);
  62      }
  63  }
  64  
  65  /**
  66   * Class to interface aspell
  67   *
  68   * Needs PHP >= 4.3.0
  69   */
  70  class Aspell{
  71      var $language = null;
  72      var $jargon   = null;
  73      var $personal = null;
  74      var $encoding = 'iso8859-1';
  75      var $mode     = PSPELL_NORMAL;
  76      var $version  = 0;
  77  
  78      var $args='';
  79  
  80      /**
  81       * Constructor. Works like pspell_config_create()
  82       *
  83       * @author   Andreas Gohr <andi@splitbrain.org>
  84       */
  85      function Aspell($language, $jargon=null, $encoding='iso8859-1'){
  86          $this->language = $language;
  87          $this->jargon   = $jargon;
  88          $this->encoding = $encoding;
  89      }
  90  
  91      /**
  92       * Set the spelling mode like pspell_config_mode()
  93       *
  94       * Mode can be PSPELL_FAST, PSPELL_NORMAL, PSPELL_BAD_SPELLER or ASPELL_ULTRA
  95       *
  96       * @author   Andreas Gohr <andi@splitbrain.org>
  97       */
  98      function setMode($mode){
  99          if(!in_array($mode,array(PSPELL_FAST,PSPELL_NORMAL,PSPELL_BAD_SPELLER,ASPELL_ULTRA))){
 100              $mode = PSPELL_NORMAL;
 101          }
 102  
 103          $this->mode = $mode;
 104          return $mode;
 105      }
 106  
 107      /**
 108       * Prepares the needed arguments for the call to the aspell binary
 109       *
 110       * No need to call this directly
 111       *
 112       * @author   Andreas Gohr <andi@splitbrain.org>
 113       */
 114      function _prepareArgs(){
 115          $this->args = '';
 116  
 117          if($this->language != null){
 118              $this->args .= ' --lang='.escapeshellarg($this->language);
 119          }else{
 120              return false; // no lang no spell
 121          }
 122  
 123          if($this->jargon != null){
 124              $this->args .= ' --jargon='.escapeshellarg($this->jargon);
 125          }
 126  
 127          if($this->personal != null){
 128              $this->args .= ' --personal='.escapeshellarg($this->personal);
 129          }
 130  
 131          if($this->encoding != null){
 132              $this->args .= ' --encoding='.escapeshellarg($this->encoding);
 133          }
 134  
 135          switch ($this->mode){
 136              case PSPELL_FAST:
 137                  $this->args .= ' --sug-mode=fast';
 138                  break;
 139              case PSPELL_BAD_SPELLERS:
 140                  $this->args .= ' --sug-mode=bad-spellers';
 141                  break;
 142              case ASPELL_ULTRA:
 143                  $this->args .= ' --sug-mode=ultra';
 144                  break;
 145              default:
 146                  $this->args .= ' --sug-mode=normal';
 147          }
 148  
 149          return true;
 150      }
 151  
 152  
 153      /**
 154       * Pipes a text to aspell
 155       *
 156       * This opens a bidirectional pipe to the aspell binary, writes
 157       * the given text to STDIN and returns STDOUT and STDERR
 158       *
 159       * You can give an array of special commands to be executed first
 160       * as $specials parameter. Data lines are escaped automatically
 161       *
 162       * @author   Andreas Gohr <andi@splitbrain.org>
 163       * @link     http://aspell.sf.net/man-html/Through-A-Pipe.html
 164       */
 165      function runAspell($text,&$out,&$err,$specials=null){
 166          if(empty($text)) return true;
 167          $terse = true;
 168  
 169          // prepare arguments
 170          $this->_prepareArgs();
 171          $command = ASPELL_BIN.' -a'.$this->args;
 172          $stdin   = '';
 173  
 174          // prepare specials
 175          if(is_array($specials)){
 176              foreach($specials as $s){
 177                  if ($s == '!') $terse = false;
 178                  $stdin .= "$s\n";
 179              }
 180          }
 181  
 182          // prepare text
 183          $stdin .= "^".str_replace("\n", "\n^",$text);
 184  
 185          // run aspell through the pipe
 186          $rc = $this->execPipe($command,$stdin,$out,$err);
 187          if(is_null($rc)){
 188              $err = "Could not run Aspell '".ASPELL_BIN."'";
 189              return false;
 190          }
 191  
 192          // Aspell has a bug that can't be autodetected because both versions
 193          // might produce the same output but under different conditions. So
 194          // we check Aspells version number here to divide broken and working
 195          // versions of Aspell.
 196          $tmp = array();
 197          preg_match('/^\@.*Aspell (\d+)\.(\d+).(\d+)/',$out,$tmp);
 198          $this->version = $tmp[1]*100 + $tmp[2]*10 + $tmp[3];
 199  
 200          if ($this->version <= 603)  // version 0.60.3
 201              $r = $terse ? "\n*\n\$1" : "\n\$1"; // replacement for broken Aspell
 202          else
 203              $r = $terse ? "\n*\n" : "\n";    // replacement for good Aspell
 204  
 205          // lines starting with a '?' are no realy misspelled words and some
 206          // Aspell versions doesn't produce usable output anyway so we filter
 207          // them out here.
 208          $out = preg_replace('/\n\? [^\n\&\*]*([\n]?)/',$r, $out);
 209  
 210          if ($err){
 211              //something went wrong
 212              $err = "Aspell returned an error(".ASPELL_BIN." exitcode: $rc ):\n".$err;
 213              return false;
 214          }
 215          return true;
 216      }
 217  
 218  
 219      /**
 220       * Runs the given command with the given input on STDIN
 221       *
 222       * STDOUT and STDERR are written to the given vars, the command's
 223       * exit code is returned. If the pip couldn't be opened null is returned
 224       *
 225       * @author <richard at 2006 dot atterer dot net>
 226       * @link http://www.php.net/manual/en/function.proc-open.php#64116
 227       */
 228      function execPipe($command,$stdin,&$stdout,&$stderr){
 229          $descriptorSpec = array(0 => array("pipe", "r"),
 230                                  1 => array('pipe', 'w'),
 231                                  2 => array('pipe', 'w'));
 232          $process = proc_open($command, $descriptorSpec, $pipes);
 233          if(!$process) return null;
 234  
 235          $txOff = 0;
 236          $txLen = strlen($stdin);
 237          $stdoutDone = FALSE;
 238          $stderrDone = FALSE;
 239  
 240          stream_set_blocking($pipes[0], 0); // Make stdin/stdout/stderr non-blocking
 241          stream_set_blocking($pipes[1], 0);
 242          stream_set_blocking($pipes[2], 0);
 243  
 244          if ($txLen == 0) fclose($pipes[0]);
 245          while (TRUE) {
 246              $rx = array(); // The program's stdout/stderr
 247              if (!$stdoutDone) $rx[] = $pipes[1];
 248              if (!$stderrDone) $rx[] = $pipes[2];
 249              $tx = array(); // The program's stdin
 250              if ($txOff < $txLen) $tx[] = $pipes[0];
 251              stream_select($rx, $tx, $ex = NULL, NULL, NULL); // Block til r/w possible
 252  
 253              if (!empty($tx)) {
 254                  $txRet = fwrite($pipes[0], substr($stdin, $txOff, 8192));
 255                  if ($txRet !== FALSE) $txOff += $txRet;
 256                  if ($txOff >= $txLen) fclose($pipes[0]);
 257              }
 258  
 259              foreach ($rx as $r) {
 260                  if ($r == $pipes[1]) {
 261                      $stdout .= fread($pipes[1], 8192);
 262                      if (feof($pipes[1])) {
 263                          fclose($pipes[1]);
 264                          $stdoutDone = TRUE;
 265                      }
 266                  } else if ($r == $pipes[2]) {
 267                      $stderr .= fread($pipes[2], 8192);
 268                      if (feof($pipes[2])) {
 269                          fclose($pipes[2]);
 270                          $stderrDone = TRUE;
 271                      }
 272                  }
 273              }
 274              if (!is_resource($process)) break;
 275              if ($txOff >= $txLen && $stdoutDone && $stderrDone) break;
 276          }
 277          return proc_close($process);
 278      }
 279  
 280  
 281  
 282  
 283      /**
 284       * Checks a single word for correctness
 285       *
 286       * @returns  array of suggestions or true on correct spelling
 287       * @author   Andreas Gohr <andi@splitbrain.org>
 288       */
 289      function suggest($word){
 290          if($this->runAspell("^$word",$out,$err)){
 291              //parse output
 292              $lines = split("\n",$out);
 293              foreach ($lines as $line){
 294                  $line = trim($line);
 295                  if(empty($line))    continue;       // empty line
 296                  if($line[0] == '@') continue;       // comment
 297                  if($line[0] == '*') return true;    // no mistakes made
 298                  if($line[0] == '#') return array(); // mistake but no suggestions
 299                  if($line[0] == '&'){
 300                      $line = preg_replace('/&.*?: /','',$line);
 301                      return split(', ',$line);
 302                  }
 303              }
 304          }
 305          return array();
 306      }
 307  
 308      /**
 309       * Check if a word is mispelled like pspell_check
 310       *
 311       * @author   Andreas Gohr <andi@splitbrain.org>
 312       */
 313      function check($word){
 314          if(is_array($this->suggest($word))){
 315              return false;
 316          }else{
 317              return true;
 318          }
 319      }
 320  }
 321  
 322  //Setup VIM: ex: et ts=4 enc=utf-8 :


Généré le : Tue Apr 3 20:47:31 2007 par Balluche grâce à PHPXref 0.7