PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/Zend/Filter/Inflector.php

https://github.com/grandison/budo16
PHP | 506 lines | 234 code | 50 blank | 222 comment | 30 complexity | 8689e51f25bf4282d62d9cdc10e6714b 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-2009 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Inflector.php 17705 2009-08-21 07:50:57Z thomas $
  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-2009 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 != '') {
  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. if (is_string($this->_rules[$spec])) {
  349. $temp = $this->_rules[$spec];
  350. $this->_rules[$spec] = array();
  351. $this->_rules[$spec][] = $temp;
  352. }
  353. foreach ($ruleSet as $rule) {
  354. $this->_rules[$spec][] = $this->_getRule($rule);
  355. }
  356. return $this;
  357. }
  358. /**
  359. * Set a static rule for a spec. This is a single string value
  360. *
  361. * @param string $name
  362. * @param string $value
  363. * @return Zend_Filter_Inflector
  364. */
  365. public function setStaticRule($name, $value)
  366. {
  367. $name = $this->_normalizeSpec($name);
  368. $this->_rules[$name] = (string) $value;
  369. return $this;
  370. }
  371. /**
  372. * Set Static Rule Reference.
  373. *
  374. * This allows a consuming class to pass a property or variable
  375. * in to be referenced when its time to build the output string from the
  376. * target.
  377. *
  378. * @param string $name
  379. * @param mixed $reference
  380. * @return Zend_Filter_Inflector
  381. */
  382. public function setStaticRuleReference($name, &$reference)
  383. {
  384. $name = $this->_normalizeSpec($name);
  385. $this->_rules[$name] =& $reference;
  386. return $this;
  387. }
  388. /**
  389. * Inflect
  390. *
  391. * @param string|array $source
  392. * @return string
  393. */
  394. public function filter($source)
  395. {
  396. // clean source
  397. foreach ( (array) $source as $sourceName => $sourceValue) {
  398. $source[ltrim($sourceName, ':')] = $sourceValue;
  399. }
  400. $pregQuotedTargetReplacementIdentifier = preg_quote($this->_targetReplacementIdentifier, '#');
  401. $processedParts = array();
  402. foreach ($this->_rules as $ruleName => $ruleValue) {
  403. if (isset($source[$ruleName])) {
  404. if (is_string($ruleValue)) {
  405. // overriding the set rule
  406. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $source[$ruleName]);
  407. } elseif (is_array($ruleValue)) {
  408. $processedPart = $source[$ruleName];
  409. foreach ($ruleValue as $ruleFilter) {
  410. $processedPart = $ruleFilter->filter($processedPart);
  411. }
  412. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $processedPart);
  413. }
  414. } elseif (is_string($ruleValue)) {
  415. $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $ruleValue);
  416. }
  417. }
  418. // all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences
  419. $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->_target);
  420. if ($this->_throwTargetExceptionsOn && (preg_match('#(?='.$pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) {
  421. // require_once 'Zend/Filter/Exception.php';
  422. 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);
  423. }
  424. return $inflectedTarget;
  425. }
  426. /**
  427. * Normalize spec string
  428. *
  429. * @param string $spec
  430. * @return string
  431. */
  432. protected function _normalizeSpec($spec)
  433. {
  434. return ltrim((string) $spec, ':&');
  435. }
  436. /**
  437. * Resolve named filters and convert them to filter objects.
  438. *
  439. * @param string $rule
  440. * @return Zend_Filter_Interface
  441. */
  442. protected function _getRule($rule)
  443. {
  444. if ($rule instanceof Zend_Filter_Interface) {
  445. return $rule;
  446. }
  447. $rule = (string) $rule;
  448. $className = $this->getPluginLoader()->load($rule);
  449. $ruleObject = new $className();
  450. if (!$ruleObject instanceof Zend_Filter_Interface) {
  451. // require_once 'Zend/Filter/Exception.php';
  452. throw new Zend_Filter_Exception('No class named ' . $rule . ' implementing Zend_Filter_Interface could be found');
  453. }
  454. return $ruleObject;
  455. }
  456. }