1: <?php
2: /*
3: File: xajaxScriptPlugin.inc.php
4:
5: Contains the xajaxScriptPlugin class declaration.
6:
7: Title: xajaxScriptPlugin class
8:
9: Please see <copyright.inc.php> for a detailed description, copyright
10: and license information.
11: */
12:
13: /*
14: @package xajax
15: @version $Id: xajaxScriptPlugin.inc.php 362 2007-05-29 15:32:24Z calltoconstruct $
16: @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
17: @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson
18: @license http://www.xajaxproject.org/bsd_license.txt BSD License
19: */
20:
21: /*
22: Class: xajaxScriptPlugin
23:
24: Contains the code that can produce script and style data during deferred script
25: generation. This allows the xajax generated javascript and style sheet information
26: to be loaded via an external file reference instead of inlined into the page
27: source.
28: */
29: class xajaxScriptPlugin extends xajaxRequestPlugin
30: {
31: /*
32: String: sRequest
33: */
34: var $sRequest;
35:
36: /*
37: String: sHash
38: */
39: var $sHash;
40:
41: /*
42: String: sRequestURI
43: */
44: var $sRequestURI;
45:
46: /*
47: Boolean: bDeferScriptGeneration
48: */
49: var $bDeferScriptGeneration;
50:
51: /*
52: Boolean: bValidateHash
53: */
54: var $bValidateHash;
55:
56: /*
57: Boolean: bWorking
58: */
59: var $bWorking;
60:
61: /*
62: Function: xajaxScriptPlugin
63:
64: Construct and initialize the xajax script plugin object. During
65: initialization, this plugin will look for hash codes in the
66: GET data (parameters passed on the request URI) and store them
67: for later use.
68: */
69: function xajaxScriptPlugin()
70: {
71: $this->sRequestURI = '';
72: $this->bDeferScriptGeneration = false;
73: $this->bValidateHash = true;
74:
75: $this->bWorking = false;
76:
77: $this->sRequest = '';
78: $this->sHash = null;
79:
80: if (isset($_GET['xjxGenerateJavascript'])) {
81: $this->sRequest = 'script';
82: $this->sHash = $_GET['xjxGenerateJavascript'];
83: }
84:
85: if (isset($_GET['xjxGenerateStyle'])) {
86: $this->sRequest = 'style';
87: $this->sHash = $_GET['xjxGenerateStyle'];
88: }
89: }
90:
91: /*
92: Function: configure
93:
94: Sets/stores configuration options used by this plugin. See also:
95: <xajax::configure>. This plugin will watch for and store the current
96: setting for the following configuration options:
97:
98: - <requestURI> (string): The requestURI of the current script file.
99: - <deferScriptGeneration> (boolean): A flag that indicates whether
100: script deferral is in effect or not.
101: - <deferScriptValidateHash> (boolean): A flag that indicates whether
102: or not the script hash should be validated.
103: */
104: function configure($sName, $mValue)
105: {
106: if ('requestURI' == $sName) {
107: $this->sRequestURI = $mValue;
108: } else if ('deferScriptGeneration' == $sName) {
109: if (true === $mValue || false === $mValue)
110: $this->bDeferScriptGeneration = $mValue;
111: } else if ('deferScriptValidateHash' == $sName) {
112: if (true === $mValue || false === $mValue)
113: $this->bValidateHash = $mValue;
114: }
115: }
116:
117: /*
118: Function: generateClientScript
119:
120: Called by the <xajaxPluginManager> when the text of the client script
121: (or style) declarations are needed.
122:
123: This function will only output script or style information if the
124: request URI contained an appropriate hash code and script deferral
125: is in effect.
126: */
127: function generateClientScript()
128: {
129: if ($this->bWorking)
130: return;
131:
132: if (true === $this->bDeferScriptGeneration)
133: {
134: $this->bWorking = true;
135:
136: $sQueryBase = '?';
137: if (0 < strpos($this->sRequestURI, '?'))
138: $sQueryBase = '&';
139:
140: $aScripts = $this->_getSections('script');
141: if (0 < count($aScripts))
142: {
143: // echo "<!--" . print_r($aScripts, true) . "-->";
144:
145: $sHash = md5(implode($aScripts));
146: $sQuery = $sQueryBase . "xjxGenerateJavascript=" . $sHash;
147:
148: echo "\n<script type='text/javascript' src='" . $this->sRequestURI . $sQuery . "' charset='UTF-8'></script>\n";
149: }
150:
151: $aStyles = $this->_getSections('style');
152: if (0 < count($aStyles))
153: {
154: // echo "<!--" . print_r($aStyles, true) . "-->";
155:
156: $sHash = md5(implode($aStyles));
157: $sQuery = $sQueryBase . "xjxGenerateStyle=" . $sHash;
158:
159: echo "\n<link href='" . $this->sRequestURI . $sQuery . "' rel='Stylesheet' />\n";
160: }
161:
162: $this->bWorking = false;
163: }
164: }
165:
166: /*
167: Function: canProcessRequest
168:
169: Called by the <xajaxPluginManager> to determine if this plugin can
170: process the current request. This will return true when the
171: requestURI contains an appropriate hash code.
172: */
173: function canProcessRequest()
174: {
175: return ('' != $this->sRequest);
176: }
177:
178: function _getSections($sType)
179: {
180: $objPluginManager = xajaxPluginManager::getInstance();
181:
182: $objPluginManager->configure('deferScriptGeneration', 'deferred');
183:
184: $aSections = array();
185:
186: // buffer output
187:
188: ob_start();
189: $objPluginManager->generateClientScript();
190: $sScript = ob_get_clean();
191:
192: // parse out blocks
193:
194: $aParts = explode('</' . $sType . '>', $sScript);
195: foreach ($aParts as $sPart)
196: {
197: $aValues = explode('<' . $sType, $sPart, 2);
198: if (2 == count($aValues))
199: {
200: list($sJunk, $sPart) = $aValues;
201:
202: $aValues = explode('>', $sPart, 2);
203: if (2 == count($aValues))
204: {
205: list($sJunk, $sPart) = $aValues;
206:
207: if (0 < strlen($sPart))
208: $aSections[] = $sPart;
209: }
210: }
211: }
212:
213: $objPluginManager->configure('deferScriptGeneration', $this->bDeferScriptGeneration);
214:
215: return $aSections;
216: }
217:
218: /*
219: Function: processRequest
220:
221: Called by the <xajaxPluginManager> when the current request should be
222: processed. This plugin will generate the javascript or style sheet information
223: that would normally be output by the other xajax plugin objects, when script
224: deferral is in effect. If script deferral is disabled, this function returns
225: without performing any functions.
226: */
227: function processRequest()
228: {
229: if ($this->canProcessRequest())
230: {
231: $aSections = $this->_getSections($this->sRequest);
232:
233: // echo "<!--" . print_r($aSections, true) . "-->";
234:
235: // validate the hash
236: $sHash = md5(implode($aSections));
237: if (false == $this->bValidateHash || $sHash == $this->sHash)
238: {
239: $sType = 'text/javascript';
240: if ('style' == $this->sRequest)
241: $sType = 'text/css';
242:
243: $objResponse = new xajaxCustomResponse($sType);
244:
245: foreach ($aSections as $sSection)
246: $objResponse->append($sSection . "\n");
247:
248: $objResponseManager = xajaxResponseManager::getInstance();
249: $objResponseManager->append($objResponse);
250:
251: header ('Expires: ' . gmdate('D, d M Y H:i:s', time() + (60*60*24)) . ' GMT');
252:
253: return true;
254: }
255:
256: return 'Invalid script or style request.';
257: trigger_error('Hash mismatch: ' . $this->sRequest . ': ' . $sHash . ' <==> ' . $this->sHash, E_USER_ERROR);
258: }
259: }
260: }
261:
262: /*
263: Register the plugin with the xajax plugin manager.
264: */
265: $objPluginManager = xajaxPluginManager::getInstance();
266: $objPluginManager->registerPlugin(new xajaxScriptPlugin(), 9999);
267: