PageRenderTime 64ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/standard/tags/release-1.5.0PR/library/Zend/Filter/Inflector.php

https://github.com/bhaumik25/zend-framework
PHP | 495 lines | 232 code | 46 blank | 217 comment | 30 complexity | c005220d9e6a97a89bfe8131b5e66c44 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Filter
  17. * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id$
  20. */
  21. /**
  22. * @see Zend_Filter
  23. * @see Zend_Filter_Interface
  24. */
  25. require_once 'Zend/Filter.php';
  26. /**
  27. * @see Zend_Loader_PluginLoader
  28. */
  29. require_once 'Zend/Loader/PluginLoader.php';
  30. /**
  31. * Filter chain for string inflection
  32. *
  33. * @category Zend
  34. * @package Zend_Filter
  35. * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
  36. * @license http://framework.zend.com/license/new-bsd New BSD License
  37. */
  38. class Zend_Filter_Inflector implements Zend_Filter_Interface
  39. {
  40. /**
  41. * @var Zend_Loader_PluginLoader_Interface
  42. */
  43. protected $_pluginLoader = null;
  44. /**
  45. * @var string
  46. */
  47. protected $_target = null;
  48. /**
  49. * @var bool
  50. */
  51. protected $_throwTargetExceptionsOn = true;
  52. /**
  53. * @var string
  54. */
  55. protected $_targetReplacementIdentifier = ':';
  56. /**
  57. * @var array
  58. */
  59. protected $_rules = array();
  60. /**
  61. * Constructor
  62. *
  63. * @param string $target
  64. * @param array $rules
  65. */
  66. public function __construct($target = null, Array $rules = array(), $throwTargetExceptionsOn = null, $targetReplacementIdentifer = null)
  67. {
  68. if ($target instanceof Zend_Config) {
  69. $this->setConfig($target);
  70. } else {
  71. if ((null !== $target) && is_string($target)) {
  72. $this->setTarget($target);
  73. }
  74. if (null !== $rules) {
  75. $this->addRules($rules);
  76. }
  77. if ($throwTargetExceptionsOn != null) {
  78. $this->setThrowTargetExceptionsOn($throwTargetExceptionsOn);
  79. }
  80. if ($targetReplacementIdentifer != null) {
  81. $this->setTargetReplacementIdentifier($targetReplacementIdentifer);
  82. }
  83. }
  84. }
  85. /**
  86. * Retreive PluginLoader
  87. *
  88. * @return Zend_Loader_PluginLoader_Interface
  89. */
  90. public function getPluginLoader()
  91. {
  92. if (!$this->_pluginLoader instanceof Zend_Loader_PluginLoader_Interface) {
  93. $this->_pluginLoader = new Zend_Loader_PluginLoader(array('Zend_Filter_' => 'Zend/Filter/'), __CLASS__);
  94. }
  95. return $this->_pluginLoader;
  96. }
  97. /**
  98. * Set PluginLoader
  99. *
  100. * @param Zend_Loader_PluginLoader_Interface $pluginLoader
  101. * @return Zend_Filter_Inflector
  102. */
  103. public function setPluginLoader(Zend_Loader_PluginLoader_Interface $pluginLoader)
  104. {
  105. $this->_pluginLoader = $pluginLoader;
  106. return $this;
  107. }
  108. /**
  109. * Use Zend_Config object to set object state
  110. *
  111. * @param Zend_Config $config
  112. * @return Zend_Filter_Inflector
  113. */
  114. public function setConfig(Zend_Config $config)
  115. {
  116. foreach ($config as $key => $value) {
  117. switch ($key) {
  118. case 'target':
  119. $this->setTarget($value);
  120. break;
  121. case 'filterPrefixPath':
  122. if (is_scalar($value)) {
  123. break;
  124. }
  125. $paths = $value->toArray();
  126. foreach ($paths as $prefix => $path) {
  127. $this->addFilterPrefixPath($prefix, $path);
  128. }
  129. break;
  130. case 'throwTargetExceptionsOn':
  131. $this->setThrowTargetExceptionsOn($value);
  132. break;
  133. case 'targetReplacementIdentifier':
  134. $this->setTargetReplacementIdentifier($value);
  135. break;
  136. case 'rules':
  137. $this->addRules($value->toArray());
  138. break;
  139. default:
  140. break;
  141. }
  142. }
  143. return $this;
  144. }
  145. /**
  146. * Convienence method to add prefix and path to PluginLoader
  147. *
  148. * @param string $prefix
  149. * @param string $path
  150. * @return Zend_Filter_Inflector
  151. */
  152. public function addFilterPrefixPath($prefix, $path)
  153. {
  154. $this->getPluginLoader()->addPrefixPath($prefix, $path);
  155. return $this;
  156. }
  157. /**
  158. * Set Whether or not the inflector should throw an exception when a replacement
  159. * identifier is still found within an inflected target.
  160. *
  161. * @param bool $throwTargetExceptions
  162. * @return Zend_Filter_Inflector
  163. */
  164. public function setThrowTargetExceptionsOn($throwTargetExceptionsOn)
  165. {
  166. $this->_throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false;
  167. return $this;
  168. }
  169. /**
  170. * Will exceptions be thrown?
  171. *
  172. * @return bool
  173. */
  174. public function isThrowTargetExceptionsOn()
  175. {
  176. return $this->_throwTargetExceptionsOn;
  177. }
  178. /**
  179. * Set the Target Replacement Identifier, by default ':'
  180. *
  181. * @param string $targetReplacementIdentifier
  182. * @return Zend_Filter_Inflector
  183. */
  184. public function setTargetReplacementIdentifier($targetReplacementIdentifier)
  185. {
  186. $this->_targetReplacementIdentifier = (string) $targetReplacementIdentifier;
  187. return $this;
  188. }
  189. /**
  190. * Get Target Replacement Identifier
  191. *
  192. * @return string
  193. */
  194. public function getTargetReplacementIdentifier()
  195. {
  196. return $this->_targetReplacementIdentifier;
  197. }
  198. /**
  199. * Set a Target
  200. * ex: 'scripts/:controller/:action.:suffix'
  201. *
  202. * @param string
  203. * @return Zend_Filter_Inflector
  204. */
  205. public function setTarget($target)
  206. {
  207. $this->_target = (string) $target;
  208. return $this;
  209. }
  210. /**
  211. * Retrieve target
  212. *
  213. * @return string
  214. */
  215. public function getTarget()
  216. {
  217. return $this->_target;
  218. }
  219. /**
  220. * Set Target Reference
  221. *
  222. * @param reference $target
  223. * @return Zend_Filter_Inflector
  224. */
  225. public function setTargetReference(&$target)
  226. {
  227. $this->_target =& $target;
  228. return $this;
  229. }
  230. /**
  231. * SetRules() is the same as calling addRules() with the exception that it
  232. * clears the rules before adding them.
  233. *
  234. * @param array $rules
  235. * @return Zend_Filter_Inflector
  236. */
  237. public function setRules(Array $rules)
  238. {
  239. $this->clearRules();
  240. $this->addRules($rules);
  241. return $this;
  242. }
  243. /**
  244. * AddRules(): multi-call to setting filter rules.
  245. *
  246. * If prefixed with a ":" (colon), a filter rule will be added. If not
  247. * prefixed, a static replacement will be added.
  248. *
  249. * ex:
  250. * array(
  251. * ':controller' => array('CamelCaseToUnderscore','StringToLower'),
  252. * ':action' => array('CamelCaseToUnderscore','StringToLower'),
  253. * 'suffix' => 'phtml'
  254. * );
  255. *
  256. * @param array
  257. * @return Zend_Filter_Inflector
  258. */
  259. public function addRules(Array $rules)
  260. {
  261. $keys = array_keys($rules);
  262. foreach ($keys as $spec) {
  263. if ($spec[0] == ':') {
  264. $this->addFilterRule($spec, $rules[$spec]);
  265. } else {
  266. $this->setStaticRule($spec, $rules[$spec]);
  267. }
  268. }
  269. return $this;
  270. }
  271. /**
  272. * Get rules
  273. *
  274. * By default, returns all rules. If a $spec is provided, will return those
  275. * rules if found, false otherwise.
  276. *
  277. * @param string $spec
  278. * @return array|false
  279. */
  280. public function getRules($spec = null)
  281. {
  282. if (null !== $spec) {
  283. $spec = $this->_normalizeSpec($spec);
  284. if (isset($this->_rules[$spec])) {
  285. return $this->_rules[$spec];
  286. }
  287. return false;
  288. }
  289. return $this->_rules;
  290. }
  291. /**
  292. * getRule() returns a rule set by setFilterRule(), a numeric index must be provided
  293. *
  294. * @param string $spec
  295. * @param int $index
  296. * @return Zend_Filter_Interface|false
  297. */
  298. public function getRule($spec, $index)
  299. {
  300. $spec = $this->_normalizeSpec($spec);
  301. if (isset($this->_rules[$spec]) && is_array($this->_rules[$spec])) {
  302. if (isset($this->_rules[$spec][$index])) {
  303. return $this->_rules[$spec][$index];
  304. }
  305. }
  306. return false;
  307. }
  308. /**
  309. * ClearRules() clears the rules currently in the inflector
  310. *
  311. * @return Zend_Filter_Inflector
  312. */
  313. public function clearRules()
  314. {
  315. $this->_rules = array();
  316. return $this;
  317. }
  318. /**
  319. * Set a filtering rule for a spec. $ruleSet can be a string, Filter object
  320. * or an array of strings or filter objects.
  321. *
  322. * @param string $spec
  323. * @param array|string|Zend_Filter_Interface $ruleSet
  324. * @return Zend_Filter_Inflector
  325. */
  326. public function setFilterRule($spec, $ruleSet)
  327. {
  328. $spec = $this->_normalizeSpec($spec);
  329. $this->_rules[$spec] = array();
  330. return $this->addFilterRule($spec, $ruleSet);
  331. }
  332. /**
  333. * Add a filter rule for a spec
  334. *
  335. * @param mixed $spec
  336. * @param mixed $ruleSet
  337. * @return void
  338. */
  339. public function addFilterRule($spec, $ruleSet)
  340. {
  341. $spec = $this->_normalizeSpec($spec);
  342. if (!isset($this->_rules[$spec])) {
  343. $this->_rules[$spec] = array();
  344. }
  345. if (!is_array($ruleSet)) {
  346. $ruleSet = array($ruleSet);
  347. }
  348. foreach ($ruleSet as $rule) {
  349. $this->_rules[$spec][] = $this->_getRule($rule);
  350. }
  351. return $this;
  352. }
  353. /**
  354. * Set a static rule for a spec. This is a single string value
  355. *
  356. * @param string $name
  357. * @param string $value
  358. * @return Zend_Filter_Inflector
  359. */
  360. public function setStaticRule($name, $value)
  361. {
  362. $name = $this->_normalizeSpec($name);
  363. $this->_rules[$name] = (string) $value;
  364. return $this;
  365. }
  366. /**
  367. * Set Static Rule Reference.
  368. *
  369. * This allows a consuming class to pass a property or variable
  370. * in to be referenced when its time to build the output string from the
  371. * target.
  372. *
  373. * @param string $name
  374. * @param mixed $reference
  375. * @return Zend_Filter_Inflector
  376. */
  377. public function setStaticRuleReference($name, &$reference)
  378. {
  379. $name = $this->_normalizeSpec($name);
  380. $this->_rules[$name] =& $reference;
  381. return $this;
  382. }
  383. /**
  384. * Inflect
  385. *
  386. * @param string|array $source
  387. * @return string
  388. */
  389. public function filter($source)
  390. {
  391. // clean source
  392. foreach ( (array) $source as $sourceName => $sourceValue) {
  393. $source[ltrim($sourceName, ':')] = $sourceValue;
  394. }
  395. $pregQuotedTargetReplacementIdentifier = preg_quote($this->_targetReplacementIdentifier, '#');
  396. foreach ($this->_rules as $ruleName => $ruleValue) {
  397. if (isset($source[$ruleName])) {
  398. if (is_string($ruleValue)) {
  399. // overriding the set rule
  400. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = $source[$ruleName];
  401. } elseif (is_array($ruleValue)) {
  402. $processedPart = $source[$ruleName];
  403. foreach ($ruleValue as $ruleFilter) {
  404. $processedPart = $ruleFilter->filter($processedPart);
  405. }
  406. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = $processedPart;
  407. }
  408. } elseif (is_string($ruleValue)) {
  409. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = $ruleValue;
  410. }
  411. }
  412. $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->_target);
  413. if ($this->_throwTargetExceptionsOn && (preg_match('#(?='.$pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) {
  414. require_once 'Zend/Filter/Exception.php';
  415. throw new Zend_Filter_Exception('A replacement identifier ' . $this->_targetReplacementIdentifier . ' was found inside the inflected target, perhaps a rule was not satisfied with a target source? Unsatisfied inflected target: ' . $inflectedTarget);
  416. }
  417. return $inflectedTarget;
  418. }
  419. /**
  420. * Normalize spec string
  421. *
  422. * @param string $spec
  423. * @return string
  424. */
  425. protected function _normalizeSpec($spec)
  426. {
  427. return ltrim((string) $spec, ':&');
  428. }
  429. /**
  430. * Resolve named filters and convert them to filter objects.
  431. *
  432. * @param string $rule
  433. * @return Zend_Filter_Interface
  434. */
  435. protected function _getRule($rule)
  436. {
  437. if ($rule instanceof Zend_Filter_Interface) {
  438. return $rule;
  439. }
  440. $rule = (string) $rule;
  441. $className = $this->getPluginLoader()->load($rule);
  442. $ruleObject = new $className();
  443. if (!$ruleObject instanceof Zend_Filter_Interface) {
  444. require_once 'Zend/Filter/Exception.php';
  445. throw new Zend_Filter_Exception('No class named ' . $rule . ' implementing Zend_Filter_Interface could be found');
  446. }
  447. return $ruleObject;
  448. }
  449. }