|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * Verbal Expressions v0.1 (https://github.com/jehna/VerbalExpressions) ported in PHP |
| 4 | + * @author Mihai Ionut Vilcu ([email protected]) |
| 5 | + * 22.July.2013 |
| 6 | + */ |
| 7 | + |
| 8 | + |
| 9 | +// // some tests |
| 10 | + |
| 11 | +// $regex = new VerEx; |
| 12 | + |
| 13 | +// $regex ->startOfLine() |
| 14 | +// ->then( "http" ) |
| 15 | +// ->maybe( "s" ) |
| 16 | +// ->then( "://" ) |
| 17 | +// ->maybe( "www." ) |
| 18 | +// ->anythingBut( " " ) |
| 19 | +// ->endOfLine(); |
| 20 | + |
| 21 | + |
| 22 | +// if($regex->test("http://github.com")) |
| 23 | +// echo "valid url"; |
| 24 | +// else |
| 25 | +// echo "invalid url"; |
| 26 | + |
| 27 | + |
| 28 | +// echo "<pre>". $regex->getRegex() ."</pre>"; |
| 29 | + |
| 30 | + |
| 31 | +// echo $regex ->clean(array("modifiers"=> "m","replaceLimit"=>4)) |
| 32 | +// ->find(' ') |
| 33 | +// ->replace("This is a small test http://somesite.com and some more text.", "-"); |
| 34 | + |
| 35 | + |
| 36 | +class VerEx { |
| 37 | + |
| 38 | + var $prefixes = ""; |
| 39 | + var $source = ""; |
| 40 | + var $suffixes = ""; |
| 41 | + var $modifiers = "m"; // default to global multiline matching |
| 42 | + var $replaceLimit = 1; // the limit of preg_replace when g modifier is not set |
| 43 | + |
| 44 | + /** |
| 45 | + * Sanitation function for adding anything safely to the expression |
| 46 | + * @param string $value the to be added |
| 47 | + * @return string escaped value |
| 48 | + */ |
| 49 | + function sanitize( $value ) { |
| 50 | + if(!$value) |
| 51 | + return $value; |
| 52 | + return preg_quote($value, "/"); |
| 53 | + } |
| 54 | + /** |
| 55 | + * Add stuff to the expression |
| 56 | + * @param string $value the stuff to be added |
| 57 | + */ |
| 58 | + function add( $value ) { |
| 59 | + $this->source .= $value; |
| 60 | + return $this; |
| 61 | + } |
| 62 | + /** |
| 63 | + * Mark the expression to start at the beginning of the line. |
| 64 | + * @param boolean $enable Enables or disables the line starting. Default value: true |
| 65 | + */ |
| 66 | + function startOfLine( $enable = true ) { |
| 67 | + $this->prefixes = $enable ? "^" : ""; |
| 68 | + return $this; |
| 69 | + } |
| 70 | + /** |
| 71 | + * Mark the expression to end at the last character of the line. |
| 72 | + * @param boolean $enable Enables or disables the line ending. Default value: true |
| 73 | + */ |
| 74 | + function endOfLine( $enable = true ) { |
| 75 | + $this->suffixes = $enable ? "$" : ""; |
| 76 | + return $this; |
| 77 | + } |
| 78 | + /** |
| 79 | + * Add a string to the expression |
| 80 | + * @param string $value The string to be looked for |
| 81 | + */ |
| 82 | + function then( $value ) { |
| 83 | + $this->add("(".$this->sanitize($value).")"); |
| 84 | + return $this; |
| 85 | + } |
| 86 | + |
| 87 | + /** |
| 88 | + * alias for then() |
| 89 | + * @param string $value The string to be looked for |
| 90 | + */ |
| 91 | + function find( $value ) { |
| 92 | + return $this->then($value); |
| 93 | + } |
| 94 | + /** |
| 95 | + * Add a string to the expression that might appear once (or not). |
| 96 | + * @param string $value The string to be looked for |
| 97 | + */ |
| 98 | + function maybe( $value ) { |
| 99 | + $this->add("(".$this->sanitize($value).")?"); |
| 100 | + return $this; |
| 101 | + } |
| 102 | + /** |
| 103 | + * Accept any string |
| 104 | + */ |
| 105 | + function anything() { |
| 106 | + $this->add("(.*)"); |
| 107 | + return $this; |
| 108 | + } |
| 109 | + /** |
| 110 | + * Anything but this chars |
| 111 | + * @param string $value The unaccepted chars |
| 112 | + */ |
| 113 | + function anythingBut( $value ) { |
| 114 | + $this->add("([^". $this->sanitize($value) ."]*)"); |
| 115 | + return $this; |
| 116 | + } |
| 117 | + /** |
| 118 | + * Shorthand for preg_replace() |
| 119 | + * @param string $source the string that will be affected(subject) |
| 120 | + * @param string $value the replacement |
| 121 | + */ |
| 122 | + function replace($source, $value) { |
| 123 | + // php doesn't have g modifier so we remove it if it's there and we remove limit param |
| 124 | + if(strpos($this->modifiers, 'g') !== false){ |
| 125 | + $this->modifiers = str_replace('g', '', $this->modifiers); |
| 126 | + return preg_replace($this->getRegex(), $value, $source); |
| 127 | + } |
| 128 | + return preg_replace($this->getRegex(), $value, $source, $this->replaceLimit); |
| 129 | + } |
| 130 | + /** |
| 131 | + * Match line break |
| 132 | + */ |
| 133 | + function lineBreak() { |
| 134 | + $this->add("(\\n|(\\r\\n))"); |
| 135 | + return $this; |
| 136 | + } |
| 137 | + /** |
| 138 | + * Shorthand for lineBreak |
| 139 | + */ |
| 140 | + function br() { |
| 141 | + return $this->lineBreak(); |
| 142 | + } |
| 143 | + /** |
| 144 | + * Match tabs. |
| 145 | + */ |
| 146 | + function tab() { |
| 147 | + $this->add("\\t"); |
| 148 | + return $this; |
| 149 | + } |
| 150 | + /** |
| 151 | + * Match any alfanumeric |
| 152 | + */ |
| 153 | + function word() { |
| 154 | + $this->add("\\w+"); |
| 155 | + return $this; |
| 156 | + } |
| 157 | + /** |
| 158 | + * Any of the listed chars |
| 159 | + * @param string $value The chars looked for |
| 160 | + */ |
| 161 | + function anyOf( $value ) { |
| 162 | + $this->add("["+ value +"]"); |
| 163 | + return $this; |
| 164 | + } |
| 165 | + /** |
| 166 | + * Shorthand for anyOf |
| 167 | + * @param string $value The chars looked for |
| 168 | + */ |
| 169 | + function any( $value ) { |
| 170 | + return $this->anyOf($value); |
| 171 | + } |
| 172 | + /** |
| 173 | + * Adds a range to our expresion ex: range(a,z) => a-z, range(a,z,0,9) => a-z0-9 |
| 174 | + */ |
| 175 | + function range() { |
| 176 | + |
| 177 | + $arg_num = func_num_args(); |
| 178 | + if($arg_num%2 != 0) |
| 179 | + throw new Exception("Number of args must be even", 1); |
| 180 | + $value = "["; |
| 181 | + $arg_list = func_get_args(); |
| 182 | + for($i = 0; $i < $arg_num;) |
| 183 | + $value .= $this->sanitize($arg_list[$i++]) . " - " . $this->sanitize($arg_list[$i++]); |
| 184 | + $value .= "]"; |
| 185 | + |
| 186 | + $this->add($value); |
| 187 | + |
| 188 | + return $this; |
| 189 | + } |
| 190 | + /** |
| 191 | + * Adds a modifier |
| 192 | + */ |
| 193 | + function addModifier( $modifier ) { |
| 194 | + if(strpos($this->modifiers, $modifier) === false) |
| 195 | + $this->modifiers .= $modifier; |
| 196 | + |
| 197 | + return $this; |
| 198 | + } |
| 199 | + /** |
| 200 | + * Removes a modifier |
| 201 | + */ |
| 202 | + function removeModifier( $modifier ) { |
| 203 | + |
| 204 | + $this->modifiers = str_replace($modifier, '', $modifier); |
| 205 | + |
| 206 | + return $this; |
| 207 | + } |
| 208 | + /** |
| 209 | + * Match case insensitive or sensitive based on $enable value |
| 210 | + * @param boolean $enable Enables or disables case sensitive. Default true |
| 211 | + */ |
| 212 | + function withAnyCase( $enable = true ) { |
| 213 | + if($enable) |
| 214 | + $this->addModifier('i'); |
| 215 | + else |
| 216 | + $this->removeModifier('i'); |
| 217 | + |
| 218 | + return $this; |
| 219 | + } |
| 220 | + /** |
| 221 | + * Toggles g modifier |
| 222 | + * @param boolean $enable Enables or disables g modifier. Default true |
| 223 | + */ |
| 224 | + function stopAtFirst( $enable = true ) { |
| 225 | + if($enable) |
| 226 | + $this->addModifier('g'); |
| 227 | + else |
| 228 | + $this->removeModifier('g'); |
| 229 | + return $this; |
| 230 | + } |
| 231 | + /** |
| 232 | + * Toggles m modifier |
| 233 | + * @param boolean $enable Enables or disables m modifier. Default true |
| 234 | + */ |
| 235 | + function searchOneLine( $enable = true ) { |
| 236 | + if($enable) |
| 237 | + $this->addModifier('m'); |
| 238 | + else |
| 239 | + $this->removeModifier('m'); |
| 240 | + |
| 241 | + return $this; |
| 242 | + } |
| 243 | + /** |
| 244 | + * Adds the multiple modifier at the end of your expresion |
| 245 | + * @param string $value Your expresion |
| 246 | + */ |
| 247 | + function multiple( $value ) { |
| 248 | + |
| 249 | + $value = $this->sanitize($value); |
| 250 | + |
| 251 | + switch (substr($value, -1)) { |
| 252 | + case '+': |
| 253 | + case '*': |
| 254 | + break; |
| 255 | + |
| 256 | + default: |
| 257 | + $value += '+'; |
| 258 | + break; |
| 259 | + } |
| 260 | + |
| 261 | + $this->add($value); |
| 262 | + |
| 263 | + return $this; |
| 264 | + } |
| 265 | + |
| 266 | + /** |
| 267 | + * Wraps the current expresion in an `or` with $value |
| 268 | + * @param string $value new expression |
| 269 | + */ |
| 270 | + function _or( $value ) { |
| 271 | + if(strpos($this->prefixes, "(") === false) |
| 272 | + $this->prefixes .= "("; |
| 273 | + if(strpos($this->suffixes, ")") === false) |
| 274 | + $this->suffixes .= ")"; |
| 275 | + |
| 276 | + $this->add(")|("); |
| 277 | + if($value) |
| 278 | + $this->add($value); |
| 279 | + |
| 280 | + return $this; |
| 281 | + |
| 282 | + } |
| 283 | + /** |
| 284 | + * Creates the final regex. |
| 285 | + * @return string The final regex |
| 286 | + */ |
| 287 | + function getRegex() { |
| 288 | + return "/".$this->prefixes . $this->source . $this->suffixes. "/" . $this->modifiers; |
| 289 | + } |
| 290 | + |
| 291 | + /** |
| 292 | + * tests the match of a string to the current regex |
| 293 | + * @param string $value The string to be tested |
| 294 | + * @return boolean true if it's a match |
| 295 | + */ |
| 296 | + function test($value) { |
| 297 | + // php doesn't have g modifier so we remove it if it's there and call preg_match_all() |
| 298 | + if(strpos($this->modifiers, 'g') !== false){ |
| 299 | + $this->modifiers = str_replace('g', '', $this->modifiers); |
| 300 | + return preg_match_all($this->getRegex(), $value); |
| 301 | + } |
| 302 | + return preg_match($this->getRegex(), $value); |
| 303 | + } |
| 304 | + |
| 305 | + /** |
| 306 | + * deletes the current regex for a fresh start |
| 307 | + */ |
| 308 | + function clean($options = array()) { |
| 309 | + $options = array_merge(array("prefixes"=> "", "source"=>"", "suffixes"=>"", "modifiers"=>"gm","replaceLimit"=>"1"), $options); |
| 310 | + $this->prefixes = $options['prefixes']; |
| 311 | + $this->source = $options['source']; |
| 312 | + $this->suffixes = $options['suffixes']; |
| 313 | + $this->modifiers = $options['modifiers']; // default to global multiline matching |
| 314 | + $this->replaceLimit = $options['replaceLimit']; // default to global multiline matching |
| 315 | + |
| 316 | + return $this; |
| 317 | + } |
| 318 | + |
| 319 | +} |
| 320 | + |
| 321 | + |
0 commit comments