*/ public function extractTokens(?string $xref): array { if (empty($xref)) { return []; } $tokens = []; foreach (explode(' ', $xref) as $token) { if (preg_match(self::XREF_PATTERN_WITH_NUM, $token, $m) || preg_match(self::XREF_PATTERN_NO_NUM, $token, $m)) { $tokens[] = $m[0]; } } return $tokens; } /** * Returns tokens that appear in $headerXref but not in $existingXref. * * @return list */ public function diffNewTokens(?string $existingXref, ?string $headerXref): array { $existing = $this->extractTokens($existingXref); $incoming = $this->extractTokens($headerXref); return array_values(array_diff($incoming, $existing)); } /** @return list */ public function extractGroupNames(?string $xref): array { $groups = []; foreach ($this->extractTokens($xref) as $token) { $group = preg_replace('/:\d+$/', '', (string) $token); if ($group !== null && $group !== '') { $groups[$group] = true; } } return array_keys($groups); } }