-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] HyphenationService and TypoScript Implementation added
- Loading branch information
1 parent
b05d456
commit b089811
Showing
5 changed files
with
400 additions
and
313 deletions.
There are no files selected for viewing
322 changes: 322 additions & 0 deletions
322
Classes/Wegmeister/Hyphenator/Service/HyphenationService.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,322 @@ | ||
<?php | ||
namespace Wegmeister\Hyphenator\Service; | ||
|
||
/** | ||
* This script belongs to the TYPO3 Flow Package "Wegmeister.Hyphenator". | ||
* This service handles the hyphenation of texts. | ||
* | ||
* wegmeister/hyphenator 1.0.0 | ||
* Neos-Integration of the phpHyphenator with some enhancements on | ||
* the pattern-converter by Benjamin Klix | ||
* | ||
* phpHyphenator 1.6.1 | ||
* Enhanced by Erik Krause | ||
* | ||
* based on | ||
* | ||
* phpHyphenator 1.6 | ||
* Enhanced by Liedtke.IT Jens Liedtke | ||
* PHP version of the JavaScript Hyphenator version 3.1.0 by | ||
* Mathias Nater, <a href = "mailto:[email protected]">[email protected]</a> | ||
* | ||
* based on | ||
* | ||
* phpHyphenator 1.5 | ||
* Developed by yellowgreen designbüro | ||
* PHP version of the JavaScript Hyphenator 1.0 (Beta) by Matthias Nater | ||
* | ||
* Licensed under Creative Commons Attribution-Share Alike 2.5 Switzerland | ||
* http://creativecommons.org/licenses/by-sa/2.5/ch/deed.en | ||
* | ||
* Associated pages: | ||
* http://www.dokuwiki.org/plugin:hyphenation | ||
* | ||
* Special thanks to: | ||
* Dave Gööck (webvariants.de) | ||
* Markus Birth (birth-online.de) | ||
* Nico Wenig (yellowgreen.de) | ||
*/ | ||
|
||
use TYPO3\Flow\Annotations as Flow; | ||
|
||
/** | ||
* @Flow\Scope("singleton") | ||
*/ | ||
class HyphenationService | ||
{ | ||
/** | ||
* @Flow\Inject | ||
* @var \TYPO3\Flow\I18n\Service | ||
*/ | ||
protected $localizationService; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $settings; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $dictionary; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $patterns; | ||
|
||
|
||
/** | ||
* Inject the settings | ||
* | ||
* @param array $settings | ||
* @return void | ||
*/ | ||
public function injectSettings(array $settings) | ||
{ | ||
$excludeTags = []; | ||
foreach ($settings['excludeTags'] as $tag => $exclude) { | ||
if ($exclude === true) { | ||
$excludeTags[] = $tag; | ||
} | ||
} | ||
$settings['excludeTags'] = $excludeTags; | ||
$this->settings = $settings; | ||
|
||
$this->dictionary = []; | ||
if (file_exists($this->settings['dictionary'])) { | ||
$entries = file($this->settings['dictionary']); | ||
foreach ($entries as $entry) { | ||
$entry = trim($entry); | ||
if (strlen($entry) > 0) { | ||
$this->dictionary[str_replace('/', '', mb_strtolower($entry))] = str_replace('/', $this->settings['hyphen'], $entry); | ||
} | ||
} | ||
} | ||
|
||
$this->patterns = []; | ||
} | ||
|
||
|
||
/** | ||
* Add text hyphenation. | ||
* | ||
* @param string $text | ||
* @param string $locale | ||
* @return string | ||
*/ | ||
public function hyphenate($text, $locale = null) | ||
{ | ||
if (!is_string($text) && !(is_object($text) && method_exists($text, '__toString'))) { | ||
return $text; | ||
} | ||
|
||
if ($locale === null || $locale === '') { | ||
$locale = $this->localizationService->getConfiguration()->getCurrentLocale()->getLanguage(); | ||
} | ||
if ($locale === 'en') { | ||
$locale .= '-gb'; | ||
} | ||
|
||
if (!isset($this->patterns[$locale])) { | ||
$filename = $this->settings['patternPath'] . $locale; | ||
if (file_exists($filename . '.php')) { | ||
$this->patterns[$locale] = include($filename . '.php'); | ||
} elseif (file_exists($filename . '.js')) { | ||
if ($this->makePHPPattern($filename)) { | ||
$this->patterns[$locale] = include($filename . '.php'); | ||
} else { | ||
$this->patterns[$locale] = []; | ||
} | ||
} else { | ||
$this->patterns[$locale] = []; | ||
} | ||
} | ||
if ($this->patterns[$locale] === []) { | ||
return $text; | ||
} | ||
|
||
$word = ''; | ||
$tag = ''; | ||
$tagJump = ''; | ||
$output = []; | ||
|
||
$text .= ' '; | ||
$inAttr1 = false; | ||
$inAttr2 = false; | ||
|
||
for ($i = 0; $i < mb_strlen($text); $i++) { | ||
$char = mb_substr($text, $i, 1); | ||
if ($tag !== '') { | ||
if ($char === '"' && !$inAttr2) $inAttr1 = !$inAttr1; | ||
if ($char === "'" && !$inAttr1) $inAttr2 = !$inAttr2; | ||
} | ||
if (mb_strpos($this->settings['wordBoundaries'], $char) === false && $tag === '') { | ||
$word .= $char; | ||
} else { | ||
if ($word !== '') { | ||
$output[] = $this->wordHyphenation($word, $locale); | ||
$word = ''; | ||
} | ||
if ($tag !== '' || $char === '<') { | ||
$tag .= $char; | ||
} | ||
if ($tag !== '' && $char === '>' && !$inAttr1 && !$inAttr2) { | ||
$spacePos = mb_strpos($tag, ' '); | ||
$bracketPos = mb_strpos($tag, '>'); | ||
$tagName = ($spacePos && $spacePos < $bracketPos) ? mb_substr($tag, 1, $spacePos - 1) : mb_substr($tag, 1, $bracketPos - 1); | ||
if ($tagJump === '' && in_array(mb_strtolower($tagName), $this->settings['excludeTags'])) { | ||
$tagJump = mb_strtolower($tagName); | ||
} else if ($tagJump === '' || mb_strtolower(mb_substr($tag, -mb_strlen($tagName) - 3)) === '</' . $tagJump . '>') { | ||
$output[] = $tag; | ||
$tag = ''; | ||
$tagJump = ''; | ||
} | ||
} | ||
if ($tag === '' && $char !== '<' && $char !== '>') $output[] = $char; | ||
} | ||
} | ||
|
||
$text = join($output); | ||
return mb_substr($text, 0, mb_strlen($text) - 1); | ||
} | ||
|
||
/** | ||
* Word hyphenation. | ||
* | ||
* @param string $word | ||
* @param string $locale | ||
* @return string | ||
*/ | ||
protected function wordHyphenation($word, $locale) | ||
{ | ||
if (mb_strlen($word) < $this->settings['shortestPattern'] | ||
|| mb_strpos($word, $this->settings['hyphen']) !== false | ||
|| mb_strpos($word, $this->settings['altHyphen']) !== false) { | ||
return $word; | ||
} | ||
if (isset($this->dictionary[mb_strtolower($word)])) { | ||
return $this->dictionary[mb_strtolower($word)]; | ||
} | ||
|
||
$w = '_' . $word . '_'; | ||
$wLength = mb_strlen($w); | ||
$chars = $this->mb_split_chars($w); | ||
$w = mb_strtolower($w); | ||
$hyphenatedWord = []; | ||
$hypos = []; | ||
|
||
$n = $wLength - $this->settings['shortestPattern']; | ||
for ($p = 0; $p <= $n; $p++) { | ||
$maxWins = min(($wLength - $p), $this->settings['longestPattern']); | ||
for ($win = $this->settings['shortestPattern']; $win <= $maxWins; $win++) { | ||
if (isset($this->patterns[$locale][mb_substr($w, $p, $win)])) { | ||
$pat = $this->patterns[$locale][mb_substr($w, $p, $win)]; | ||
$patLength = mb_strlen($pat); | ||
|
||
$t = 0; | ||
$val = []; | ||
for ($i = 0; $i < $patLength; $i++) { | ||
$c = mb_substr($pat, $i, 1); | ||
if (is_numeric($c)) { | ||
$val[] = $i - $t; | ||
$val[] = (int)$c; | ||
$t++; | ||
} | ||
} | ||
$pat = $val; | ||
} else { | ||
continue; | ||
} | ||
|
||
for ($i = 0; $i < count($pat); $i += 2) { | ||
$c = $p - 1 + $pat[$i]; | ||
if (!isset($hypos[$c]) || $hypos[$c] < $pat[$i + 1]) { | ||
$hypos[$c] = $pat[$i + 1]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
$inserted = 0; | ||
for ($i = $this->settings['leftmin']; $i <= (mb_strlen($word) - $this->settings['rightmin']); $i++) { | ||
if (isset($hypos[$i]) && !!$hypos[$i] & 1) { | ||
array_splice($chars, $i + $inserted + 1, 0, $this->settings['hyphen']); | ||
$inserted++; | ||
} | ||
} | ||
$hyphenatedWord = implode(array_splice($chars, 1, -1)); | ||
|
||
/** | ||
* @TODO Add caching? | ||
*/ | ||
return $hyphenatedWord; | ||
} | ||
|
||
|
||
/** | ||
* Internal helper function to split chars. | ||
* | ||
* @param string $string | ||
* @return array | ||
*/ | ||
protected function mb_split_chars($string) | ||
{ | ||
$i = 0; | ||
$strlen = mb_strlen($string); | ||
$array = []; | ||
while ($strlen - $i > 0) { | ||
$array[] = mb_substr($string, $i++, 1, 'utf-8'); | ||
} | ||
return $array; | ||
} | ||
|
||
/** | ||
* Internal helper function to convert js-Files from hyphenator.js | ||
* to a php-Pattern file. | ||
* | ||
* @param string $filename | ||
* @return void | ||
*/ | ||
protected function makePHPPattern($filename) | ||
{ | ||
$lines = file($filename . '.js'); | ||
$lines = str_replace(':', '=', $lines); | ||
$lines = str_replace(',', ';', $lines); | ||
$lines = str_replace('leftmin', '$leftmin', $lines); | ||
$lines = str_replace('rightmin', '$rightmin', $lines); | ||
$lines = str_replace('shortestPattern', '$shortestPattern', $lines); | ||
$lines = str_replace('longestPattern', '$longestPattern', $lines); | ||
$lines = str_replace(' ', '', $lines); | ||
$lines = str_replace("\t", '', $lines); | ||
|
||
$patterns = []; | ||
foreach ($lines as $lineNum => $line) { | ||
if (preg_match('/^([0-9]+)=/', $line, $matches)) { | ||
$num = $matches[1]; | ||
if ($num >= 3) { | ||
$str1 = explode('"', $line); | ||
for ($i = 0; $i < mb_strlen($str1[1]) / $num; $i++) { | ||
$pattern = mb_substr($str1[1], $i * $num, $num, 'utf-8'); | ||
$patterns[] = "'" . preg_replace('/[0-9]/', '', $pattern) . "'=>'" . $pattern . "'"; | ||
} | ||
} | ||
} | ||
} | ||
|
||
$filename = $filename . '.php'; | ||
if (!($handle = fopen($filename, 'w'))) { | ||
// TODO: Add Exception | ||
return false; | ||
} | ||
|
||
$pattern = 'return [' . implode(', ', $patterns) . '];'; | ||
if (!fwrite($handle, "<?php\n" . $pattern)) { | ||
// TODO: Add Exception | ||
return false; | ||
} | ||
|
||
fclose($handle); | ||
return true; | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
Classes/Wegmeister/Hyphenator/TypoScript/HyphenateImplementation.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
namespace Wegmeister\Hyphenator\TypoScript; | ||
|
||
/** | ||
* This script belongs to the TYPO3 Flow Package "Wegmeister.Hyphenator" | ||
*/ | ||
|
||
use TYPO3\Flow\Annotations as Flow; | ||
use TYPO3\Neos\Domain\Exception; | ||
use TYPO3\TYPO3CR\Domain\Model\NodeInterface; | ||
use TYPO3\TypoScript\TypoScriptObjects\AbstractTypoScriptObject; | ||
|
||
/** | ||
* A TypoScript Object that adds hyphens to texts | ||
* | ||
* Usage:: | ||
* | ||
* [email protected] = Wegmeister.Hyphenator:Hyphenate | ||
*/ | ||
class HyphenateImplementation extends AbstractTypoScriptObject | ||
{ | ||
/** | ||
* @Flow\Inject | ||
* @var \Wegmeister\Hyphenator\Service\HyphenationService | ||
*/ | ||
protected $hyphenationService; | ||
|
||
|
||
/** | ||
* Add hyphens to the given text | ||
* | ||
* If the workspace of the current node context is not live, | ||
* no replacement will be done unless forceConversion is set. | ||
* | ||
* @return string | ||
* @throws Exception | ||
*/ | ||
public function evaluate() | ||
{ | ||
$text = $this->tsValue('value'); | ||
$locale = $this->tsValue('locale'); | ||
|
||
if ($text === '' || $text === null) { | ||
return ''; | ||
} | ||
|
||
$node = $this->tsValue('node'); | ||
|
||
if (!$node instanceof NodeInterface) { | ||
throw new Exception(sprintf('The current node must be an instance of NodeInterface, given: "%s".', gettype($text)), 1382624087); | ||
} | ||
|
||
if ($node->getContext()->getWorkspace()->getName() !== 'live' && !($this->tsValue('forceConversion'))) { | ||
return $text; | ||
} | ||
|
||
$processedContent = $this->hyphenationService->hyphenate($text, $locale); | ||
|
||
return $processedContent; | ||
} | ||
} |
Oops, something went wrong.