Index: src/__phutil_library_map__.php =================================================================== --- src/__phutil_library_map__.php +++ src/__phutil_library_map__.php @@ -355,6 +355,8 @@ 'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/DifferentialCommitsFieldSpecification.php', 'DifferentialConflictsFieldSpecification' => 'applications/differential/field/specification/DifferentialConflictsFieldSpecification.php', 'DifferentialController' => 'applications/differential/controller/DifferentialController.php', + 'DifferentialCustomFieldDependsOnParser' => 'applications/differential/field/parser/DifferentialCustomFieldDependsOnParser.php', + 'DifferentialCustomFieldDependsOnParserTestCase' => 'applications/differential/field/parser/__tests__/DifferentialCustomFieldDependsOnParserTestCase.php', 'DifferentialCustomFieldNumericIndex' => 'applications/differential/storage/DifferentialCustomFieldNumericIndex.php', 'DifferentialCustomFieldStorage' => 'applications/differential/storage/DifferentialCustomFieldStorage.php', 'DifferentialCustomFieldStringIndex' => 'applications/differential/storage/DifferentialCustomFieldStringIndex.php', @@ -1369,6 +1371,7 @@ 'PhabricatorCustomFieldIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldIndexStorage.php', 'PhabricatorCustomFieldInterface' => 'infrastructure/customfield/interface/PhabricatorCustomFieldInterface.php', 'PhabricatorCustomFieldList' => 'infrastructure/customfield/field/PhabricatorCustomFieldList.php', + 'PhabricatorCustomFieldMonogramParser' => 'infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php', 'PhabricatorCustomFieldNotAttachedException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotAttachedException.php', 'PhabricatorCustomFieldNotProxyException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotProxyException.php', 'PhabricatorCustomFieldNumericIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldNumericIndexStorage.php', @@ -2870,6 +2873,8 @@ 'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialConflictsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialController' => 'PhabricatorController', + 'DifferentialCustomFieldDependsOnParser' => 'PhabricatorCustomFieldMonogramParser', + 'DifferentialCustomFieldDependsOnParserTestCase' => 'PhabricatorTestCase', 'DifferentialCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'DifferentialCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'DifferentialCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', @@ -4053,6 +4058,7 @@ 'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception', 'PhabricatorCustomFieldIndexStorage' => 'PhabricatorLiskDAO', 'PhabricatorCustomFieldList' => 'Phobject', + 'PhabricatorCustomFieldMonogramParser' => 'Phobject', 'PhabricatorCustomFieldNotAttachedException' => 'Exception', 'PhabricatorCustomFieldNotProxyException' => 'Exception', 'PhabricatorCustomFieldNumericIndexStorage' => 'PhabricatorCustomFieldIndexStorage', Index: src/applications/differential/field/parser/DifferentialCustomFieldDependsOnParser.php =================================================================== --- /dev/null +++ src/applications/differential/field/parser/DifferentialCustomFieldDependsOnParser.php @@ -0,0 +1,32 @@ + array(), + 'D123' => array(), + 'depends on D123' => array( + array( + 'match' => 'depends on D123', + 'prefix' => 'depends on', + 'infix' => '', + 'monograms' => array('D123'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'depends on D123.' => array( + array( + 'match' => 'depends on D123', + 'prefix' => 'depends on', + 'infix' => '', + 'monograms' => array('D123'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'depends on D123, D124' => array( + array( + 'match' => 'depends on D123, D124', + 'prefix' => 'depends on', + 'infix' => '', + 'monograms' => array('D123', 'D124'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'depends on rev D123' => array( + array( + 'match' => 'depends on rev D123', + 'prefix' => 'depends on', + 'infix' => 'rev', + 'monograms' => array('D123'), + 'suffix' => '', + 'offset' => 0, + ), + ), + 'depends on duck' => array( + ), + 'depends on D123abc' => array( + ), + ); + + foreach ($map as $input => $expect) { + $parser = new DifferentialCustomFieldDependsOnParser(); + $output = $parser->parseCorpus($input); + + $this->assertEqual($expect, $output, $input); + } + } + +} Index: src/infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php =================================================================== --- /dev/null +++ src/infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php @@ -0,0 +1,71 @@ +getPrefixes(); + $suffixes = $this->getSuffixes(); + $infixes = $this->getInfixes(); + + $prefix_regex = $this->buildRegex($prefixes); + $infix_regex = $this->buildRegex($infixes, true); + $suffix_regex = $this->buildRegex($suffixes, true, true); + + $monogram_pattern = $this->getMonogramPattern(); + + $pattern = + '/'. + '(?:^|\b)'. + $prefix_regex. + $infix_regex. + '((?:'.$monogram_pattern.'[,\s]*)+)'. + $suffix_regex. + '(?:$|\b)'. + '/i'; + + $matches = null; + $ok = preg_match_all( + $pattern, + $corpus, + $matches, + PREG_SET_ORDER | PREG_OFFSET_CAPTURE); + + if ($ok === false) { + throw new Exception(pht('Regular expression "%s" is invalid!', $pattern)); + } + + $results = array(); + foreach ($matches as $set) { + $results[] = array( + 'match' => $set[0][0], + 'prefix' => $set[1][0], + 'infix' => $set[2][0], + 'monograms' => array_filter(preg_split('/[,\s]+/', $set[3][0])), + 'suffix' => $set[4][0], + 'offset' => $set[0][1], + ); + } + + return $results; + } + + private function buildRegex(array $list, $optional = false, $final = false) { + $parts = array(); + foreach ($list as $string) { + $parts[] = preg_quote($string, '/'); + } + $parts = implode('|', $parts); + + $maybe_tail = $final ? '' : '\s+'; + $maybe_optional = $optional ? '?' : ''; + + return '(?:('.$parts.')'.$maybe_tail.')'.$maybe_optional; + } + +}