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.
16
* @package Zend_Filter
17
* @copyright Copyright (c) 2005-2008 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 8226 2008-02-20 22:07:05Z ralph $
24
* @see Zend_Filter_Interface
26
require_once 'Zend/Filter.php';
29
* @see Zend_Loader_PluginLoader
31
require_once 'Zend/Loader/PluginLoader.php';
34
* Filter chain for string inflection
37
* @package Zend_Filter
38
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
39
* @license http://framework.zend.com/license/new-bsd New BSD License
41
class Zend_Filter_Inflector implements Zend_Filter_Interface
44
* @var Zend_Loader_PluginLoader_Interface
46
protected $_pluginLoader = null;
51
protected $_target = null;
56
protected $_throwTargetExceptionsOn = true;
61
protected $_targetReplacementIdentifier = ':';
66
protected $_rules = array();
71
* @param string $target
74
public function __construct($target = null, Array $rules = array(), $throwTargetExceptionsOn = null, $targetReplacementIdentifer = null)
76
if ($target instanceof Zend_Config) {
77
$this->setConfig($target);
79
if ((null !== $target) && is_string($target)) {
80
$this->setTarget($target);
83
if (null !== $rules) {
84
$this->addRules($rules);
87
if ($throwTargetExceptionsOn !== null) {
88
$this->setThrowTargetExceptionsOn($throwTargetExceptionsOn);
91
if ($targetReplacementIdentifer != '') {
92
$this->setTargetReplacementIdentifier($targetReplacementIdentifer);
98
* Retreive PluginLoader
100
* @return Zend_Loader_PluginLoader_Interface
102
public function getPluginLoader()
104
if (!$this->_pluginLoader instanceof Zend_Loader_PluginLoader_Interface) {
105
$this->_pluginLoader = new Zend_Loader_PluginLoader(array('Zend_Filter_' => 'Zend/Filter/'), __CLASS__);
108
return $this->_pluginLoader;
114
* @param Zend_Loader_PluginLoader_Interface $pluginLoader
115
* @return Zend_Filter_Inflector
117
public function setPluginLoader(Zend_Loader_PluginLoader_Interface $pluginLoader)
119
$this->_pluginLoader = $pluginLoader;
124
* Use Zend_Config object to set object state
126
* @param Zend_Config $config
127
* @return Zend_Filter_Inflector
129
public function setConfig(Zend_Config $config)
131
foreach ($config as $key => $value) {
134
$this->setTarget($value);
136
case 'filterPrefixPath':
137
if (is_scalar($value)) {
140
$paths = $value->toArray();
141
foreach ($paths as $prefix => $path) {
142
$this->addFilterPrefixPath($prefix, $path);
145
case 'throwTargetExceptionsOn':
146
$this->setThrowTargetExceptionsOn($value);
148
case 'targetReplacementIdentifier':
149
$this->setTargetReplacementIdentifier($value);
152
$this->addRules($value->toArray());
162
* Convienence method to add prefix and path to PluginLoader
164
* @param string $prefix
165
* @param string $path
166
* @return Zend_Filter_Inflector
168
public function addFilterPrefixPath($prefix, $path)
170
$this->getPluginLoader()->addPrefixPath($prefix, $path);
175
* Set Whether or not the inflector should throw an exception when a replacement
176
* identifier is still found within an inflected target.
178
* @param bool $throwTargetExceptions
179
* @return Zend_Filter_Inflector
181
public function setThrowTargetExceptionsOn($throwTargetExceptionsOn)
183
$this->_throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false;
188
* Will exceptions be thrown?
192
public function isThrowTargetExceptionsOn()
194
return $this->_throwTargetExceptionsOn;
198
* Set the Target Replacement Identifier, by default ':'
200
* @param string $targetReplacementIdentifier
201
* @return Zend_Filter_Inflector
203
public function setTargetReplacementIdentifier($targetReplacementIdentifier)
205
$this->_targetReplacementIdentifier = (string) $targetReplacementIdentifier;
210
* Get Target Replacement Identifier
214
public function getTargetReplacementIdentifier()
216
return $this->_targetReplacementIdentifier;
221
* ex: 'scripts/:controller/:action.:suffix'
224
* @return Zend_Filter_Inflector
226
public function setTarget($target)
228
$this->_target = (string) $target;
237
public function getTarget()
239
return $this->_target;
243
* Set Target Reference
245
* @param reference $target
246
* @return Zend_Filter_Inflector
248
public function setTargetReference(&$target)
250
$this->_target =& $target;
255
* SetRules() is the same as calling addRules() with the exception that it
256
* clears the rules before adding them.
258
* @param array $rules
259
* @return Zend_Filter_Inflector
261
public function setRules(Array $rules)
264
$this->addRules($rules);
269
* AddRules(): multi-call to setting filter rules.
271
* If prefixed with a ":" (colon), a filter rule will be added. If not
272
* prefixed, a static replacement will be added.
276
* ':controller' => array('CamelCaseToUnderscore','StringToLower'),
277
* ':action' => array('CamelCaseToUnderscore','StringToLower'),
278
* 'suffix' => 'phtml'
282
* @return Zend_Filter_Inflector
284
public function addRules(Array $rules)
286
$keys = array_keys($rules);
287
foreach ($keys as $spec) {
288
if ($spec[0] == ':') {
289
$this->addFilterRule($spec, $rules[$spec]);
291
$this->setStaticRule($spec, $rules[$spec]);
301
* By default, returns all rules. If a $spec is provided, will return those
302
* rules if found, false otherwise.
304
* @param string $spec
305
* @return array|false
307
public function getRules($spec = null)
309
if (null !== $spec) {
310
$spec = $this->_normalizeSpec($spec);
311
if (isset($this->_rules[$spec])) {
312
return $this->_rules[$spec];
317
return $this->_rules;
321
* getRule() returns a rule set by setFilterRule(), a numeric index must be provided
323
* @param string $spec
325
* @return Zend_Filter_Interface|false
327
public function getRule($spec, $index)
329
$spec = $this->_normalizeSpec($spec);
330
if (isset($this->_rules[$spec]) && is_array($this->_rules[$spec])) {
331
if (isset($this->_rules[$spec][$index])) {
332
return $this->_rules[$spec][$index];
339
* ClearRules() clears the rules currently in the inflector
341
* @return Zend_Filter_Inflector
343
public function clearRules()
345
$this->_rules = array();
350
* Set a filtering rule for a spec. $ruleSet can be a string, Filter object
351
* or an array of strings or filter objects.
353
* @param string $spec
354
* @param array|string|Zend_Filter_Interface $ruleSet
355
* @return Zend_Filter_Inflector
357
public function setFilterRule($spec, $ruleSet)
359
$spec = $this->_normalizeSpec($spec);
360
$this->_rules[$spec] = array();
361
return $this->addFilterRule($spec, $ruleSet);
365
* Add a filter rule for a spec
368
* @param mixed $ruleSet
371
public function addFilterRule($spec, $ruleSet)
373
$spec = $this->_normalizeSpec($spec);
374
if (!isset($this->_rules[$spec])) {
375
$this->_rules[$spec] = array();
377
if (!is_array($ruleSet)) {
378
$ruleSet = array($ruleSet);
380
foreach ($ruleSet as $rule) {
381
$this->_rules[$spec][] = $this->_getRule($rule);
387
* Set a static rule for a spec. This is a single string value
389
* @param string $name
390
* @param string $value
391
* @return Zend_Filter_Inflector
393
public function setStaticRule($name, $value)
395
$name = $this->_normalizeSpec($name);
396
$this->_rules[$name] = (string) $value;
401
* Set Static Rule Reference.
403
* This allows a consuming class to pass a property or variable
404
* in to be referenced when its time to build the output string from the
407
* @param string $name
408
* @param mixed $reference
409
* @return Zend_Filter_Inflector
411
public function setStaticRuleReference($name, &$reference)
413
$name = $this->_normalizeSpec($name);
414
$this->_rules[$name] =& $reference;
421
* @param string|array $source
424
public function filter($source)
427
foreach ( (array) $source as $sourceName => $sourceValue) {
428
$source[ltrim($sourceName, ':')] = $sourceValue;
431
$pregQuotedTargetReplacementIdentifier = preg_quote($this->_targetReplacementIdentifier, '#');
433
foreach ($this->_rules as $ruleName => $ruleValue) {
434
if (isset($source[$ruleName])) {
435
if (is_string($ruleValue)) {
436
// overriding the set rule
437
$processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $source[$ruleName]);
438
} elseif (is_array($ruleValue)) {
439
$processedPart = $source[$ruleName];
440
foreach ($ruleValue as $ruleFilter) {
441
$processedPart = $ruleFilter->filter($processedPart);
443
$processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $processedPart);
445
} elseif (is_string($ruleValue)) {
446
$processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $ruleValue);
450
// all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences
451
$inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->_target);
453
if ($this->_throwTargetExceptionsOn && (preg_match('#(?='.$pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) {
454
require_once 'Zend/Filter/Exception.php';
455
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);
458
return $inflectedTarget;
462
* Normalize spec string
464
* @param string $spec
467
protected function _normalizeSpec($spec)
469
return ltrim((string) $spec, ':&');
473
* Resolve named filters and convert them to filter objects.
475
* @param string $rule
476
* @return Zend_Filter_Interface
478
protected function _getRule($rule)
480
if ($rule instanceof Zend_Filter_Interface) {
484
$rule = (string) $rule;
486
$className = $this->getPluginLoader()->load($rule);
487
$ruleObject = new $className();
488
if (!$ruleObject instanceof Zend_Filter_Interface) {
489
require_once 'Zend/Filter/Exception.php';
490
throw new Zend_Filter_Exception('No class named ' . $rule . ' implementing Zend_Filter_Interface could be found');