PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Zend/Markup/Renderer/RendererAbstract.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 702 lines | 461 code | 54 blank | 187 comment | 46 complexity | fa85f0d36b7f82f50a0fd4077368f552 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  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_Markup
  17. * @subpackage Renderer
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: RendererAbstract.php 22197 2010-05-19 13:32:25Z kokx $
  21. */
  22. /**
  23. * @see Zend_config
  24. */
  25. #require_once 'Zend/Config.php';
  26. /**
  27. * @see Zend_Filter
  28. */
  29. #require_once 'Zend/Filter.php';
  30. /**
  31. * @see Zend_Markup_Renderer_TokenConverterInterface
  32. */
  33. #require_once 'Zend/Markup/Renderer/TokenConverterInterface.php';
  34. /**
  35. * Defines the basic rendering functionality
  36. *
  37. * @category Zend
  38. * @package Zend_Markup
  39. * @subpackage Renderer
  40. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  41. * @license http://framework.zend.com/license/new-bsd New BSD License
  42. */
  43. abstract class Zend_Markup_Renderer_RendererAbstract
  44. {
  45. const TYPE_CALLBACK = 4;
  46. const TYPE_REPLACE = 8;
  47. const TYPE_ALIAS = 16;
  48. /**
  49. * Tag info
  50. *
  51. * @var array
  52. */
  53. protected $_markups = array();
  54. /**
  55. * Parser
  56. *
  57. * @var Zend_Markup_Parser_ParserInterface
  58. */
  59. protected $_parser;
  60. /**
  61. * What filter to use
  62. *
  63. * @var bool
  64. */
  65. protected $_filter;
  66. /**
  67. * Filter chain
  68. *
  69. * @var Zend_Filter
  70. */
  71. protected $_defaultFilter;
  72. /**
  73. * The current group
  74. *
  75. * @var string
  76. */
  77. protected $_group;
  78. /**
  79. * Groups definition
  80. *
  81. * @var array
  82. */
  83. protected $_groups = array();
  84. /**
  85. * Plugin loader for tags
  86. *
  87. * @var Zend_Loader_PluginLoader
  88. */
  89. protected $_pluginLoader;
  90. /**
  91. * The current token
  92. *
  93. * @var Zend_Markup_Token
  94. */
  95. protected $_token;
  96. /**
  97. * Encoding
  98. *
  99. * @var string
  100. */
  101. protected static $_encoding = 'UTF-8';
  102. /**
  103. * Constructor
  104. *
  105. * @param array|Zend_Config $options
  106. *
  107. * @return void
  108. */
  109. public function __construct($options = array())
  110. {
  111. if ($options instanceof Zend_Config) {
  112. $options = $options->toArray();
  113. }
  114. if (isset($options['encoding'])) {
  115. $this->setEncoding($options['encoding']);
  116. }
  117. if (isset($options['parser'])) {
  118. $this->setParser($options['parser']);
  119. }
  120. if (!isset($options['useDefaultFilters']) || ($options['useDefaultFilters'] === true)) {
  121. $this->addDefaultFilters();
  122. }
  123. if (isset($options['defaultFilter'])) {
  124. $this->addDefaultFilter($options['defaultFilter']);
  125. }
  126. }
  127. /**
  128. * Set the parser
  129. *
  130. * @param Zend_Markup_Parser_ParserInterface $parser
  131. * @return Zend_Markup_Renderer_RendererAbstract
  132. */
  133. public function setParser(Zend_Markup_Parser_ParserInterface $parser)
  134. {
  135. $this->_parser = $parser;
  136. return $this;
  137. }
  138. /**
  139. * Get the parser
  140. *
  141. * @return Zend_Markup_Parser_ParserInterface
  142. */
  143. public function getParser()
  144. {
  145. return $this->_parser;
  146. }
  147. /**
  148. * Get the plugin loader
  149. *
  150. * @return Zend_Loader_PluginLoader
  151. */
  152. public function getPluginLoader()
  153. {
  154. return $this->_pluginLoader;
  155. }
  156. /**
  157. * Set the renderer's encoding
  158. *
  159. * @param string $encoding
  160. *
  161. * @return void
  162. */
  163. public static function setEncoding($encoding)
  164. {
  165. self::$_encoding = $encoding;
  166. }
  167. /**
  168. * Get the renderer's encoding
  169. *
  170. * @return string
  171. */
  172. public static function getEncoding()
  173. {
  174. return self::$_encoding;
  175. }
  176. /**
  177. * Add a new markup
  178. *
  179. * @param string $name
  180. * @param string $type
  181. * @param array $options
  182. *
  183. * @return Zend_Markup_Renderer_RendererAbstract
  184. */
  185. public function addMarkup($name, $type, array $options)
  186. {
  187. if (!isset($options['group']) && ($type ^ self::TYPE_ALIAS)) {
  188. #require_once 'Zend/Markup/Renderer/Exception.php';
  189. throw new Zend_Markup_Renderer_Exception("There is no render group defined.");
  190. }
  191. // add the filter
  192. if (isset($options['filter'])) {
  193. if ($options['filter'] instanceof Zend_Filter_Interface) {
  194. $filter = $options['filter'];
  195. } elseif ($options['filter'] === true) {
  196. $filter = $this->getDefaultFilter();
  197. } else {
  198. $filter = false;
  199. }
  200. } else {
  201. $filter = $this->getDefaultFilter();
  202. }
  203. // check the type
  204. if ($type & self::TYPE_CALLBACK) {
  205. // add a callback tag
  206. if (isset($options['callback'])) {
  207. if (!($options['callback'] instanceof Zend_Markup_Renderer_TokenConverterInterface)) {
  208. #require_once 'Zend/Markup/Renderer/Exception.php';
  209. throw new Zend_Markup_Renderer_Exception("Not a valid tag callback.");
  210. }
  211. if (method_exists($options['callback'], 'setRenderer')) {
  212. $options['callback']->setRenderer($this);
  213. }
  214. } else {
  215. $options['callback'] = null;
  216. }
  217. $options['type'] = $type;
  218. $options['filter'] = $filter;
  219. $this->_markups[$name] = $options;
  220. } elseif ($type & self::TYPE_ALIAS) {
  221. // add an alias
  222. if (empty($options['name'])) {
  223. #require_once 'Zend/Markup/Renderer/Exception.php';
  224. throw new Zend_Markup_Renderer_Exception(
  225. 'No alias was provided but tag was defined as such');
  226. }
  227. $this->_markups[$name] = array(
  228. 'type' => self::TYPE_ALIAS,
  229. 'name' => $options['name']
  230. );
  231. } else {
  232. if ($type && array_key_exists('empty', $options) && $options['empty']) {
  233. // add a single replace markup
  234. $options['type'] = $type;
  235. $options['filter'] = $filter;
  236. $this->_markups[$name] = $options;
  237. } else {
  238. // add a replace markup
  239. $options['type'] = $type;
  240. $options['filter'] = $filter;
  241. $this->_markups[$name] = $options;
  242. }
  243. }
  244. return $this;
  245. }
  246. /**
  247. * Remove a markup
  248. *
  249. * @param string $name
  250. *
  251. * @return void
  252. */
  253. public function removeMarkup($name)
  254. {
  255. unset($this->_markups[$name]);
  256. }
  257. /**
  258. * Remove the default tags
  259. *
  260. * @return void
  261. */
  262. public function clearMarkups()
  263. {
  264. $this->_markups = array();
  265. }
  266. /**
  267. * Render function
  268. *
  269. * @param Zend_Markup_TokenList|string $tokenList
  270. * @return string
  271. */
  272. public function render($value)
  273. {
  274. if ($value instanceof Zend_Markup_TokenList) {
  275. $tokenList = $value;
  276. } else {
  277. $tokenList = $this->getParser()->parse($value);
  278. }
  279. $root = $tokenList->current();
  280. $this->_filter = $this->getDefaultFilter();
  281. return $this->_render($root);
  282. }
  283. /**
  284. * Render a single token
  285. *
  286. * @param Zend_Markup_Token $token
  287. * @return string
  288. */
  289. protected function _render(Zend_Markup_Token $token)
  290. {
  291. $return = '';
  292. $this->_token = $token;
  293. // if this tag has children, execute them
  294. if ($token->hasChildren()) {
  295. foreach ($token->getChildren() as $child) {
  296. $return .= $this->_execute($child);
  297. }
  298. }
  299. return $return;
  300. }
  301. /**
  302. * Get the group of a token
  303. *
  304. * @param Zend_Markup_Token $token
  305. * @return string|bool
  306. */
  307. protected function _getGroup(Zend_Markup_Token $token)
  308. {
  309. if (!isset($this->_markups[$token->getName()])) {
  310. return false;
  311. }
  312. $tag = $this->_markups[$token->getName()];
  313. // alias processing
  314. while ($tag['type'] & self::TYPE_ALIAS) {
  315. $tag = $this->_markups[$tag['name']];
  316. }
  317. return isset($tag['group']) ? $tag['group'] : false;
  318. }
  319. /**
  320. * Execute the token
  321. *
  322. * @param Zend_Markup_Token $token
  323. * @return string
  324. */
  325. protected function _execute(Zend_Markup_Token $token)
  326. {
  327. // first return the normal text tags
  328. if ($token->getType() == Zend_Markup_Token::TYPE_NONE) {
  329. return $this->_filter($token->getTag());
  330. }
  331. // if the token doesn't have a notation, return the plain text
  332. if (!isset($this->_markups[$token->getName()])) {
  333. $oldToken = $this->_token;
  334. $return = $this->_filter($token->getTag()) . $this->_render($token) . $token->getStopper();
  335. $this->_token = $oldToken;
  336. return $return;
  337. }
  338. $name = $this->_getMarkupName($token);
  339. $markup = (!$name) ? false : $this->_markups[$name];
  340. $empty = (is_array($markup) && array_key_exists('empty', $markup) && $markup['empty']);
  341. // check if the tag has content
  342. if (!$empty && !$token->hasChildren()) {
  343. return '';
  344. }
  345. // check for the context
  346. if (is_array($markup) && !in_array($markup['group'], $this->_groups[$this->_group])) {
  347. $oldToken = $this->_token;
  348. $return = $this->_filter($token->getTag()) . $this->_render($token) . $token->getStopper();
  349. $this->_token = $oldToken;
  350. return $return;
  351. }
  352. // check for the filter
  353. if (!isset($markup['filter'])
  354. || (!($markup['filter'] instanceof Zend_Filter_Interface) && ($markup['filter'] !== false))) {
  355. $this->_markups[$name]['filter'] = $this->getDefaultFilter();
  356. }
  357. // save old values to reset them after the work is done
  358. $oldFilter = $this->_filter;
  359. $oldGroup = $this->_group;
  360. $return = '';
  361. // set the filter and the group
  362. $this->_filter = $this->getFilter($name);
  363. if ($group = $this->_getGroup($token)) {
  364. $this->_group = $group;
  365. }
  366. // callback
  367. if (is_array($markup) && ($markup['type'] & self::TYPE_CALLBACK)) {
  368. // load the callback if the tag doesn't exist
  369. if (!($markup['callback'] instanceof Zend_Markup_Renderer_TokenConverterInterface)) {
  370. $class = $this->getPluginLoader()->load($name);
  371. $markup['callback'] = new $class;
  372. if (!($markup['callback'] instanceof Zend_Markup_Renderer_TokenConverterInterface)) {
  373. #require_once 'Zend/Markup/Renderer/Exception.php';
  374. throw new Zend_Markup_Renderer_Exception("Callback for tag '$name' found, but it isn't valid.");
  375. }
  376. if (method_exists($markup['callback'], 'setRenderer')) {
  377. $markup['callback']->setRenderer($this);
  378. }
  379. }
  380. if ($markup['type'] && !$empty) {
  381. $return = $markup['callback']->convert($token, $this->_render($token));
  382. } else {
  383. $return = $markup['callback']->convert($token, null);
  384. }
  385. } else {
  386. // replace
  387. if ($markup['type'] && !$empty) {
  388. $return = $this->_executeReplace($token, $markup);
  389. } else {
  390. $return = $this->_executeSingleReplace($token, $markup);
  391. }
  392. }
  393. // reset to the old values
  394. $this->_filter = $oldFilter;
  395. $this->_group = $oldGroup;
  396. return $return;
  397. }
  398. /**
  399. * Filter method
  400. *
  401. * @param string $value
  402. *
  403. * @return string
  404. */
  405. protected function _filter($value)
  406. {
  407. if ($this->_filter instanceof Zend_Filter_Interface) {
  408. return $this->_filter->filter($value);
  409. }
  410. return $value;
  411. }
  412. /**
  413. * Get the markup name
  414. *
  415. * @param Zend_Markup_Token
  416. *
  417. * @return string
  418. */
  419. protected function _getMarkupName(Zend_Markup_Token $token)
  420. {
  421. $name = $token->getName();
  422. if (empty($name)) {
  423. return false;
  424. }
  425. return $this->_resolveMarkupName($name);
  426. }
  427. /**
  428. * Resolve aliases for a markup name
  429. *
  430. * @param string $name
  431. *
  432. * @return string
  433. */
  434. protected function _resolveMarkupName($name)
  435. {
  436. while (($type = $this->_getMarkupType($name))
  437. && ($type & self::TYPE_ALIAS)
  438. ) {
  439. $name = $this->_markups[$name]['name'];
  440. }
  441. return $name;
  442. }
  443. /**
  444. * Retrieve markup type
  445. *
  446. * @param string $name
  447. * @return false|int
  448. */
  449. protected function _getMarkupType($name)
  450. {
  451. if (!isset($this->_markups[$name])) {
  452. return false;
  453. }
  454. if (!isset($this->_markups[$name]['type'])) {
  455. return false;
  456. }
  457. return $this->_markups[$name]['type'];
  458. }
  459. /**
  460. * Execute a replace token
  461. *
  462. * @param Zend_Markup_Token $token
  463. * @param array $tag
  464. * @return string
  465. */
  466. protected function _executeReplace(Zend_Markup_Token $token, $tag)
  467. {
  468. return $tag['start'] . $this->_render($token) . $tag['end'];
  469. }
  470. /**
  471. * Execute a single replace token
  472. *
  473. * @param Zend_Markup_Token $token
  474. * @param array $tag
  475. * @return string
  476. */
  477. protected function _executeSingleReplace(Zend_Markup_Token $token, $tag)
  478. {
  479. return $tag['replace'];
  480. }
  481. /**
  482. * Get the default filter
  483. *
  484. * @return void
  485. */
  486. public function getDefaultFilter()
  487. {
  488. if (null === $this->_defaultFilter) {
  489. $this->addDefaultFilters();
  490. }
  491. return $this->_defaultFilter;
  492. }
  493. /**
  494. * Add a default filter
  495. *
  496. * @param string $filter
  497. *
  498. * @return void
  499. */
  500. public function addDefaultFilter(Zend_Filter_Interface $filter, $placement = Zend_Filter::CHAIN_APPEND)
  501. {
  502. if (!($this->_defaultFilter instanceof Zend_Filter)) {
  503. $defaultFilter = new Zend_Filter();
  504. $defaultFilter->addFilter($filter);
  505. $this->_defaultFilter = $defaultFilter;
  506. }
  507. $this->_defaultFilter->addFilter($filter, $placement);
  508. }
  509. /**
  510. * Set the default filter
  511. *
  512. * @param Zend_Filter_Interface $filter
  513. *
  514. * @return void
  515. */
  516. public function setDefaultFilter(Zend_Filter_Interface $filter)
  517. {
  518. $this->_defaultFilter = $filter;
  519. }
  520. /**
  521. * Get the filter for an existing markup
  522. *
  523. * @param string $markup
  524. *
  525. * @return Zend_Filter_Interface
  526. */
  527. public function getFilter($markup)
  528. {
  529. $markup = $this->_resolveMarkupName($markup);
  530. if (!isset($this->_markups[$markup]['filter'])
  531. || !($this->_markups[$markup]['filter'] instanceof Zend_Filter_Interface)
  532. ) {
  533. if (isset($this->_markups[$markup]['filter']) && $this->_markups[$markup]['filter']) {
  534. $this->_markups[$markup]['filter'] = $this->getDefaultFilter();
  535. } else {
  536. return false;
  537. }
  538. }
  539. return $this->_markups[$markup]['filter'];
  540. }
  541. /**
  542. * Add a filter for an existing markup
  543. *
  544. * @param Zend_Filter_Interface $filter
  545. * @param string $markup
  546. * @param string $placement
  547. *
  548. * @return Zend_Markup_Renderer_RendererAbstract
  549. */
  550. public function addFilter(Zend_Filter_Interface $filter, $markup, $placement = Zend_Filter::CHAIN_APPEND)
  551. {
  552. $markup = $this->_resolveMarkupName($markup);
  553. $oldFilter = $this->getFilter($markup);
  554. // if this filter is the default filter, clone it first
  555. if ($oldFilter === $this->getDefaultFilter()) {
  556. $oldFilter = clone $oldFilter;
  557. }
  558. if (!($oldFilter instanceof Zend_Filter)) {
  559. $this->_markups[$markup]['filter'] = new Zend_Filter();
  560. if ($oldFilter instanceof Zend_Filter_Interface) {
  561. $this->_markups[$markup]['filter']->addFilter($oldFilter);
  562. }
  563. } else {
  564. $this->_markups[$markup]['filter'] = $oldFilter;
  565. }
  566. $this->_markups[$markup]['filter']->addFilter($filter, $placement);
  567. return $this;
  568. }
  569. /**
  570. * Set the filter for an existing
  571. *
  572. * @param Zend_Filter_Interface $filter
  573. * @param string $markup
  574. *
  575. * @return Zend_Markup_Renderer_RendererAbstract
  576. */
  577. public function setFilter(Zend_Filter_Interface $filter, $markup)
  578. {
  579. $markup = $this->_resolveMarkupName($markup);
  580. $this->_markups[$markup]['filter'] = $filter;
  581. return $this;
  582. }
  583. /**
  584. * Add a render group
  585. *
  586. * @param string $name
  587. * @param array $allowedInside
  588. * @param array $allowsInside
  589. *
  590. * @return void
  591. */
  592. public function addGroup($name, array $allowedInside = array(), array $allowsInside = array())
  593. {
  594. $this->_groups[$name] = $allowsInside;
  595. foreach ($allowedInside as $group) {
  596. $this->_groups[$group][] = $name;
  597. }
  598. }
  599. /**
  600. * Get group definitions
  601. *
  602. * @return array
  603. */
  604. public function getGroups()
  605. {
  606. return $this->_groups;
  607. }
  608. /**
  609. * Set the default filters
  610. *
  611. * @return void
  612. */
  613. abstract public function addDefaultFilters();
  614. }