Page MenuHomeWickedGov Phorge

Grammar.php
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

Grammar.php

<?php
/**
* @license GPL-2.0-or-later
* @file
*/
namespace Wikimedia\Leximorph\Handler;
use Psr\Log\LoggerInterface;
use Wikimedia\Leximorph\Handler\Overrides\GrammarFallbackRegistry;
use Wikimedia\Leximorph\Provider;
/**
* Grammar
*
* The Grammar class performs language-specific grammatical transformations on a given word.
* It uses transformation rules (loaded from JSON files) to convert the input word into
* the specified grammatical case.
*
* Usage Example:
* <code>
* echo $grammar->process( 'Википедия', 'genitive' );
* </code>
*
* @since 1.45
* @author Doğu Abaris (abaris@null.net)
* @license https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
*/
class Grammar {
/**
* Initializes the Grammar handler with the given transformations provider and a logger.
*
* @param Provider $provider Provider instance.
* @param GrammarFallbackRegistry $postProcessor The post processor registry.
* @param LoggerInterface $logger The logger instance to use.
*
* @since 1.45
*/
public function __construct(
protected readonly Provider $provider,
private readonly GrammarFallbackRegistry $postProcessor,
private readonly LoggerInterface $logger,
) {
}
/**
* Transforms the given word into the specified grammatical case.
*
* This method applies language-specific grammatical transformations by using transformation
* rules loaded from JSON configuration files. The input word is modified according to the first
* matching rule for the target grammatical case.
*
* @param string $word The word to transform.
* @param string $case The target grammatical case.
*
* @since 1.45
* @return string The transformed word in the specified case.
*/
public function process( string $word, string $case ): string {
$grammarTransformations = $this->provider->getGrammarTransformationsProvider()->getTransformations();
if ( array_key_exists( $case, $grammarTransformations ) ) {
$forms = $grammarTransformations[$case];
// Some names of grammar rules are aliases for other rules.
// In such cases the value is a string rather than object,
// so load the actual rules.
if ( is_string( $forms ) ) {
$alias = $forms;
if ( isset( $grammarTransformations[$alias] ) && is_array( $grammarTransformations[$alias] ) ) {
$forms = $grammarTransformations[$alias];
} else {
$this->logger->error(
'Expected alias {alias} to resolve to an array in grammar transformations.',
[ 'alias' => $alias ]
);
return $word;
}
}
if ( !is_array( $forms ) ) {
$this->logger->error(
'Invalid type for grammar forms. Expected array, got {type}.',
[ 'type' => gettype( $forms ) ]
);
return $word;
}
foreach ( $forms as $rule ) {
if ( !is_array( $rule ) || !isset( $rule[0] ) || !isset( $rule[1] ) ) {
$this->logger->warning(
'Skipping malformed grammar rule. Expected [pattern, replacement]. Case: {case}, Rule: {rule}',
[
'case' => $case,
'rule' => json_encode( $rule ),
]
);
continue;
}
if ( !is_string( $rule[0] ) ) {
$this->logger->warning(
'Invalid grammar rule format: first element must be string. Case: {case}, Rule: {rule}',
[
'case' => $case,
'rule' => json_encode( $rule ),
]
);
continue;
}
$form = $rule[0];
if ( $form === '@metadata' ) {
continue;
}
$replacement = is_string( $rule[1] ) ? $rule[1] : '';
$regex = '/' . addcslashes( $form, '/' ) . '/u';
$patternMatches = preg_match( $regex, $word );
if ( $patternMatches === false ) {
$this->logger->error(
'An error occurred while processing grammar: {error}. Word: {word}. Regex: /{form}/.',
[
'error' => preg_last_error_msg(),
'word' => $word,
'form' => $form,
]
);
} elseif ( $patternMatches === 1 ) {
$word = preg_replace( $regex, $replacement, $word ) ?? $word;
break;
}
}
} else {
$word = $this->postProcessor->apply( $this->provider->getLanguageCode(), $word, $case );
}
return $word;
}
}

File Metadata

Mime Type
text/x-php
Expires
Aug 21 2026, 03:25 (12 w, 6 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
bb/23/48ff1183efad7b86d5b79718f2cb
Default Alt Text
Grammar.php (4 KB)

Event Timeline