PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/WebContent/Chapter13-AjaxFrameworks/JPSpan/JPSpan/Include.php

https://gitlab.com/bruce.ng/Professional-Ajax
PHP | 476 lines | 215 code | 50 blank | 211 comment | 12 complexity | 22afd5b0c5a1e8b7409e13937923ff11 MD5 | raw file
  1. <?php
  2. /**
  3. * @package JPSpan
  4. * @subpackage Include
  5. * @version $Id: Include.php,v 1.6 2005/04/25 10:13:20 harryf Exp $
  6. */
  7. //-----------------------------------------------------------------------------
  8. /**
  9. * When to compress the Javascript (remove whitespace formatting)
  10. * Set to TRUE and Javascript will be "compressed"
  11. */
  12. if ( !defined('JPSPAN_INCLUDE_COMPRESS') ) {
  13. define ('JPSPAN_INCLUDE_COMPRESS',FALSE);
  14. }
  15. //-----------------------------------------------------------------------------
  16. /**
  17. * Make sure a file_get_contents() implementation exists
  18. * PHP backwards compatability
  19. */
  20. if ( !function_exists('file_get_contents') ) {
  21. /**
  22. * @see http://www.php.net/file_get_contents
  23. * @param string filename
  24. * @return string file content
  25. * @package JPSpan
  26. * @subpackage Include
  27. */
  28. function file_get_contents($filename) {
  29. $fd = fopen("$filename", 'rb');
  30. $content = fread($fd, filesize($filename));
  31. fclose($fd);
  32. return $content;
  33. }
  34. }
  35. //-----------------------------------------------------------------------------
  36. /**
  37. * Include a Javascript file. Filename must be relative to the
  38. * JPSpan/js/ directory (without a leading slash if in subdir)
  39. * This is the recommended point to include Javascript files
  40. * Calling this registers a shutdown function which takes care of displaying
  41. * the Javascript
  42. * @package JPSpan
  43. * @subpackage Include
  44. * @param string filename
  45. * @return void
  46. * @access public
  47. */
  48. function JPSpan_Include($file) {
  49. $Includer = & JPSpan_Include::instance();
  50. $Includer->loadFile($file);
  51. register_shutdown_function('JPSpan_Include_Shutdown');
  52. }
  53. //-----------------------------------------------------------------------------
  54. /**
  55. * PHP shutdown function making sure Javascript is displayed
  56. * @package JPSpan
  57. * @subpackage Include
  58. * @access private
  59. * @return void
  60. */
  61. function JPSpan_Include_Shutdown() {
  62. $Includer = & JPSpan_Include::instance();
  63. echo $Includer->getCode();
  64. }
  65. //-----------------------------------------------------------------------------
  66. /**
  67. * Loads Javascript but does not register shutdown fn
  68. * @see JPSpan_Include
  69. * @package JPSpan
  70. * @subpackage Include
  71. * @param string filename
  72. * @return void
  73. * @access public
  74. */
  75. function JPSpan_Include_Register($file) {
  76. $Includer = & JPSpan_Include::instance();
  77. $Includer->loadFile($file);
  78. }
  79. //-----------------------------------------------------------------------------
  80. /**
  81. * Loads the Javascript error reader
  82. * @see JPSpan_Include
  83. * @package JPSpan
  84. * @subpackage Include
  85. * @param string (optional) 2 letter localization code e.g. 'en'
  86. * @param array (optional) list of Application_Errors to merge in
  87. * @param array (optional) list of Server_Errors to merge in
  88. * @param array (optional) list of Client_Errors to merge in
  89. * @todo Break this function up
  90. * @return void
  91. * @access public
  92. */
  93. function JPSpan_Include_ErrorReader($lang='en',$app=array(),$ser=array(),$cli=array()) {
  94. $errorfile = 'errors.'.$lang.'.ini';
  95. if ( !file_exists(JPSPAN. 'errors/'.$errorfile) ) {
  96. $errorfile = 'errors.en.ini';
  97. }
  98. $errors = parse_ini_file(JPSPAN . 'errors/'.$errorfile,TRUE);
  99. $script = "/**@\n* include 'util/errorreader.js';\n*/\n";
  100. // Use Object instead of Array as Javascript will fill empty elements
  101. $script .= "JPSpan_Util_ErrorReader.prototype.errorList = new Object();\n";
  102. foreach ( $errors['Client_Error'] as $key => $value ) {
  103. $value = addcslashes($value,"\000\042\047\134");
  104. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  105. }
  106. foreach ( $cli as $key => $value ) {
  107. if ( array_key_exists($key, $errors['Client_Error']) ) {
  108. continue;
  109. }
  110. $value = addcslashes($value,"\000\042\047\134");
  111. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  112. }
  113. foreach ( $errors['Server_Error'] as $key => $value ) {
  114. $value = addcslashes($value,"\000\042\047\134");
  115. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  116. }
  117. foreach ( $ser as $key => $value ) {
  118. if ( array_key_exists($key, $errors['Server_Error']) ) {
  119. continue;
  120. }
  121. $value = addcslashes($value,"\000\042\047\134");
  122. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  123. }
  124. foreach ( $errors['Application_Error'] as $key => $value ) {
  125. $value = addcslashes($value,"\000\042\047\134");
  126. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  127. }
  128. foreach ( $app as $key => $value ) {
  129. if ( array_key_exists($key, $errors['Application_Error']) ) {
  130. continue;
  131. }
  132. $value = addcslashes($value,"\000\042\047\134");
  133. $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
  134. }
  135. $Includer = & JPSpan_Include::instance();
  136. $Includer->loadString('errorreaderlist',$script);
  137. }
  138. //-----------------------------------------------------------------------------
  139. /**
  140. * Returns all loaded Javascript
  141. * @see JPSpan_Include
  142. * @package JPSpan
  143. * @subpackage Include
  144. * @return string
  145. * @access public
  146. */
  147. function JPSpan_Includes_Fetch() {
  148. $Includer = & JPSpan_Include::instance();
  149. return $Includer->getCode();
  150. }
  151. //-----------------------------------------------------------------------------
  152. /**
  153. * Displays all loaded Javascript
  154. * @see JPSpan_Include
  155. * @package JPSpan
  156. * @subpackage Include
  157. * @return void
  158. * @access public
  159. */
  160. function JPSpan_Includes_Display() {
  161. echo JPSpan_Includes_Fetch();
  162. }
  163. //-----------------------------------------------------------------------------
  164. /**
  165. * Front for dealing with includes
  166. * @package JPSpan
  167. * @subpackage Include
  168. * @access public
  169. */
  170. class JPSpan_Include {
  171. /**
  172. * @var JPSpan_Include_Manager
  173. * @access private
  174. */
  175. var $Manager;
  176. /**
  177. * Do not construct JPSpan_Include directly! Use instance method
  178. * @see instance
  179. * @access private
  180. */
  181. function JPSpan_Include() {
  182. $this->Manager = & new JPSpan_Include_Manager();
  183. }
  184. /**
  185. * Load a Javascript file
  186. * @param string filename
  187. * @return void
  188. * @access public
  189. */
  190. function loadFile($file) {
  191. $file = JPSPAN . 'js/' . $file;
  192. $this->Manager->loadFile($file);
  193. }
  194. /**
  195. * Load a Javascript script from a string
  196. * @param string source code
  197. * @return void
  198. * @access public
  199. */
  200. function loadString($name, $src) {
  201. $this->Manager->load($name,$src);
  202. }
  203. /**
  204. * Get the code
  205. * @return string Javascript
  206. * @access public
  207. */
  208. function getCode() {
  209. if ( JPSPAN_INCLUDE_COMPRESS ) {
  210. require_once JPSPAN . 'Script.php';
  211. $code = $this->Manager->getCode();
  212. return JPSpan_Script::compress($code);
  213. } else {
  214. return $this->Manager->getCode();
  215. }
  216. }
  217. /**
  218. * Obtain singleton instance of JPSpan_Include
  219. * @return JPSpan_Include
  220. * @access public
  221. * @static
  222. */
  223. function & instance() {
  224. static $importer = NULL;
  225. if ( !$importer ) {
  226. $importer = new JPSpan_Include();
  227. }
  228. return $importer;
  229. }
  230. }
  231. //-----------------------------------------------------------------------------
  232. /**
  233. * Manages the includes, making sure dependencies are resolved
  234. * @package JPSpan
  235. * @subpackage Include
  236. * @access protected
  237. */
  238. class JPSpan_Include_Manager {
  239. /**
  240. * List of files to include. Dependencies are added at end of list
  241. * @var array
  242. * @access private
  243. */
  244. var $includes = array();
  245. /**
  246. * Map of file name to source code
  247. * @var array
  248. * @access private
  249. */
  250. var $code = array();
  251. /**
  252. * Load a Javascript file
  253. * @param string full path to file
  254. * @return void
  255. * @access protected
  256. */
  257. function loadFile($file) {
  258. $src = file_get_contents($file);
  259. $this->load($file,$src);
  260. }
  261. /**
  262. * Load a Javascript contained in a string
  263. * @param string indentifier for script (e.g. full path + filename)
  264. * @param string Javascript source
  265. * @return void
  266. * @access protected
  267. */
  268. function load($name, $src) {
  269. if ( !in_array($name,$this->includes) ) {
  270. $this->includes[] = $name;
  271. $File = & new JPSpan_Include_File($this);
  272. $File->parse($src);
  273. $this->code[$name] = $File->src;
  274. $this->resolveDependencies($File->includes);
  275. }
  276. }
  277. /**
  278. * Resolve any dependencies a script has on others
  279. * @param array list of dependencies (filenames)
  280. * @return void
  281. * @access private
  282. */
  283. function resolveDependencies($includes) {
  284. foreach ( $includes as $include ) {
  285. $src = file_get_contents($include);
  286. $this->load($include,$src);
  287. }
  288. }
  289. /**
  290. * Get the source
  291. * @return string
  292. * @access protected
  293. */
  294. function getCode() {
  295. $includes = array_reverse($this->includes);
  296. $code = '';
  297. foreach ( $includes as $include ) {
  298. $code .= $this->code[$include];
  299. }
  300. return $code;
  301. }
  302. }
  303. //-----------------------------------------------------------------------------
  304. /**
  305. * Represents a single file - manages parsing the file for dependencies
  306. * Right now this does no error checking / validation of parse files
  307. * @package JPSpan
  308. * @subpackage Include
  309. * @access protected
  310. */
  311. class JPSpan_Include_File {
  312. /**
  313. * List of dependencies, obtained from parsing the source
  314. * @var array
  315. * @access protected
  316. */
  317. var $includes = array();
  318. /**
  319. * Source code with dependency statements removed
  320. * @var string
  321. * @access protected
  322. */
  323. var $src = '';
  324. /**
  325. * Parse the file for dependencies
  326. * @param string Javascript source
  327. * @return void
  328. * @access protected
  329. */
  330. function parse($src) {
  331. $Parser = & new JPSpan_Include_Parser($this);
  332. $Parser->parse($src);
  333. }
  334. /**
  335. * Parser handler
  336. * @param string script token (base state)
  337. * @param int state (unused)
  338. * @access protected
  339. * @return boolean TRUE
  340. */
  341. function script($script, $state) {
  342. $this->src .= $script;
  343. return TRUE;
  344. }
  345. /**
  346. * Parser handler (discards)
  347. * @param string declaration
  348. * @param int state (unused)
  349. * @access protected
  350. * @return boolean TRUE
  351. */
  352. function declaration($decl, $state) {
  353. return TRUE;
  354. }
  355. /**
  356. * Parser handler - handles include statements
  357. * @param string include
  358. * @param int state
  359. * @access protected
  360. * @return boolean TRUE
  361. */
  362. function inc($file, $state) {
  363. if ( $state == JPSPAN_LEXER_UNMATCHED ) {
  364. $file = str_replace(array("'",'"'),'',$file);
  365. $this->includes[] = JPSPAN . 'js/' . trim($file);
  366. }
  367. return TRUE;
  368. }
  369. }
  370. //-----------------------------------------------------------------------------
  371. /**
  372. * Parses source for include statements
  373. * @package JPSpan
  374. * @subpackage Include
  375. * @access protected
  376. */
  377. class JPSpan_Include_Parser {
  378. /**
  379. * Callback handler for parser
  380. * @var JPSpan_Include_File
  381. * @access private
  382. */
  383. var $Handler;
  384. /**
  385. * @param JPSpan_Include_File
  386. * @access protected
  387. */
  388. function JPSpan_Include_Parser(& $Handler) {
  389. $this->Handler = & $Handler;
  390. }
  391. /**
  392. * Parse some Javascript
  393. * @param string Javascript
  394. * @return void
  395. * @access protected
  396. */
  397. function parse($src) {
  398. $Lexer = & $this->getLexer();
  399. $Lexer->parse($src);
  400. }
  401. /**
  402. * Create the Lexer
  403. * @see JPSpan_Lexer
  404. * @return JPSpan_Lexer
  405. * @access private
  406. */
  407. function & getLexer() {
  408. require_once JPSPAN . 'Lexer.php';
  409. $Lexer = new JPSpan_Lexer($this->Handler,'script');
  410. $Lexer->addEntryPattern('/\*\*@','script','declaration');
  411. $Lexer->addExitPattern('\*/','declaration');
  412. $Lexer->addEntryPattern('include','declaration','inc');
  413. $Lexer->addExitPattern(';','inc');
  414. return $Lexer;
  415. }
  416. }