/src/String/Filter.php

https://github.com/heavenshell/php-string-filter · PHP · 202 lines · 69 code · 14 blank · 119 comment · 5 complexity · 794291480d25ea66252271842c72accd MD5 · raw file

  1. <?php
  2. /**
  3. * String\Filter - a regexp-based string filter.
  4. *
  5. * The original module is String::Filter(Perl module).
  6. *
  7. * PHP version 5.3
  8. *
  9. * Copyright (c) 2010-2011 Shinya Ohyanagi, All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * * Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. *
  23. * * Neither the name of Shinya Ohyanagi nor the names of his
  24. * contributors may be used to endorse or promote products derived
  25. * from this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * @uses String
  41. * @category String
  42. * @package String\Filter
  43. * @version $id$
  44. * @copyright (c) 2010 Cybozu Labs, Inc. Written by Kazuho Oku.
  45. * @copyright (c) 2010-2010 Shinya Ohyanagi
  46. * @author Shinya Ohyanagi <sohyanagi@gmail.com>
  47. * @license New BSD License
  48. * @link http://search.cpan.org/~kazuho/String-Filter-0.01/
  49. */
  50. namespace String;
  51. use String;
  52. /**
  53. * Filter
  54. *
  55. * <pre>
  56. * The module is a regexp-based string filter,
  57. * Original module is Perl's String::Filter.
  58. * see @link.
  59. * </pre>
  60. *
  61. * @uses String
  62. * @category String
  63. * @package String\Filter
  64. * @version $id$
  65. * @copyright (C) 2010 Cybozu Labs, Inc. Written by Kazuho Oku.
  66. * @copyright (C) 2010-2011 Shinya Ohyanagi
  67. * @author Shinya Ohyanagi <sohyanagi@gmail.com>
  68. * @license New BSD License
  69. * @link http://search.cpan.org/~kazuho/String-Filter-0.01/
  70. */
  71. class Filter
  72. {
  73. /**
  74. * Version.
  75. */
  76. const VERSION = '0.0.1';
  77. /**
  78. * Default rule
  79. *
  80. * @var mixed
  81. * @access private
  82. */
  83. private $_defaultRule = null;
  84. /**
  85. * Rules
  86. *
  87. * @var array
  88. * @access private
  89. */
  90. private $_rules = array();
  91. /**
  92. * Regex pattern.
  93. *
  94. * @var mixed
  95. * @access private
  96. */
  97. private $_ra = null;
  98. /**
  99. * Instantiates the filter object.
  100. *
  101. * @param array $rules Rules
  102. * @access public
  103. * @return void
  104. */
  105. public function __construct(array $rules)
  106. {
  107. $this->defaultRule($rules['defaultRule']);
  108. if (isset($rules['rules'])) {
  109. $this->addRule($rules['rules']);
  110. }
  111. }
  112. /**
  113. * Setter / getter for the default conversion function.
  114. *
  115. * @param mixed $rule
  116. * @access public
  117. * @return mixed Filtered output of the input
  118. */
  119. public function defaultRule($rule = null)
  120. {
  121. if (is_null($rule)) {
  122. return $this->_defaultRule;
  123. }
  124. if (!is_callable($rule)) {
  125. throw new Exception('Args is not callable.');
  126. }
  127. $this->_defaultRule = $rule;
  128. return $rule;
  129. }
  130. /**
  131. * Adds a conversion rule.
  132. *
  133. * @param mixed $rule
  134. * @access public
  135. * @return \String\Filter Fluent interface
  136. */
  137. public function addRule(array $rule)
  138. {
  139. // Fixme
  140. foreach ($rule as $k => $v) {
  141. $this->_rules[$k] = $v;
  142. }
  143. $pattern = str_replace(
  144. '/', '\\/', implode('|', array_keys($this->_rules))
  145. );
  146. $this->_ra = sprintf('/%s/', $pattern);
  147. return $this;
  148. }
  149. /**
  150. * Converts the input string using the given rules and returns it.
  151. *
  152. * @param mixed $text String to convert
  153. * @access public
  154. * @return String Converted string
  155. */
  156. public function filter($text)
  157. {
  158. // Fixme
  159. $token = array();
  160. if (preg_match_all($this->_ra, $text, $match, PREG_OFFSET_CAPTURE)) {
  161. $token = $match[0];
  162. }
  163. // In this case preg_split() returns unmatched token.
  164. $token = array_merge(
  165. $token,
  166. preg_split(
  167. $this->_ra, $text, null,
  168. PREG_SPLIT_NO_EMPTY|PREG_SPLIT_OFFSET_CAPTURE
  169. )
  170. );
  171. $ret = array();
  172. foreach ($token as $key => $val) {
  173. foreach ($this->_rules as $k => $v) {
  174. $rule = '/' . str_replace('/', '\\/', $k) . '/';
  175. if (preg_match($rule, $val[0], $match)) {
  176. $ret[$val[1]] = $v($match[0]);
  177. goto NEXT_TOKEN;
  178. }
  179. }
  180. $default = $this->defaultRule();
  181. $ret[$val[1]] = $default($val[0]);
  182. NEXT_TOKEN:
  183. ;
  184. }
  185. ksort($ret);
  186. return implode('', $ret);
  187. }
  188. }