Cgiapp2
[ class tree: Cgiapp2 ] [ index: Cgiapp2 ] [ all elements ]

Source for file Xslt.class.php

Documentation is available at Xslt.class.php

  1. <?php
  2. /**
  3. * Cgiapp2 - Framework for building reusable web-applications
  4. *
  5. * A PHP5 port of perl's CGI::Application, a framework for building reusable web
  6. * applications.
  7. *
  8. * @package Cgiapp2
  9. * @author Matthew Weier O'Phinney <mweierophinney@gmail.com>; based on
  10. * CGI::Application, by Jesse Erlbaum <jesse@erlbaum.net>, et. al.
  11. * @copyright (c) 2004 - present, Matthew Weier O'Phinney
  12. * @license BSD License (http://www.opensource.org/licenses/bsd-license.php)
  13. * @category Tools and Utilities
  14. * @tutorial Cgiapp2/Cgiapp2.cls
  15. * @version $Id:$
  16. */
  17.  
  18. /**
  19. * Cgiapp2 plugin
  20. */
  21. require_once 'Cgiapp2.class.php';
  22.  
  23. /**
  24. * Implements Cgiapp2_Plugin_Template_Interface
  25. */
  26. require_once 'Cgiapp2/Plugin/Template/Interface.class.php';
  27.  
  28. /**
  29. * XSLT processor
  30. *
  31. * Implements {@link Cgiapp2_Plugin_Template_Interface} to create an XSLT
  32. * plugin for {@link Cgiapp2}.
  33. *
  34. * Registers with Cgiapp2's tmpl_path, tmpl_assign, and tmpl_fetch hooks;
  35. * registration is done with the Cgiapp2 class.
  36. *
  37. * By default, it turns on registerPHPFunctions(), allowing you to use PHP
  38. * functions as helpers with XSLT stylesheets. If you pass the
  39. * {@link $params 'registerPHPFunctions' key} to
  40. * {@link getInstance() the constructor}, you can turn off this functionality or
  41. * restrict which functions are allowed. See
  42. * {@link http://php.net/xsl the PHP XSL extension documentation} for more
  43. * information.
  44. *
  45. * {@link fetch()} operates differently than other template plugins in that you
  46. * will typically need to pass an array with two elements, the XML to transform
  47. * and the XSL to transform it with. However, if you provide the 'xsl' key in
  48. * the extra parameters sent to {@link init()} or {@link getInstance()}, it will
  49. * use that value for transforming the XML; this is useful if you have an
  50. * overriding template that includes required templates on demand based on the
  51. * variables set.
  52. *
  53. * @package Cgiapp2
  54. * @author Matthew Weier O'Phinney <mweierophinney@gmail.com>
  55. * @version @release-version@
  56. */
  57. class Cgiapp2_Plugin_Xslt implements Cgiapp2_Plugin_Template_Interface
  58. {
  59. /**
  60. * Hold template instance
  61. *
  62. * @var string
  63. * @access private
  64. * @static
  65. */
  66. private static $_instance = false;
  67.  
  68. /**
  69. * Template path
  70. * @var string
  71. * @access public
  72. */
  73. public $tmpl_path = null;
  74.  
  75. /**
  76. * Extra parameters passed to the constructor
  77. * Valid parameters include:
  78. * - 'xsl' - name of an XSL file or XSL string to use for all
  79. * transformations
  80. * - 'registerPHPFunctions' - boolean, string, or array. 'true' (default)
  81. * indicates the XSLT processor should allow processing of any PHP
  82. * function; 'false' turns this off. If a string is passed, that single
  83. * PHP function will be allowed; if an array is passed, any function in
  84. * that array will be allowed.
  85. * @var null|array
  86. * @access public
  87. */
  88. public $params = null;
  89.  
  90. /**
  91. * Assigned variables
  92. * @var array
  93. * @access public
  94. */
  95. public $vars = array();
  96.  
  97. /**
  98. * Constructor
  99. *
  100. * Creates an instance and initializes the {@link $tmpl_path} property.
  101. *
  102. * @param mixed $extra_params
  103. * @access private
  104. * @return void
  105. */
  106. private function __construct($params = null)
  107. {
  108. if (null !== $params && is_array($params)) {
  109. if (is_array($params)) {
  110. if (isset($params['xsl']) && !is_string($params['xsl'])) {
  111. throw new Cgiapp2_Exception('Invalid XSL specified');
  112. }
  113.  
  114. $this->params = $params;
  115. }
  116. }
  117. }
  118.  
  119. /**
  120. * Overloading: retrieve property values
  121. *
  122. * @access public
  123. * @param string $key
  124. * @return mixed
  125. */
  126. public function __get($key)
  127. {
  128. if (isset($this->vars[$key])) {
  129. return $this->vars[$key];
  130. }
  131.  
  132. return null;
  133. }
  134.  
  135. /**
  136. * Overloading: set property values
  137. *
  138. * @access public
  139. * @param mixed $key
  140. * @param mixed $val
  141. * @return void
  142. */
  143. public function __set($key, $val)
  144. {
  145. $this->vars[$key] = utf8_encode($val);
  146.  
  147. return;
  148. }
  149.  
  150. /**
  151. * Singleton
  152. *
  153. * Returns false if unable to find instance or missing arguments.
  154. * You can access this at any time:
  155. *
  156. * <code>
  157. * $tpl = Cgiapp2_Plugin_Xslt::getInstance();
  158. * </code>
  159. *
  160. * @static
  161. * @access public
  162. * @param mixed $cgiapp Cgiapp2 instance object
  163. * @param mixed $tmpl_path Path to template root directory
  164. * @return void
  165. */
  166. public static function getInstance($extra_params = null)
  167. {
  168. // Return instance if it exists already
  169. if (!self::$_instance) {
  170. self::$_instance = new self($extra_params);
  171. }
  172.  
  173. return self::$_instance;
  174. }
  175.  
  176. /**
  177. * Initialize a template instance and/or set the template path
  178. *
  179. * If no instance currently exists, it is first initialized via {@link }
  180. * getInstance()} using the extra parameters.
  181. *
  182. * init() is used to set the template path. If the template path has not
  183. * changed, nothing is done.
  184. *
  185. * @static
  186. * @access public
  187. * @param mixed $cgiapp
  188. * @param mixed $tmpl_path
  189. * @param mixed $extra_params
  190. * @return bool
  191. */
  192. public static function init(Cgiapp2 $cgiapp, $tmpl_path, $extra_params = null)
  193. {
  194. // Get xslt object
  195. $self = self::getInstance($extra_params);
  196.  
  197. if ($self->tmpl_path != $tmpl_path) {
  198. $self->tmpl_path = $tmpl_path;
  199. }
  200.  
  201. return true;
  202. }
  203.  
  204. /**
  205. * Assign a variable or variables to a template
  206. *
  207. * assign() can be used to assign data to a template.
  208. *
  209. * You can also send it an associative array of variable names => values,
  210. * and all elements included will be sent to the template.
  211. *
  212. * @static
  213. * @access public
  214. * @return bool
  215. * @throws Cgiapp2_Exception when bad data passed
  216. */
  217. public static function assign(Cgiapp2 $cgiapp)
  218. {
  219. $argv = func_get_args();
  220. $cgiapp = array_shift($argv);
  221. $argc = count($argv);
  222.  
  223. $self = self::getInstance();
  224.  
  225. if (1 == $argc) {
  226. $values = array_shift($argv);
  227. if (Cgiapp2::is_assoc_array($values)) {
  228. foreach ($values as $key => $value) {
  229. $self->$key = $value;
  230. }
  231. } else {
  232. throw new Cgiapp2_Exception('Bad array passed to Cgiapp2_Plugin_Xslt::assign()');
  233. return false;
  234. }
  235. } elseif (2 == $argc) {
  236. $key = array_shift($argv);
  237. if (is_string($key)) {
  238. $val = array_shift($argv);
  239. $self->$key = $val;
  240. } else {
  241. throw new Cgiapp2_Exception('Attempting to assign non-string key');
  242. return false;
  243. }
  244. } else {
  245. throw new Cgiapp2_Exception('Bad number or type of arguments passed to Cgiapp2_Plugin_Xslt::assign()');
  246. return false;
  247. }
  248.  
  249. return true;
  250. }
  251.  
  252. /**
  253. * Fetch template contents
  254. *
  255. * $args may be one of the following:
  256. * - An XML string
  257. * - The path to an XML file to transform
  258. * - An array with two elements, the xml string or file to transform and the
  259. * xsl stylesheet to transform it with
  260. *
  261. * In the first two options, the XSL stylesheet provided by
  262. * {@link $params $params['xsl']} will be used.
  263. *
  264. * If no xml or xsl file is provided or either is invalid, returns an empty
  265. * string.
  266. *
  267. * @static
  268. * @access public
  269. * @param mixed $cgiapp
  270. * @param mixed $args
  271. * @return string
  272. */
  273. public static function fetch(Cgiapp2 $cgiapp, $args)
  274. {
  275. $self = self::getInstance();
  276. $parameters = null;
  277.  
  278. // Check arguments
  279. if (empty($args)) {
  280. return '';
  281. } elseif (is_array($args) && (2 == count($args))) {
  282. $xml = $args[0];
  283. $xsl = $args[1];
  284. } elseif (is_string($args)) {
  285. $xml = $args;
  286. if (!isset($self->params['xsl'])) {
  287. throw new Cgiapp2_Exception('No XSL stylesheet provided to Cgiapp2 instance');
  288. }
  289. $xsl = $self->params['xsl'];
  290. } else {
  291. throw new Cgiapp2_Exception('Invalid arguments provided to Xslt');
  292. }
  293.  
  294. // Initialize XSLT handle
  295. // * Create DOMDocument object
  296. // * Determine type of XSL:
  297. if (0 !== strpos(trim($xsl), '<xsl:stylesheet')) {
  298. $xsl = $self->tmpl_path . '/' . $xsl;
  299. $xslDoc = DOMDocument::load($xsl);
  300. } else {
  301. $xslDoc = DOMDocument::loadXML($xsl);
  302. }
  303. if (!$xslDoc instanceof DOMDocument) {
  304. throw new Cgiapp2_Exception('Invalid XSL or XSL file');
  305. }
  306.  
  307. // * Create XSLTProcessor
  308. $proc = new XSLTProcessor();
  309.  
  310. // Determine if we should register PHP functions with the XSLT
  311. // processor; if so, do we need to restrict them?
  312. if (isset($self->params['registerPHPFunctions'])) {
  313. if (false !== ($functions = $self->params['registerPHPFunctions']))
  314. {
  315. $proc->registerPHPFunctions($functions);
  316. }
  317. } else {
  318. $proc->registerPHPFunctions();
  319. }
  320. // * Load XSL into processor
  321. $proc->importStylesheet($xslDoc);
  322.  
  323. // * Load parameters
  324. if (is_array($self->vars) && !empty($self->vars)) {
  325. foreach ($self->vars as $key => $value) {
  326. $ns = ($self->namespace ? $self->namespace : '');
  327. $proc->setParameter($ns, $key, $value);
  328. }
  329. }
  330.  
  331. // * Prepare XML DOMDocument
  332. $xmlDoc = new DOMDocument();
  333. if (0 !== strpos(trim($xml), '<?xml')) {
  334. $xml = $self->tmpl_path . '/' . $xml;
  335. $xmlDoc = DOMDocument::load($xml);
  336. } else {
  337. $xmlDoc = DOMDocument::loadXML($xml);
  338. }
  339. if (!$xmlDoc instanceof DOMDocument) {
  340. throw new Cgiapp2_Exception('Unable to load XML');
  341. }
  342.  
  343. // EVENTUALLY
  344. // * Allow the ability to register PHP functions as helpers
  345.  
  346. // * Process
  347. if (!$output = $proc->transformToXML($xmlDoc)) {
  348. throw new Cgiapp2_Exception('Unable to transform XML with XSLT');
  349. }
  350.  
  351. return $output;
  352. }
  353. }
  354.  
  355. /**
  356. * Register callbacks with tmpl_path, tmpl_assign, and tmpl_fetch callback hooks
  357. * of Cgiapp2
  358. */
  359. Cgiapp2::add_callback('tmpl_path', array('Cgiapp2_Plugin_Xslt', 'init'), 'Cgiapp2');
  360. Cgiapp2::add_callback('tmpl_assign', array('Cgiapp2_Plugin_Xslt', 'assign'), 'Cgiapp2');
  361. Cgiapp2::add_callback('tmpl_fetch', array('Cgiapp2_Plugin_Xslt', 'fetch'), 'Cgiapp2');

Documentation generated on Sat, 03 Jun 2006 10:49:00 -0400 by phpDocumentor 1.3.0RC5