@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3abstract class PhabricatorCustomFieldMonogramParser
4 extends Phobject {
5
6 abstract protected function getPrefixes();
7 abstract protected function getSuffixes();
8 abstract protected function getInfixes();
9 abstract protected function getMonogramPattern();
10
11 public function parseCorpus($corpus) {
12 $prefixes = $this->getPrefixes();
13 $suffixes = $this->getSuffixes();
14 $infixes = $this->getInfixes();
15
16 $prefix_regex = $this->buildRegex($prefixes);
17 $infix_regex = $this->buildRegex($infixes, true);
18 $suffix_regex = $this->buildRegex($suffixes, true, true);
19
20 $monogram_pattern = $this->getMonogramPattern();
21
22 $pattern =
23 '/'.
24 '(?:^|\b)'.
25 $prefix_regex.
26 $infix_regex.
27 '((?:'.$monogram_pattern.'(?:\b|$)[,\s]*)+)'.
28 '(?:\band\s+('.$monogram_pattern.'(?:\b|$)))?'.
29 $suffix_regex.
30 '(?:$|\b)'.
31 '/';
32
33 $matches = null;
34 $ok = preg_match_all(
35 $pattern,
36 $corpus,
37 $matches,
38 PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
39
40 if ($ok === false) {
41 throw new Exception(pht('Regular expression "%s" is invalid!', $pattern));
42 }
43
44 $results = array();
45 foreach ($matches as $set) {
46 $monograms = array_filter(preg_split('/[,\s]+/', $set[3][0]));
47
48 if (isset($set[4]) && $set[4][0]) {
49 $monograms[] = $set[4][0];
50 }
51
52 $results[] = array(
53 'match' => $set[0][0],
54 'prefix' => $set[1][0],
55 'infix' => $set[2][0],
56 'monograms' => $monograms,
57 'suffix' => idx(idx($set, 5, array()), 0, ''),
58 'offset' => $set[0][1],
59 );
60 }
61
62 return $results;
63 }
64
65 private function buildRegex(array $list, $optional = false, $final = false) {
66 $parts = array();
67 foreach ($list as $string) {
68 $parts[] = preg_quote($string, '/');
69 }
70 $parts = implode('|', $parts);
71
72 $maybe_tail = $final ? '' : '\s+';
73 $maybe_optional = $optional ? '?' : '';
74
75 return '(?i:('.$parts.')'.$maybe_tail.')'.$maybe_optional;
76 }
77
78}