Skip to content

Commit

Permalink
Merge 671186b into bc2ccf8
Browse files Browse the repository at this point in the history
  • Loading branch information
Synida committed Apr 30, 2020
2 parents bc2ccf8 + 671186b commit d5acdec
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 73 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ git:
php:
- 7.2
- 7.3
- 7.4

matrix:
fast_finish: true
Expand All @@ -16,7 +15,8 @@ matrix:
- COVERALLS_FLAG="--coverage-clover build/logs/clover.xml"

before_install:
- sudo apt-get install hunspell
- sudo apt-get install hunspell php-pear
- printf "\n" | pecl install parallel
- travis_retry composer self-update

install:
Expand Down
61 changes: 43 additions & 18 deletions src/HunSpellPhpWrapper/DictionaryEditor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace HunSpellPhpWrapper;

use HunSpellPhpWrapper\exception\FileOperationException;
use Exception;

/**
* Class DictionaryEditor
Expand Down Expand Up @@ -58,20 +58,25 @@ public function create($path)
$pathParts = explode('.', $path);
$extension = end($pathParts);

if (!in_array($extension, [
static::DICTIONARY_EXTENSION, static::RULESET_EXTENSION, static::TEMPLATE_EXTENSION
])) {
if (!in_array(
$extension,
[
static::DICTIONARY_EXTENSION,
static::RULESET_EXTENSION,
static::TEMPLATE_EXTENSION
]
)) {
$this->message = "Invalid extension({$extension})";
return false;
}

try {
$file = fopen($path, 'w');

fwrite($file,'');
fwrite($file, '');

fclose($file);
} catch (FileOperationException $exception) {
} catch (Exception $exception) {
$this->message = 'Failed to create new dictionary: ' . $exception->getMessage();
return false;
}
Expand All @@ -97,9 +102,14 @@ public function delete($path)
$pathParts = explode('.', $path);
$extension = end($pathParts);

if (!in_array($extension, [
static::DICTIONARY_EXTENSION, static::RULESET_EXTENSION, static::TEMPLATE_EXTENSION
])) {
if (!in_array(
$extension,
[
static::DICTIONARY_EXTENSION,
static::RULESET_EXTENSION,
static::TEMPLATE_EXTENSION
]
)) {
$this->message = "Invalid extension({$extension})";
return false;
}
Expand Down Expand Up @@ -141,9 +151,12 @@ public function addWord($path, $word)

$words[] = $word;

$words = array_filter($words, function($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
});
$words = array_filter(
$words,
function ($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
}
);

natcasesort($words);

Expand Down Expand Up @@ -186,9 +199,12 @@ public function deleteWord($path, $word)
}
}

$words = array_filter($words, function($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
});
$words = array_filter(
$words,
function ($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
}
);

if ($ext !== static::TEMPLATE_EXTENSION) {
array_unshift($words, count($words));
Expand All @@ -202,6 +218,7 @@ public function deleteWord($path, $word)
$this->message = "The defined dictionary({$path}) does not contain this word({$word})";
return false;
}

/**
* Modifies and existing word in a dictionary.
*
Expand All @@ -225,16 +242,24 @@ public function editWord($path, $word, $modifiedWord)
unset($words[0]);
}

if (in_array($modifiedWord, $words)) {
$this->message = 'This word is already in the dictionary';
return false;
}

foreach ($words as $wordKey => $currentWord) {
if ($word === $currentWord) {
$words[$wordKey] = $modifiedWord;
break;
}
}

$words = array_filter($words, function($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
});
$words = array_filter(
$words,
function ($value) {
return !is_null($value) && $value !== '' && $value !== PHP_EOL;
}
);

if ($ext !== static::TEMPLATE_EXTENSION) {
array_unshift($words, count($words));
Expand Down
95 changes: 45 additions & 50 deletions src/HunSpellPhpWrapper/HunSpell.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
use Closure;
use Exception;
use HunSpellPhpWrapper\config\Configuration;
use HunSpellPhpWrapper\validation\InputValidator;
use HunSpellPhpWrapper\exception\InvalidResponseTypeException;
use HunSpellPhpWrapper\exception\InvalidThreadNumberException;
use HunSpellPhpWrapper\validation\InputValidator;
use parallel\Channel;
use parallel\Error;
use parallel\Runtime;
Expand All @@ -22,7 +22,7 @@
*
* @property int $maxThreads
* @property int $minWordPerThread
* @property string $dictionaries
* @property string $dictionary
* @property string $encoding
* @property string $responseType
* @property Closure $findCommandClosure
Expand Down Expand Up @@ -101,11 +101,11 @@ class HunSpell
const ARRAY_RESPONSE = 'array';

/**
* Selected dictionary or dictionaries separated by coma(,)
* Selected dictionary - hunspell can handle only one
*
* @var string
*/
protected $dictionaries = 'en_GB';
protected $dictionary = 'en_GB';

/**
* Encoding of the text
Expand Down Expand Up @@ -151,16 +151,21 @@ class HunSpell
* HunSpell constructor.
*
* @param string $encoding
* @param string $dictionaries
* @param string $dictionary
* @param string $responseType
* @param int $threads
* @param int $wordThreadRatio
* @throws InvalidResponseTypeException
* @throws InvalidThreadNumberException
* @author Synida Pry
*/
public function __construct($encoding = 'en_GB.utf8', $dictionaries = 'en_GB', $responseType = 'json', $threads = 1, $wordThreadRatio = 1)
{
public function __construct(
$encoding = 'en_GB.utf8',
$dictionary = 'en_GB',
$responseType = 'json',
$threads = 1,
$wordThreadRatio = 1
) {
$this->inputValidator = new InputValidator();

// Validates the response type
Expand All @@ -171,16 +176,16 @@ public function __construct($encoding = 'en_GB.utf8', $dictionaries = 'en_GB', $

$this->responseType = $responseType;
$this->encoding = $encoding;
$this->dictionaries = $dictionaries;
$this->dictionary = $dictionary;

$this->maxThreads = $threads ?: Configuration::MAX_THREADS;
$this->minWordPerThread = $wordThreadRatio ?: Configuration::MIN_WORD_PER_THREAD;

$this->findCommandClosure = extension_loaded('parallel')
? static function (Channel $channel, $text, $encoding, $dictionaries) {
? static function (Channel $channel, $text, $encoding, $dictionary) {
$encode = strncasecmp(PHP_OS, 'WIN', 3) === 0 ? '' : "LANG=\"{$encoding}\"; ";

$channel->send(shell_exec("{$encode}echo \"{$text}\" | hunspell -d \"{$dictionaries}\""));
$channel->send(shell_exec("{$encode}echo \"{$text}\" | hunspell -d \"{$dictionary}\""));
} : null;
}

Expand Down Expand Up @@ -212,26 +217,26 @@ public function setResponseType($responseType)
}

/**
* Returns with the selected dictionaries
* Returns with the selected dictionary
*
* @return string
* @author Synida Pry
*/
public function getDictionaries()
public function getDictionary()
{
return $this->dictionaries;
return $this->dictionary;
}

/**
* Sets the dictionary/dictionaries
* Sets the dictionary
*
* @param string $dictionaries
* @param string $dictionary
* @return void
* @author Synida Pry
*/
public function setDictionaries($dictionaries)
public function setDictionary($dictionary)
{
$this->dictionaries = $dictionaries;
$this->dictionary = $dictionary;
}

/**
Expand All @@ -257,18 +262,6 @@ public function setEncoding($encoding)
$this->encoding = $encoding;
}

/**
* Counts the words in the text.
*
* @param string $text
* @return int
* @author Synida Pry
*/
public function getWordCount($text)
{
return str_word_count($text);
}

/**
* Tries to find words from the dictionary. Returns only with the suggestions if any of them is incorrect.
*
Expand All @@ -284,14 +277,14 @@ public function suggest($text)
$text = str_replace('"', '', $text);

// Counts the words in the text.
$wordCount = $this->getWordCount($text);
$wordCount = str_word_count($text);

$spellCheckResults =
extension_loaded('parallel') && $this->maxThreads > 1 && $wordCount > $this->minWordPerThread
// Splits the text into smaller chunks and process them with threads.
? $this->findWithThreading($text, $wordCount)
// Executes the find command on a text.
: $this->findCommand($text);
// Splits the text into smaller chunks and process them with threads.
? $this->findWithThreading($text, $wordCount)
// Executes the find command on a text.
: $this->findCommand($text);

preg_replace('/(\r\n)|\r|\n/', "\n", $spellCheckResults);
$resultLines = explode("\n", trim($spellCheckResults));
Expand Down Expand Up @@ -362,7 +355,9 @@ protected function findWithThreading($text, $wordCount)
$result = '';
$threads = [];
try {
$threadCount = (int)ceil($wordCount / $chunkSize > $optimalThread ? $optimalThread : $wordCount / $chunkSize);
$threadCount = (int)ceil(
$wordCount / $chunkSize > $optimalThread ? $optimalThread : $wordCount / $chunkSize
);
for ($i = 0; $i < $threadCount; $i++) {
$chunk = '';
$initPosition = $i * $chunkSize;
Expand All @@ -375,7 +370,7 @@ protected function findWithThreading($text, $wordCount)
}

$threads[] = (new Runtime())
->run($this->findCommandClosure, [$channel, $chunk, $this->encoding, $this->dictionaries]);
->run($this->findCommandClosure, [$channel, $chunk, $this->encoding, $this->dictionary]);
}

for ($i = 0; $i < $threadCount; $i++) {
Expand Down Expand Up @@ -406,19 +401,17 @@ public function getOptimalThreads($wordCount)
}

/**
* Sets the optimal thread number.
* Executes the find command on a text.
*
* @param int $maxThreads
* @return void
* @throws InvalidThreadNumberException
* @param string $text
* @return string
* @author Synida Pry
*/
public function setMaxThreads($maxThreads)
protected function findCommand($text)
{
// Validates the thread number.
$this->inputValidator->validateThreadNumber($maxThreads);
$encode = strncasecmp(PHP_OS, 'WIN', 3) === 0 ? '' : "LANG=\"{$this->encoding}\"; ";

$this->maxThreads = $maxThreads;
return shell_exec("{$encode}echo \"{$text}\" | hunspell -d \"{$this->dictionary}\"");
}

/**
Expand All @@ -433,16 +426,18 @@ public function getMaxThreads()
}

/**
* Executes the find command on a text.
* Sets the optimal thread number.
*
* @param string $text
* @return string
* @param int $maxThreads
* @return void
* @throws InvalidThreadNumberException
* @author Synida Pry
*/
protected function findCommand($text)
public function setMaxThreads($maxThreads)
{
$encode = strncasecmp(PHP_OS, 'WIN', 3) === 0 ? '' : "LANG=\"{$this->encoding}\"; ";
// Validates the thread number.
$this->inputValidator->validateThreadNumber($maxThreads);

return shell_exec("{$encode}echo \"{$text}\" | hunspell -d \"{$this->dictionaries}\"");
$this->maxThreads = $maxThreads;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* Created by Synida Pry.
* Copyright © 2020. TakeNote. All rights reserved.
* Copyright © 2020. All rights reserved.
*/

namespace HunSpellPhpWrapper\exception;
Expand Down

0 comments on commit d5acdec

Please sign in to comment.