Matcher.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace libphonenumber;
  3. /**
  4. * Matcher for various regex matching
  5. *
  6. * Note that this is NOT the same as google's java PhoneNumberMatcher class.
  7. * This class is a minimal port of java's built-in matcher class, whereas PhoneNumberMatcher
  8. * is designed to recognize phone numbers embedded in any text.
  9. *
  10. * @internal
  11. */
  12. class Matcher
  13. {
  14. /**
  15. * @var string
  16. */
  17. protected $pattern;
  18. /**
  19. * @var string
  20. */
  21. protected $subject = '';
  22. /**
  23. * @var array
  24. */
  25. protected $groups = array();
  26. private $searchIndex = 0;
  27. /**
  28. * @param string $pattern
  29. * @param string $subject
  30. */
  31. public function __construct($pattern, $subject)
  32. {
  33. $this->pattern = str_replace('/', '\/', (string)$pattern);
  34. $this->subject = (string)$subject;
  35. }
  36. protected function doMatch($type = 'find', $offset = 0)
  37. {
  38. $final_pattern = '(?:' . $this->pattern . ')';
  39. switch ($type) {
  40. case 'matches':
  41. $final_pattern = '^' . $final_pattern . '$';
  42. break;
  43. case 'lookingAt':
  44. $final_pattern = '^' . $final_pattern;
  45. break;
  46. case 'find':
  47. default:
  48. // no changes
  49. break;
  50. }
  51. $final_pattern = '/' . $final_pattern . '/ui';
  52. $search = mb_substr($this->subject, $offset);
  53. $result = preg_match($final_pattern, $search, $groups, PREG_OFFSET_CAPTURE);
  54. if ($result === 1) {
  55. // Expand $groups into $this->groups, but being multi-byte aware
  56. $positions = array();
  57. foreach ($groups as $group) {
  58. $positions[] = array(
  59. $group[0],
  60. $offset + mb_strlen(substr($search, 0, $group[1]))
  61. );
  62. }
  63. $this->groups = $positions;
  64. }
  65. return ($result === 1);
  66. }
  67. /**
  68. * @return bool
  69. */
  70. public function matches()
  71. {
  72. return $this->doMatch('matches');
  73. }
  74. /**
  75. * @return bool
  76. */
  77. public function lookingAt()
  78. {
  79. return $this->doMatch('lookingAt');
  80. }
  81. /**
  82. * @return bool
  83. */
  84. public function find($offset = null)
  85. {
  86. if ($offset === null) {
  87. $offset = $this->searchIndex;
  88. }
  89. // Increment search index for the next time we call this
  90. $this->searchIndex++;
  91. return $this->doMatch('find', $offset);
  92. }
  93. /**
  94. * @return int
  95. */
  96. public function groupCount()
  97. {
  98. if (empty($this->groups)) {
  99. return null;
  100. }
  101. return count($this->groups) - 1;
  102. }
  103. /**
  104. * @param int $group
  105. * @return string
  106. */
  107. public function group($group = null)
  108. {
  109. if ($group === null) {
  110. $group = 0;
  111. }
  112. return isset($this->groups[$group][0]) ? $this->groups[$group][0] : null;
  113. }
  114. /**
  115. * @param int|null $group
  116. * @return int
  117. */
  118. public function end($group = null)
  119. {
  120. if ($group === null) {
  121. $group = 0;
  122. }
  123. if (!isset($this->groups[$group])) {
  124. return null;
  125. }
  126. return $this->groups[$group][1] + mb_strlen($this->groups[$group][0]);
  127. }
  128. public function start($group = null)
  129. {
  130. if ($group === null) {
  131. $group = 0;
  132. }
  133. if (!isset($this->groups[$group])) {
  134. return null;
  135. }
  136. return $this->groups[$group][1];
  137. }
  138. /**
  139. * @param string $replacement
  140. * @return string
  141. */
  142. public function replaceFirst($replacement)
  143. {
  144. return preg_replace('/' . $this->pattern . '/x', $replacement, $this->subject, 1);
  145. }
  146. /**
  147. * @param string $replacement
  148. * @return string
  149. */
  150. public function replaceAll($replacement)
  151. {
  152. return preg_replace('/' . $this->pattern . '/x', $replacement, $this->subject);
  153. }
  154. /**
  155. * @param string $input
  156. * @return Matcher
  157. */
  158. public function reset($input = '')
  159. {
  160. $this->subject = $input;
  161. return $this;
  162. }
  163. }