1<?php 2/** 3 * Zend Framework (http://framework.zend.com/) 4 * 5 * @link http://github.com/zendframework/zf2 for the canonical source repository 6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 7 * @license http://framework.zend.com/license/new-bsd New BSD License 8 */ 9 10namespace Zend\Filter; 11 12use Traversable; 13 14class PregReplace extends AbstractFilter 15{ 16 protected $options = array( 17 'pattern' => null, 18 'replacement' => '', 19 ); 20 21 /** 22 * Constructor 23 * Supported options are 24 * 'pattern' => matching pattern 25 * 'replacement' => replace with this 26 * 27 * @param array|Traversable|string|null $options 28 */ 29 public function __construct($options = null) 30 { 31 if ($options instanceof Traversable) { 32 $options = iterator_to_array($options); 33 } 34 35 if (!is_array($options) || (!isset($options['pattern']) && !isset($options['replacement']))) { 36 $args = func_get_args(); 37 if (isset($args[0])) { 38 $this->setPattern($args[0]); 39 } 40 if (isset($args[1])) { 41 $this->setReplacement($args[1]); 42 } 43 } else { 44 $this->setOptions($options); 45 } 46 } 47 48 /** 49 * Set the regex pattern to search for 50 * @see preg_replace() 51 * 52 * @param string|array $pattern - same as the first argument of preg_replace 53 * @return self 54 * @throws Exception\InvalidArgumentException 55 */ 56 public function setPattern($pattern) 57 { 58 if (!is_array($pattern) && !is_string($pattern)) { 59 throw new Exception\InvalidArgumentException(sprintf( 60 '%s expects pattern to be array or string; received "%s"', 61 __METHOD__, 62 (is_object($pattern) ? get_class($pattern) : gettype($pattern)) 63 )); 64 } 65 66 if (is_array($pattern)) { 67 foreach ($pattern as $p) { 68 $this->validatePattern($p); 69 } 70 } 71 72 if (is_string($pattern)) { 73 $this->validatePattern($pattern); 74 } 75 76 $this->options['pattern'] = $pattern; 77 return $this; 78 } 79 80 /** 81 * Get currently set match pattern 82 * 83 * @return string|array 84 */ 85 public function getPattern() 86 { 87 return $this->options['pattern']; 88 } 89 90 /** 91 * Set the replacement array/string 92 * @see preg_replace() 93 * 94 * @param array|string $replacement - same as the second argument of preg_replace 95 * @return self 96 * @throws Exception\InvalidArgumentException 97 */ 98 public function setReplacement($replacement) 99 { 100 if (!is_array($replacement) && !is_string($replacement)) { 101 throw new Exception\InvalidArgumentException(sprintf( 102 '%s expects replacement to be array or string; received "%s"', 103 __METHOD__, 104 (is_object($replacement) ? get_class($replacement) : gettype($replacement)) 105 )); 106 } 107 $this->options['replacement'] = $replacement; 108 return $this; 109 } 110 111 /** 112 * Get currently set replacement value 113 * 114 * @return string|array 115 */ 116 public function getReplacement() 117 { 118 return $this->options['replacement']; 119 } 120 121 /** 122 * Perform regexp replacement as filter 123 * 124 * @param mixed $value 125 * @return mixed 126 * @throws Exception\RuntimeException 127 */ 128 public function filter($value) 129 { 130 if (!is_scalar($value) && !is_array($value)) { 131 return $value; 132 } 133 134 if ($this->options['pattern'] === null) { 135 throw new Exception\RuntimeException(sprintf( 136 'Filter %s does not have a valid pattern set', 137 get_class($this) 138 )); 139 } 140 141 return preg_replace($this->options['pattern'], $this->options['replacement'], $value); 142 } 143 144 /** 145 * Validate a pattern and ensure it does not contain the "e" modifier 146 * 147 * @param string $pattern 148 * @return bool 149 * @throws Exception\InvalidArgumentException 150 */ 151 protected function validatePattern($pattern) 152 { 153 if (!preg_match('/(?<modifier>[imsxeADSUXJu]+)$/', $pattern, $matches)) { 154 return true; 155 } 156 157 if (false !== strstr($matches['modifier'], 'e')) { 158 throw new Exception\InvalidArgumentException(sprintf( 159 'Pattern for a PregReplace filter may not contain the "e" pattern modifier; received "%s"', 160 $pattern 161 )); 162 } 163 } 164} 165