OSDN Git Service

accf17465569cf954b592de53319fe70577138e5
[embrj/master.git] / common / Regex.php
1 <?php
2 /**
3  * @author     Mike Cochrane <mikec@mikenz.geek.nz>
4  * @author     Nick Pope <nick@nickpope.me.uk>
5  * @copyright  Copyright © 2010, Mike Cochrane, Nick Pope
6  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License v2.0
7  * @package    Twitter
8  */
9
10 /**
11  * Twitter Regex Abstract Class
12  *
13  * Used by subclasses that need to parse tweets.
14  *
15  * Originally written by {@link http://github.com/mikenz Mike Cochrane}, this
16  * is based on code by {@link http://github.com/mzsanford Matt Sanford} and
17  * heavily modified by {@link http://github.com/ngnpope Nick Pope}.
18  *
19  * @author     Mike Cochrane <mikec@mikenz.geek.nz>
20  * @author     Nick Pope <nick@nickpope.me.uk>
21  * @copyright  Copyright © 2010, Mike Cochrane, Nick Pope
22  * @license    http://www.apache.org/licenses/LICENSE-2.0  Apache License v2.0
23  * @package    Twitter
24  */
25 abstract class Twitter_Regex {
26
27   /**
28    * Expression to at sign characters
29    *
30    * @var  string
31    */
32   const REGEX_AT_SIGNS = '[@@]';
33
34   /**
35    * Expression to match characters that may come before a URL.
36    *
37    * @var  string
38    */
39   const REGEX_URL_CHARS_BEFORE = '(?:[^-\\/"\':!=a-z0-9_@@]|^|\\:)';
40
41   /**
42    * Expression to match the domain portion of a URL.
43    *
44    * @var  string
45    */
46   const REGEX_URL_DOMAIN = '(?:[^\\p{P}\\p{Lo}\\s][\\.-](?=[^\\p{P}\\p{Lo}\\s])|[^\\p{P}\\p{Lo}\\s])+\\.[a-z]{2,}(?::[0-9]+)?';
47
48   /**
49    * Expression to match handful of probable TLDs for protocol-less URLS.
50    *
51    * @var  string
52    */
53   const REGEX_PROBABLE_TLD = '/\\.(?:com|net|org|gov|edu)$/iu';
54
55   /**
56    * Expression to match characters that may come in the URL path.
57    *
58    * @var  string
59    */
60   const REGEX_URL_CHARS_PATH = '(?:(?:\\([a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_,~]+\\))|@[a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_,~]+\\/|[\\.\\,]?(?:[a-z0-9!\\*\';:=\\+\\$\\/%#\\[\\]\\-_~]|,(?!\s)))';
61
62   /**
63    * Expression to match characters that may come at the end of the URL path.
64    *
65    * @var  string
66    */
67   const REGEX_URL_CHARS_PATH_END = '[a-z0-9=#\\/]';
68
69   /**
70    * Expression to match characters that may come in the URL query string.
71    *
72    * @var  string
73    */
74   const REGEX_URL_CHARS_QUERY = '[a-z0-9!\\*\'\\(\\);:&=\\+\\$\\/%#\\[\\]\\-_\\.,~]';
75
76   /**
77    * Expression to match characters that may come at the end of the URL query
78    * string.
79    *
80    * @var  string
81    */
82   const REGEX_URL_CHARS_QUERY_END = '[a-z0-9_&=#\\/]';
83
84   /**
85    * Expression to match a username followed by a list.
86    *
87    * @var  string
88    */
89   const REGEX_USERNAME_LIST = '/([^a-z0-9_\/]|^|RT:?)([@@]+)([a-z0-9_]{1,20})(\/[a-z][-_a-z0-9\x80-\xFF]{0,24})?([@@\xC0-\xD6\xD8-\xF6\xF8-\xFF]?)/iu';
90
91   /**
92    * Expression to match a username mentioned anywhere in a tweet.
93    *
94    * @var  string
95    */
96   const REGEX_USERNAME_MENTION = '/(^|[^a-z0-9_])[@@]([a-z0-9_]{1,20})([@@\xC0-\xD6\xD8-\xF6\xF8-\xFF]?)/iu';
97
98   /**
99    * Expression to match a hashtag.
100    *
101    * @var  string
102    */
103   const REGEX_HASHTAG = '/(^|[^0-9A-Z&\/\?]+)([##]+)([0-9A-Z_]*[A-Z_]+[a-z0-9_üÀ-ÖØ-öø-ÿ]*)/iu';
104
105   /**
106    * Expression to match whitespace.
107    *
108    * Single byte whitespace characters
109    *   0x0009-0x000D White_Space # Cc # <control-0009>..<control-000D>
110    *   0x0020        White_Space # Zs # SPACE
111    *   0x0085        White_Space # Cc # <control-0085>
112    *   0x00A0        White_Space # Zs # NO-BREAK SPACE
113    * Multi byte whitespace characters
114    *   0x1680        White_Space # Zs # OGHAM SPACE MARK
115    *   0x180E        White_Space # Zs # MONGOLIAN VOWEL SEPARATOR
116    *   0x2000-0x200A White_Space # Zs # EN QUAD..HAIR SPACE
117    *   0x2028        White_Space # Zl # LINE SEPARATOR
118    *   0x2029        White_Space # Zp # PARAGRAPH SEPARATOR
119    *   0x202F        White_Space # Zs # NARROW NO-BREAK SPACE
120    *   0x205F        White_Space # Zs # MEDIUM MATHEMATICAL SPACE
121    *   0x3000        White_Space # Zs # IDEOGRAPHIC SPACE
122    *
123    * @var  string
124    */
125   const REGEX_WHITESPACE = '[\x09-\x0D\x20\x85\xA0]|\xe1\x9a\x80|\xe1\xa0\x8e|\xe2\x80[\x80-\x8a,\xa8,\xa9,\xaf\xdf]|\xe3\x80\x80';
126
127   /**
128    * Contains the complete valid URL pattern string.
129    *
130    * This should be generated the first time the constructor is called.
131    *
132    * @var  string  The regex pattern for a valid URL.
133    */
134   protected static $REGEX_VALID_URL = null;
135
136   /**
137    * Contains the reply username pattern string.
138    *
139    * This should be generated the first time the constructor is called.
140    *
141    * @var  string  The regex pattern for a reply username.
142    */
143   protected static $REGEX_REPLY_USERNAME = null;
144
145   /**
146    * The tweet to be used in parsing.  This should be populated by the
147    * constructor of all subclasses.
148    *
149    * @var  string
150    */
151   protected $tweet = '';
152
153   /**
154    * This constructor is used to populate some variables.
155    *
156    * @param  string  $tweet  The tweet to parse.
157    */
158   protected function __construct($tweet) {
159     if (is_null(self::$REGEX_VALID_URL)) {
160       self::$REGEX_VALID_URL = '/(?:'             # $1 Complete match (preg_match already matches everything.)
161         . '('.self::REGEX_URL_CHARS_BEFORE.')'    # $2 Preceding character
162         . '('                                     # $3 Complete URL
163         . '((?:https?:\\/\\/|www\\.)?)'           # $4 Protocol (or www)
164         . '('.self::REGEX_URL_DOMAIN.')'          # $5 Domain(s) (and port)
165         . '(\\/'.self::REGEX_URL_CHARS_PATH.'*'   # $6 URL Path
166         . self::REGEX_URL_CHARS_PATH_END.'?)?'
167         . '(\\?'.self::REGEX_URL_CHARS_QUERY.'*'  # $7 Query String
168         . self::REGEX_URL_CHARS_QUERY_END.')?'
169         . ')'
170         . ')/iux';
171     }
172     if (is_null(self::$REGEX_REPLY_USERNAME)) {
173       self::$REGEX_REPLY_USERNAME = '/^('.self::REGEX_WHITESPACE.')*[@@]([a-zA-Z0-9_]{1,20})/';
174     }
175     $this->tweet = $tweet;
176   }
177
178 }