<?php
namespace Deefour;
/*
* This file is part of the SpellSuggest utility of the Deefour Package.
*
* (c) Jason Daly <hide@address.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* The SpellSuggest class, part of Deefour's library of utilities.
*
* See README.md or http://github.com/deefour/SpellCheck for more information
*
* @method string getOriginalText() Returns the current $_originalText value
* @method string getCorrectedText() Returns the current $_correctedText value
* @method boolean getHasProcessed() Returns the current $_hasProcessed value
*
* @author Jason 'Deefour' Daly
* @package Deefour
* @subpackage SpellSuggest
* @version 1.0
*/
class SpellCheck{
/**
* Stores the original text to later be transformed
*
* @access private
* @var string
*/
private $_originalText;
/**
* Stores the corrected text; the text transformed by the
* `SpellSuggest::process()` method.
*
* @access private
* @var string
*/
private $_correctedText;
/**
* Stores whether or not the current originalText has been processed
* or not
*
* @access private
* @var boolean
*/
private $_hasProcessed = false;
/**
* Constructor; optionally sets the originalText value if passed
*
* @param string $string [optional] the text to spellcheck
*
* @return sfDeefourUtilsSpellSuggest instance of $this
*/
public function __construct($string = null){
if ($string !== null && is_string($string)) {
$this->setText($string);
}
return $this;
}
/**
* Sets the original text for this instance
*
* @param string $string the text to spellcheck
*
* @return sfDeefourUtilsSpellSuggest instance of $this
*/
public function setText($string){
$this->_hasProcessed = false;
$this->_correctedText = null;
$this->_originalText = $string;
return $this;
}
/**
* Processes the translation of the originalString into the correctedString,
* making changes based on the best suggestions for each word returned by the
* Google Toolbar SpellCheck XML response
*
* @throws
*
* @return sfDeefourUtilsSpellSuggest instance of $this
*/
public function process(){
if ($this->_hasProcessed) {
return $this->_correctedText;
} else {
$this->_correctedText = null;
}
if ($this->_originalText === null) {
throw new \BadMethodCallException('There is no original text to spell check.');
}
$url = 'https://www.google.com/tbproxy/spell?lang=en&hl=en';
$request = sprintf('<?xml version="1.0" encoding="utf-8" ?>
<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">
<text>%s</text>
</spellrequest>', $this->_originalText);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
$xml = new \SimpleXMLElement($output);
$changes = array();
foreach ($xml->c as $replacements) {
$start_pos = (int)$replacements['o'];
$length = (int)$replacements['l'];
$replacements = preg_split('/\t/', (string)$replacements);
$changes[substr($this->_originalText, $start_pos, $length)] = $replacements[0];
}
$this->_correctedText = strtr($this->_originalText, $changes);
$this->_hasProcessed = true;
return $this;
}
/**
* Boolean test whether or not the corrected version of the text is any different
* from the original (suggesting a change has been applied). To guarantee the accuracy
* of the test, `true` will only be returned if the text has actually been spellchecked
* previously.
*
* @return boolean whether or not the corrected text has changed from the original
* after the spellcheck has been performed
*/
public function hasChanged(){
return strcmp($this->_originalText, $this->_correctedText) !== 0 && $this->_hasProcessed;
}
/**
* PHP's magic __toString method...
*
* @return mixed the correctedText string if available, otherwise null
*/
public function __toString(){
return (string)$this->_correctedText;
}
/**
* PHP's magic __call method; provides functionality of PHP's magic __get()
* method, with the difference that the user is exepected to request a private
* variable using a `$instance->getVariableNameHere()` format. The previous
* example would return some `$_variableNameHere` private variable from the
* class instance if it existed as a defined property of the class.
*
* @param string $method the method name to transform into the private variable
* name to check for
* @param array $arguments [optional] arguments that were passed to the
* non-existent method
*
* @return mixed the transformed private variable value, otherwise null
*/
public function __call($method, array $arguments = null){
$variable = '_' . lcfirst(preg_replace('/^get/', '', $method));
if (substr($variable, 0, 1) === '_' && strcmp($variable, $method) !== 0 && property_exists($this, $variable)) {
return $this->$variable;
}
throw new \BadMethodCallException('Unknown class method called.');
}
}