diff options
Diffstat (limited to 'MLEB/Translate/insertables/RegexInsertablesSuggester.php')
-rw-r--r-- | MLEB/Translate/insertables/RegexInsertablesSuggester.php | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/MLEB/Translate/insertables/RegexInsertablesSuggester.php b/MLEB/Translate/insertables/RegexInsertablesSuggester.php new file mode 100644 index 00000000..f054f4e0 --- /dev/null +++ b/MLEB/Translate/insertables/RegexInsertablesSuggester.php @@ -0,0 +1,129 @@ +<?php +/** + * @file + * @author Abijeet Patro + * @license GPL-2.0-or-later + */ + +/** + * Regex InsertablesSuggester implementation that can be extended or used + * for insertables in message groups + * @since 2019.06 + */ +class RegexInsertablesSuggester implements InsertablesSuggester { + /** + * The regex to run on the message. The regex must use named group captures + * @var string + */ + protected $regex = null; + + /** + * The named parameter from the regex that should be used for + * insertable display. + * @var string + */ + protected $display = null; + + /** + * The named parameter from the regex that should be used as pre + * @var string + */ + protected $pre = null; + + /** + * The named paramater from the regex that should be used as post + * @var string + */ + protected $post = null; + + /** + * Constructur function + * @param array|string $params If params is specified as a string, it is used as the regex. + * Eg: "/\$[a-z0-9]+/". In this case `display` is the first value from the regex match. + * `pre` is also the first value from the regex match, `post` is left empty. + * + * If params is specified as a collection / array, see below for further details. + * + * Example: + * + * ``` + * params: + * regex: "/(?<pre>\[)[^]]+(?<post>\]\([^)]+\))/" + * display: "$pre $post" + * pre: "$pre" + * post: "$post" + * ``` + * + * Details: + * + * $params = [ + * 'regex' => (string, required) The regex to be used for insertable. Must use named captures. + * When specifying named captures, do not use the $ symbol in the name. In the above + * example, two named captures are used - `pre` and `post` + * 'display' => (string) Mandatory value. The display value for the insertable. Named captures + * prefixed with $ are used here. + * 'pre' => (string) The pre value for the insertable. Named captures prefixed with $ are used + * here. If not specified, is set to the display value. + * 'post' => (string) The post value for the insertable. Named captures prefixed with $ are used + * here. If not specified, defaults to an empty string. + * ] + */ + public function __construct( $params ) { + if ( is_string( $params ) ) { + $this->regex = $params; + } elseif ( is_array( $params ) ) { + // Validate if the array is in a proper format. + $this->regex = $params['regex'] ?? null; + $this->display = $params['display'] ?? null; + $this->pre = $params['pre'] ?? null; + $this->post = $params['post'] ?? null; + } + + if ( $this->regex === null ) { + throw new InvalidArgumentException( + 'Invalid configuration for the RegexInsertablesSuggester. Did not find a regex specified' + ); + } + + if ( $this->display !== null && $this->pre === null ) { + // if display value is set, and pre value is not set, set the display to pre. + // makes the configuration easier. + $this->pre = $this->display; + } + } + + public function getInsertables( $text ) { + $insertables = []; + + $matches = []; + preg_match_all( $this->regex, $text, $matches, PREG_SET_ORDER ); + + $insertables = array_map( [ $this, 'mapInsertables' ], $matches ); + + return $insertables; + } + + protected function mapInsertables( array $match ) { + if ( $this->display === null ) { + return new Insertable( $match[0], $match[0] ); + } + + $replacements = []; + // add '$' to the other keys for replacement. + foreach ( $match as $key => $value ) { + if ( !is_int( $key ) ) { + $tmpKey = '$' . $key; + $replacements[ $tmpKey ] = $value; + } + } + + $displayVal = strtr( $this->display, $replacements ); + $preVal = strtr( $this->pre, $replacements ); + $postVal = ''; + if ( $this->post !== null ) { + $postVal = strtr( $this->post, $replacements ); + } + + return new Insertable( $displayVal, $preVal, $postVal ); + } +} |